{ config, lib, pkgs, ... }: let localListenPort = 4443; localGrpcPort = 50442; externalGrpcPort = 50443; in { services.headscale = { enable = true; address = "127.0.0.1"; port = localListenPort; settings = { server_url = "https://scale.isomorphis.me:443"; dns_config = { override_local_dns = true; base_domain = "infracoll.su"; }; derp = { urls = [ ]; server = { # If enabled, runs the embedded DERP server and merges it into the rest of the DERP config # The Headscale server_url defined above MUST be using https, DERP requires TLS to be in place enabled = true; # Region ID to use for the embedded DERP server. # The local DERP prevails if the region ID collides with other region ID coming from # the regular DERP config. region_id = 999; # Region code and name are displayed in the Tailscale UI to identify a DERP region region_code = "headscale"; region_name = "Headscale Embedded DERP"; # Listens over UDP at the configured address for STUN connections - to help with NAT traversal. # When the embedded DERP server is enabled stun_listen_addr MUST be defined. # # For more details on how this works, check this great article: https://tailscale.com/blog/how-tailscale-works/ stun_listen_addr = "0.0.0.0:3478"; }; }; # List of IP prefixes to allocate tailaddresses from. # Each prefix consists of either an IPv4 or IPv6 address, # and the associated prefix length, delimited by a slash. # It must be within IP ranges supported by the Tailscale # client - i.e., subnets of 100.64.0.0/10 and fd7a:115c:a1e0::/48. # See below: # IPv6: https://github.com/tailscale/tailscale/blob/22ebb25e833264f58d7c3f534a8b166894a89536/net/tsaddr/tsaddr.go#LL81C52-L81C71 # IPv4: https://github.com/tailscale/tailscale/blob/22ebb25e833264f58d7c3f534a8b166894a89536/net/tsaddr/tsaddr.go#L33 # Any other range is NOT supported, and it will cause unexpected issues. ip_prefixes = [ "fd7a:115c:a1e0::/48" "100.64.0.0/10" ]; # Address to listen for gRPC. # gRPC is used for controlling a headscale server # remotely with the CLI # Note: Remote access _only_ works if you have # valid certificates. grpc_listen_addr = "127.0.0.1:" + builtins.toString localGrpcPort; # Allow the gRPC admin interface to run in INSECURE # mode. This is not recommended as the traffic will # be unencrypted. Only enable if you know what you # are doing. grpc_allow_insecure = true; # we're behind a reverse proxy logtail = { enabled = false; }; }; }; services.nginx.enable = true; services.nginx.virtualHosts."scale.isomorphis.me" = { useACMEHost = "scale.isomorphis.me"; onlySSL = true; locations."/" = { proxyPass = "http://127.0.0.1:" + builtins.toString localListenPort; recommendedProxySettings = false; extraConfig = '' proxy_http_version 1.1; proxy_set_header Upgrade $http_upgrade; proxy_set_header Connection $connection_upgrade; proxy_set_header Host $server_name; proxy_redirect http:// https://; proxy_buffering off; proxy_set_header X-Real-IP $remote_addr; proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for; proxy_set_header X-Forwarded-Proto $http_x_forwarded_proto; add_header Strict-Transport-Security "max-age=15552000; includeSubDomains" always; ''; }; }; services.nginx.virtualHosts."headscale-grpc" = { serverName = "scale.isomorphis.me"; useACMEHost = "scale.isomorphis.me"; onlySSL = true; listen = [ { addr = "0.0.0.0"; port = externalGrpcPort; ssl = true; } { addr = "[::]"; port = externalGrpcPort; ssl = true; } ]; locations."/" = { extraConfig = '' grpc_pass grpc://127.0.0.1:${builtins.toString localGrpcPort}; ''; }; }; security.acme.certs."scale.isomorphis.me" = { group = config.services.nginx.group; }; }