Firefox Send is a great file sharing service with E2EE and automatic deletion. In this post, I walk you through the steps to self host your own instance.
Last Updated: 2020-09-30 (Fixed a mistake in the Nginx configuration)
Firefox Send is an open-source file sharing service from Mozilla, it lets you share files with end-to-end encryption and a link that automatically expires. So you can keep what you share private and make sure your stuff doesn’t stay online forever.
Benefits of Send
- End-end encryption.
 - Short lifetime for sharing links.
 - Password protection for files.
 - Up to 2.5GB per file.
 
Self Hosting Your Own Send Instance
You are going to need:
- A VPS running Ubuntu 18.04.
 - A Subdomain pointing to your VPS (let's assume we are using send.ahmedmusaad.com)
 - (Optional) S3 or GCP Bucket for file storage.
 
Install
Install git curl nginx nodejs npm
sudo apt install git curl nginx nodejs npmInstall Docker & Docker-Compose
sudo apt-get update
sudo apt-get install apt-transport-https ca-certificates curl gnupg-agent software-properties-common
curl -fsSL https://download.docker.com/linux/ubuntu/gpg | sudo apt-key add -
sudo add-apt-repository "deb [arch=amd64] https://download.docker.com/linux/ubuntu $(lsb_release -cs) stable"
sudo apt-get update
sudo apt-get install docker-ce
sudo curl -L https://github.com/docker/compose/releases/download/1.21.2/docker-compose-`uname -s`-`uname -m` -o /usr/local/bin/docker-compose
sudo chmod +x /usr/local/bin/docker-composeClone The Code
cd /opt
mkdir send
git clone https://github.com/mozilla/send.git send/
cd send/Configure Send & Web Server
You can find the configuration file for Send at server/config.js. The most important configuration options are:
s3_bucket: The name of your S3 bucket.
gcs_bucket: The name of you GCS bucket.
listen_address & listen_port: The listening address and port.
base_url: The base url of the application.Configure Size Limits
The configuration file contains a section for size limit configuration, adjust the values to your desired limit. The default limit is 2.5 GB.
max_file_size: {
    format: Number,
    default: 1024 * 1024 * 1024 * 2.5,
    env: 'MAX_FILE_SIZE'
}Configure Nginx Reverse Proxy
Below you can find the nginx configuration you need to use to get things working properly. Remember to:
- Fetch a SSL certificate using Let's Encrypt
 - Replace <(sub)Domain> with your domain/subdomain.
 
upstream websocket {
                server 127.0.0.1:1443;
}
map $http_upgrade $connection_upgrade {
                default upgrade;
                '' close;
}
server {
        root /var/www/html;
        # Add index.php to the list if you are using PHP
        index index.html index.htm index.nginx-debian.html;
        server_name send.ahmedmusaad.com;
        location / {
                proxy_pass http://127.0.0.1:1443;
                proxy_redirect / $scheme://$http_host/;
                proxy_set_header Upgrade $http_upgrade;
                proxy_http_version 1.1;
                proxy_set_header Connection $connection_upgrade;
        }
        location /api {
                proxy_pass http://websocket;
                proxy_redirect / $scheme://$http_host/;
                proxy_set_header Upgrade $http_upgrade;
                proxy_http_version 1.1;
                proxy_set_header Connection $connection_upgrade;
                proxy_set_header Host $host;
        }
    listen [::]:443 ssl ipv6only=on; # managed by Certbot
    listen 443 ssl; # managed by Certbot
    ssl_certificate /etc/letsencrypt/live/send.ahmedmusaad.com/fullchain.pem; # managed by Certbot
    ssl_certificate_key /etc/letsencrypt/live/send.ahmedmusaad.com/privkey.pem; # managed by Certbot
    include /etc/letsencrypt/options-ssl-nginx.conf; # managed by Certbot
    ssl_dhparam /etc/letsencrypt/ssl-dhparams.pem; # managed by Certbot
}
server {
    if ($host = send.ahmedmusaad.com) {
        return 301 https://$host$request_uri;
    } # managed by Certbot
        listen 80 default_server;
        listen [::]:80 default_server;
        server_name send.ahmedmusaad.com;
    return 404; # managed by Certbot
}Run Send
sudo docker-compose up -d
sudo systemctl restart nginx.serviceAdd Basic HTTP Authentication
If we leave the Send instance open on the internet, a malicious actor will find and abuse it. In this section, we will add a basic HTTP authentication to our Send instance to prevent abuse or unwanted attention.
Install apache2-Utils
sudo apt-get update
sudo apt-get install apache2-utilsCreate a username/password
sudo htpasswd -c /etc/nginx/.htpasswd <USERNAME> #Replace USERNAME with the username you want to use. Update Nginx Configuration
You updated Nginx configuration should look like this:
upstream websocket {
                server 127.0.0.1:1443;
}
map $http_upgrade $connection_upgrade {
                default upgrade;
                '' close;
}
server {
        root /var/www/html;
        # Add index.php to the list if you are using PHP
        index index.html index.htm index.nginx-debian.html;
        server_name send.ahmedmusaad.com;
        auth_basic           "Firefox Send";
        auth_basic_user_file /etc/apache2/.htpasswd;
        location / {
                proxy_pass http://127.0.0.1:1443;
                proxy_redirect / $scheme://$http_host/;
                proxy_set_header Upgrade $http_upgrade;
                proxy_http_version 1.1;
                proxy_set_header Connection $connection_upgrade;
        }
        location /download/ {
                auth_basic off;
                proxy_pass http://127.0.0.1:1443;
                proxy_redirect / $scheme://$http_host/;
                proxy_set_header Upgrade $http_upgrade;
                proxy_http_version 1.1;
                proxy_set_header Connection $connection_upgrade;
        }
        location /api {
                auth_basic off;
                proxy_pass http://websocket;
                proxy_redirect / $scheme://$http_host/;
                proxy_set_header Upgrade $http_upgrade;
                proxy_http_version 1.1;
                proxy_set_header Connection $connection_upgrade;
                proxy_set_header Host $host;
        }
        location ~* \.(js|css|png|svg|woff2)$
        {
                auth_basic off;
                proxy_pass http://127.0.0.1:1443;
                proxy_redirect / $scheme://$http_host/;
                proxy_set_header Upgrade $http_upgrade;
                proxy_http_version 1.1;
                proxy_set_header Connection $connection_upgrade;
        }
    listen [::]:443 ssl ipv6only=on; # managed by Certbot
    listen 443 ssl; # managed by Certbot
    ssl_certificate /etc/letsencrypt/live/send.ahmedmusaad.com/fullchain.pem; # managed by Certbot
    ssl_certificate_key /etc/letsencrypt/live/send.ahmedmusaad.com/privkey.pem; # managed by Certbot
    include /etc/letsencrypt/options-ssl-nginx.conf; # managed by Certbot
    ssl_dhparam /etc/letsencrypt/ssl-dhparams.pem; # managed by Certbot
}
server {
    if ($host = send.ahmedmusaad.com) {
        return 301 https://$host$request_uri;
    } # managed by Certbot
        listen 80 default_server;
        listen [::]:80 default_server;
        server_name send.ahmedmusaad.com;
    return 404; # managed by Certbot
}Restart Nginx
sudo service nginx restartThat's it.