{ config, lib, pkgs, ... }: let hostPort = 9005; subdomain = "auth"; name = "authentik"; in { options.sysconfig.docker.authentik.enable = with lib; mkOption { type = with types; bool; default = false; }; config = lib.mkIf (config.sysconfig.docker.authentik.enable && config.sysconfig.docker.enable) { networking.firewall.interfaces = { "ve-traefik" = { allowedTCPPorts = [ hostPort ]; }; }; sops.secrets = { "authentik/pass" = {}; "authentik/secret_key" = {}; }; sops.templates."authentik.env" = { content = '' PG_PASS=${config.sops.placeholder."authentik/pass"} SECRET_KEY=${config.sops.placeholder."authentik/secret_key"} ''; }; virtualisation.oci-containers.containers."authentik-postgresql" = { image = "docker.io/library/postgres:16-alpine"; environment = { "POSTGRES_DB" = "authentik"; "POSTGRES_PASSWORD" = "\${PG_PASS}"; "POSTGRES_USER" = "authentik"; }; environmentFiles = [ config.sops.templates."authentik.env".path ]; volumes = [ "authentik_database:/var/lib/postgresql/data:rw" ]; log-driver = "journald"; extraOptions = [ "--health-cmd=pg_isready -d \${POSTGRES_DB} -U \${POSTGRES_USER}" "--health-interval=30s" "--health-retries=5" "--health-start-period=20s" "--health-timeout=5s" "--network-alias=postgresql" "--network=authentik_default" ]; }; systemd.services."docker-authentik-postgresql" = { serviceConfig = { Restart = lib.mkOverride 90 "always"; RestartMaxDelaySec = lib.mkOverride 90 "1m"; RestartSec = lib.mkOverride 90 "100ms"; RestartSteps = lib.mkOverride 90 9; }; after = [ "docker-network-authentik_default.service" "docker-volume-authentik_database.service" ]; requires = [ "docker-network-authentik_default.service" "docker-volume-authentik_database.service" ]; partOf = [ "docker-compose-authentik-root.target" ]; wantedBy = [ "docker-compose-authentik-root.target" ]; }; virtualisation.oci-containers.containers."authentik-server" = { image = "ghcr.io/goauthentik/server:2025.12.2"; environment = { "AUTHENTIK_POSTGRESQL__HOST" = "postgresql"; "AUTHENTIK_POSTGRESQL__NAME" = "authentik"; "AUTHENTIK_POSTGRESQL__PASSWORD" = "\${PG_PASS}"; "AUTHENTIK_POSTGRESQL__USER" = "authentik"; "AUTHENTIK_SECRET_KEY" = "\${SECRET_KEY}"; }; environmentFiles = [ config.sops.templates."authentik.env".path ]; labels = { "traefik.enable" = "true"; "traefik.http.routers.${name}.entrypoints" = "websecure,localsecure"; "traefik.http.routers.${name}.rule" = "Host(`${subdomain}.esotericbytes.com`)"; "traefik.http.routers.${name}.service" = "${name}"; "traefik.http.routers.${name}.tls.certResolver" = "cloudflare"; "traefik.http.services.${name}.loadbalancer.server.url" = "http://192.168.101.1:${builtins.toString hostPort}"; }; volumes = [ "/etc/Authentik/custom-templates:/templates:rw" "/etc/Authentik/data:/data:rw" ]; ports = [ "${builtins.toString hostPort}:9000/tcp" #"9443:9443/tcp" ]; cmd = [ "server" ]; dependsOn = [ "authentik-postgresql" ]; log-driver = "journald"; extraOptions = [ "--network-alias=server" "--network-alias=authentik-server" "--network-alias=${name}" ]; networks = [ "docker-main" "authentik_default" ]; }; systemd.services."docker-authentik-server" = { serviceConfig = { Restart = lib.mkOverride 90 "always"; RestartMaxDelaySec = lib.mkOverride 90 "1m"; RestartSec = lib.mkOverride 90 "100ms"; RestartSteps = lib.mkOverride 90 9; }; after = [ "docker-network-authentik_default.service" "docker-network-setup.service" ]; requires = [ "docker-network-authentik_default.service" "docker-network-setup.service" ]; partOf = [ "docker-compose-authentik-root.target" ]; wantedBy = [ "docker-compose-authentik-root.target" ]; }; virtualisation.oci-containers.containers."authentik-worker" = { image = "ghcr.io/goauthentik/server:2025.12.2"; environment = { "AUTHENTIK_POSTGRESQL__HOST" = "postgresql"; "AUTHENTIK_POSTGRESQL__NAME" = "authentik"; "AUTHENTIK_POSTGRESQL__PASSWORD" = "\${PG_PASS}"; "AUTHENTIK_POSTGRESQL__USER" = "authentik"; "AUTHENTIK_SECRET_KEY" = "\${SECRET_KEY}"; }; environmentFiles = [ config.sops.templates."authentik.env".path ]; volumes = [ "/etc/Authentik/certs:/certs:rw" "/etc/Authentik/custom-templates:/templates:rw" "/etc/Authentik/data:/data:rw" "/var/run/docker.sock:/var/run/docker.sock:rw" ]; cmd = [ "worker" ]; dependsOn = [ "authentik-postgresql" ]; user = "root"; log-driver = "journald"; extraOptions = [ "--network-alias=worker" "--network=authentik_default" ]; }; systemd.services."docker-authentik-worker" = { serviceConfig = { Restart = lib.mkOverride 90 "always"; RestartMaxDelaySec = lib.mkOverride 90 "1m"; RestartSec = lib.mkOverride 90 "100ms"; RestartSteps = lib.mkOverride 90 9; }; after = [ "docker-network-authentik_default.service" ]; requires = [ "docker-network-authentik_default.service" ]; partOf = [ "docker-compose-authentik-root.target" ]; wantedBy = [ "docker-compose-authentik-root.target" ]; }; # Networks systemd.services."docker-network-authentik_default" = { path = [ pkgs.docker ]; serviceConfig = { Type = "oneshot"; RemainAfterExit = true; ExecStop = "docker network rm -f authentik_default"; }; script = '' docker network inspect authentik_default || docker network create authentik_default ''; partOf = [ "docker-compose-authentik-root.target" ]; wantedBy = [ "docker-compose-authentik-root.target" ]; }; # Volumes systemd.services."docker-volume-authentik_database" = { path = [ pkgs.docker ]; serviceConfig = { Type = "oneshot"; RemainAfterExit = true; }; script = '' docker volume inspect authentik_database || docker volume create authentik_database --driver=local ''; partOf = [ "docker-compose-authentik-root.target" ]; wantedBy = [ "docker-compose-authentik-root.target" ]; }; # Root service # When started, this will automatically create all resources and start # the containers. When stopped, this will teardown all resources. systemd.targets."docker-compose-authentik-root" = { unitConfig = { Description = "Root target generated by compose2nix."; }; wantedBy = [ "multi-user.target" ]; }; }; }