Running Your Own Relay

The relay is a single static Linux binary, peckboard-relay, built from the peckboard-relay/ directory of the repository. Running your own gives you a relay under your control with your own limits, and you can optionally require boxes to register before they may use the relayed fallback. This page covers what the host needs, building and installing with the bundled deploy script, pointing your boxes at it, and the registration gate. Security and Encryption describes what your relay will and won’t be able to see, and how the bundled unit is hardened.

Requirements

You need a Linux host with a public IP address and three things in place before first start:

  • a DNS name, such as relay.example.com, pointing at the host;
  • TCP port 443 reachable from the internet — the relay serves its encrypted signaling there and obtains its own Let’s Encrypt certificate through the TLS-ALPN-01 challenge on the same port, so nothing else may listen on 443;
  • UDP port 3478 reachable, for the relay’s authenticated address discovery (STUN).

Relayed traffic rides the existing 443 connections, so no further ports are needed. Open both ports in the host firewall yourself; the deploy script does not touch it. No release ships a prebuilt relay binary.

Build and Install

peckboard-relay/deploy.sh builds a static x86_64-unknown-linux-musl binary on your machine and installs it on the host over SSH. It needs the musl target (rustup target add x86_64-unknown-linux-musl) plus either cargo zigbuild or a musl cross compiler named in CC_x86_64_unknown_linux_musl, and the remote user needs sudo. It refuses to deploy a binary that isn’t statically linked.

The bundled unit peckboard-relay/deploy/peckboard-relay.service names the official domain, so first change --domain relay.peckboard.com in its ExecStart line to your DNS name, then run:

SSH_OPTS="-o StrictHostKeyChecking=yes" peckboard-relay/deploy.sh admin@relay.example.com

The script creates a peckrelay system user if missing, installs the binary as /opt/peckboard-relay/peckboard-relay — owned by root, so the service can run it but never replace it — keeps the previous binary as peckboard-relay.prev, installs and enables the systemd unit, and restarts the service. --no-restart installs without restarting; --rollback swaps peckboard-relay.prev back in and restarts.

The unit runs the relay as peckrelay with only the capability to bind port 443, a read-only filesystem apart from its state directory, a system-call filter, and a 2 GB memory cap. Its state — the certificate cache and the registry of registered boxes — lives in /var/lib/peckrelay, which systemd creates with mode 0700 and passes to the relay as its --state-dir.

Building without the deploy script
cargo build --release --features server --manifest-path peckboard-relay/Cargo.toml

Run the result with --domain, --state-dir, and, if wanted, --acme-contact. --listen (default [::]:443) and --stun-listen (default [::]:3478) set the two sockets; --stun-public-port advertises a different UDP port when a NAT in front of the host maps 3478 elsewhere. Add --acme-staging while testing to stay clear of Let’s Encrypt’s rate limits.

Changing settings after install

The unit reads /etc/peckboard-relay.env (create it as root, mode 0600). Put the ACME contact address and any of the PECKRELAY_* variables below in it, plus extra command-line flags as PECKRELAY_ARGS, then sudo systemctl restart peckboard-relay:

PECKRELAY_ACME_CONTACT=ops@example.com
PECKRELAY_REGISTRATION_GATE=true
PECKRELAY_ARGS=--acme-staging

deploy.sh rewrites /etc/systemd/system/peckboard-relay.service on every run, so keep host-specific unit changes in the copy you deploy from, or in a drop-in made with sudo systemctl edit peckboard-relay. The unit also blocks private address ranges (IPAddressDeny=, inbound as well as outbound); if your boxes reach the relay over a LAN rather than through its public address, clear that line in a drop-in.

Logs: journalctl -u peckboard-relay -f. sudo systemctl kill -s USR1 peckboard-relay toggles debug logging. The certificate renews itself while the service runs.

Point a Box at It

On each box, open Settings → Connections → Remote Access, replace the Relay host with your DNS name — add :port only if the relay isn’t on 443 — and press Save. Devices paired earlier carry the old relay in their pairing link, so pair them again with + Pair device.

The box checks the relay’s certificate against the public certificate authorities, which is why the relay needs a real DNS name and its Let’s Encrypt certificate. --dev-self-signed swaps in a throwaway self-signed certificate (written to dev-cert.der in the state directory) for local development and tests; boxes and the app will not connect to a relay running that way.

Relayed Traffic Limits

The relayed fallback is on by default. Each limit is a flag, or the matching environment variable in /etc/peckboard-relay.env; over-limit packets are dropped and the encrypted connection slows down to fit.

Flag / variable Default Limit
--relay-rate-per-id / PECKRELAY_RELAY_RATE_PER_ID 512 KiB/s per pairing, both directions together
--relay-burst-per-id / PECKRELAY_RELAY_BURST_PER_ID 2 MiB burst per pairing
--relay-rate-per-ip / PECKRELAY_RELAY_RATE_PER_IP 1 MiB/s per sending IP address (IPv6: per /64)
--relay-burst-per-ip / PECKRELAY_RELAY_BURST_PER_IP 4 MiB burst per IP address
--relay-rate-global / PECKRELAY_RELAY_RATE_GLOBAL 50 MiB/s across the whole relay
--relay-burst-global / PECKRELAY_RELAY_BURST_GLOBAL 100 MiB global burst
--relay-max-pairs / PECKRELAY_RELAY_MAX_PAIRS 1000 pairings relaying at the same time
--relay-idle-secs / PECKRELAY_RELAY_IDLE_SECS 60 idle seconds before a pairing frees its slot

Rates are bytes per second. --no-relay-data (PECKRELAY_NO_RELAY_DATA=true) turns the fallback off entirely for a rendezvous-only relay: boxes and devices still connect directly through it, and a pair that cannot connect directly fails instead of being relayed.

Optional Registration Gate

The gate is off by default. On an ungated relay every box may use the relayed fallback without registering, and the box’s Remote Access section shows a reminder that registration isn’t required yet.

Start the relay with --registration-gate (PECKRELAY_REGISTRATION_GATE=true) and only registered boxes may use the relayed fallback; rendezvous, direct connections, and STUN stay open to all. Boxes register exactly as on the official relay: their Register button opens https://<your relay>/register#<box key>, a page your relay serves on port 443, where a browser proof-of-work check stands in for a captcha. --registration-pow-bits (PECKRELAY_REGISTRATION_POW_BITS, default 18, range 8–28) sets its difficulty; each extra bit doubles the work. The page works with the gate off too, so boxes can register ahead of switching it on.

The page caps how far registration can grow: --registration-max-keys (PECKRELAY_REGISTRATION_MAX_KEYS, default 100,000) is the most boxes it will register in total, and --registrations-per-ip-per-day (PECKRELAY_REGISTRATIONS_PER_IP_PER_DAY, default 50) is how many new boxes one address may register per day. Neither limits the registry add command below.

Registered boxes are kept in registered-boxes.txt in the state directory, one public key and registration time per line. The running relay rereads the file within a few seconds of a change, so additions and revocations need no restart. Manage it with the registry subcommand, run as the service user so the file stays readable by the relay:

sudo -u peckrelay /opt/peckboard-relay/peckboard-relay registry list
sudo -u peckrelay /opt/peckboard-relay/peckboard-relay registry add <box-key>
sudo -u peckrelay /opt/peckboard-relay/peckboard-relay registry revoke <box-key>

add registers a box without the proof-of-work step. A box’s key is the part after # in the registration link its Register button opens. All three default to --state-dir /var/lib/peckrelay; pass --state-dir if yours differs.


Assembled with many small pecks.

This site uses Just the Docs, a documentation theme for Jekyll.