Archived
feat(ipa): add reusable declarative FreeIPA client module #74
+10
@@ -63,6 +63,16 @@ creation_rules:
|
|||||||
- *lxc-nix-cache
|
- *lxc-nix-cache
|
||||||
- *proxmox-nix-cache
|
- *proxmox-nix-cache
|
||||||
|
|
||||||
|
# Host keytab for nix-cache FreeIPA enrollment (binary sops file).
|
||||||
|
# Generate with: sops -e --input-type binary /tmp/nix-cache.keytab > secrets/nix-cache.keytab
|
||||||
|
- path_regex: secrets/nix-cache\.keytab$
|
||||||
|
key_groups:
|
||||||
|
- age:
|
||||||
|
- *admin
|
||||||
|
- *linode-nix-cache
|
||||||
|
- *lxc-nix-cache
|
||||||
|
- *proxmox-nix-cache
|
||||||
|
|
||||||
- path_regex: secrets/server\.yaml$
|
- path_regex: secrets/server\.yaml$
|
||||||
key_groups:
|
key_groups:
|
||||||
- age:
|
- age:
|
||||||
|
|||||||
@@ -0,0 +1,9 @@
|
|||||||
|
# Placeholder — replace with the actual FreeIPA CA certificate before deploying.
|
||||||
|
#
|
||||||
|
# Retrieve from the IPA server (it is a public certificate, safe to commit):
|
||||||
|
# curl -o certs/ipa-ca.crt http://<ipa-server>/ipa/config/ca.crt
|
||||||
|
#
|
||||||
|
# This file must contain a valid PEM certificate for SSSD to authenticate
|
||||||
|
# against FreeIPA over TLS. The Nix build succeeds with a placeholder, but
|
||||||
|
# the deployed host will not be able to join the domain until the real cert
|
||||||
|
# is committed and the system is rebuilt.
|
||||||
@@ -6,10 +6,15 @@
|
|||||||
name = "nix-cache";
|
name = "nix-cache";
|
||||||
sopsFile = ../../secrets/nix-cache.yaml;
|
sopsFile = ../../secrets/nix-cache.yaml;
|
||||||
})
|
})
|
||||||
|
(import ../../modules/ipa/client.nix {
|
||||||
|
keytabSopsFile = ../../secrets/nix-cache.keytab;
|
||||||
|
caCertFile = ../../certs/ipa-ca.crt;
|
||||||
|
})
|
||||||
];
|
];
|
||||||
|
|
||||||
networking = {
|
networking = {
|
||||||
hostName = vars.nixCacheHost;
|
hostName = vars.nixCacheHost;
|
||||||
|
domain = vars.homeDomain;
|
||||||
useDHCP = false;
|
useDHCP = false;
|
||||||
interfaces.${vars.lxcLanInterface}.ipv4.addresses = [{
|
interfaces.${vars.lxcLanInterface}.ipv4.addresses = [{
|
||||||
address = vars.nixCacheIp;
|
address = vars.nixCacheIp;
|
||||||
|
|||||||
@@ -0,0 +1,73 @@
|
|||||||
|
# Fully declarative FreeIPA domain membership.
|
||||||
|
#
|
||||||
|
# Configures security.ipa (SSSD, Kerberos, PAM, NSSwitch) and places a
|
||||||
|
# pre-provisioned host keytab via sops-nix so no imperative ipa-client-install
|
||||||
|
# step is needed after deployment.
|
||||||
|
#
|
||||||
|
# Usage (in a host.nix imports list):
|
||||||
|
# (import ../../modules/ipa/client.nix {
|
||||||
|
# keytabSopsFile = ../../secrets/nix-cache.keytab;
|
||||||
|
# caCertFile = ../../certs/ipa-ca.crt;
|
||||||
|
# })
|
||||||
|
#
|
||||||
|
# One-time operator setup per host (do this BEFORE deploying):
|
||||||
|
#
|
||||||
|
# 1. Fetch the IPA CA certificate (public — safe to commit):
|
||||||
|
# curl -o certs/ipa-ca.crt http://<ipa-server>/ipa/config/ca.crt
|
||||||
|
# Replace the placeholder at certs/ipa-ca.crt and commit it.
|
||||||
|
#
|
||||||
|
# 2. On the FreeIPA server, add the host and generate a keytab:
|
||||||
|
# ipa host-add <fqdn> --ip-address=<ip>
|
||||||
|
# ipa-getkeytab -s <ipa-server> -p host/<fqdn> -k /tmp/<host>.keytab
|
||||||
|
#
|
||||||
|
# 3. sops-encrypt the keytab as a binary secret from your admin machine:
|
||||||
|
# sops -e --input-type binary /tmp/<host>.keytab \
|
||||||
|
# > secrets/<host>.keytab
|
||||||
|
# Add secrets/<host>.keytab to .sops.yaml with the host's age key as a
|
||||||
|
# recipient (see the nix-cache.keytab entry for the pattern), then run:
|
||||||
|
# scripts/secrets/sync-host-keys.sh <target> # if not done yet
|
||||||
|
# sops updatekeys secrets/<host>.keytab
|
||||||
|
# Commit the encrypted file.
|
||||||
|
#
|
||||||
|
# 4. nixos-rebuild switch (or create-proxmox-resource.sh) — no further
|
||||||
|
# manual enrollment steps required.
|
||||||
|
#
|
||||||
|
# vars dependencies: homeDomain, ipaServer
|
||||||
|
|
||||||
|
{ keytabSopsFile, caCertFile }:
|
||||||
|
{ config, lib, pkgs, vars, ... }:
|
||||||
|
|
||||||
|
let
|
||||||
|
realm = lib.strings.toUpper vars.homeDomain;
|
||||||
|
fqdn = "${config.networking.hostName}.${vars.homeDomain}";
|
||||||
|
# "sweet.home" -> "dc=sweet,dc=home"
|
||||||
|
basedn = lib.strings.concatMapStringsSep "," (c: "dc=${c}") (lib.strings.splitString "." vars.homeDomain);
|
||||||
|
# security.ipa.certificate expects a derivation (package), not a raw path.
|
||||||
|
caCertPkg = pkgs.writeText "ipa-ca.crt" (builtins.readFile caCertFile);
|
||||||
|
in
|
||||||
|
{
|
||||||
|
security.ipa = {
|
||||||
|
enable = true;
|
||||||
|
domain = vars.homeDomain;
|
||||||
|
realm = realm;
|
||||||
|
server = vars.ipaServer;
|
||||||
|
certificate = caCertPkg;
|
||||||
|
basedn = basedn;
|
||||||
|
ipaHostname = fqdn;
|
||||||
|
offlinePasswords = true;
|
||||||
|
cacheCredentials = true;
|
||||||
|
};
|
||||||
|
|
||||||
|
# Host keytab: pre-provisioned on the IPA server, sops-encrypted binary.
|
||||||
|
# Placed at /etc/krb5.keytab before SSSD starts so the host authenticates
|
||||||
|
# to IPA without running ipa-client-install.
|
||||||
|
sops.secrets."ipa-host-keytab" = {
|
||||||
|
sopsFile = keytabSopsFile;
|
||||||
|
format = "binary";
|
||||||
|
path = "/etc/krb5.keytab";
|
||||||
|
owner = "root";
|
||||||
|
group = "root";
|
||||||
|
mode = "0600";
|
||||||
|
restartUnits = [ "sssd.service" ];
|
||||||
|
};
|
||||||
|
}
|
||||||
@@ -17,6 +17,7 @@
|
|||||||
dockerIp = "192.168.2.225"; # docker Proxmox VM LAN IP
|
dockerIp = "192.168.2.225"; # docker Proxmox VM LAN IP
|
||||||
pbsIp = "192.168.2.244"; # Proxmox Backup Server LAN IP (not NixOS-managed)
|
pbsIp = "192.168.2.244"; # Proxmox Backup Server LAN IP (not NixOS-managed)
|
||||||
domainControllerIp = "192.168.2.253"; # FreeIPA domain controller / primary DNS (not NixOS-managed)
|
domainControllerIp = "192.168.2.253"; # FreeIPA domain controller / primary DNS (not NixOS-managed)
|
||||||
|
ipaServer = "ipa.sweet.home"; # FreeIPA server hostname (used by security.ipa and Kerberos; must be a resolvable FQDN, not an IP — update if different)
|
||||||
|
|
||||||
# Cross-host references (LAN hostnames/users other hosts reach over the network)
|
# Cross-host references (LAN hostnames/users other hosts reach over the network)
|
||||||
nixCacheHost = "nix-cache"; # substituter/remote-builder hostname
|
nixCacheHost = "nix-cache"; # substituter/remote-builder hostname
|
||||||
|
|||||||
Reference in New Issue
Block a user