Run the sync server
Este conteúdo não está disponível em sua língua ainda.
Run your own sync server with Docker starts the server on one computer with the release’s docker-compose.yml and a .env file. This page covers what it needs before other people and devices use it. Run the docker compose commands below in the folder that holds those two files. Every setting is listed in Environment variables.
Settings
Section titled “Settings”The server reads its settings from environment variables, which the docker-compose.yml of each release takes from the .env file next to it. STERNWAY_VERSION picks the image, ghcr.io/kuscko/sternway-server:<version>. One line per variable:
STERNWAY_VERSION=0.1.0-alpha.56STERNWAY_SERVER_SECRET=<the secret you keep>STERNWAY_PUBLIC_URL=https://sternway.example.comSTERNWAY_TRUST_PROXY=172.18.0.1STERNWAY_SMTP_URL=smtp://user:password@mail.example.com:587After changing .env, run docker compose up -d again; Compose recreates the server’s container with the new values.
STERNWAY_SERVER_SECRETmust stay the same. Changing it makes stored two-factor secrets unreadable: those users set up two-factor again.- Keep
.envreadable only by you (chmod 600 .env): it holds the secret and any passwords you put there. - The database lives in a Docker volume.
docker compose downand a laterup -dkeep it;docker compose down -vdeletes it. - For anything the Compose file does not have, such as mounting the licence file, put a
docker-compose.override.ymlnext to it. Docker Compose reads it automatically together withdocker-compose.yml, and you keep it when you replace the Compose file of a newer release.
Put TLS in front of it
Section titled “Put TLS in front of it”The server speaks plain HTTP on 127.0.0.1:8080, and the apps refuse plain http:// for anything but a server on the same computer (the phone always). Put a TLS reverse proxy in front of it (Caddy, nginx, Traefik and the like) that:
- passes every request, the WebSocket upgrades on
/api/v1/wsand/api/v1/relay/included, to127.0.0.1:8080; - passes
/api/v1/auth/saml/…too, if teams use SAML: identity providers post sign-ins there; - sets
X-Forwarded-For.
With Caddy on the same machine, for example, this is the whole site block (Caddy gets a certificate and passes WebSockets by itself):
sternway.example.com { reverse_proxy 127.0.0.1:8080}Then set on the server:
STERNWAY_PUBLIC_URLto thehttps://address people use. Invite links, passkeys, SAML and the licence are built from it; changing it later breaks every team’s SAML set-up and every passkey outside the new domain.STERNWAY_TRUST_PROXYto the address the server sees your proxy’s requests come from, and nothing else. With the proxy on the host and the server in Docker, that is the gateway of the Compose project’s network, not127.0.0.1(docker network inspecton the server’s network shows it). With a CDN in front of the proxy, list both. Without it, every user shares the proxy’s address and its request limits, and the server logs a warning the first time a request comes through a proxy.
curl -sf https://sternway.example.com/healthz from another machine should answer {"ok":true,…}.
Request limits
Section titled “Request limits”The server allows 300 requests a minute per signed-in account, from any address, and the same per client address for everything else (signing up, signing in); one address also has a ceiling of 3,000 a minute over all its requests. That is why STERNWAY_TRUST_PROXY matters: the limits count real client addresses only when the server can see them.
Run one instance
Section titled “Run one instance”Run one server process per database. Short-lived state (single-use WebSocket tickets, pending single sign-on and passkey sign-ins, failed sign-in counts) lives in that process’s memory, so a second instance would not know tickets the first one issued. A restart only loses that state; the apps ask again.
Back up the database
Section titled “Back up the database”The database holds every account’s encrypted vault data, wrapped keys and metadata. Back it up like any production database. In the folder with docker-compose.yml:
docker compose exec -T postgres sh -c 'pg_dump -U "$POSTGRES_USER" "$POSTGRES_DB"' > sternway-$(date +%F).sqlTo restore into an empty database:
docker compose exec -T postgres sh -c 'psql -U "$POSTGRES_USER" "$POSTGRES_DB"' < sternway-2026-10-23.sqlA restore brings every account back as it was at the dump. Keep .env (with STERNWAY_SERVER_SECRET) with the backups: without the secret, two-factor secrets in the dump cannot be read.
Upgrade
Section titled “Upgrade”-
Back up the database (above).
-
In
.env, setSTERNWAY_VERSIONto the new version. -
Run:
Terminal window docker compose pulldocker compose up -d
The server applies its database migrations itself when it starts. If a release’s notes say its docker-compose.yml changed, download that one too (https://downloads.sternway.dev/<version>/docker-compose.yml) and check it against that version’s SHA256SUMS; .env and docker-compose.override.yml stay as they are.
Set STERNWAY_SMTP_URL (smtp://user:password@mail.example.com:587) to send invite emails and passkey notices and to let people verify their email address with a mailed code. Without it everything else works; invites go by link.
Passkeys
Section titled “Passkeys”Passkeys are bound to a domain: by default the host of STERNWAY_PUBLIC_URL, with that URL’s origin as the only accepted origin.
STERNWAY_WEBAUTHN_RP_IDnames a parent domain instead (example.comforhttps://sync.example.com), so passkeys keep working if the server moves to another subdomain.STERNWAY_WEBAUTHN_ORIGINSadds origins when the server is reached under more than one address.
Passkeys need HTTPS. Moving the server outside the domain makes every passkey stop working; people then sign in with their password and add their passkeys again. See Sign in with a passkey.
Single sign-on
Section titled “Single sign-on”Teams set up SAML themselves in the desktop app; the server needs nothing but a correct STERNWAY_PUBLIC_URL and a proxy that passes /api/v1/auth/saml/…. Server-wide OpenID Connect is STERNWAY_OIDC. See Set up single sign-on.
The licence file
Section titled “The licence file”Business and Enterprise features of teams on a self-hosted server need a licence file. Put it next to the Compose file, mount it into the server’s container with a docker-compose.override.yml, and point STERNWAY_LICENCE at it:
services: server: environment: STERNWAY_LICENCE: /licence/sternway.licence volumes: - ./sternway.licence:/licence/sternway.licence:roThen docker compose up -d. The server reads the file at start and every hour, so a newer file takes effect within the hour. The licence is bound to the server’s address: STERNWAY_PUBLIC_URL must be one of the addresses it names, or it counts as expired. Teams › Licence in the app shows its state. What a licence covers and what happens when it runs out: Licensing of self-hosted servers.
If the server’s clock was wrong and you fixed it, the licence’s own record of the time may keep it from counting the corrected time. Reset that record with the server’s licence reset-clock command, run in its container:
docker compose exec server node_modules/.bin/tsx apps/server/src/index.ts licence reset-clockThe reset is recorded in the audit log.
Push audit events to a SIEM
Section titled “Push audit events to a SIEM”STERNWAY_AUDIT_PUSH_URL (and STERNWAY_AUDIT_PUSH_TOKEN) sends every audit event to an HTTPS endpoint, with a licence that includes it. See Export the audit log.
Admins’ signed changes
Section titled “Admins’ signed changes”STERNWAY_DELEGATED_SIGNING=off makes the server refuse every team change an admin signs, at once, while the owners’ changes still go through. It undoes nothing already kept. Use it if you suspect an admin’s account is compromised.
Devices and members
Section titled “Devices and members”- Revoking a device (Settings › Account & Sync › Devices › Revoke) signs it out. Its own hosts and keys stay on it; its copies of team vaults are removed the next time it reaches the server.
- Removing a team member rotates the key of each vault they could open, so they receive nothing new. It cannot take back what they already had on their devices. If they may have seen credentials that matter, change those credentials (new keys, new passwords).
What the server can see
Section titled “What the server can see”Item contents, session logs, vault names and wrapped keys are encrypted; the server cannot read them. It does see and keep: accounts’ email, name and handle, device names and platforms, team names and members, the signed member lists (with a team’s policy values and reasons), item ids, types, sizes, revision numbers and times, and client IP addresses. See What leaves your device and Threat model.
© 2026 IRONPINE LABS LLC
ALL RIGHTS RESERVED.