diff --git a/docs/relay.md b/docs/relay.md new file mode 100644 index 0000000..cd34695 --- /dev/null +++ b/docs/relay.md @@ -0,0 +1,159 @@ +# How to setup a relay + +In this little guide we will document a few of `iroh-relay`'s configuration options. While +usable out of the box, if you are running a relay from an existing machine you have access to +then you might see things that need to be adapted, such as running ports and whether to +reuse an existing wildcard certificate instead of letting the relay provision its own. + +> This guide is a work in progress and based off of information from [uniclipboard's +> docs][unidocs]. As of 2026-07-07, we need to +> practically verify the config examples below. + +[unidocs]: https://www.uniclipboard.app/docs/guides/self-host-relay + +The relay has many knobs that can be configured: individually controllable allowlists and +denylists, setting tokens that restrict access only to requesters with the right credentials, rate +limiting received data, as well as automatically provisioning TLS or deciding to bring one's +own certs. + +## Ports + +Ports `80` and `443` are bound by default. These can be overridden in the config (next +section). + +For QUIC's Address Discovery mechanism, port `7842` is important to open. If you run a +different port than `80` or `443`, make sure to forward correctly from your webserver/reverse +proxy. + +Port `3340` will be used when the relay is run with `--dev`. + +Unless disabled, metrics (presumably for the relay operator only?) will be served on port `9090`. + +**Reverse proxying** + +We have also seen mentioned that you could also set up a reverse proxy for the following +routes being served from the domain/subdomain you use for your relay and directed to wherever +your relay is running: + +``` +/ +/relay +/ping +/generate_204 +``` + +This could be feasible if you set the relay to run on its own subdomain. + +## Configuration file + +The relay's configuration file is in TOML. Below we list all the options we could find, and +then after this section we provide more narrow configurations that can be copied. + +```toml +http_bind_addr = "[::]:80" +https_bind_addr = "[::]:443" +# note: not sure if these are under [tls] or not +enable_quic_addr_discovery = true +enable_relay = true # if false can still be used for quic address discovery (?) +enable_metrics = true # true is default and port 9090 will be used to serve metrics for this relay + +[tls] +cert_mode = "LetsEncrypt" # or "Manual" for own cert +hostname = "relay.example.com" # if "LetsEncrypt" +# manual_cert_path = "/etc/iroh-relay/fullchain.pem" # if "Manual" +# manual_key_path = "/etc/iroh-relay/privkey.pem" # if "Manual" +contact = "fake-email@example.com" # if "LetsEncrypt" +prod_tls = true # if "LetsEncrypt" +cert_dir = "/var/lib/iroh-relay/certs" # if "LetsEncrypt" + +# limits should also be a section i think? +# https://github.com/n0-computer/iroh/blob/9afd2bc1985d80b9afea9900ac26290c84f1f6a6/iroh-relay/src/main.rs#L506-L512 +# [limits.client.rx] +# bytes_per_seconds = number +# max_burst_bytes = number + +# From uniclipboard docs: 'For centralized auth, `access.http` POSTs each new connection\'s node ID +# to an endpoint you control; see the iroh-relay sources for the request +# schema.' +# access.http.url = "https://example.com/foo" +# access.http.bearer_token = "foo" +# or equivalently +# access.http = { url = "https://example.com/foo", bearer_token = "foo" } +# +# [access] # default is just `access = "everyone"` +# https://github.com/n0-computer/iroh/blob/9afd2bc1985d80b9afea9900ac26290c84f1f6a6/iroh-relay/src/main.rs#L861-L863 +# +# re shared_token, see https://github.com/n0-computer/iroh/blob/9afd2bc1985d80b9afea9900ac26290c84f1f6a6/iroh-relay/src/main.rs#L176-L195 +# can also be overridden by the `IROH_RELAY_ACCESS_TOKEN` environment +# variable, which sets a single allowed token and takes precedence over shared_token's value +# +# shared_token = ["token-a", "token-b"] +# +# optionally set {allow,deny}lists +# +# allowlist = [ +# "abcd1234...64hex", # laptop's node id +# "ef567890...64hex", # desktop's node id +# ] +# denylist = ["bad1234...64hex"] +``` + +### Iroh relay with own certs + +The below config can be adapted for use with your own wildcard cert infrastructure. Be sure to +include the config's hostname (below: `relay.example.com`) in your list of domains when provisioning your own +cert. + +Note: the below config tries to be as minimal as possible. As of 2026-07-07, it is untested and +may need adjustment. + +```toml +http_bind_addr = "[::]:80" # can maybe leave out this? should only used for lets encrypt provisioning +https_bind_addr = "[::]:443" +enable_quic_addr_discovery = true + +[tls] +cert_mode = "Manual" +manual_cert_path = "/etc/path/to/fullchain.pem" +manual_key_path = "/etc/path/to/privkey.pem" +``` + +### Systemd + +`/etc/systemd/system/iroh-relay.service`: + +Note - this is untested: + +``` +[Unit] +Description=iroh relay server +After=network-online.target +Wants=network-online.target + +[Service] +ExecStart=/usr/local/bin/iroh-relay --config-path /etc/iroh-relay/config.toml +Restart=on-failure +RestartSec=5s +# Let iroh-relay bind 80/443 without root by granting the capability +AmbientCapabilities=CAP_NET_BIND_SERVICE +CapabilityBoundingSet=CAP_NET_BIND_SERVICE +DynamicUser=true +StateDirectory=iroh-relay +# StateDirectory=iroh-relay creates /var/lib/iroh-relay owned by the +# dynamic user. Point cert_dir at that path. + +[Install] +WantedBy=multi-user.target +``` + +Enable and watch: + +``` +sudo systemctl daemon-reload +sudo systemctl enable --now iroh-relay +sudo journalctl -u iroh-relay -f +``` + +### Poking the relay with curl + +TODO as of 2026-07-07, see [Uniclipboard's docs][unidocs].