Docker
Synclet ships as a single container image. The fastest way to get running is Docker Compose, which bundles PostgreSQL alongside Synclet. You can also run the container standalone or skip Docker entirely with a bare binary.
Docker Compose (Recommended)
Section titled “Docker Compose (Recommended)”Docker Compose starts PostgreSQL 16, runs database migrations, and starts Synclet in one command.
git clone https://github.com/synclet-io/synclet.gitcd syncletecho "AUTH_JWT_SECRET=$(openssl rand -base64 32)" >> .envecho "SECRET_ENCRYPTION_KEY=$(openssl rand -base64 32)" >> .envmkdir -p /tmp/synclet && chmod 1777 /tmp/syncletdocker compose up -dThe image runs as UID 65532. On Linux, add DOCKER_GID=$(stat -c %g /var/run/docker.sock) to .env so the container can reach the Docker socket (Docker Desktop and OrbStack need nothing).
The default docker-compose.yml includes three services:
postgres— PostgreSQL 16, data stored in a named volume.migrate— Runssynclet migrate uponce before Synclet starts and exits.synclet— API, scheduler, and workers in a single container (started withserver --standalone).
The compose file has no default secrets: it refuses to start until AUTH_JWT_SECRET and SECRET_ENCRYPTION_KEY are set in .env. Back up the encryption key — stored connector secrets cannot be decrypted without it.
Once the containers are healthy, open the dashboard at http://localhost:8080.
Customizing the Compose file
Section titled “Customizing the Compose file”| Variable | Purpose | Default |
|---|---|---|
DB_DSN | PostgreSQL connection string | Set by Compose |
AUTH_JWT_SECRET | Token signing key (min. 32 characters) | Read from .env, required |
SECRET_ENCRYPTION_KEY | Base64-encoded 32-byte AES-256 key for credentials | Read from .env, required |
DOCKER_GID | Group that owns the Docker socket, added to the container | 0 |
PUBLIC_HTTP_SERVER_ADDR | Public HTTP listen address | 0.0.0.0:8080 |
INTERNAL_HTTP_SERVER_ADDR | Internal HTTP listen address (executor API, /live, /ready, /metrics) | 0.0.0.0:8081 |
DOCKER_EXECUTOR_TEMP_DIR_ROOT | Per-task scratch dir (config / catalog / state) under which connector bind mounts are created. Required when Synclet itself runs in a container with the host docker.sock mounted — see note below. | /tmp/synclet |
Generate production secrets before first start:
# AUTH_JWT_SECRETopenssl rand -base64 32
# SECRET_ENCRYPTION_KEY (must be exactly 32 bytes, base64-encoded)openssl rand -base64 32Docker Standalone
Section titled “Docker Standalone”If you already have a PostgreSQL 16 instance, run Synclet on its own.
docker build -t synclet .docker run -d \ --name synclet \ -p 8080:8080 \ -e DB_DSN="postgres://synclet:password@host.docker.internal:5432/synclet?sslmode=disable" \ -e AUTH_JWT_SECRET="$(openssl rand -base64 32)" \ -e SECRET_ENCRYPTION_KEY="$(openssl rand -base64 32)" \ -e DOCKER_EXECUTOR_TEMP_DIR_ROOT="/tmp/synclet" \ -v /var/run/docker.sock:/var/run/docker.sock \ -v /tmp/synclet:/tmp/synclet \ synclet server --standaloneWhy the docker.sock and the temp dir? Synclet needs access to the Docker socket (
/var/run/docker.sock) to launch Airbyte connector containers during syncs.When Synclet itself runs inside a container and talks to the host daemon via that socket, every per-task scratch file (the rendered
config.json,catalog.json, andstate.json) is created by Synclet on the container’s filesystem, but the daemon that mounts it into the connector container is on the host.DOCKER_EXECUTOR_TEMP_DIR_ROOTis the path inside Synclet’s container where those files are written — it must be bind-mounted from an identically-named path on the host (e.g. both/tmp/synclet) so the host daemon can resolve the bind-mount source.Running the binary natively on the host? Leave
DOCKER_EXECUTOR_TEMP_DIR_ROOTunset — Synclet falls back to the OS temp dir, which the host daemon can already see.Run
synclet migrate uponce against the same database before starting the server (or front it with amigratesidecar — see the bundled compose file).
Verify the container is running:
docker logs syncletBinary (No Docker)
Section titled “Binary (No Docker)”You can run Synclet as a plain binary without Docker.
- Download the latest release from GitHub Releases.
- Set the required environment variables (see Environment Variables).
- Run migrations and start the server:
export DB_DSN="postgres://synclet:password@localhost:5432/synclet?sslmode=disable"export ENVIRONMENT=production
# Required outside local development; generate each with: openssl rand -base64 32export AUTH_JWT_SECRET="your-jwt-secret"export SECRET_ENCRYPTION_KEY="your-encryption-key"
synclet migrate upsynclet server --standaloneThe dashboard is available at http://localhost:8080.
Important: Connectors still require Docker on the host: every connector, Synclet’s own Go connectors included, runs as a Docker container.
Health Checks
Section titled “Health Checks”Synclet serves /live and /ready on the internal port (8081 by default) for load balancers and orchestrators:
curl http://localhost:8081/ready# Returns HTTP 200 when the database, background jobs and event router are upThe default Synclet image is based on distroless and does not include curl or wget. To add Docker health checks, use a multi-stage build that includes a health-check binary, or check from outside the container:
# Health check from the host or a sidecarcurl -f http://localhost:8081/readyMonitoring
Section titled “Monitoring”- Dashboard — The built-in web UI at
http://localhost:8080shows pipeline status, job history, and logs. - Prometheus metrics — Synclet exposes a
/metricsendpoint compatible with Prometheus on the internal port (8081). See Production Checklist for scraping configuration.
Backup & Restore
Section titled “Backup & Restore”Database backup
Section titled “Database backup”Back up your PostgreSQL database regularly:
pg_dump -Fc "$DB_DSN" > synclet_$(date +%Y%m%d).dump
# Restorepg_restore -d "$DB_DSN" synclet_20260401.dumpAirbyte is a trademark of Airbyte, Inc. Synclet is not affiliated with, endorsed by or sponsored by Airbyte, Inc. Connector images keep their own licenses: see Connector licenses.