Use Docker to Deploy Your Own Sync Server
Mozilla publishes Docker images of its
syncstorage-rs builds
on ghcr.io. This guide provides a simple docker compose setup that can act as
a starting point to self-host Sync.
Images are available for both MySQL and PostgreSQL as the database. Differences in configuration or deployment steps will be noted.
Tagged release builds are available on ghcr.io. To pin to a specific version,
set SYNCSERVER_VERSION to the desired release tag (e.g., SYNCSERVER_VERSION=v1.45.0)
before running docker compose. Available releases can be found on the
syncstorage-rs releases page.
If SYNCSERVER_VERSION is not set, the compose files below default to latest.
Prerequisites and Presumptions
- The reader is familiar with the command line interface and
docker. - The reader is going to use Mozilla accounts for authentication and authorization.
- The service will be deployed at http://localhost:8000/.
Docker Compose, Sync Services Only
With a MySQL or PostgreSQL database is already up and running, save the yaml
below into a file, e.g. docker-compose.yaml, and ensure the image field is
using the correct MySQL or PostgreSQL build for the database.
services:
syncserver:
image: ghcr.io/mozilla-services/syncstorage-rs/syncstorage-rs-mysql:${SYNCSERVER_VERSION:-latest}
platform: linux/amd64
container_name: syncserver
ports:
- "8000:8000"
environment:
SYNC_HOST: "0.0.0.0"
SYNC_PORT: "8000"
SYNC_MASTER_SECRET: "${SYNC_MASTER_SECRET}"
SYNC_SYNCSTORAGE__DATABASE_URL: "${SYNC_SYNCSTORAGE__DATABASE_URL}"
SYNC_TOKENSERVER__DATABASE_URL: "${SYNC_TOKENSERVER__DATABASE_URL}"
SYNC_TOKENSERVER__ENABLED: "true"
SYNC_TOKENSERVER__RUN_MIGRATIONS: "true"
SYNC_TOKENSERVER__FXA_EMAIL_DOMAIN: "api.accounts.firefox.com"
SYNC_TOKENSERVER__FXA_OAUTH_SERVER_URL: "https://oauth.accounts.firefox.com"
SYNC_TOKENSERVER__INIT_NODE_URL: "${SYNC_TOKENSERVER__INIT_NODE_URL:-http://localhost:${SYNC_PORT}}"
restart: unless-stopped
healthcheck:
test: ["CMD", "curl", "-f", "http://localhost:${SYNC_PORT}/__heartbeat__"]
interval: 30s
timeout: 10s
retries: 3
start_period: 60s
Note that multiple values will be read from the environment:
SYNC_MASTER_SECRET: a secret used in cryptographic operations, a passphrase or random character string, e.g.use_your_own_secret_4d3d3d3dSYNC_SYNCSTORAGE__DATABASE_URL: database URL for syncstorage, e.g.mysql://sync:test@example.io/syncstorageorpostgres://testo:@localhost/syncdbSYNC_TOKENSERVER__DATABASE_URL: database URL for tokenserver, e.g.mysql://sync:test@example.io/tokenserverorpostgres://testo:@localhost/syncdbSYNC_TOKENSERVER__INIT_NODE_URL: the storage node URL (defaults tohttp://localhost:8000). Replace with the actual URL where clients will access the sync server.
The values can be directly written into the yaml as well.
Next, start the service with docker compose:
SYNC_MASTER_SECRET=use_your_own_secret_4d3d3d3d \
SYNC_SYNCSTORAGE__DATABASE_URL="mysql://sync:test@example.io/syncstorage" \
SYNC_TOKENSERVER__DATABASE_URL="mysql://sync:test@example.io/tokenserver" \
SYNC_TOKENSERVER__INIT_NODE_URL="http://localhost:8000" \
docker compose -f docker-compose.yaml up -d
Docker Compose, One-Shot with PostgreSQL
Alternatively, the database can be started through docker compose as well. The real service URL can be set with the INIT_NODE_URL environment variable.
Save the yaml below into a file, e.g. docker-compose.one-shot.yaml.
services:
syncserver:
image: ghcr.io/mozilla-services/syncstorage-rs/syncserver-postgres:${SYNCSERVER_VERSION:-latest}
platform: linux/amd64
container_name: syncserver
ports:
- "8000:8000"
environment:
SYNC_HOST: "0.0.0.0"
SYNC_PORT: "8000"
SYNC_MASTER_SECRET: "${SYNC_MASTER_SECRET:-changeme_secret_key}"
SYNC_SYNCSTORAGE__DATABASE_URL: "postgres://sync:sync@postgres:5432/syncserver"
SYNC_TOKENSERVER__DATABASE_URL: "postgres://sync:sync@postgres:5432/syncserver"
SYNC_TOKENSERVER__ENABLED: "true"
SYNC_TOKENSERVER__RUN_MIGRATIONS: "true"
SYNC_TOKENSERVER__FXA_EMAIL_DOMAIN: "api.accounts.firefox.com"
SYNC_TOKENSERVER__FXA_OAUTH_SERVER_URL: "https://oauth.accounts.firefox.com"
SYNC_HUMAN_LOGS: "${SYNC_HUMAN_LOGS:-false}"
RUST_LOG: "${RUST_LOG:-info}"
SYNC_TOKENSERVER__INIT_NODE_URL: "${SYNC_TOKENSERVER__INIT_NODE_URL:-http://localhost:${SYNC_PORT}}"
depends_on:
postgres:
condition: service_healthy
restart: unless-stopped
healthcheck:
test: ["CMD", "curl", "-f", "http://localhost:${SYNC_PORT}/__heartbeat__"]
interval: 30s
timeout: 10s
retries: 3
start_period: 60s
postgres:
image: postgres:18
container_name: syncserver-postgres
environment:
POSTGRES_USER: sync
POSTGRES_PASSWORD: sync
POSTGRES_DB: syncserver
volumes:
- postgres_data:/var/lib/postgresql
healthcheck:
test: ["CMD-SHELL", "pg_isready -U sync -d syncserver"]
interval: 10s
timeout: 5s
retries: 5
start_period: 30s
restart: unless-stopped
volumes:
postgres_data:
driver: local
Next, start the service with docker compose:
docker compose -f docker-compose.one-shot.yaml up -d
Configuring Firefox (Desktop)
Firefox itself needs to be configured to use the self-hosted Sync server.
- Go to
about:configin Firefox. - Find the
identity.sync.tokenserver.uriconfiguration. - Change the value to
http://localhost:8000/1.0/sync/1.5. - Restart Firefox.
Firefox should be using the self-hosted Sync server at this point. That can be
verified by checking the logs in about:sync-log.
Configuring Firefox (Mobile)
Firefox itself needs to be configured to use the self-hosted Sync server.
- Go to Settings -> About Firefox
- Repeadetly press the Firefox logo (six times) to activate the debug menu
- Go back to the main Setting menu.
- Click on the “Sync Debug” menu
- Click on “custom sync server” and change the value to
http://localhost:8000/1.0/sync/1.5. - After changing the “custom sync server” click on “Stop Firefox” in the same menu so the changes can be applied.