{ lib, config, ... }: let cfg = config.lab.tailscale; secretName = "tailscale-auth"; roleName = "tailscale"; sidecarContainername = "tailscale-sidecar"; in { options = with lib.types; { lab.tailscale = { enable = lib.mkEnableOption "tailscale"; allowedServiceAccounts = lib.mkOption { type = listOf str; description = '' Allow specified service accounts to manage Tailscale authentication. ''; }; deploymentsWithSidecarContainers = lib.mkOption { type = attrsOf (submodule ({ name, ... }: { options.hostName = lib.mkOption { type = str; }; })); }; }; }; config = let mkRoleBinding = name: { name = "${name}-${roleName}"; value = { subjects = [{ inherit name; kind = "ServiceAccount"; }]; roleRef = { kind = "Role"; name = roleName; apiGroup = "rbac.authorization.k8s.io"; }; }; }; mkSidecarContainer = name: { hostName, ... }: { spec.template.spec.containers.${sidecarContainername} = { imagePullPolicy = "Always"; image = "ghcr.io/tailscale/tailscale:latest"; env = { TS_HOSTNAME.value = hostName; TS_KUBE_SECRET.value = secretName; TS_USERSPACE.value = "false"; TS_DEBUG_FIREWALL_MODE.value = "auto"; TS_AUTHKEY.valueFrom.secretKeyRef = { name = secretName; key = "TS_AUTHKEY"; optional = true; }; }; securityContext.capabilities.add = [ "NET_ADMIN" ]; }; }; in { kubernetes.resources = lib.mkIf cfg.enable { secrets.${secretName}.stringData.TS_AUTHKEY = "ref+sops://secrets/kubernetes.yaml#/tailscale/authKey"; roles.${roleName}.rules = [ { apiGroups = [ "" ]; resources = [ "secrets" ]; verbs = [ "create" ]; } { apiGroups = [ "" ]; resourceNames = [ secretName ]; resources = [ "secrets" ]; verbs = [ "get" "update" "patch" ]; } ]; roleBindings = builtins.listToAttrs (map mkRoleBinding cfg.allowedServiceAccounts); deployments = builtins.mapAttrs mkSidecarContainer cfg.deploymentsWithSidecarContainers; }; }; }