Self-Hosting a Secure, End-to-End Encrypted Temporary File Sharing Platform with Community-Patched Firefox Send on Docker VPS
Introduction: The Crisis of Enterprise Data Sovereignty
In the modern corporate ecosystem, data is both a primary asset and a critical vulnerability. Every day, enterprises exchange vast volumes of sensitive information, from intellectual property and financial audits to personally identifiable information (PII) and legal contracts. While the convenience of public cloud storage providers is undeniable, it introduces a profound architectural flaw: the relinquishment of data control.
When your teams upload sensitive payloads to third-party public platforms, your cryptographic boundaries are compromised. Even with transport-layer security (TLS), data is frequently stored unencrypted or encrypted with keys held by the service provider. For businesses operating under strict regulatory frameworks like GDPR, HIPAA, or ISO 27001, this paradigm is no longer acceptable. The solution lies in self-hosting an open-source, end-to-end encrypted (E2EE) temporary file-sharing platform. While Mozilla officially discontinued its public Firefox Send service, the global open-source community has maintained, patched, and secured the codebase. Deploying a community-patched version of Firefox Send on your own virtual private server (VPS) via Docker delivers a robust, secure, and ephemeral file-sharing infrastructure tailored for corporate compliance.
The Core Architecture of Firefox Send: Why E2EE and Ephemerality Matter
Firefox Send stands out because of its strict zero-knowledge security architecture. Unlike traditional file servers where the host can inspect data at rest, Firefox Send utilizes client-side encryption executed directly within the user's web browser.
How Client-Side Encryption Functions
When a user drops a file into the Firefox Send interface, the following cryptographic sequence occurs:
- The browser generates a strong, random symmetric cryptographic key locally via the Web Crypto API.
- The file is encrypted in the browser using AES-128-GCM or AES-256-GCM before a single byte leaves the local machine.
- The encrypted payload is transmitted to the server.
- The cryptographic key is appended to the sharing URL as a hash fragment (the portion after the '#' symbol).
Because hash fragments are never transmitted to the host server during HTTP requests, the server hosting the application remains entirely blind to the contents of the file. If an adversary compromises your VPS, they will only discover encrypted binary large objects (BLOBs) devoid of context or decryption capability.
The Power of Ephemeral Storage
Data hoarding is a significant operational risk. Firefox Send mitigates this through enforced ephemerality. Files are automatically purged from the server's storage media based on two configurable thresholds: a specific download count limit or a time-to-live (TTL) expiration. This automated lifecycle management guarantees that your enterprise storage footprint remains lean and minimizes the blast radius of any historical data leaks.
Prerequisites for Enterprise Deployment
Before initiating the deployment process, ensure your infrastructure meets the following technical baselines:
- Virtual Private Server (VPS): A Linux VPS running a modern distribution (Ubuntu 22.04 LTS or Debian 12 recommended). Minimum specifications: 2 vCPUs, 4GB RAM, and high-performance NVMe SSD storage adjusted to your projected maximum concurrent file volume.
- Domain Name & DNS: A dedicated domain or subdomain (e.g.,
share.yourcompany.com) with an A/AAAA record pointing to your VPS public IP address. - Docker Engine & Compose: Docker Engine v24+ and Docker Compose v2+ installed and running on the host system.
- Reverse Proxy: An edge proxy like Nginx, Caddy, or Traefik to handle TLS termination, automated Let's Encrypt certificates, and request routing.
Step-by-Step Deployment Guide via Docker Compose
Because the original Mozilla repository is archived, we leverage trusted community-maintained forks (such as those maintained by the timvisee/send project) which fix critical dependencies, update Node.js vulnerabilities, and optimize performance.
Step 1: Establishing the Directory Structure
Connect to your VPS via SSH and construct an isolated workspace for the application stack:
mkdir -p /opt/firefox-send/data
cd /opt/firefox-sendStep 2: Configuring the Environment Variables
Create an environment configuration file named .env. This file manages the operational parameters of your Send instance. It is imperative to configure these securely.
Security Note: Always generate unique, cryptographically secure keys for your application secrets to prevent session tampering.
Construct your .env file with the following variables:
# Send Application Configuration
PORT=1443
NODE_ENV=production
# Base URL of your service (Critical for generating sharing links)
BASE_URL=[https://share.yourcompany.com](https://share.yourcompany.com)
# Storage Limits (Adjust based on business needs)
MAX_FILE_SIZE=2147483648 # 2 GB in bytes
MAX_DOWNLOADS=20
MAX_EXPIRE_SECONDS=604800 # 7 days in seconds
# Redis Configuration for Session & Metadata
REDIS_HOST=send-redis
REDIS_PORT=6379Step 3: Creating the Docker Compose Specification
Create a docker-compose.yml file in the same directory. This manifest defines a multi-container architecture isolating the application web frontend from the Redis memory cache used for tracking download counts and metadata states.
version: '3.8'
services:
send-app:
image: timvisee/send:latest
container_name: send-web
restart: always
ports:
- "127.0.0.1:1443:1443"
environment:
- PORT=1443
- NODE_ENV=production
- BASE_URL=${BASE_URL}
- MAX_FILE_SIZE=${MAX_FILE_SIZE}
- MAX_DOWNLOADS=${MAX_DOWNLOADS}
- MAX_EXPIRE_SECONDS=${MAX_EXPIRE_SECONDS}
- REDIS_HOST=${REDIS_HOST}
- REDIS_PORT=${REDIS_PORT}
volumes:
- ./data:/uploads
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: bridgeStep 4: Launching the Application Stack
With the specifications written, initialize and daemonize your containers by executing:
docker compose up -dVerify that both containers are functional and healthy by reviewing the system logs:
docker compose ps
docker compose logs -f send-appConfiguring Nginx Reverse Proxy and SSL Termination
Exposing the raw application port directly to the web is a severe security anti-pattern. You must sit the application behind a reverse proxy configured for secure HTTPS transmission to guarantee that the client-side encryption scripts cannot be injected or modified via a Man-in-the-Middle (MitM) attack.
Install Nginx on your host system and deploy an appropriate configuration block within /etc/nginx/sites-available/send:
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);
# Enhanced SSL Security Policies
ssl_protocols TLSv1.2 TLSv1.3;
ssl_prefer_server_ciphers on;
ssl_ciphers 'ECDHE-ECDSA-AES256-GCM-SHA384:ECDHE-RSA-AES256-GCM-SHA384';
# Security Headers
add_header X-Content-Type-Options nosniff fallback;
add_header X-Frame-Options DENY;
add_header X-XSS-Protection "1; mode=block";
add_header Strict-Transport-Security "max-age=31536000; includeSubDomains" always;
# Adjust client body size to match your MAX_FILE_SIZE
client_max_body_size 2500M;
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 upload progress bars
proxy_http_version 1.1;
proxy_set_header Upgrade $http_upgrade;
proxy_set_header Connection "upgrade";
}
}Link the site configuration to enable it, test for syntax validity, and reload the Nginx engine:
ln -s /etc/nginx/sites-available/send /etc/nginx/sites-enabled/
nginx -t
systemctl reload nginxPost-Deployment Maintenance and Backup Best Practices
Self-hosting is an active responsibility. To keep your platform secure and efficient, incorporate these structural maintenance workflows:
- Automated Image Updates: Utilize tools like Watchtower or configure a cron job to routinely pull community image security updates. Because community forks frequently patch critical npm security alerts, staying updated is paramount.
- Storage Volume Pruning: Although Firefox Send removes assets upon expiration, aborted or failed uploads can occasionally leave orphaned files in the
./datadirectory. Setting up a monthly maintenance cron job to verify file sync health prevents unexpected storage consumption. - Server Hardening: Configure UFW (Uncomplicated Firewall) to block all inbound traffic except for ports 80, 443, and your secure SSH port. Implement Fail2ban to actively deter brute-force access attempts against your VPS infrastructure.
Conclusion: Control Your Assets, Mitigate Your Risk
By migrating from generic public file-sharing utilities to a self-hosted, community-patched instance of Firefox Send on a private Docker VPS, your organization successfully closes a massive security loophole. You ensure that your business assets remain hidden from foreign servers, secure from passive wiretapping, and strictly bound by the compliance and retention policies you define. True privacy requires infrastructural ownership—and with Docker and modern open-source codebases, that ownership is entirely within reach.
