{ config, pkgs, ... }: let baseDomain = "vimium.com"; domain = "auth.${baseDomain}"; mkRandomSecret = { generator.script = "alnum"; mode = "440"; group = "kanidm"; }; in { age.secrets.kanidm-admin-password = mkRandomSecret; age.secrets.kanidm-idm-admin-password = mkRandomSecret; age.secrets.kanidm-oauth2-gitea = mkRandomSecret; age.secrets.kanidm-oauth2-open-webui = mkRandomSecret; services.kanidm = let uri = "https://${domain}"; in { package = pkgs.unstable.kanidmWithSecretProvisioning; enableClient = true; enableServer = true; clientSettings = { inherit uri; }; serverSettings = { bindaddress = "127.0.0.1:3013"; ldapbindaddress = "100.64.0.1:636"; domain = baseDomain; origin = uri; tls_chain = "${config.security.acme.certs.${domain}.directory}/full.pem"; tls_key = "${config.security.acme.certs.${domain}.directory}/key.pem"; version = "2"; }; provision = { enable = true; adminPasswordFile = config.age.secrets.kanidm-admin-password.path; idmAdminPasswordFile = config.age.secrets.kanidm-idm-admin-password.path; persons.jordan = { displayName = "Jordan Holt"; legalName = "Jordan Holt"; mailAddresses = [ "jordan@vimium.com" ]; groups = [ "gitea_admins" "gitea_users" "jellyfin_admins" "jellyfin_users" "open-webui_admins" "open-webui_users" ]; }; groups."gitea_admins" = { }; groups."gitea_users" = { }; systems.oauth2.gitea = { displayName = "Gitea"; originUrl = "https://git.vimium.com/user/oauth2/Vimium/callback"; originLanding = "https://git.vimium.com/"; basicSecretFile = config.age.secrets.kanidm-oauth2-gitea.path; scopeMaps."gitea_users" = [ "openid" "email" "profile" ]; allowInsecureClientDisablePkce = true; preferShortUsername = true; claimMaps.groups = { joinType = "array"; valuesByGroup."gitea_admins" = [ "admin" ]; }; }; groups."jellyfin_admins" = { }; groups."jellyfin_users" = { }; groups."open-webui_admins" = { }; groups."open-webui_users" = { }; systems.oauth2.open-webui = { displayName = "Open WebUI"; originUrl = "https://chat.ai.vimium.com/oauth/oidc/callback"; originLanding = "https://chat.ai.vimium.com/"; basicSecretFile = config.age.secrets.kanidm-oauth2-open-webui.path; scopeMaps."open-webui_users" = [ "openid" "email" "profile" ]; allowInsecureClientDisablePkce = true; claimMaps.groups = { joinType = "array"; valuesByGroup."open-webui_admins" = [ "admin" ]; }; }; }; }; # LDAP server binds to tailscale network interface systemd.services.kanidm = { requires = [ "tailscaled.service" ]; after = [ "tailscaled.service" ]; }; services.nginx.virtualHosts = { "${domain}" = { useACMEHost = "${domain}"; forceSSL = true; locations."/" = { proxyPass = "https://127.0.0.1:3013"; }; }; }; users.extraGroups.acme.members = [ "kanidm" "nginx" ]; security.acme.certs."${domain}" = { postRun = "systemctl restart kanidm.service"; group = "acme"; }; environment.persistence."/persist".directories = [ { directory = "/var/lib/kanidm"; user = "kanidm"; group = "kanidm"; mode = "0700"; } ]; }