Archived
Worktree ipa common config #83
+59
-26
@@ -63,16 +63,6 @@ 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:
|
||||||
@@ -127,16 +117,6 @@ creation_rules:
|
|||||||
# scripts/secrets/sync-host-keys.sh yet, so whichever variant is actually
|
# scripts/secrets/sync-host-keys.sh yet, so whichever variant is actually
|
||||||
# deployed next needs its recipient added here (and `sops updatekeys` rerun)
|
# deployed next needs its recipient added here (and `sops updatekeys` rerun)
|
||||||
# before it can decrypt this.
|
# before it can decrypt this.
|
||||||
# Host keytab for tailscale-router FreeIPA enrollment (binary sops file).
|
|
||||||
# Generated by scripts/ipa/create-nixos-ipa-host-account.sh.
|
|
||||||
- path_regex: secrets/tailscale-router\.keytab$
|
|
||||||
key_groups:
|
|
||||||
- age:
|
|
||||||
- *admin
|
|
||||||
- *lxc-tailscale-router
|
|
||||||
- *proxmox-tailscale-router
|
|
||||||
- *linode-tailscale-router
|
|
||||||
|
|
||||||
- path_regex: secrets/gui\.yaml$
|
- path_regex: secrets/gui\.yaml$
|
||||||
key_groups:
|
key_groups:
|
||||||
- age:
|
- age:
|
||||||
@@ -146,19 +126,72 @@ creation_rules:
|
|||||||
- *linode-gui
|
- *linode-gui
|
||||||
- *proxmox-gui
|
- *proxmox-gui
|
||||||
|
|
||||||
# Host keytab for tailscale-router FreeIPA enrollment (binary sops file).
|
# IPA host keytabs (binary sops files).
|
||||||
# Generated by scripts/ipa/create-nixos-ipa-host-account.sh.
|
# Each keytab is encrypted for all platform variants of that host so any
|
||||||
|
# deployed variant can decrypt it at boot. Run
|
||||||
|
# scripts/ipa/create-nixos-ipa-host-account.sh <hostname> to enroll a new
|
||||||
|
# host and produce the keytab; this section is updated by that script.
|
||||||
|
|
||||||
|
- path_regex: secrets/nix-cache\.keytab$
|
||||||
|
key_groups:
|
||||||
|
- age:
|
||||||
|
- *admin
|
||||||
|
- *linode-nix-cache
|
||||||
|
- *lxc-nix-cache
|
||||||
|
- *proxmox-nix-cache
|
||||||
|
|
||||||
- path_regex: secrets/tailscale-router\.keytab$
|
- path_regex: secrets/tailscale-router\.keytab$
|
||||||
key_groups:
|
key_groups:
|
||||||
- age:
|
- age:
|
||||||
- *admin
|
- *admin
|
||||||
|
- *linode-tailscale-router
|
||||||
- *lxc-tailscale-router
|
- *lxc-tailscale-router
|
||||||
- *proxmox-tailscale-router
|
- *proxmox-tailscale-router
|
||||||
- *linode-tailscale-router
|
|
||||||
|
|
||||||
# Host keytab for nixos.sweet.home FreeIPA enrollment (binary sops file).
|
- path_regex: secrets/pxe-boot\.keytab$
|
||||||
# Generated by scripts/ipa/create-nixos-ipa-host-account.sh.
|
|
||||||
- path_regex: secrets/nixos.sweet.home\.keytab$
|
|
||||||
key_groups:
|
key_groups:
|
||||||
- age:
|
- age:
|
||||||
- *admin
|
- *admin
|
||||||
|
- *lxc-pxe-boot
|
||||||
|
- *proxmox-pxe-boot
|
||||||
|
|
||||||
|
# nixos = the workstation (hosts/nixos/host.nix). All gui platform variants
|
||||||
|
# share the hostname "nixos" and must be able to decrypt at boot.
|
||||||
|
- path_regex: secrets/nixos\.keytab$
|
||||||
|
key_groups:
|
||||||
|
- age:
|
||||||
|
- *admin
|
||||||
|
- *baremetal-gui
|
||||||
|
- *lxc-gui
|
||||||
|
- *proxmox-gui
|
||||||
|
- *linode-gui
|
||||||
|
|
||||||
|
- path_regex: secrets/server\.keytab$
|
||||||
|
key_groups:
|
||||||
|
- age:
|
||||||
|
- *admin
|
||||||
|
- *linode-server
|
||||||
|
- *lxc-server
|
||||||
|
- *proxmox-server
|
||||||
|
|
||||||
|
- path_regex: secrets/docker\.keytab$
|
||||||
|
key_groups:
|
||||||
|
- age:
|
||||||
|
- *admin
|
||||||
|
- *linode-docker
|
||||||
|
- *lxc-docker
|
||||||
|
- *proxmox-docker
|
||||||
|
|
||||||
|
- path_regex: secrets/tor-relay\.keytab$
|
||||||
|
key_groups:
|
||||||
|
- age:
|
||||||
|
- *admin
|
||||||
|
- *lxc-tor-relay
|
||||||
|
|
||||||
|
- path_regex: secrets/nix-minimal\.keytab$
|
||||||
|
key_groups:
|
||||||
|
- age:
|
||||||
|
- *admin
|
||||||
|
- *lxc-minimal
|
||||||
|
- *proxmox-minimal
|
||||||
|
- *linode-minimal
|
||||||
|
|||||||
@@ -6,15 +6,10 @@
|
|||||||
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;
|
||||||
|
|||||||
@@ -6,15 +6,10 @@
|
|||||||
name = "tailscale-router";
|
name = "tailscale-router";
|
||||||
sopsFile = ../../secrets/tailscale-router.yaml;
|
sopsFile = ../../secrets/tailscale-router.yaml;
|
||||||
})
|
})
|
||||||
(import ../../modules/ipa/client.nix {
|
|
||||||
keytabSopsFile = ../../secrets/tailscale-router.keytab;
|
|
||||||
caCertFile = ../../certs/ipa-ca.crt;
|
|
||||||
})
|
|
||||||
];
|
];
|
||||||
|
|
||||||
networking = {
|
networking = {
|
||||||
hostName = "tailscale-router";
|
hostName = "tailscale-router";
|
||||||
domain = vars.homeDomain;
|
|
||||||
useDHCP = false;
|
useDHCP = false;
|
||||||
interfaces.${vars.lxcLanInterface}.ipv4.addresses = [{
|
interfaces.${vars.lxcLanInterface}.ipv4.addresses = [{
|
||||||
address = vars.tailscaleRouterIp;
|
address = vars.tailscaleRouterIp;
|
||||||
|
|||||||
@@ -6,6 +6,7 @@
|
|||||||
# Include the results of the hardware scan.
|
# Include the results of the hardware scan.
|
||||||
# ./hardware-configuration.nix
|
# ./hardware-configuration.nix
|
||||||
./set-locale.nix
|
./set-locale.nix
|
||||||
|
../ipa/client.nix
|
||||||
];
|
];
|
||||||
# Use the GRUB 2 boot loader.
|
# Use the GRUB 2 boot loader.
|
||||||
# boot.loader.grub.enable = true;
|
# boot.loader.grub.enable = true;
|
||||||
|
|||||||
+18
-32
@@ -1,34 +1,15 @@
|
|||||||
# Fully declarative FreeIPA domain membership.
|
# Fully declarative FreeIPA domain membership.
|
||||||
#
|
#
|
||||||
# Configures security.ipa (SSSD, Kerberos, PAM, NSSwitch) and places a
|
# Imported by modules/common/configuration.nix — no per-host wiring needed.
|
||||||
# pre-provisioned host keytab via sops-nix so no imperative ipa-client-install
|
# Enables itself automatically on any host that has a sops-encrypted keytab
|
||||||
# step is needed after deployment.
|
# at secrets/<hostname>.keytab; is a no-op for all other hosts.
|
||||||
#
|
#
|
||||||
# Usage (in a host.nix imports list):
|
# To enroll a new host:
|
||||||
# (import ../../modules/ipa/client.nix {
|
# 0. scripts/secrets/sync-host-keys.sh <flake-target>
|
||||||
# keytabSopsFile = ../../secrets/<hostname>.keytab;
|
# 1. scripts/ipa/create-nixos-ipa-host-account.sh [--ip <addr>] <hostname>
|
||||||
# caCertFile = ../../certs/ipa-ca.crt; # already committed — do not re-fetch
|
# (adds .sops.yaml rule, runs ipa host-add, encrypts keytab in one step)
|
||||||
# })
|
# 2. git add secrets/<hostname>.keytab .sops.yaml && git commit
|
||||||
#
|
# 3. Deploy — no further steps required.
|
||||||
# The host.nix networking block must also set:
|
|
||||||
# networking.domain = vars.homeDomain; # needed for Kerberos FQDN
|
|
||||||
# networking.nameservers = [ vars.domainControllerIp ]; # IPA DNS
|
|
||||||
#
|
|
||||||
# One-time operator setup per host (do this BEFORE deploying):
|
|
||||||
#
|
|
||||||
# 0. Generate SSH host keys and the host's age key for sops:
|
|
||||||
# scripts/secrets/sync-host-keys.sh <flake-target>
|
|
||||||
# This must run before step 1 so the host age key is in .sops.yaml
|
|
||||||
# and the keytab can be encrypted for the host to read at boot.
|
|
||||||
#
|
|
||||||
# 1. Add the IPA host account and produce the sops-encrypted keytab:
|
|
||||||
# scripts/ipa/create-nixos-ipa-host-account.sh [--ip <addr>] <hostname>
|
|
||||||
# The script handles ipa host-add, ipa-getkeytab, .sops.yaml patching,
|
|
||||||
# and sops encryption in one step. See the script header for details.
|
|
||||||
#
|
|
||||||
# 2. Wire up the host (see "Usage" above), then deploy:
|
|
||||||
# nixos-rebuild switch (or create-proxmox-resource.sh)
|
|
||||||
# No further manual enrollment steps are required after deployment.
|
|
||||||
#
|
#
|
||||||
# Manual fallback (if the script isn't usable):
|
# Manual fallback (if the script isn't usable):
|
||||||
# a. On the FreeIPA server: ipa host-add <fqdn> [--ip-address=<ip>] --force
|
# a. On the FreeIPA server: ipa host-add <fqdn> [--ip-address=<ip>] --force
|
||||||
@@ -40,18 +21,23 @@
|
|||||||
#
|
#
|
||||||
# vars dependencies: homeDomain, ipaServer, domainControllerIp
|
# vars dependencies: homeDomain, ipaServer, domainControllerIp
|
||||||
|
|
||||||
{ keytabSopsFile, caCertFile }:
|
|
||||||
{ config, lib, pkgs, vars, ... }:
|
{ config, lib, pkgs, vars, ... }:
|
||||||
|
|
||||||
let
|
let
|
||||||
|
keytabPath = ../../secrets + "/${config.networking.hostName}.keytab";
|
||||||
|
enabled = builtins.pathExists keytabPath;
|
||||||
|
|
||||||
realm = lib.strings.toUpper vars.homeDomain;
|
realm = lib.strings.toUpper vars.homeDomain;
|
||||||
fqdn = "${config.networking.hostName}.${vars.homeDomain}";
|
fqdn = "${config.networking.hostName}.${vars.homeDomain}";
|
||||||
# "sweet.home" -> "dc=sweet,dc=home"
|
# "sweet.home" -> "dc=sweet,dc=home"
|
||||||
basedn = lib.strings.concatMapStringsSep "," (c: "dc=${c}") (lib.strings.splitString "." vars.homeDomain);
|
basedn = lib.strings.concatMapStringsSep "," (c: "dc=${c}") (lib.strings.splitString "." vars.homeDomain);
|
||||||
# security.ipa.certificate expects a derivation (package), not a raw path.
|
# security.ipa.certificate expects a derivation (package), not a raw path.
|
||||||
caCertPkg = pkgs.writeText "ipa-ca.crt" (builtins.readFile caCertFile);
|
caCertPkg = pkgs.writeText "ipa-ca.crt" (builtins.readFile ../../certs/ipa-ca.crt);
|
||||||
in
|
in
|
||||||
{
|
lib.mkIf enabled {
|
||||||
|
networking.domain = lib.mkDefault vars.homeDomain;
|
||||||
|
networking.nameservers = lib.mkDefault [ vars.domainControllerIp ];
|
||||||
|
|
||||||
security.ipa = {
|
security.ipa = {
|
||||||
enable = true;
|
enable = true;
|
||||||
domain = vars.homeDomain;
|
domain = vars.homeDomain;
|
||||||
@@ -92,7 +78,7 @@ in
|
|||||||
# Placed at /etc/krb5.keytab before SSSD starts so the host authenticates
|
# Placed at /etc/krb5.keytab before SSSD starts so the host authenticates
|
||||||
# to IPA without running ipa-client-install.
|
# to IPA without running ipa-client-install.
|
||||||
sops.secrets."ipa-host-keytab" = {
|
sops.secrets."ipa-host-keytab" = {
|
||||||
sopsFile = keytabSopsFile;
|
sopsFile = keytabPath;
|
||||||
format = "binary";
|
format = "binary";
|
||||||
path = "/etc/krb5.keytab";
|
path = "/etc/krb5.keytab";
|
||||||
owner = "root";
|
owner = "root";
|
||||||
|
|||||||
@@ -1,14 +0,0 @@
|
|||||||
{
|
|
||||||
"data": "ENC[AES256_GCM,data:dY+YT+OIM3yk9MSfTEiiHQuBP12fLn2txqK2W4p2uLWxc/KY1wbvIwNE7ug2S27NH3w3jLqvlAIfII4pKxujNEQIZ7ylX+2J/F7finn6G8QnTJMFj20JQo7TSDOOOHcOsmjtb6C/07qCPjOUxQ58SiYH2+qDf5DbniNldcFGpWDkw9DbrYJ6G3Ugnfl5D6ZSCNjBjmTavEDFW9GPLBgmseaDycIung7Rz3MjNEx31LVTBnlztweqoQhpOTqWcLiXK+4YnVaNAiWyNOpFXeronWNU+fItntp5TxJInUdbQioZJ6+qUjk3ZHxuikKuGjEpORTeHptX8m3AxenPiKEvDzLuRN6lnGzcbuH8+DvKIwA06QUeLRYARAnbGujkfS24i2Zkm+HQq0ZK5Y/0d4OoHi9dX5YQo39mCAUJxN/+R3T4QdMVLi+eDnkbNNCwlsRyivhwl64SjGMvFq1uXl6+wGTQ0/Aj16dJR273l+WsSSu509Q0sVdwbE0u,iv:UnpS8KFuNVtdYa/eCMWtQlm9awwNDgMU3Cy5x7Vfycc=,tag:NlGOfcg59NdwXJJesTZ1/w==,type:str]",
|
|
||||||
"sops": {
|
|
||||||
"age": [
|
|
||||||
{
|
|
||||||
"enc": "-----BEGIN AGE ENCRYPTED FILE-----\nYWdlLWVuY3J5cHRpb24ub3JnL3YxCi0+IFgyNTUxOSB3ZEdXUEF4WWhPTGFFcWkr\nV3ZsVjl2SWQ0V3VjeHdjVmJ5ZnRGcExPN0ZzCjBZbTNVYWlqd0NnRHZmSUpObC9s\nUUhJQkp1em9YeGxGaHN3ZjE5eWFPSEEKLS0tIDdOSWU3b1pRSzBxMDhIWjJ4SDRO\nRVA5S3FVSFZGRm5XejdlQytCL2k3NmcKFeQ/nRcuEiFwgJEDj8z0KMeyEcFGbG35\nBcuM5cUh5qLArOQlONThmOt/Jepfo2dMPblQ6kd0zSqWfLNqZDg3Hw==\n-----END AGE ENCRYPTED FILE-----\n",
|
|
||||||
"recipient": "age1njap586hc0q43kr03g6c8eqhdsmk8zcafkl3f83xwlc2gqhlmfgs4tmwad"
|
|
||||||
}
|
|
||||||
],
|
|
||||||
"lastmodified": "2026-07-28T00:42:31Z",
|
|
||||||
"mac": "ENC[AES256_GCM,data:IiLoY24bVjvbsA3bd9a6/OEw0PDkHm1Uc3OiHG2FlOxAoPhb6zvE5t2tpZyqeT2goIYv+mr4C/y8BYSsVcZr1FtgqwYx7Y5eiAq9uVzFQ838TDN5ndgkKYrbyPwHSKCHCrOPZ/jDiQTSSO/dv1R8cQHfBf8kX5GEt6ovtGvI2AY=,iv:PctMMNSv0iPZYATsACcQ0aqgFME7xGGCD915k/RiuEI=,tag:Pxaet5zPXIYicExNRFyzGA==,type:str]",
|
|
||||||
"version": "3.13.2"
|
|
||||||
}
|
|
||||||
}
|
|
||||||
@@ -0,0 +1,22 @@
|
|||||||
|
{
|
||||||
|
"data": "ENC[AES256_GCM,data:Q++XWxg9tvY7ugT8+8FWCC5jgOfQ1+LYLsnqN0/WGxTf5XT2VmoXvszcE/ow2BUOBG3qBTXS3OHYFPwmj1GgaBHB8rpdXX6+LveSBE2gmx1VR+NUDTxy+0/DBq411MK9n/J9eIYcybdFIE11biFSAob9EgfxBF5roCDXIPDPyVCSe6LyhNvqYPnGQsfHCbejSewLTcRQEiguP9BX96CpMPIpmaB9fHN25t5RWCgMI7MtacrRxRsyKg44+2FZstXdZrp2Wv9u86BxqdAFqtZE8qpPeGdrdzluZx9jhnw0wZPzHdKg5wS7/UrLCb0UxIQiDxDMDuuBuLGkKXfAhb6SGZU41wWAWYk548iGRUaG+79BO4HhRZNObOFvfsjpMXEfcH/Vbv/wHVY4OpJUPe/ZWK4wpL9YrY4nT0t62HH7MirOy1uhwLE50h2+6dHKj6ur5G7thkSqgzVWXQ==,iv:zaRBwS+gfXLhH30havn6Q2+oPWuLV3qBfbOj00kewlQ=,tag:Vr5iEQ2u+9YNahryhgzwSw==,type:str]",
|
||||||
|
"sops": {
|
||||||
|
"age": [
|
||||||
|
{
|
||||||
|
"enc": "-----BEGIN AGE ENCRYPTED FILE-----\nYWdlLWVuY3J5cHRpb24ub3JnL3YxCi0+IFgyNTUxOSArTGJnaVhleUtsWnlITE1s\nNmRCaW1QWTFNSG5LRFdmb1lzRlV5NWl3YTBNCmF6eUN6RkJBZzc0MmJJa0dKTW01\ncVh4K1VLR2lURUpKQXpxNGpQNnpSUlUKLS0tIFJONnJFWkNCR3pqalRsUW9POVBj\nQ0pFQ3ltKzBETTVXTW5sV1ppWTFJc1kKzxUboNZO+Nwn2eTWy11VP9w1pRswCHaJ\nE2dYU0oUOClVzc0oSuIJxraG6TPj1N4WGC24gS+UmpkmSuCiOeZBsw==\n-----END AGE ENCRYPTED FILE-----\n",
|
||||||
|
"recipient": "age1njap586hc0q43kr03g6c8eqhdsmk8zcafkl3f83xwlc2gqhlmfgs4tmwad"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"enc": "-----BEGIN AGE ENCRYPTED FILE-----\nYWdlLWVuY3J5cHRpb24ub3JnL3YxCi0+IFgyNTUxOSBDSmxNR1I3dUFKT0xUVG9h\nWkRIakNVeWRQOEN3blNRVjZlWHF4K2NRa0hBClRiOXlmTTJ4T2JTUEw2c1l0R2N2\nMnRwdDA5bEZlQWJRTm9vUmNKclBSU1EKLS0tIFcyeDFjbTZyVEVDUjN1VzU1VHly\nNWNDMW9rTXY2bHNWYVR0SmtMckovUzQKhTWr6yFVW9am3okCiIswwqR5+/p9OLmB\nWCgPtwoFaBt1RjUXPK4/eS4LlucR2K6V/mNMn4xVsnkIl193U9632g==\n-----END AGE ENCRYPTED FILE-----\n",
|
||||||
|
"recipient": "age16j42pdc5dr6wnj7xayhkqdj2rny9u68fcqejs50hqq42scssh4gsnrrnlt"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"enc": "-----BEGIN AGE ENCRYPTED FILE-----\nYWdlLWVuY3J5cHRpb24ub3JnL3YxCi0+IFgyNTUxOSA2ME9CbmVGcENRWksyL0pW\nOEJyUGhpbGMwWlBhVXBSeXQ2MW1EWnFuR0E4CnMwU0pjdk1YMzF5ZEhTVFlBaHZq\nam94UWVGbjhZSEx6VHBmem9JRWgwYzAKLS0tIHFJZWRyRjRHNzhXdDJSYWN3bDlR\nYVp3eGJWWkh3Y09ZWElyclZQN1ZSVFkKjR32//EcFAdMjVlNgky5zvVkwXwEN68D\nrkTuHKjiO5aV7yAQGPkdNw0UM0oRGF0u4YF3oOUcZfSvnKgDeoi2Zw==\n-----END AGE ENCRYPTED FILE-----\n",
|
||||||
|
"recipient": "age1ug787sgt6st6k82fgkrug2lzltw4qsukrrqqs3w27ewwqj8rg4hsxcmylz"
|
||||||
|
}
|
||||||
|
],
|
||||||
|
"lastmodified": "2026-07-28T00:27:46Z",
|
||||||
|
"mac": "ENC[AES256_GCM,data:AbJIHYcFpeanQsJ3x7RPL9Yjlg5BJgkepKax0fL9L/PpA03Antab93iUNG95Mp6k/duovp8Jm445lbuppDZq1dh9ij/deBa8GbzJ50wwEe9zMc3EwRKScpqZEhRPF7KlJsIjsHJyd8NkcI5ji49XkHb4Ae1//8zG5HpVgy+3b04=,iv:uxQCbMwMIfP5S1dbsvIx3F79YWEguxwox8T0YZvUBdc=,tag:3utjmBGDmPc8q4JjaXvCkA==,type:str]",
|
||||||
|
"version": "3.13.2"
|
||||||
|
}
|
||||||
|
}
|
||||||
Reference in New Issue
Block a user