Codex bootstrapped this as an uncommitted, parallel identity/control plane under domain2 (lukasrosier.com) alongside the router migration; committing it now that it's been exercised together this session: - LLDAP admin login verified against a freshly rotated, pinix-only admin secret (pinixLldapAdmin.age, distinct from the lldapAdmin secret shared with blunix -- rotating one no longer risks the other). - Dex OIDC discovery and the LDAP connector work end-to-end through Traefik (dex.lukasrosier.com, head.lukasrosier.com). - Headscale's OIDC `allowed_groups` gate is intentionally not set yet: any account in this still-empty LLDAP directory may register a node for now. Re-add the "intern" gate once real accounts exist and the bootstrap is done. - tnix successfully joined headscale-pinix via a pre-auth key as a second, parallel tailscale identity (not yet made declarative). Not committed: tailnet-dns.nix (a separate, more speculative netns'd resolver experiment for this tailnet, untouched today) and its default.nix import. This remains a parallel control plane during bootstrap -- see docs/pinix-identity-stack.md. tailscale.nix on tnix/pinix, the existing blunix-controlled tailnet, and 0ff.space DNS are unchanged. Co-Authored-By: Claude Sonnet 5 <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_01C5FvfdKcQjEFQ4aLrepcS1
51 lines
2.4 KiB
Nix
51 lines
2.4 KiB
Nix
{ config, ... }:
|
|
{
|
|
# Zweite, eigenstaendige LLDAP-Instanz fuer den Identitaets-Stack auf
|
|
# pinix. Bewusst mit **leerer, neuer Datenbank** -- kein Kopieren von
|
|
# blunix' Verzeichnis. Damit gibt es kein Divergenzproblem zwischen zwei
|
|
# parallel laufenden Verzeichnissen, aber auch keine Nutzer: bevor
|
|
# Headscale hier per OIDC anmelden kann, muss der eigene Account neu
|
|
# angelegt werden (Gruppen-Gate `intern` bewusst noch nicht aktiv, siehe
|
|
# headscale.nix).
|
|
#
|
|
# Eigenes Admin-Passwort seit 13.09.2026 (secrets/pinixLldapAdmin.age):
|
|
# anfangs wiederverwendete dieses Verzeichnis das mit blunix geteilte
|
|
# lldapAdmin-Secret, was schlicht verwirrend war -- welches der beiden
|
|
# Passwoerter hier gilt, war nicht ersichtlich. Getrennt, damit ein
|
|
# Password-Rotieren auf der einen Seite nicht die andere anfasst.
|
|
#
|
|
# Das Branding von blunix' Instanz ist hier absichtlich nicht kopiert.
|
|
# Es sind rund 100 Zeilen CSS-Overrides, die dupliziert sofort
|
|
# auseinanderlaufen wuerden; beim Cutover gehoert die gebrandete
|
|
# Paket-Derivation in ein gemeinsames Modul unter
|
|
# hosts/globalServices/, aus dem beide Hosts importieren.
|
|
services.lldap = {
|
|
enable = true;
|
|
settings = {
|
|
# Enger gebunden als auf blunix, wo beides auf 0.0.0.0 laeuft: die
|
|
# Web-UI erreicht nur Traefik auf diesem Host, und LDAP nur das
|
|
# lokale Dex. Beides braucht keine erreichbare Adresse, und pinix'
|
|
# Firewall oeffnet diese Ports ohnehin nicht.
|
|
http_host = "127.0.0.1";
|
|
http_port = 17170;
|
|
ldap_host = "127.0.0.1";
|
|
ldap_port = 3890;
|
|
|
|
# Eigener Base DN, nicht config.ldapBaseDN: dieses Verzeichnis ist von
|
|
# blunix' unabhaengig und replizierten nie. Unterschiedliche DNs
|
|
# verhindern, dass ein Client versehentlich gegen das falsche
|
|
# Verzeichnis bindet und scheinbar funktioniert.
|
|
ldap_base_dn = config.ldapBaseDN2;
|
|
ldap_user_dn = "admin";
|
|
ldap_user_mail = config.adminEmail;
|
|
ldap_user_pass_file = "/run/credentials/lldap.service/ldap-user-pass";
|
|
force_ldap_user_pass_reset = "always";
|
|
};
|
|
};
|
|
|
|
# Wie auf blunix: systemd liest das root-eigene agenix-Secret und legt es
|
|
# nur innerhalb des Dienstes ab. LoadCredential laeuft als root, bevor der
|
|
# Dienst die Rechte abgibt.
|
|
systemd.services.lldap.serviceConfig.LoadCredential =
|
|
"ldap-user-pass:${config.age.secrets.pinixLldapAdmin.path}";
|
|
}
|