{ pkgs, inputs, lib, config, ... }: with lib; let cfg = config.xyno.services.authentik; defaultAppOptions = { options = { name = mkOption { type = types.str; }; group = mkOption { type = types.nullOr types.str; default = null; }; groups = mkOption { type = types.listOf types.str; default = [ ]; }; meta_description = mkOption { type = types.nullOr types.str; default = null; }; meta_icon = mkOption { type = types.nullOr types.str; default = null; }; meta_launch_url = mkOption { type = types.nullOr types.str; default = null; }; meta_publisher = mkOption { type = types.nullOr types.str; default = null; }; }; }; terrraformStateDir = "/var/lib/authentik-terraform-config"; environmentFileDir = "/run/authentik-terraform-config"; terranixConfig = inputs.terranix.lib.terranixConfiguration { system = pkgs.system; modules = [ ./authentik/provider.nix { inherit (cfg) oauthApps ldapApps proxyApps url insecure ; stateFile = "${terrraformStateDir}/state.tfstate"; } ]; }; in { options.xyno.services.authentik.enable = mkEnableOption "enables the authentik SSO thing"; options.xyno.services.authentik.oauthApps = mkOption { default = { }; type = types.attrsOf ( types.submodule ( { name, ... }: ({ options = { environmentFile = mkOption { type = types.str; default = "${environmentFileDir}/${name}_environment"; }; } // defaultAppOptions.options; }) ) ); }; options.xyno.services.authentik.ldapApps = mkOption { default = { }; type = types.attrsOf (types.submodule (defaultAppOptions)); }; options.xyno.services.authentik.proxyApps = mkOption { default = { }; type = types.attrsOf ( types.submodule ({ options = { externalHost = mkOption { type = types.str; }; } // defaultAppOptions.options; }) ); }; options.xyno.services.authentik.url = mkOption { type = types.str; default = "https://auth.hailsatan.eu"; }; options.xyno.services.authentik.insecure = mkOption { type = types.bool; default = false; }; options.xyno.services.authentik.after = mkOption { type = types.listOf types.str; default = []; }; config = lib.mkIf cfg.enable { environment.etc."authentik-config/config.tf.json".source = terranixConfig; xyno.impermanence.directories = [ terrraformStateDir ]; services.authentik = { enable = true; createDatabase = true; environmentFile = config.sops.secrets."authentik/env".path; settings = { disable_startup_analytics = true; }; }; systemd.services.authentik.after = cfg.after; systemd.services.authentik-ldap.after = [ "authentik-config.service" ]; systemd.services.authentik-ldap.environment.AUTHENTIK_LISTEN__METRICS = mkForce "[::1]:9302"; services.authentik-ldap = { environmentFile = "${environmentFileDir}/ldap_config"; enable = true; }; systemd.services.authentik-proxy.after = [ "authentik-config.service" ]; systemd.services.authentik-proxy.environment.AUTHENTIK_LISTEN__HTTP = mkForce "[::1]:9001"; systemd.services.authentik-proxy.environment.AUTHENTIK_LISTEN__METRICS = mkForce "[::1]:9301"; services.authentik-proxy = { enable = true; environmentFile = "${environmentFileDir}/proxy_config"; }; systemd.services.authentik-config = { after = [ "authentik.service" ]; wantedBy = [ "multi-user.target" ]; wants = [ "network-online.target" ]; before = [ "authentik-ldap.service" "authentik-proxy.service" ]; serviceConfig = { Type = "oneshot"; RemainAfterExit = true; EnvironmentFile = [ config.services.authentik.environmentFile ]; Restart = "on-failure"; RestartSec = 30; StateDirectory = "authentik-config"; }; script = let opentofu = pkgs.opentofu.withPlugins (p: [ inputs.authentik.packages.${pkgs.system}.terraform-provider-authentik ]); in '' set -xeuo pipefail umask u=rw,go= export PATH=$PATH:${opentofu}/bin:${pkgs.curl}/bin cd $STATE_DIRECTORY cp ${terranixConfig} ./main.tf.json export AUTHENTIK_URL=${cfg.url} export AUTHENTIK_INSECURE=${toString cfg.insecure} export AUTHENTIK_TOKEN=$AUTHENTIK_BOOTSTRAP_TOKEN tofu init tofu validate || exit 1 while [[ "$(curl -L -s -o /dev/null -I -w "%{http_code}" ''${AUTHENTIK_URL}/api/v3/flows/instances/)" =~ (502|000) ]]; do echo "[+] Authentik still starting, sleeping for 2s" sleep 2 done tofu apply -auto-approve tofu show -state mkdir ${environmentFileDir} tofu output -show-sensitive -raw proxy_config > ${environmentFileDir}/proxy_config cat ${environmentFileDir}/proxy_config tofu output -show-sensitive -raw ldap_config > ${environmentFileDir}/ldap_config ${concatStringsSep "\n" ( mapAttrsToList ( n: v: "tofu output -show-sensitive -raw ${n}_environment > ${v.environmentFile}" ) cfg.oauthApps )} ''; }; sops.secrets."authentik/env" = { sopsFile = ../../instances/${config.networking.hostName}/secrets/authentik.yaml; }; services.caddy.extraConfig = '' (reverse_proxy_auth) { route { # always forward outpost path to actual outpost reverse_proxy /outpost.goauthentik.io/* http://[::1]:9001 { } forward_auth http://[::1]:9001 { uri /outpost.goauthentik.io/auth/caddy copy_headers X-Authentik-Username X-Copyparty-Group X-Authentik-Groups X-Authentik-Entitlements X-Authentik-Email X-Authentik-Name X-Authentik-Uid X-Authentik-Jwt X-Authentik-Meta-Jwks X-Authentik-Meta-Outpost X-Authentik-Meta-Provider X-Authentik-Meta-App X-Authentik-Meta-Version X-Grafana-Role } reverse_proxy {args[:]} } ''; xyno.services.monitoring.exporters.authentik = 9300; xyno.services.monitoring.exporters.authentik-proxy = 9301; xyno.services.monitoring.exporters.authentik-ldap = 9302; }; }