Currently in testing: the GitHub code will be opened once complete.

Ticketing Server Deployment

Environment
Shell
Mode
bash
Client connection example
rust
Quick test with nc
bash

Environment Variables ​

Server configuration is done entirely through environment variables. Keys are case-insensitive, an empty value counts as unset, and flag-style values are only true for 1/true/yes/on. The Docker image is scratch-based, so config is injected purely through environment variables with no config file.

Environment variableDefaultDescription
PORT5225Listen port in single mode. Ignored in cluster mode, where the port from CLUSTER_SELF is used instead
SOCKET_BIND0.0.0.0Listen address
CLIENT_TOKENS(none)Comma-separated list of client auth tokens. If unset, an empty token is allowed
CLUSTER_SELF(none)This node's advertised address, host:port. Presence enables cluster mode
CLUSTER_PEERS(none)Comma-separated list of every node's advertised address. Exactly 3 or 5, same order on every node, must include self
CLUSTER_TOKENS(none)Comma-separated list of peer-to-peer auth tokens
TLS_CERT / TLS_KEY(none)Paths to the certificate/private key PEM files — set both together to enable TLS
TLS_CA(none)CA for verifying peer certificates — falls back to the system trust store if unset
TLS_SKIP_VERIFYfalseSkip peer certificate verification — test only
DOCKERfalsePins the internal listen ports to 5225/6225 in cluster mode — set by default in the official image
DEBUGDepends on build1/true enables debug logging

For the complete rules (port derivation, advertised addresses, zero-downtime token rotation, etc.) see Configuration (Env Vars).

Single vs. Cluster ​

  • Single (1 node): without CLUSTER_*, the node runs standalone. Fastest, but there's a brief blip on restart, and state is in-memory so it's lost on restart (lease is the safety net).
  • Cluster (non-stop): 3 or 5 nodes. The nodes share a single lock state via Raft consensus — only the leader handles requests, and every state change is only finalized after a majority commit. If the leader dies, a new one is elected within 0.5-1 second, and as long as a majority stays alive, the lock state and service keep running. See How It Works and Protocol (Cluster) for the full explanation.
  • Each cluster node listens on the client port plus a Raft port (client port + 1000) — open both ports in your firewall.

Kubernetes cluster deployments use a StatefulSet + headless Service. Give each pod a stable DNS name (ticketing-0.ticketing…, ticketing-1.ticketing…), put those names into CLUSTER_PEERS, and auto-inject each pod's CLUSTER_SELF via the downward API (metadata.name).

Non-Stop Restart (Rolling) ​

There's one core rule — a majority must always stay alive (at most 1 of 3 down at a time).

  1. Restart followers first, one at a time. Once a restarted node catches up via replication or a snapshot, move on to the next.
  2. Finally, take down the leader — a new one is elected within 0.5-1 second, and clients switch over transparently.
  3. Bringing a downed node back up rejoins it as a follower.

See Rolling Restart Procedure for the detailed steps.

Reference ​