# Deploying FRX Three roles: **member node** (`frxd serve`), **relay** (`frxd relay`), **registry** (`frxd registry`, run by the MA). TLS is only a concern for servers. Members connect outbound and need no domain, port, or certificate. ## Member node (zero TLS work) ``` frxd init --name alice --id alice.frx.example \ --registry https://ma.example.com/registry.json --ma-key \ --relay https://relay.example.com --data-dir ./alice-data frxd add ~/documents --name docs --shared --exposure full frxd serve ``` The node connects outbound over HTTPS, verifies the registry with the pinned MA key, and holds an SSE stream per relay. Nothing inbound, no DNS, no certificates. Members at departmental level can start here. ## Relay with TLS (one line) Run `frxd` on loopback and terminate TLS with Caddy: ``` caddy reverse-proxy --from relay.example.com --to 127.0.0.1:7700 ``` Caddyfile equivalent: ``` relay.example.com { reverse_proxy 127.0.0.1:7700 } ``` Relay command (peers and registry gated by the MA): ``` frxd relay --listen 127.0.0.1:7700 \ --url https://relay.example.com \ --peer https://relay2.example.com \ --registry https://ma.example.com/registry.json --ma-key ``` No domain or open ports? Tunnel it: ``` frxd relay --listen 127.0.0.1:7700 --allow-insecure cloudflared tunnel --url http://127.0.0.1:7700 ``` `systemd` unit example: ```ini [Unit] Description=FRX relay After=network-online.target [Service] ExecStart=/usr/local/bin/frxd relay --listen 127.0.0.1:7700 \ --url https://relay.example.com \ --registry https://ma.example.com/registry.json --ma-key Restart=on-failure DynamicUser=yes NoNewPrivileges=yes ProtectSystem=strict ProtectHome=yes [Install] WantedBy=multi-user.target ``` The same unit shape works for `frxd serve` (add `--config /etc/frxd/frxd.toml`). ## Registry (MA) ``` frxd registry --dir /var/lib/frxd/registry init frxd registry --dir /var/lib/frxd/registry add alice.frx.example --enc-key frxd registry --dir /var/lib/frxd/registry serve --listen 127.0.0.1:7800 ``` Put the same Caddy in front, or distribute `registry.json` out of band (it is signed, so the channel does not matter). The snapshot is versioned; nodes reject rollback and fail static during outages. ## Private networks and custom CAs - `ca_cert = "/etc/ssl/private-ca.pem"` in `[node]`, or `--ca-cert` on the relay: adds a private/corporate root CA for relay and registry connections. - `allow_insecure = true` / `--allow-insecure`: explicit opt-in for plain `http://` on a VPN/LAN. Without it, non-loopback `http://` endpoints are refused at startup. - `http://127.0.0.1` is always allowed for development. ## Static binary ``` rustup target add x86_64-unknown-linux-musl cargo build --release --target x86_64-unknown-linux-musl ``` `[profile.release]` enables LTO and stripping. All dependencies are pure Rust, so the musl build has no system-library requirements. ## What TLS does and does not cover Envelopes are signed and registry snapshots are MA-signed, so TLS is not what protects message authenticity or registry integrity. TLS protects traffic from network observers, authenticates the relay endpoint, and hides mailbox metadata. Unicast response bodies are already encrypted end-to-end to the recipient's X25519 key.