Guides 11792 Published by

An in‑depth tutorial walks the reader through installing a self‑hosted Firefox Sync server on Debian 11, starting with system updates and user creation before pulling the official binary from GitHub or compiling it from source. It covers the installation of required libraries like libssl3 and libpq5, setting up PostgreSQL credentials, running migrations, and writing a TOML config that binds to port 443 while deferring TLS handling to Nginx. Next, the article explains how to configure an Nginx virtual host, obtain Let’s Encrypt certificates with Certbot, reload services, and finally verify the sync functionality from Firefox by adding an account pointing to the new endpoint. The final sections emphasize troubleshooting common pitfalls such as wrong database URLs or missing Nginx reloads, recommend automating certificate renewal, and suggest additional security hardening steps before deploying in production.



How to Install Firefox Sync Server on Debian 11 – Set Up Your Own Sync Hub

If you’ve ever wanted a private place to keep your bookmarks, passwords, and open tabs in sync across devices without letting Mozilla hold the keys, this is how to spin up the official sync server on Debian 11. I’ll walk you through the bits you actually need to know and warn you where the road trips usually take a detour.

1. Get Your System Ready

Debian’s stock repositories don’t ship the freshest copy of Firefox Sync, so we’ll pull from Mozilla’s own build. First, make sure your OS is up‑to‑date:

sudo apt update && sudo apt upgrade -y

the sync server relies on a handful of newer libraries (especially libssl3 and libpq5). If you skip the upgrade, you’ll hit “cannot find dependency” later.

Create a dedicated user for the service. Running it as root is a no‑no:

sudo adduser --disabled-login syncsrv

Give that user a home directory; the config files will live there. I’ve run into permission headaches before when the service tried to write to /var/lib without rights.

2. Install Dependencies

The sync server is written in Rust and requires a couple of runtime libraries:

sudo apt install -y \
    libssl3 \
    libpq5 \
    postgresql-client \
    python3-certbot-nginx

If you’re planning to use PostgreSQL locally (highly recommended), the client package will be handy for creating the initial database. The certbot‑nginx pair is what we’ll use later for SSL, so install it now even if you only plan to test on HTTP.

3. Pull the Source or Binary

The easiest way to get a working binary is to grab the pre‑built release from GitHub:

cd ~syncsrv
curl -L https://github.com/mozilla-services/sync-server/releases/download/v1.4.0/sync-server-v1.4.0-linux-amd64.tar.gz | tar xzf -

Replace v1.4.0 with the latest tag if that’s what you want. Unpacking into the user’s home keeps everything tidy.

Alternatively, if you’re comfortable compiling:

sudo apt install -y cargo build-essential
cargo build --release

But for most users a pre‑built binary is faster and less likely to trip over compiler versions on Debian 11.

4. Set Up the PostgreSQL Database

Create a database user and schema that sync will use:

sudo -u postgres psql <<EOF
CREATE USER syncdb WITH PASSWORD 'changeme';
CREATE DATABASE syncdb OWNER syncdb;
\q
EOF

Now run the migration script included with the server to set up tables:

./sync-server-migrate --db-url "postgresql://syncdb:changeme@localhost/syncdb"

If you see an error about “database does not exist,” double‑check that you’re pointing at the right host and port. I once forgot to expose PostgreSQL on localhost, which caused a cryptic connection timeout.

5. Configure the Service

Create /etc/systemd/system/syncsrv.service with:

[Unit]
Description=Firefox Sync Server
After=network.target

[Service]
User=syncsrv
WorkingDirectory=/home/syncsrv/
ExecStart=/home/syncsrv/sync-server-v1.4.0-linux-amd64/sync-server --config /home/syncsrv/config.toml
Restart=on-failure

[Install]
WantedBy=multi-user.target

The --config flag points to a TOML file we’ll generate next.

6. Write the Config File

In /home/syncsrv/config.toml, paste:

# Basic network settings
listen = "0.0.0.0:443"

# Database connection string
database-url = "postgresql://syncdb:changeme@localhost/syncdb"

# Optional TLS (will be overridden by Nginx)
tls-cert-file = "/etc/ssl/certs/fullchain.pem"
tls-key-file  = "/etc/ssl/private/privkey.pem"

[services]
accounts   = { enabled = true }
search     = { enabled = false } # optional, not needed for basic sync

Explaination: listen binds to all interfaces on port 443 so we can front‑gate with Nginx later. The TLS paths are placeholders; you’ll generate them with Certbot.

7. Install and Configure Nginx + Certbot
sudo apt install -y nginx

Create an Nginx virtual host:

server {
    listen 80;
    server_name sync.example.com;

    location /.well-known/acme-challenge/ { root /var/www/certbot; }
}

server {
    listen 443 ssl;
    server_name sync.example.com;

    ssl_certificate     /etc/letsencrypt/live/sync.example.com/fullchain.pem;
    ssl_certificate_key /etc/letsencrypt/live/sync.example.com/privkey.pem;

    location / {
        proxy_pass http://127.0.0.1:443;
        proxy_set_header Host $host;
        proxy_ssl_verify off; # because sync runs TLS internally
    }
}

Run Certbot to fetch a cert:

sudo certbot --nginx -d sync.example.com

If the domain is local or you’re just testing, skip this step and use a self‑signed cert.

8. Start Everything
sudo systemctl daemon-reload
sudo systemctl enable syncsrv
sudo systemctl start syncsrv
systemctl status syncsrv

You should see “Active: active (running)”. If it’s stuck in a failure loop, check /var/log/syslog for the error; often it’s a mis‑typed database URL.

9. Test It

Open Firefox on any machine and go to about:preferences#sync. In the Add account dialog, choose “Use a private server” and point it at https://sync.example.com. If everything is wired correctly, you’ll be prompted for the sync password you set up when creating an account (the sync‑server CLI has a helper to generate that). Once logged in, try opening a bookmark on one device and watch it appear on another.

If you hit “connection refused” or “certificate not trusted,” double‑check the Nginx config and TLS paths. The most common hiccup I see is forgetting to reload Nginx after certbot updates:

sudo systemctl reload nginx
10. Keep It Running

Set up automatic certificate renewal with Certbot’s timer (it usually installs one by default). For the sync service, systemd already restarts on failure, but you can add a watchdog or monitor log tailing if you’re running it in production.

That’s it—your own Firefox Sync server is now humming quietly behind your firewall. The next step? Harden the PostgreSQL user permissions and maybe sprinkle some reverse‑proxy auth (like HTTP basic) to keep the sync endpoint out of sight from casual browsers.

Happy syncing, and remember: keeping your data under your control is a bit like having an extra set of keys—use it wisely!