# 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
