4.4 KiB
Deployment
Running echoIRCd in production. The repo ships ready-to-use units and scripts in
deploy/.
1. Build a release binary
Always run the release build in production — a debug build is unoptimized and far slower on the CPU-bound paths (TLS crypto, password hashing, cloaking, line parsing):
cargo build --release
2. Pin the binary
Copy the release binary to a stable path and run that, not target/. This
decouples "what's running" from "what you're compiling" — a stray cargo build
can never change what a restart would launch:
mkdir -p bin
cp target/release/echoircd bin/echoircd
bin/ is gitignored. Deploying an update is then: build release → copy over
bin/echoircd → restart the service.
3. Supervise it with systemd
deploy/echoircd-dev.service runs the pinned
binary, restarts on failure, raises the file-descriptor limit, and starts on boot:
[Service]
Type=simple
User=youruser
WorkingDirectory=/path/to/echoIRCd
LimitNOFILE=200000
ExecStart=/path/to/echoIRCd/bin/echoircd /path/to/echoIRCd/echoircd.conf
Restart=on-failure
RestartSec=2
[Install]
WantedBy=multi-user.target
Install it (adjust the paths / User first):
sudo cp deploy/echoircd-dev.service /etc/systemd/system/
sudo systemctl daemon-reload
sudo systemctl enable --now echoircd-dev.service
LimitNOFILE is what lets the reactor pool reach tens of thousands of
connections — each connection is a file descriptor. Restart=on-failure means a
crash self-heals instead of leaving the network down.
4. Add a liveness probe
Restart=on-failure catches a crash, but not a hang (a process that's alive
but stopped answering). deploy/echoircd-liveness.timer
runs scripts/liveness.sh every couple of minutes: it
does a real NICK/USER register round-trip on the plaintext port and restarts the
service if it doesn't get a welcome.
sudo cp deploy/echoircd-liveness.service deploy/echoircd-liveness.timer /etc/systemd/system/
sudo systemctl daemon-reload
sudo systemctl enable --now echoircd-liveness.timer
5. Harden the firewall
Add the kernel-layer connection-rate limit (see anti-abuse):
sudo deploy/firewalld-echoircd.sh add
For volumetric (SYN/UDP) floods, rely on your upstream provider's scrubbing — nothing on the host can absorb a saturating flood.
Behind a reverse proxy / load balancer
If a TCP proxy (HAProxy, nginx stream) sits in front, enable the PROXY protocol so the real client IP is used instead of the proxy's:
proxy = 10.0.0.0/8 # trust the PROXY header from these sources (repeatable)
A connection from a trusted proxy must lead with a PROXY (v1 or v2) header. This
applies to the plaintext and TLS client listeners; for browser clients over
WebSocket, use ws_proxyranges with X-Forwarded-For instead.
Log shipping & metrics
| Setting | Sends the notice/log stream to |
|---|---|
syslog = yes (+ syslog_target) |
the system logger (/dev/log or host:port) |
log_json = <path> |
a file, as JSON lines (easy to ingest) |
chanlog = #snotices |
an in-network channel staff can watch |
The core also surfaces its own health: slow_command_ms raises a notice when an
event runs long, and watchdog_ms logs if the core is stuck.
For a metrics pipeline, bind the OpenMetrics/Prometheus endpoint with
metrics_bind = 127.0.0.1:9109 and scrape it (counters for commands / messages /
connects, gauges for users / channels / servers / links). For scripted control,
the JSON-RPC plane (rpc / rpc_bind / rpc_token) exposes admin operations over
HTTP. Bind both privately — on loopback or behind the reverse proxy, never on a
public interface.
TLS certificates
Point tls_cert / tls_key at your PEM files (the same pair serves bind_tls
and wss://). After renewing a certificate, REHASH reloads it without dropping
the server. Client-certificate fingerprints are read automatically for SASL
EXTERNAL / CertFP.
Updating checklist
git pull&&cargo build --releasecargo test(the integration suite spawns the binary and exercises the real paths)cp target/release/echoircd bin/echoircdsudo systemctl restart echoircd-dev.service- Confirm:
systemctl is-active echoircd-dev.service, then check a client connects on the TLS port.