headplane_headscale_nix/keycloak.nix
David Gillespie 7c1bdb2c54 feat: Complete Keycloak OIDC integration for Headplane
- Added Keycloak service with PostgreSQL backend
- Configured OIDC for both Headscale and Headplane
- Added systemd service to auto-create /var/lib/headplane directory
- Updated Keycloak realm JSON with required client scopes (openid, profile, email)
- Generated and configured Headscale API key for Headplane OIDC
- Added production hardening: auto-restart, garbage collection, boot cleanup

The setup now supports:
- User login via Keycloak OIDC at https://auth.kennys.mom
- Headplane web UI with SSO at https://headplane.kennys.mom/admin
- Fallback API key authentication
- Automated secret generation and permissions management
2025-12-05 17:37:53 -07:00

91 lines
2.5 KiB
Nix

{ config, pkgs, lib, ... }:
let
domain = "kennys.mom";
authDomain = "auth.${domain}";
in
{
# PostgreSQL for Keycloak
services.postgresql = {
enable = true;
ensureDatabases = [ "keycloak" ];
ensureUsers = [{
name = "keycloak";
ensureDBOwnership = true;
}];
};
# Keycloak service
services.keycloak = {
enable = true;
database = {
type = "postgresql";
username = "keycloak";
name = "keycloak";
host = "localhost";
createLocally = false;
passwordFile = "/var/lib/keycloak-credentials/db-password";
};
settings = {
hostname = authDomain;
http-host = "127.0.0.1";
http-port = 8080;
http-enabled = true;
proxy-headers = "xforwarded";
hostname-strict-https = false;
};
};
# Generate database password and use LoadCredential
systemd.services.keycloak = {
serviceConfig = {
LoadCredential = [ "db-password:/var/lib/keycloak-credentials/db-password" ];
TimeoutStartSec = "5min";
};
};
systemd.services.keycloak-db-password = {
description = "Generate Keycloak database password";
wantedBy = [ "multi-user.target" ];
before = [ "keycloak.service" ];
after = [ "postgresql.service" ];
serviceConfig = {
Type = "oneshot";
RemainAfterExit = true;
};
script = ''
mkdir -p /var/lib/keycloak-credentials
if [ ! -f /var/lib/keycloak-credentials/db-password ]; then
echo "Generating Keycloak database password..."
DB_PASS=$(${pkgs.openssl}/bin/openssl rand -base64 32)
echo -n "$DB_PASS" > /var/lib/keycloak-credentials/db-password
chmod 600 /var/lib/keycloak-credentials/db-password
# Set the password in PostgreSQL
${pkgs.sudo}/bin/sudo -u postgres ${config.services.postgresql.package}/bin/psql -c "ALTER USER keycloak WITH PASSWORD '$DB_PASS';"
echo "Database password set"
fi
'';
};
# Ngin configuration for Keycloak
services.nginx.virtualHosts."${authDomain}" = {
forceSSL = true;
enableACME = true;
locations."/" = {
proxyPass = "http://127.0.0.1:8080";
extraConfig = ''
proxy_set_header Host $host;
proxy_set_header X-Real-IP $remote_addr;
proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;
proxy_set_header X-Forwarded-Proto $scheme;
proxy_set_header X-Forwarded-Host $host;
proxy_buffer_size 128k;
proxy_buffers 4 256k;
proxy_busy_buffers_size 256k;
'';
};
};
}