{config, pkgs, lib, ...}: with lib; let cfg = config.services.headscale; authServer = cfg.settings.server_url; connectContainer = name: options: { enableTun = true; bindMounts = { "/var/tailauth" = { hostPath = cfg.ensureUsers."${name}".path; }; }; config = {config, pkgs, ...}: { networking.nameservers = [ "1.1.1.1" ]; networking.useHostResolvConf = false; networking.firewall = { enable = false; }; services.tailscale = { enable = true; useRoutingFeatures = "client"; authKeyFile = "/var/tailauth"; extraUpFlags = ["--login-server" "${authServer}"]; }; # Resolves https://github.com/NixOS/nixpkgs/issues/430756 systemd.services.tailscaled-autoconnect.serviceConfig.Type = lib.mkForce "simple"; }; }; mkContainerAfterToken = name: options: { requires = ["headscale-preauth-regen-${name}.service"]; after = ["headscale-preauth-regen-${name}.service"]; }; ensureContainerUser = name: options: { }; in { # Extend NixOS containers to automatically # create a headscale user with the container # name, generate its auth, and binds it to # the container imports = [ ./headscale.nix ]; options = { services.headscale.containers = mkOption { type = types.attrsOf (types.submodule ( {config, options, name, ...}: { } )); default = {}; }; }; config = { # networking.bridges = { # "br0" = { # interfaces = []; # }; # }; # networking.interfaces.br0.ipv4.addresses = [{ # address = "10.0.0.1"; # prefixLength = 24; # }]; networking.nat = { enable = true; # Check for hostBridge use vb instead of ve internalInterfaces = (map (n: "ve-${n}") (attrNames cfg.containers)); externalInterface = "enp0s25"; enableIPv6 = true; }; containers = mapAttrs connectContainer cfg.containers; systemd.services = mapAttrs' (n: v: nameValuePair "container@${n}" (mkContainerAfterToken n v)) cfg.containers; services.headscale.ensureUsers = mapAttrs ensureContainerUser cfg.containers; }; }