Self-Hosting a Secure, End-to-End Encrypted Temporary File Sharing Platform: Deploying the Community-Patched Firefox Send on Docker VPS
Introduction: The Imperative for Private, Temporary File Sharing
In the modern digital enterprise, data privacy and secure asset transfer are paramount. Businesses frequently need to exchange sensitive documents, cryptographic keys, database dumps, or proprietary media with external partners, clients, or remote teams. Relying on mainstream, centralized cloud storage providers introduces significant compliance risks, potential data harvesting, and an unnecessarily permanent data footprint.
When Mozilla discontinued its open-source Firefox Send service in 2020, the open-source community lost a premier tool for simple, secure, and ephemeral file sharing. Fortunately, the open-source community stepped in to maintain, patch, and secure the codebase. This guide delivers a comprehensive blueprint for self-hosting a community-patched, end-to-end encrypted (E2EE) temporary file-sharing platform on your own Virtual Private Server (VPS) utilizing Docker and Docker Compose.
Why Choose the Community-Patched Firefox Send?
While the official service is defunct, the underlying architecture remains exceptionally robust. The community-driven forks address critical security vulnerabilities, update deprecated dependencies, and optimize the platform for modern containerized environments. By self-hosting this solution, your enterprise benefits from:
- True End-to-End Encryption (E2EE): Files are encrypted directly within the user's browser via the Web Crypto API before upload. The server only stores encrypted blobs and hashes; it never possesses the decryption key.
- Absolute Ephemerality: Files automatically expire based on strict, customizable thresholds: a specific number of downloads, a set time limit (e.g., hours or days), or immediate deletion after the initial download.
- Data Sovereignty: Your data remains entirely on your infrastructure, complying fully with stringent data protection frameworks such as GDPR, HIPAA, or local data localization laws.
- Resource Efficiency: The Node.js backend paired with a Redis key-value store operates with minimal memory and CPU overhead, making it ideal for cost-effective VPS instances.
Architecture and Security Model Overview
Understanding how the application handles data is crucial for trust. Firefox Send uses a split-key architecture to ensure zero-knowledge storage on the hosting server:
- Client-Side Encryption: When a file is selected, the browser generates a strong, random secret key. The file is encrypted locally in the browser.
- Payload Splitting: The secret key is appended to the URL hash fragment (the portion after the
#symbol). Crucially, modern web browsers do not send the hash fragment to the HTTP server during requests. - Server Obliviousness: The server receives only the encrypted payload and metadata. If an attacker compromises your VPS storage, they obtain nothing but unreadable cryptographic noise.
- Decryption on Demand: When the recipient clicks the download link, their browser fetches the encrypted data, extracts the key from the URL hash, and performs local client-side decryption.
Security Note: Because the server holds no keys, losing the original URL means the file is permanently unrecoverable. There is no password-reset or recovery mechanism for lost links.---
Prerequisites and Environment Setup
Before initiating the deployment, ensure your infrastructure meets the following baseline requirements:
- VPS Instance: A Linux-based VPS (Ubuntu 22.04 LTS or newer recommended) with at least 1 vCPU and 1 GB to 2 GB of RAM, depending on anticipated concurrent users.
- Domain Name: A dedicated domain or subdomain (e.g.,
share.yourcompany.com) with A/AAAA records pointed to your VPS IP address. - Docker Engine & Docker Compose: Installed and configured on the host machine.
- Reverse Proxy: Traefik, Nginx, or Caddy to handle SSL/TLS termination, which is mandatory for the Web Crypto API to function.
Step-by-Step Deployment Guide via Docker Compose
To deploy the community-maintained version of Firefox Send securely, we will utilize a multi-container Docker Compose setup consisting of the application front/backend, a Redis database for state and metadata management, and an upstream volume for file storage.
1. Structuring the Directory
Log into your VPS via SSH and create a structured directory for the application configuration:
mkdir -p /opt/firefox-send/data
cd /opt/firefox-send2. Creating the Environment Configuration
Create an .env file to define localized variables, file size limitations, and storage backends. This separation of configuration from code prevents accidental credential leaks.
# .env File
NODE_ENV=production
PORT=1443
# The external public URL of your service
BASE_URL=[https://share.yourcompany.com](https://share.yourcompany.com)
# Redis connection configuration
REDIS_HOST=send-redis
REDIS_PORT=6379
# Storage constraints (in bytes)
# Example: 2GB Maximum File Size
MAX_FILE_SIZE=2147483648
MAX_EXPIRE_SECONDS=604800
# Path inside the container where files are temporarily stored
FILE_STORAGE=file
VCAP_SERVICES={}3. Writing the Docker Compose File
Create a docker-compose.yml file. We utilize verified community forks (such as those maintained by reliable open-source contributors like timvisee or audited enterprise equivalents) that actively patch legacy Firefox Send bugs.
version: '3.8'
services:
send-app:
image: timvisee/ffsend:latest
container_name: send-application
restart: always
environment:
- NODE_ENV=${NODE_ENV}
- PORT=${PORT}
- BASE_URL=${BASE_URL}
- REDIS_HOST=${REDIS_HOST}
- REDIS_PORT=${REDIS_PORT}
- MAX_FILE_SIZE=${MAX_FILE_SIZE}
- MAX_EXPIRE_SECONDS=${MAX_EXPIRE_SECONDS}
- FILE_STORAGE=${FILE_STORAGE}
volumes:
- ./data:/uploads
ports:
- "127.0.0.1:1443:1443"
depends_on:
- send-redis
networks:
- send-network
send-redis:
image: redis:7-alpine
container_name: send-redis
restart: always
command: redis-server --appendonly yes
volumes:
- redis-data:/data
networks:
- send-network
volumes:
redis-data:
networks:
send-network:
driver: bridgeIn this configuration, notice that the application port 1443 is bound exclusively to 127.0.0.1. This prevents direct public exposure of the raw HTTP port, forcing all incoming external traffic to route through your secure reverse proxy.
Configuring the Reverse Proxy with Nginx and Let's Encrypt
Because the Web Crypto API strictly requires a secure context, deployment over HTTPS is non-negotiable. Below is a production-grade Nginx configuration fragment designed to forward traffic securely to our containerized application while enforcing modern security headers.
server {
listen 80;
server_name share.yourcompany.com;
return 301 https://$host$request_uri;
}
server {
listen 443 ssl http2;
server_name share.yourcompany.com;
ssl_certificate /etc/letsencrypt/live/[share.yourcompany.com/fullchain.pem](https://share.yourcompany.com/fullchain.pem);
ssl_certificate_key /etc/letsencrypt/live/[share.yourcompany.com/privkey.pem](https://share.yourcompany.com/privkey.pem);
# Security Headers
add_header X-Content-Type-Options nosniff always;
add_header X-Frame-Options "DENY" always;
add_header X-XSS-Protection "1; mode=block" always;
add_header Content-Security-Policy "default-src 'self'; script-src 'self' 'unsafe-eval'; style-src 'self' 'unsafe-inline';img-src 'self' data:; connect-src 'self' wss:;" always;
# Adjust client body size to accommodate large uploads
client_max_body_size 2048M;
location / {
proxy_pass [http://127.0.0.1:1443](http://127.0.0.1:1443);
proxy_set_header Host $host;
proxy_set_header X-Real-IP $remote_addr;
proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;
proxy_set_header X-Forwarded-Proto $scheme;
# WebSockets support for real-time upload progress
proxy_http_version 1.1;
proxy_set_header Upgrade $http_upgrade;
proxy_set_header Connection "upgrade";
}
}---Launching and Validating the Application
With configurations finalized, initiate the container ecosystem via Docker Compose:
docker compose up -dVerify that both containers are running optimally by evaluating the log outputs:
docker compose logs -f send-appNavigate to your configured domain in a secure web browser. You should be presented with a sleek, minimalist interface inviting you to drag and drop files. Test the platform by uploading a non-sensitive file, setting an expiration threshold of 1 download, and verifying that accessing the link a second time returns a valid 404 error page.
---Operational Maintenance and Automation
To keep your self-hosted platform performant, consider implementing an automated maintenance schedule. Since files are automatically purged based on time or download limits via application logic, local disk consumption remains highly predictable.
However, lingering orphaned files can occasionally manifest due to aborted uploads. It is recommended to establish a daily cron job to prune old Docker logs and clean up host-side caches:
0 3 * * * cd /opt/firefox-send && docker compose run --rm send-app npm run pruneConclusion
Deploying a community-patched version of Firefox Send on a Dockerized VPS offers a perfect balance between user convenience, minimal resource overhead, and uncompromising data security. By ensuring data never touches external third-party infrastructure unencrypted, you establish a resilient, self-hosted perimeter for corporate or personal file sharing. The zero-knowledge architecture guarantees that even in the event of an infrastructure-level breach, your structural privacy remains completely intact.
