Self Hosting Firefox Send

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 npm

Install 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-compose

Clone 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.service

Add 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-utils

Create 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 restart

That's it.

via GIPHY

References