# Headscale Configuration - Reference Copy # ========================================== # Live file location on Calypso: /volume1/docker/headscale/config/config.yaml # This file is NOT auto-deployed - must be manually placed on Calypso. # The docker-compose.yaml mounts /volume1/docker/headscale/config/ → /etc/headscale/ # # To update config on Calypso: # scp -P 62000 headscale-config.yaml Vish@100.103.48.78:/volume1/docker/headscale/config/config.yaml # docker restart headscale server_url: https://headscale.vish.gg:8443 listen_addr: 0.0.0.0:8080 metrics_listen_addr: 0.0.0.0:9090 grpc_listen_addr: 0.0.0.0:50443 grpc_allow_insecure: false tls_cert_path: "" tls_key_path: "" private_key_path: /var/lib/headscale/private.key noise: private_key_path: /var/lib/headscale/noise_private.key prefixes: v4: 100.64.0.0/10 v6: fd7a:115c:a1e0::/48 allocation: sequential derp: server: # Built-in DERP relay — region 900 "Home - Calypso" # Served at /derp on the same port as headscale (through NPM on 8443) # No STUN — UDP 3478 is occupied by coturn on Atlantis (Jitsi) enabled: true region_id: 900 region_code: "home-cal" region_name: "Home - Calypso" private_key_path: /var/lib/headscale/derp_server_private.key # Required by headscale even though UDP 3478 is not exposed in compose # (port 3478 → Atlantis on the router for Jitsi/coturn) stun_listen_addr: "0.0.0.0:3478" # We define the region manually in derpmap.yaml (stunport: -1) automatically_add_embedded_derp_region: false verify_clients: false ipv4: 184.23.52.14 # No public DERP fallback — Tailscale public DERPs reject headscale nodes (auth mismatch) # Risk: nodes behind strict NAT that cannot P2P will lose connectivity if both custom # DERPs (home-cal + seattle-vps) are unreachable simultaneously. # Mitigation: home-cal (Calypso) and seattle-vps are independent failure domains. urls: [] # Custom derpmap: region 900 (home) + region 901 (Seattle VPS) paths: - /etc/headscale/derpmap.yaml auto_update_enabled: false ephemeral_node_inactivity_timeout: 30m database: type: sqlite sqlite: path: /var/lib/headscale/db.sqlite write_ahead_log: true # OIDC via Authentik (provider pk=15, app slug=headscale at sso.vish.gg) # Credentials stored only on Calypso at /volume1/docker/headscale/config/config.yaml oidc: only_start_if_oidc_is_available: false # Allow headscale to start even if Authentik is temporarily unavailable issuer: "https://sso.vish.gg/application/o/headscale/" client_id: "REDACTED_CLIENT_ID" client_secret: "REDACTED_CLIENT_SECRET" # pragma: allowlist secret scope: ["openid", "profile", "email"] extra_params: domain_hint: vish.gg allowed_domains: [] allowed_groups: [] allowed_users: [] expiry: 180d use_expiry_from_token: false log: format: text level: info logtail: enabled: false randomize_client_port: false # DNS: MagicDNS with AdGuard nameservers for ad-blocking + split-horizon on the tailnet # Using Tailscale IPs so all mesh nodes (including remote) can reach DNS dns: magic_dns: true base_domain: tail.vish.gg nameservers: global: - 100.103.48.78 # Calypso AdGuard (Tailscale IP) - 100.83.230.112 # Atlantis AdGuard (Tailscale IP) search_domains: [] extra_records: [] unix_socket: /var/run/headscale/headscale.sock unix_socket_permission: "0770" policy: mode: file path: "" # Empty = allow all (configure ACLs later)