{ inputs', inputs, lib, pkgs, self', self, config, ... }: let inherit (lib) mkDefault mkIf ; inherit (self') packages; fqdn = "keycloak-pam.test"; passwordFile = builtins.toFile "super-secure-password" "nuhuh"; theme-name = "default"; in { virtualisation.vmVariant.virtualisation = { cores = 2; diskSize = 8192; graphics = false; memorySize = 4096; qemu.networkingOptions = lib.mkForce [ "-nic bridge,br=virbr0,id=hn0,model=virt-net-pci,helper=\${QEMU_BRIDGE_HELPER_PATH}" "-device virtio-net-pci,netdev=hn0,id=nic1,\${QEMU_NET_OPTS:+,$QEMU_NET_OPTS}" ]; }; system = { configurationRevision = self.rev or self.dirtyRev or null; stateVersion = "25.11"; }; networking = { inherit fqdn; firewall.enable = false; networkmanager.enable = true; extraHosts = let subdomains = [ ]; hosts = [ fqdn ] ++ map (sub: "${sub}.${fqdn}") subdomains; in lib.concatMapStrings (host: '' 127.0.0.1 ${host} ::1 ${host} '') hosts; }; services.getty.autologinUser = "root"; services.nginx = let mkVhost = attrs: locations: { forceSSL = false; inherit locations; } // attrs; mkProxy = port: { proxyPass = "http://127.0.0.1:${toString port}/"; extraConfig = '' proxy_buffering off; proxy_request_buffering off; proxy_set_header X-Forwarded-For $remote_addr; ''; }; in { enable = true; recommendedProxySettings = true; recommendedOptimisation = true; virtualHosts = { "${fqdn}" = mkVhost { default = true; } { "/" = mkProxy config.services.keycloak.settings.http-port; }; }; }; users = { users.admin = { password = config.services.keycloak.initialAdminPassword; isNormalUser = true; extraGroups = [ "keycloak-login" ]; }; groups.keycloak-login = { }; }; services.keycloak = { enable = true; initialAdminPassword = "dontchangeme"; settings = { hostname = "http://${fqdn}"; http-port = 3000; http-enabled = true; proxy-headers = "forwarded"; }; database = { host = "localhost"; inherit passwordFile; }; }; services.postgresql = { enable = true; authentication = pkgs.lib.mkOverride 10 '' #type database DBuser auth-method local all all trust host keycloak keycloak 127.0.0.1/32 md5 ''; }; security.pam.services = let keycloakReplacesUnix = { rules.auth.keycloak-pam = { order = config.security.pam.services.login.rules.auth.unix.order - 10; control = "sufficient"; modulePath = "${packages.keycloak-pam}/lib/libkeycloak_pam.so"; settings = { debug = true; config = builtins.toFile "keycloak-pam.json" '' { "base_url": "http://127.0.0.1:${toString config.services.keycloak.settings.http-port}", "default_realm": "master", "client_id": "account", "client_secret": "7bsrMrRuNKpqsxcOOJavWjEqek12ZCkj", "unix_group": "keycloak-login" } ''; }; }; }; in builtins.foldl' (attrs: service: attrs // { "${service}" = keycloakReplacesUnix; }) { } [ "login" "passwd" "su" "sudo" ]; }