{ name = "Authentik"; description = '' SSO provider ''; traefikRoutes = { host, ... }: let hostname = host.hostname; config = host.config.authentik; in [ { name = "${hostname}-authentik"; rule = "Host(`${config.domain}`)"; target = "http://${host.ip}:9000"; } ]; nixosModule = { lib, config, pkgs, host, ... }: let AUTHENTIK_VERSION = "2024.12.3"; publicEnv = pkgs.writeText "authentik-public.env" '' AUTHENTIK_EMAIL__USE_TLS=false AUTHENTIK_EMAIL__USE_SSL=true AUTHENTIK_EMAIL__TIMEOUT=10 ''; in { options.authentik = { domain = lib.mkOption { type = lib.types.str; }; }; config = { # Set up user to run authentik users.users."authentik" = { isSystemUser = true; group = "authentik"; }; users.groups."authentik" = { }; # TODO: Persist some/all of this into ceph cluster environment.persistence."/persistent" = { directories = [ { directory = "/appdata/authentik/redis"; mode = "0700"; } { directory = "/appdata/authentik/media"; mode = "0700"; } { directory = "/appdata/authentik/certs"; mode = "0700"; } ]; }; sops.secrets = { "authentik/db_pass" = { owner = "authentik"; }; "authentik/secret_key" = { owner = "authentik"; }; "authentik/email_host" = { owner = "authentik"; }; "authentik/email_port" = { owner = "authentik"; }; "authentik/email_from" = { owner = "authentik"; }; "authentik/email_username" = { owner = "authentik"; }; "authentik/email_password" = { owner = "authentik"; }; }; sops.templates."authentik-secret.env" = { owner = "authentik"; content = '' AUTHENTIK_POSTGRESQL__PASSWORD=${config.sops.placeholder."authentik/db_pass"} AUTHENTIK_SECRET_KEY="${config.sops.placeholder."authentik/secret_key"}" AUTHENTIK_EMAIL__HOST="${config.sops.placeholder."authentik/email_host"}" AUTHENTIK_EMAIL__PORT="${config.sops.placeholder."authentik/email_port"}" AUTHENTIK_EMAIL__FROM="${config.sops.placeholder."authentik/email_from"}" AUTHENTIK_EMAIL__USERNAME="${config.sops.placeholder."authentik/email_username"}" AUTHENTIK_EMAIL__PASSWORD="${config.sops.placeholder."authentik/email_password"}" ''; }; # Create the database postgres.databases = [ "authentik" ]; podman.containers = { # TODO: Does using system redis make sense here? "authentik-redis" = { image = "docker.io/library/redis:7.4.2-alpine"; autoStart = true; volumes = [ "/appdata/authentik/redis:/data" ]; }; "authentik-server" = { image = "ghcr.io/goauthentik/server:${AUTHENTIK_VERSION}"; autoStart = true; cmd = [ "server" ]; environment = { AUTHENTIK_REDIS__HOST = "authentik-redis"; AUTHENTIK_POSTGRESQL__HOST = "host.containers.internal"; AUTHENTIK_POSTGRESQL__USER = "authentik"; AUTHENTIK_POSTGRESQL__NAME = "authentik"; }; environmentFiles = [ config.sops.templates."authentik-secret.env".path publicEnv ]; volumes = [ "/appdata/authentik/media:/media" ]; ports = [ "9000:9000" ]; }; "authentik-worker" = { image = "ghcr.io/goauthentik/server:${AUTHENTIK_VERSION}"; user = "root"; autoStart = true; cmd = [ "worker" ]; environment = { AUTHENTIK_REDIS__HOST = "authentik-redis"; AUTHENTIK_POSTGRESQL__HOST = "host.containers.internal"; AUTHENTIK_POSTGRESQL__USER = "authentik"; AUTHENTIK_POSTGRESQL__NAME = "authentik"; }; environmentFiles = [ config.sops.templates."authentik-secret.env".path publicEnv ]; volumes = [ "/appdata/authentik/media:/media" "/appdata/authentik/certs:/certs" ]; }; }; }; }; }