Files
homelab-optimized/hosts/synology/atlantis/derper.yaml
Gitea Mirror Bot e03072e1ec
Some checks failed
Documentation / Deploy to GitHub Pages (push) Has been cancelled
Documentation / Build Docusaurus (push) Has been cancelled
Sanitized mirror from private repository - 2026-04-19 08:30:52 UTC
2026-04-19 08:30:52 +00:00

84 lines
3.6 KiB
YAML

# Standalone DERP Relay Server — Atlantis (Home NAS)
# =============================================================================
# Tailscale/Headscale DERP relay for home-network fallback connectivity.
# Serves as region 902 "Home - Atlantis" in the headscale derpmap.
#
# Why standalone (not behind nginx):
# The DERP protocol does an HTTP→binary protocol switch inside TLS.
# It is incompatible with HTTP reverse proxies. Must handle TLS directly.
#
# Port layout:
# 8445/tcp — DERP relay (direct TLS, NOT proxied through NPM)
# 3480/udp — STUN (NAT traversal hints)
# Port 3478 taken by coturn/Jitsi, 3479 taken by coturn/Matrix on matrix-ubuntu.
#
# TLS cert:
# Issued by Let's Encrypt via certbot DNS challenge (Cloudflare).
# Cert path: /volume1/docker/derper-atl/certs/
# Cloudflare credentials: /volume1/docker/derper-atl/secrets/cloudflare.ini
# Auto-renewed monthly by the cert-renewer sidecar (ofelia + certbot/dns-cloudflare).
# On first deploy or manual renewal, run:
# docker run -it --rm \
# -v /volume1/docker/derper-atl/certs:/etc/letsencrypt \
# -v /volume1/docker/derper-atl/secrets:/root/.secrets:ro \
# certbot/dns-cloudflare certonly \
# --dns-cloudflare \
# --dns-cloudflare-credentials /root/.secrets/cloudflare.ini \
# -d derp-atl.vish.gg
# Then copy certs to flat layout:
# cp certs/live/derp-atl.vish.gg/fullchain.pem certs/live/derp-atl.vish.gg/derp-atl.vish.gg.crt
# cp certs/live/derp-atl.vish.gg/privkey.pem certs/live/derp-atl.vish.gg/derp-atl.vish.gg.key
#
# Firewall / DSM rules required (one-time):
# Allow inbound 8445/tcp and 3480/udp in DSM → Security → Firewall
#
# Router port forwards required (one-time, on home router):
# 8445/tcp → 192.168.0.200 (Atlantis LAN IP, main interface)
# 3480/udp → 192.168.0.200
#
# DNS: derp-atl.vish.gg → home public IP (managed by dynamicdnsupdater.yaml, unproxied)
# =============================================================================
services:
derper-atl:
image: fredliang/derper:latest
container_name: derper-atl
restart: unless-stopped
ports:
- "8445:8445" # DERP TLS — direct, not behind NPM
- "3480:3480/udp" # STUN (3478 taken by coturn/Jitsi, 3479 taken by coturn/Matrix)
volumes:
# Full letsencrypt mount required — live/ contains symlinks into archive/
# mounting only live/ breaks symlink resolution inside the container
- /volume1/docker/derper-atl/certs:/etc/letsencrypt:ro
environment:
- DERP_DOMAIN=derp-atl.vish.gg
- DERP_CERT_MODE=manual
- DERP_CERT_DIR=/etc/letsencrypt/live/derp-atl.vish.gg
- DERP_ADDR=:8445
- DERP_STUN=true
- DERP_STUN_PORT=3480
- DERP_HTTP_PORT=-1 # disable plain HTTP, TLS only
- DERP_VERIFY_CLIENTS=false # allow any node (headscale manages auth)
cert-renewer:
# Runs certbot monthly via supercronic; after renewal copies certs to the
# flat layout derper expects, then restarts derper-atl via Docker socket.
# Schedule: 03:00 on the 1st of every month.
image: certbot/dns-cloudflare:latest
container_name: derper-atl-cert-renewer
restart: unless-stopped
depends_on:
- derper-atl
entrypoint: >-
sh -c "
apk add --no-cache supercronic curl &&
echo '0 3 1 * * /renew.sh' > /crontab &&
exec supercronic /crontab
"
volumes:
- /var/run/docker.sock:/var/run/docker.sock
- /volume1/docker/derper-atl/certs:/etc/letsencrypt
- /volume1/docker/derper-atl/secrets:/root/.secrets:ro
- /volume1/docker/derper-atl/renew.sh:/renew.sh:ro