Docs
Production setup (systemd)
For real deployments, run each service as a systemd unit on a dedicated host. An idempotent installer bootstraps users, state, coturn, and the units.
1. Stage the binaries
Download the released server archive, verify its checksum, and copy both binaries plus the deploy/ tree to the server:
# On your machine: fetch the release artifacts, verify, then copy
sha256sum -c etoki-server-<version>-linux-x86_64.tar.gz.sha256
tar xzf etoki-server-<version>-linux-x86_64.tar.gz
scp etoki etoki-botrelay root@your.host:/usr/local/bin/
scp -r deploy root@your.host:/opt/etoki-deploy2. Bootstrap the server
Run the installer as root on the box. It creates service users, sets up state directories, templates the coturn config, and installs the systemd units:
# On the server, bootstrap users, state, coturn, certificates and units.
# Idempotent: never clobbers identity/state, so fingerprints survive.
TURN_SECRET=<shared-secret> bash /opt/etoki-deploy/n1/install.sh
# A box that runs the bot relay needs a second pass: the relay's unit dials
# the router and directory, so their addresses have to exist first. Paste
# them into server.env from the output above, then re-run the same command./var/lib, so router and directory fingerprints survive a re-run or upgrade.3. TLS-camouflage gateway
A gateway on port 443 wraps the transport in TLS that looks like ordinary HTTPS, using a browser-like ClientHello. A secret bridge path upgrades to the real protocol; every other request gets a static decoy page, which resists active probing. Each host uses its own SNI name and can front the router and directory behind bridge paths.
Its certificate is camouflage, not trust: the relay fingerprint pinned inside the protocol is the only trust root, and no client ever verifies the outer certificate. It is still issued by a real CA — a self-signed certificate on :443 is an anomaly a censor can select on, and the decoy page should load in a browser like any other small site. certbot handles issuance over HTTP-01 on :80, since TLS-ALPN would need the port the gateway owns.
4. Reserved usernames
A directory refuses names that would let their holder pass for the service or its staff — admin, support, security and a dozen more. Matching is exact on the canonical name, so admin1 stays first-come. Add your own with --reserve (the installer reads RESERVED_EXTRA from server.env) and free one you legitimately run with --unreserve.
5. TURN for calls
Calls and Etoki push-to-talk use coturn. The shared TURN secret is supplied via the TURN_SECRET environment variable (or a git-ignored secrets file) — it is never committed.
Manage & redeploy
Standard systemd tooling manages each service:
systemctl status etoki-router
journalctl -u etoki-router -n 50 --no-pager
systemctl restart etoki-router # identity/fingerprint preservedTo ship a new binary, copy it over and restart — the identity persists:
# Upgrade in place: state under /var/lib is untouched, so the
# router and directory fingerprints survive the restart.
scp etoki root@your.host:/usr/local/bin/etoki
ssh root@your.host 'systemctl restart etoki-router'