First-Time Setup & Deployment (Docker Compose)
This page walks you through deploying the application using Docker Compose on a fresh host. You’ve already pulled the image (see previous page).
Prerequisites
- Docker Engine / CLI 28.1.1 (or compatible)
- Docker Compose plugin v2.x
- Image already pulled from
synaccess.azurecr.io - A deployment folder (example path used below:
/opt/syn-cloud)
Check your versions:
docker --version
docker compose version1) Create the deployment folder
sudo mkdir -p /opt/syn-cloud/{certs}
cd /opt/syn-cloud- Put any TLS/CA files you need under
./certs/(host) — they’ll appear in the container at/certs/.....
2) Create the files
Create docker-compose.yml in /opt/syn-cloud:
version: "3.9"
services:
syn-cloud:
# Default to 'latest' unless TAG is set in .env
image: synaccess.azurecr.io/syn-cloud:${TAG:-latest}
container_name: syn-cloud
env_file:
- .env
# Uncomment/leave as-is to make TLS material or other read-only assets
# available inside the container. For example, mount database CA certificates
# or HTTPS cert/key pairs and reference the in-container paths from your .env
# (e.g., TLS_CERT=/certs/fullchain.pem).
volumes:
- ./certs:/certs:ro
# Publishes the app on the same port configured in .env.
# When PORT=443 and CONNECTION_SECURITY=tls the container will terminate TLS.
ports:
- "${PORT:-80}:${PORT:-80}"
restart: unless-stopped
# Always check for a newer image on 'up' (useful when tracking 'latest')
# pull_policy: alwaysCreate .env next to it (copy/paste then edit values):
# These values are consumed by docker-compose.yml and the application at runtime.
# -----------------------------------------------------------------------------
# Database connectivity
# -----------------------------------------------------------------------------
# Full PostgreSQL connection URI. Include credentials and database name.
# Example for managed Postgres: postgres://user:password@host:5432/database
DB_CONNECTION_STRING=postgres://username:password@database-host:5432/database-name
# Connection pool sizing. Keep small for low-resource deployments.
DB_MIN_CONNECTIONS=2
DB_MAX_CONNECTIONS=40
# TLS options (optional). Set DB_SSL_MODE to one of: disable, prefer, require, verify-ca, verify-full.
# When supplying certificate paths, mount them via docker-compose (see volumes example) and
# point these variables at the in-container path (e.g. /certs/root.crt). You can also
# inline PEM content by escaping newlines with \\n
DB_SSL_MODE=
DB_SSL_ROOT_CERT=
DB_SSL_CERT=
DB_SSL_KEY=
# Set to false ONLY when you must skip certificate validation (not recommended).
DB_SSL_REJECT_UNAUTHORIZED=
# -----------------------------------------------------------------------------
# Application runtime
# -----------------------------------------------------------------------------
# The public hostname for the deployment (used when generating links/emails).
HOST=localhost
# Listening port inside the container AND host mapping. Ensure docker-compose ports section matches.
# Common values: 80 for HTTP, 443 when running TLS directly, 3000 for alternate ports.
PORT=80
# Bind address used by the web server; :: listens on all IPv4/IPv6 addresses.
BIND_HOST=0.0.0.0
# Optional override for the externally reachable URL. Leave blank to auto-generate from HOST/PORT/CONNECTION_SECURITY.
HOST_URL=
# Choose none or tls. When tls is selected, provide TLS_CERT and TLS_KEY.
CONNECTION_SECURITY=none
# When true AND running TLS, the app will redirect HTTP (80) to HTTPS (443) inside the container.
FORWARD_PORT_80_TO_443=false
# TLS certificate and key can be either inline PEM (escape newlines with \\n) or filesystem paths mounted into the container.
TLS_CERT=
TLS_KEY=
# Comma-separated list or wildcard for allowed CORS origins. Use * for testing only.
CORS_ORIGIN=
# -----------------------------------------------------------------------------
# Image pinning (optional)
# -----------------------------------------------------------------------------
# Leave TAG unset to track 'latest'. To pin/revert to a specific version, set TAG here.
# TAG=2025.10.02Tip: Keep a backup before edits:
cp .env .env.backup.$(date +%Y%m%d-%H%M%S)
3) Login (one-time per host)
docker login synaccess.azurecr.io -u <TOKEN_USER> -p '<TOKEN_PASSWORD>'Expected output: Login Succeeded.
4) Start the application
docker compose up -dCompose will create (or recreate) the container and start it with the variables from .env.
5) Verify
docker compose ps
docker compose logs --tail=200 syn-cloud
curl -I http://127.0.0.1:${PORT:-80} || true- You should see
Upindocker compose ps. - Adjust the port if you changed
PORTin.env.
6) Initial in-app setup (first login)
After the container is running and you can reach the URL, complete these one-time steps inside Syn Cloud.
-
Open your Syn Cloud URL Visit
https://<your-hostname>(orhttp://<your-hostname>:<port>if not using TLS). -
Go to Deployment Settings On first boot, the app should direct users to /deployment-settings.
-
Create the Super Admin account
- Username (or email)
- Email address
- Strong password
- Save
This Super Admin account is the primary administrator. Its email/username and password are used later when pairing PDUs to your cloud.
-
Configure SMTP (email)
- SMTP host/port (587 STARTTLS or 465 SMTPS)
- Username / password (service account recommended)
- Encryption (STARTTLS or SSL/TLS)
- Save and Send test email
SMTP enables email verification, password resets, and user invitations. Without SMTP, users won’t be able to complete email-based flows.
-
Confirm deployment details On Deployment Settings, verify the displayed Deployment URL and environment details match your
.env(for exampleHOST,PORT, and TLS settings).
When finished, continue with pairing PDUs and inviting users.
7) Database Connectivity Schemes
The app reads DB settings from .env and supports three common patterns:
| Scenario | How to configure in .env | When to use |
|---|---|---|
| Username + password | DB_CONNECTION_STRING=postgres://username:password@db-host:5432/database (leave TLS vars blank, or set DB_SSL_MODE=prefer to negotiate TLS if supported). | Simplest configuration for trusted/internal networks. |
| Server-authenticated TLS | DB_CONNECTION_STRING as above; set DB_SSL_MODE=verify-ca or verify-full; point DB_SSL_ROOT_CERT at the mounted CA (e.g., /certs/root.crt). | When the DB requires TLS and you only need to validate the server certificate. |
| Mutual TLS (client certs) | Same as above plus set DB_SSL_CERT and DB_SSL_KEY to mounted paths (e.g., /certs/client.crt, /certs/client.key). | Managed services or hardened deployments that require client certificates. |
Mounting certificates: Place your CA/client certificates under
./certs/(host). The compose file maps./certs:/certs:ro, so reference them in.envas/certs/<file>.
8) Applying Migrations
- The backend runs migrations automatically on first startup.
- Ensure your DB user has privileges to CREATE, ALTER, and INSERT.
- Watch
docker compose logs --tail=200 syn-cloudfor migration output on first boot.
9) Configure HTTPS Termination
Choose one of the following:
-
Terminate TLS inside the app
- Set
CONNECTION_SECURITY=tlsandPORT=443in.env. - Put
fullchain.pemandprivkey.pemunder./certs/. - Set in
.env:TLS_CERT=/certs/fullchain.pemTLS_KEY=/certs/privkey.pem - (Optional)
FORWARD_PORT_80_TO_443=trueto redirect HTTP→HTTPS within the container.
- Set
-
Terminate TLS at a reverse proxy (nginx, Caddy, Traefik, etc.)
- Leave
CONNECTION_SECURITY=none, keepPORT=80. - Point your proxy at the container’s HTTP listener.
- Manage certificates in the proxy; the app container does not need the private key.
- Leave
-
Hybrid / Load balancer offload
- Present certificates at the LB and forward HTTP to the container (
CONNECTION_SECURITY=none). - Ensure LB forwards
X-Forwarded-Protoso the app generates correct HTTPS links.
- Present certificates at the LB and forward HTTP to the container (
When certificates change, restart to apply:
docker compose up -d(or--force-recreate).
10) Edit configuration later
- Edit
.envand re-apply:
docker compose up -d
# If changes don’t apply, force recreation:
docker compose up -d --force-recreate- Pin or roll back to a specific image tag by setting
TAGin.env, then:
docker compose pull
docker compose up -d11) Troubleshooting
-
401 Unauthorized during pull → Re-run the login:
docker login synaccess.azurecr.io -u <TOKEN_USER> -p '<TOKEN_PASSWORD>' -
DNS/network error
nslookup synaccess.azurecr.io curl -I https://synaccess.azurecr.io/v2/ || true -
Database connection errors on first boot Verify
DB_CONNECTION_STRINGand any TLS variables. Confirm mounted cert paths (/certs/...) exist.
12 What persists between restarts
- Any mapped paths in
volumes:(e.g.,./certs,./logs) persist on the host. - If you add a DB service in your compose later, its data can live in
./pgdata.
Do not commit
.envto version control. Keep credentials safe.
Updated about 2 months ago