{ config, ... }: { services.kanidm = { enableClient = true; enableServer = true; clientSettings = { uri = "https://ki.mou.fo"; }; serverSettings = { origin = "https://ki.mou.fo"; domain = "ki.mou.fo"; bindaddress = "[::1]:7368"; trust_x_forward_for = true; # Kanidm requires TLS even behind a reverse proxy. tls_chain = "/run/credentials/kanidm.service/fullchain.pem"; tls_key = "/run/credentials/kanidm.service/key.pem"; }; }; systemd.services.kanidm = { # Kanidm runs as an unprivileged user that needs access to certificates. serviceConfig.LoadCredential = let certDir = config.security.acme.certs."ki.mou.fo".directory; in [ "fullchain.pem:${certDir}/fullchain.pem" "key.pem:${certDir}/key.pem" ]; }; services.nginx.virtualHosts."ki.mou.fo" = { enableACME = true; forceSSL = true; locations."/".proxyPass = "https://[::1]:7368"; }; # The oauth2-proxy module has a magic nginx.virtualHosts option that rewrites # nginx configs. It can be heavy handed, but we use it for brevity. In # particular, it configures Traefik-like ForwardAuth authentication with # auth_request. Note if this resource is missing for whatever reason, the # module magic will fail open (auth_request unset). services.oauth2-proxy = { enable = true; cookie.domain = "mou.fo"; nginx.domain = "op.mou.fo"; setXauthrequest = true; # let oauth2-proxy nginx module pass X-User/X-Email reverseProxy = true; # Example nestled in https://kanidm.github.io/kanidm/stable/examples/kubernetes_ingress.html provider = "oidc"; clientID = "oauth2-proxy"; oidcIssuerUrl = "https://ki.mou.fo/oauth2/openid/oauth2-proxy"; # Sets OAUTH2_PROXY_COOKIE_SECRET and OAUTH2_PROXY_CLIENT_SECRET. keyFile = "/var/secrets/oauth2-proxy.env"; # Ignore e-mail address. scope = "openid profile"; email.domains = [ "*" ]; extraConfig = { "code-challenge-method" = "S256"; "whitelist-domain" = ".mou.fo"; # allowed redirects after authentication # https://github.com/oauth2-proxy/oauth2-proxy/issues/1612#issuecomment-1099217761 "oidc-email-claim" = "sub"; }; }; # Kludge to bring up after Kanidm (otherwise OIDC discovery fails). A simple # ordering dependency isn't enough because kandim.service is active before # Kanidm responds to requests. Kanidm starts up quickly enough that boot up # may work without this. systemd.services.oauth2-proxy.serviceConfig.RestartSec = 5; # It's somewhat overkill to assign oauth2-proxy its own domain. We can't use # Kanidm's though, because it uses the /oauth2 path which the oauth2-proxy # nginx module is hardcoded for (proxyPrefix is ignored); this module magic is # also why we do not need to explicitly specify proxyPass. services.nginx.virtualHosts."op.mou.fo" = { enableACME = true; forceSSL = true; }; }