Skip to content

Docker Compose Deployment

Single-node deployments should start with docker-compose.yml. It uses the prebuilt image, explicit production secrets, persistent env files, and volumes, so it is suitable for one-server or long-running local deployments.

Development Compose is only for code work or short local previews. It builds from the local Dockerfile and includes local-only development settings, so do not reuse it for production.

If you have not chosen a deployment model yet, start with Choose a Deployment Path.

FilePurposeBehavior
docker-compose.ymlImage-based deploymentUses zijiren/synctv:latest and requires explicit production secrets
docker-compose.dev.ymlLocal developmentBuilds from the local Dockerfile and includes local-only development settings

Download the minimum required production files into an empty directory:

Before running the init script, make sure the host has Docker Compose, openssl, and python3 available. The script uses openssl to generate PostgreSQL, Redis, JWT, cluster, credential-encryption, and OPAQUE secrets, and python3 to URL-encode the database password safely.

Terminal window
mkdir synctv-compose
cd synctv-compose
curl -fsSLO https://raw.githubusercontent.com/zijiren233/synctv/next/docker-compose.yml
curl -fsSLO https://raw.githubusercontent.com/zijiren233/synctv/next/.env.postgres.example
curl -fsSLO https://raw.githubusercontent.com/zijiren233/synctv/next/.env.redis.example
curl -fsSLO https://raw.githubusercontent.com/zijiren233/synctv/next/.env.synctv.example
mkdir -p scripts
curl -fsSL https://raw.githubusercontent.com/zijiren233/synctv/next/scripts/init-compose-env.sh -o scripts/init-compose-env.sh
chmod +x scripts/init-compose-env.sh

You can also inspect the files in the source repository. The development Compose file is docker-compose.dev.yml.

Generate persistent environment files before first startup:

Terminal window
./scripts/init-compose-env.sh

Edit .env.synctv and set at least:

SYNCTV_BOOTSTRAP_ROOT_PASSWORD=replace-with-a-strong-password
# If frontend and API use different origins, use a JSON array.
SYNCTV_SERVER_CORS_ALLOWED_ORIGINS=["https://app.example.com"]

Then start:

Terminal window
docker compose config
docker compose up -d

Verify immediately after startup:

Terminal window
docker compose ps
curl -fsS http://localhost:8080/health/ready

Open http://localhost:8080 in a browser. The default root username is root; the password comes from SYNCTV_BOOTSTRAP_ROOT_PASSWORD in .env.synctv.

Docker Compose loads required .env.postgres, .env.redis, and .env.synctv files through env_file: PostgreSQL reads only database variables, Redis reads only REDIS_PASSWORD, and synctv reads only SYNCTV_* application settings. The init script writes the same generated Redis password into .env.redis as REDIS_PASSWORD and into .env.synctv inside the authenticated SYNCTV_REDIS_URL. Back up all three files and reuse them across restarts, new shells, host reboots, and upgrades. If any file is missing, docker compose config fails immediately.

When upgrading, set SYNCTV_IMAGE_TAG to the desired release before running Compose, or pin the desired image in your own Compose override file. The sample Compose file defaults to the documented app version instead of latest so deployments are reproducible. Treat PostgreSQL and Redis image tag changes as separate data-service upgrades: back up the volumes first, review upstream release notes, and keep rollback tags available.

Development Compose depends on the repository Dockerfile and source tree. Use a full checkout only when you need local builds or code changes:

Terminal window
git clone https://github.com/zijiren233/synctv.git synctv
cd synctv

Start:

Terminal window
docker compose -f docker-compose.dev.yml up -d

This starts:

  • PostgreSQL 18.
  • Redis 8.
  • SyncTV built from the local Dockerfile.

It includes local-only development credentials and settings so a full checkout can start without generating env files.

Compose uses volumes for:

  • PostgreSQL data.
  • Redis data.
  • SyncTV /data runtime directory.

/data corresponds to:

Terminal window
SYNCTV_DATA_DIR=/data

This directory may contain:

  • Management socket runtime files.
  • HLS files.
  • Proxy slice cache files.
  • Other runtime-owned outputs.

Default exposed ports:

Host portContainer portPurpose
80808080HTTP REST + gRPC + health checks
19351935RTMP
3478/udp3478/udpSTUN

If a host port conflicts, edit the Compose port mapping.

Compose checks:

http://localhost:8080/health/ready

If health checks fail, inspect logs:

Terminal window
docker compose logs -f synctv

Why does production Compose require explicit secrets?

Section titled “Why does production Compose require explicit secrets?”

Because weak automatic defaults are unsafe. The service should not accidentally start in production with known secrets.

Users cannot log in after changing SYNCTV_SECURITY_OPAQUE_SERVER_SETUP_SECRET

Section titled “Users cannot log in after changing SYNCTV_SECURITY_OPAQUE_SERVER_SETUP_SECRET”

That secret must remain stable. Changing it can make existing OPAQUE password records unverifiable.

At minimum:

  • PostgreSQL volume.
  • Production secrets.

Depending on enabled features:

  • /data HLS files.
  • Proxy slice cache.

Redis is usually short-lived shared state, but losing it can affect OAuth2 state, token blacklist, and rate-limit counters.