Commit 6da2f50
Changed files (2)
modules
hosts
hyacine
services
services
modules/hosts/hyacine/services/services.nix
@@ -1,10 +1,21 @@
{den, ...}: {
den.hosts.hyacine.settings = {
+ services.headscale = {
+ domain = "gate.trin.one";
+ port = 3465;
+ derp.enable = true;
+ dns = {
+ enable = true;
+ domain = "net.trin.one";
+ };
+ };
};
den.aspects.hyacine = {
includes = [
den.aspects.services.webserver
+
+ den.aspects.services.headscale
];
};
}
modules/services/headscale.nix
@@ -0,0 +1,141 @@
+{
+ den,
+ lib,
+ ...
+}: {
+ den.aspects.services.headscale = {
+ settings = {
+ domain = lib.mkOption {
+ type = lib.types.nullOr lib.types.str;
+ default = null;
+ };
+ port = lib.mkOption {
+ type = lib.types.port;
+ default = 8080;
+ };
+ derp = {
+ enable = lib.mkEnableOption "Enable Headscale's builtin DERP server";
+ port = lib.mkOption {
+ type = lib.types.port;
+ default = 3478;
+ };
+ };
+ dns = {
+ enable = lib.mkEnableOption "Enable Headscale's Magic DNS";
+ domain = lib.mkOption {
+ type = lib.types.str;
+ default = "ts.net";
+ };
+ };
+ };
+
+ persist = {
+ directories = [
+ {
+ directory = "/var/lib/headscale";
+ user = "headscale";
+ group = "headscale";
+ mode = "0700";
+ }
+ ];
+ };
+
+ reverseProxy = {host, ...}: let
+ cfg = host.settings.services.headscale;
+ in {
+ ${cfg.domain} = {
+ port = cfg.port;
+ };
+ };
+
+ nixos = {
+ host,
+ pkgs,
+ config,
+ ...
+ }: let
+ cfg = host.settings.services.headscale;
+ hostAddr = host.address;
+
+ headscale-wrapped =
+ pkgs.runCommandLocal "headscale-wrapped" {
+ nativeBuildInputs = [pkgs.makeWrapper];
+ } ''
+ mkdir -p $out/bin
+ makeWrapper ${lib.getExe config.services.headscale.package} $out/bin/headscale \
+ --add-flags "--config ${config.services.headscale.configFile}"
+ '';
+ in {
+ environment.systemPackages = [headscale-wrapped];
+ services.headscale = {
+ enable = true;
+ address =
+ if (host.hasAspect den.aspects.services.webserver)
+ then "127.0.0.1"
+ else abort "Not implemented for outside host webserver";
+ port = cfg.port;
+ settings = {
+ server_url = "https://${cfg.domain}";
+ database.type = "sqlite";
+ tls_cert_path = null; # Use webserver for TLS instead.
+ tls_key_path = null;
+ prefixes = {
+ v4 = "100.64.0.0/10";
+ v6 = "fd7a:115c:a1e0::/48";
+ allocation = "random";
+ };
+ derp.server = lib.optionalAttrs (cfg.derp.enable) {
+ enabled = true;
+ stun_listen_addr = "0.0.0.0:${toString cfg.derp.port}";
+ verify_clients = true;
+ region_id = 999;
+ region_code = "headscale";
+ region_name = "Headscale Embedded DERP";
+ ipv4 = lib.mkIf (hostAddr.ipv4.clearText != null) hostAddr.ipv4.clearText;
+ ipv6 = lib.mkIf (hostAddr.ipv6.clearText != null) hostAddr.ipv6.clearText;
+ };
+ dns = {
+ magic_dns = cfg.dns.enable;
+ override_local_dns = cfg.dns.enable;
+ base_domain = cfg.dns.domain;
+ nameservers.global = [
+ # IPv4
+ "119.29.29.29" # DNSPod
+ "223.5.5.5" # AliDNS
+ # IPv6
+ "2400:3200::1" # AliDNS
+ "2606:4700:4700::1111" # Cloudflare
+ ];
+ };
+ };
+ };
+
+ networking.firewall.allowedUDPPorts = lib.optional (cfg.derp.enable) 3478;
+
+ systemd.services.headscale = {
+ serviceConfig.EnvironmentFile =
+ lib.mkIf (hostAddr.ipv4.secret.name != null || hostAddr.ipv6.secret.name != null)
+ config.vaultix.templates.headscale-env.path;
+ };
+ vaultix.templates.headscale-env =
+ lib.mkIf (hostAddr.ipv4.secret.name != null || hostAddr.ipv6.secret.name != null)
+ {
+ content = lib.concatLines (
+ (
+ lib.optional
+ (hostAddr.ipv4.secret.name != null)
+ "HEADSCALE_DERP_SERVER_IPV4=${config.vaultix.placeholder.${hostAddr.ipv4.secret.name}}"
+ )
+ ++ (
+ lib.optional
+ (hostAddr.ipv6.secret.name != null)
+ "HEADSCALE_DERP_SERVER_IPV4=${config.vaultix.placeholder.${hostAddr.ipv6.secret.name}}"
+ )
+ );
+ owner = config.services.headscale.user;
+ group = config.services.headscale.group;
+ mode = "0400";
+ };
+ };
+ };
+}