Docs
VPS setup (Ubuntu 24.04)
A complete server from a fresh VPS in six steps. You need released binaries and root access — no Rust toolchain, no compiler, nothing to build.
Before you start
- A fresh Ubuntu 24.04 VPS with root access.
- 1 vCPU and 1 GB RAM is enough for a small deployment; relays are I/O-bound, not CPU-bound.
- A DNS
Arecord pointing at the box if you want the TLS-camouflage gateway on:443. - The server binary archive for your architecture from the download page.
etoki:// address when it finishes.1. Install the binaries
Download the archive, verify its checksum, and install both binaries to /usr/local/bin. Do not skip the checksum — it is the only integrity check on a binary distribution.
# On a fresh Ubuntu 24.04 box, as root
apt update && apt install -y curl ca-certificates coturn
curl -fLO <download-url>/etoki-server-<version>-linux-x86_64.tar.gz
curl -fLO <download-url>/etoki-server-<version>-linux-x86_64.tar.gz.sha256
sha256sum -c etoki-server-<version>-linux-x86_64.tar.gz.sha256
tar xzf etoki-server-<version>-linux-x86_64.tar.gz
install -m 0755 etoki etoki-botrelay /usr/local/bin/sha256sum -c does not print OK, stop. Do not install the binary.2. Stage the deploy tree
The deploy/ directory ships an idempotent installer plus verbatim systemd units for every service. Copy it to the box at /opt/etoki-deploy, then describe this server in its server.env:
# /opt/etoki-deploy/A/server.env — this box's facts
SERVER_NAME="A"
SERVER_IP="YOUR_SERVER_IP"
EXTERNAL_IP="YOUR_SERVER_IP" # coturn external-ip
TLS_SNI="relay.example.com" # gateway certificate name
HAS_BOTRELAY=1 # 0 on boxes without the bot relaySet HAS_BOTRELAY=0 on any box that should not run the bot relay. Everything else is identical between servers.
3. Bootstrap
Run the installer as root. It creates the dedicated service users, sets up state directories, templates the coturn configuration, and installs and enables the systemd units:
# Bootstrap: service users, state dirs, coturn, systemd units.
# Idempotent — safe to re-run for upgrades.
TURN_SECRET=$(openssl rand -hex 32) /opt/etoki-deploy/A/install.sh/var/lib, so it is also the upgrade path.Keep the TURN_SECRET value. You will need it again when adding the TURN server in the app, and every server in the same deployment should share it.
4. Record the service identities
On first start each service generates a long-term key and prints its address. The fingerprint in that address is what clients pin — there is no CA and no PKI, so these strings are the trust anchor:
# Each service prints its address on first start. Record these:
# clients pin the fingerprint, so it must not change.
journalctl -u etoki-router -n 20 --no-pager | grep etoki://
journalctl -u etoki-directory -n 20 --no-pager | grep etoki://Save the router and directory addresses somewhere safe. They survive restarts and upgrades because the identity lives in /var/lib.
5. Open the ports
ufw allow 22/tcp
ufw allow 443/tcp # gateway (TLS camouflage)
ufw allow 5223/tcp # router
ufw allow 5443/tcp # file relay
ufw allow 5663/tcp # directory
ufw allow 3478 # coturn (TCP + UDP)
ufw allow 5881/tcp # bot relay HTTPS (only on the bot-relay host)
ufw enableOnly open 5881 on the host that actually runs the bot relay. The bot relay’s plain-HTTP listener stays on 127.0.0.1:5880 and should never be exposed.
6. Verify
systemctl status etoki-router etoki-filerelay etoki-directory etoki-gateway
curl -sk https://YOUR_SERVER_IP:5881/v1/healthz # bot-relay host onlyAll units should report active (running). From the app, add your router address under relay management and run the built-in health check.
Running a second server
Repeat every step on the second box. Only two things differ: its TLS_SNI (each gateway needs its own certificate name) and whether it runs the bot relay. Point both servers’ bot relay at both directories so usernames resolve either way.
Upgrading
Replace the binary and restart. Identity, queues and registrations are all under /var/lib and are left untouched, so client-pinned fingerprints keep working:
# 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'