feat(netbird): relay + STUN cluster members on the netcup proxy hosts #412
@@ -17,3 +17,8 @@ netbird_proxy_domain: "proxy.renner.uno"
|
||||
# Reuse VPS-1's proxy token — a shared NB_PROXY_TOKEN across members with the
|
||||
# same NB_PROXY_DOMAIN is a valid HA cluster, so no separate token is needed.
|
||||
netbird_proxy_token: "{{ vault_netbird_proxy_token }}"
|
||||
|
||||
# Relay auth secret — MUST be identical across every relay instance and the
|
||||
# management server's Relay.Secret (same vault var as the netbird-server
|
||||
# role); credentials minted by management only validate against it.
|
||||
netbird_relay_secret: "{{ vault_netbird_relay_secret }}"
|
||||
|
||||
@@ -10,3 +10,8 @@
|
||||
ansible.builtin.command:
|
||||
cmd: docker compose up -d --force-recreate proxy
|
||||
chdir: /opt/netbird-proxy
|
||||
|
||||
- name: Restart netbird relay
|
||||
ansible.builtin.command:
|
||||
cmd: docker compose up -d --force-recreate relay
|
||||
chdir: /opt/netbird-proxy
|
||||
|
||||
@@ -63,6 +63,13 @@
|
||||
mode: "0600"
|
||||
notify: Restart netbird proxy
|
||||
|
||||
- name: Deploy relay.env (contains the shared relay auth secret)
|
||||
ansible.builtin.template:
|
||||
src: relay.env.j2
|
||||
dest: /opt/netbird-proxy/relay.env
|
||||
mode: "0600"
|
||||
notify: Restart netbird relay
|
||||
|
||||
- name: Pull reverse-proxy image
|
||||
ansible.builtin.command:
|
||||
cmd: docker compose pull
|
||||
|
||||
@@ -38,6 +38,34 @@ services:
|
||||
max-size: "500m"
|
||||
max-file: "2"
|
||||
|
||||
# Relay cluster member — additional NetBird relay (+ embedded STUN) so
|
||||
# relayed connections and new-P2P candidate discovery survive a
|
||||
# controller-VPS (Hetzner) outage. Registered in the management server's
|
||||
# Relay.Addresses/Stuns (netbird-server role, management.json). Host
|
||||
# network like the proxy: the ws listener (:33080) and STUN (:3478/udp)
|
||||
# must sit on the host's un-NATed public addresses — STUN behind NAT
|
||||
# reports wrong reflexive candidates. Both ports are >1024, so the
|
||||
# ip_unprivileged_port_start sysctl is not involved.
|
||||
#
|
||||
# Deliberately NOT covered by the netbird-proxy-watchdog (which probes the
|
||||
# proxy's public URL): this relay is a fallback with client-side failover
|
||||
# to the other relays, so a wedged instance degrades redundancy rather
|
||||
# than availability; restart: unless-stopped catches crashes. If active
|
||||
# relay monitoring is wanted later, the binary serves
|
||||
# http://localhost:9000/health (verified on 0.73.2).
|
||||
relay:
|
||||
image: netbirdio/relay:{{ netbird_version }}
|
||||
container_name: netbird-relay
|
||||
restart: unless-stopped
|
||||
network_mode: host
|
||||
env_file:
|
||||
- ./relay.env
|
||||
logging:
|
||||
driver: "json-file"
|
||||
options:
|
||||
max-size: "500m"
|
||||
max-file: "2"
|
||||
|
||||
# netbird-proxy listens on :443 only (NB_PROXY_ADDRESS=:443) and has no HTTP
|
||||
# listener, so proxy-only hosts leave port 80 unanswered. This did not show
|
||||
# while proxy.renner.uno still resolved to the controller host, because the
|
||||
|
||||
@@ -0,0 +1,21 @@
|
||||
# NetBird relay cluster member (per docs.netbird.io "Set Up External Relay
|
||||
# Servers"). Registered in the management server's Relay.Addresses so the
|
||||
# mesh keeps a working relay when the controller VPS (Hetzner) is down.
|
||||
NB_LOG_LEVEL=info
|
||||
NB_LISTEN_ADDRESS=:33080
|
||||
# Plaintext rel:// (not rels://): Let's Encrypt is impossible on this host —
|
||||
# :443 belongs to the reverse-proxy (tls-alpn-01) and :80 to the redirect, so
|
||||
# neither HTTP-01 nor a second ALPN listener can run, and shipping a
|
||||
# zone-wide DNS-01 token to an internet-facing host is a worse trade than
|
||||
# plaintext transport. Peer payload stays WireGuard-encrypted end to end;
|
||||
# the exposure is relay framing metadata and credential sniff-and-reuse
|
||||
# (bounded by the 24h credential TTL) to an on-path attacker.
|
||||
NB_EXPOSED_ADDRESS=rel://{{ inventory_hostname }}:33080
|
||||
# Must equal the management server's Relay.Secret (vault, shared with the
|
||||
# VPS relay) — mismatches fail silently per upstream docs.
|
||||
NB_AUTH_SECRET={{ netbird_relay_secret }}
|
||||
# Embedded STUN: reflexive-candidate discovery must survive a controller
|
||||
# outage, or no NEW P2P connection can form while Hetzner is down and the
|
||||
# relay diversity here would be moot for NATed peers.
|
||||
NB_ENABLE_STUN=true
|
||||
NB_STUN_PORTS=3478
|
||||
@@ -3,6 +3,14 @@
|
||||
{
|
||||
"Proto": "udp",
|
||||
"URI": "stun:{{ netbird_server_host }}:3478"
|
||||
},
|
||||
{
|
||||
"Proto": "udp",
|
||||
"URI": "stun:proxy-1.renner.uno:3478"
|
||||
},
|
||||
{
|
||||
"Proto": "udp",
|
||||
"URI": "stun:proxy-2.renner.uno:3478"
|
||||
}
|
||||
],
|
||||
"TURNConfig": {
|
||||
@@ -23,7 +31,11 @@
|
||||
"URI": "{{ netbird_server_host }}:443"
|
||||
},
|
||||
"Relay": {
|
||||
"Addresses": ["rels://{{ netbird_server_host }}:443"],
|
||||
"Addresses": [
|
||||
"rels://{{ netbird_server_host }}:443",
|
||||
"rel://proxy-2.renner.uno:33080",
|
||||
"rel://proxy-1.renner.uno:33080"
|
||||
],
|
||||
"CredentialsTTL": "24h",
|
||||
"Secret": "{{ netbird_relay_secret }}"
|
||||
},
|
||||
|
||||
Reference in New Issue
Block a user