diff --git a/.sops.yaml b/.sops.yaml index 462abf5..c044d9c 100644 --- a/.sops.yaml +++ b/.sops.yaml @@ -127,6 +127,16 @@ creation_rules: # scripts/secrets/sync-host-keys.sh yet, so whichever variant is actually # deployed next needs its recipient added here (and `sops updatekeys` rerun) # 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$ key_groups: - age: diff --git a/hosts/tailscale-router/host.nix b/hosts/tailscale-router/host.nix index 6198bf4..c95440c 100644 --- a/hosts/tailscale-router/host.nix +++ b/hosts/tailscale-router/host.nix @@ -6,10 +6,15 @@ name = "tailscale-router"; sopsFile = ../../secrets/tailscale-router.yaml; }) + (import ../../modules/ipa/client.nix { + keytabSopsFile = ../../secrets/tailscale-router.keytab; + caCertFile = ../../certs/ipa-ca.crt; + }) ]; networking = { hostName = "tailscale-router"; + domain = vars.homeDomain; useDHCP = false; interfaces.${vars.lxcLanInterface}.ipv4.addresses = [{ address = vars.tailscaleRouterIp; diff --git a/modules/ipa/client.nix b/modules/ipa/client.nix index db83042..1aa8deb 100644 --- a/modules/ipa/client.nix +++ b/modules/ipa/client.nix @@ -60,6 +60,14 @@ in cacheCredentials = true; }; + # Fetch SSH public keys from IPA so users can log in with the key stored + # in their IPA profile rather than needing ~/.ssh/authorized_keys on every + # host. sss_ssh_authorizedkeys queries SSSD (which queries IPA LDAP). + services.openssh.extraConfig = '' + AuthorizedKeysCommand ${pkgs.sssd}/bin/sss_ssh_authorizedkeys %u + AuthorizedKeysCommandUser nobody + ''; + # 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. diff --git a/secrets/tailscale-router.keytab b/secrets/tailscale-router.keytab new file mode 100644 index 0000000..9f8c5d0 --- /dev/null +++ b/secrets/tailscale-router.keytab @@ -0,0 +1,26 @@ +{ + "data": "ENC[AES256_GCM,data:+/1AAVha+86abQIX8tebqPJ6BIcCCiTJgPe0OfFOwA2Mcx0NJdiPtQgyeo3G8fAolIQOFkk5reL+GUhlOz4iEbPOCWwFCckdH0tXiCiVcD35qQNMRurY8HmpM5FWFnyzBkKuyNZ8okPuo2+fA3NQh3gs94rpm2kBsfS18xvrlv9b8u1JvAxlH6GRMN1uUgFGmOXlpGAVjDUFiKUHN8tRSZpsxG0aKKPBZ82JdKgYfCiCQifS1366gIFrsjGriUC+P8wkadRnD1JE2ZAGSL7wJLaRmzA4LAMGXFGbitOsFxKxX3q8VWEXaaL+9h4rTe0WCrvmgDM9NUeVHpfRiJrLvQgrFZMUxuZF66vQVsLybjIWpYYJcjC6nfR0U3lMa9gjzOTMPxm8HdGKC53FhLM1HiPoe1a2Nno283fV0uaByMPmo257O6l1CXqb6KoZOGFccm7fKR/VnFAS1AInF+szI7/r+UcaTW6LwYeV3OwLE4a8b4OiqTLgCu6v,iv:kUlVXF4Yl5HGvoLwu9loiuuDVtz0kARRiUU3K+BPL2A=,tag:pVaGzQAX9Etoqc5XMGmNeg==,type:str]", + "sops": { + "age": [ + { + "enc": "-----BEGIN AGE ENCRYPTED FILE-----\nYWdlLWVuY3J5cHRpb24ub3JnL3YxCi0+IFgyNTUxOSB6OUVUdkoxM1M5THlYZ1ky\nYWJ5RjhtRGoxTldwRkI2T1p6dHR4Y3gwR1ZrCjRDS1hTM01lZ0FSalBYQ1B0bENs\nUytXNmlrUkV4TmJkMUM1QW1ZaExIcGMKLS0tIHdHKzdEcUxvM0ZYUEp0a2d6SHp5\nYXQydy9uNG15V2FhUUd4NEFTMTNNMEUKkIzKEoYzoVs+nhnpkHFgDkQqrWykatND\ntsNxcr1SXSKeEW1m/QpXZnn/aW3zSQR09PqOHf7PYU47/AdkwrUaAg==\n-----END AGE ENCRYPTED FILE-----\n", + "recipient": "age1njap586hc0q43kr03g6c8eqhdsmk8zcafkl3f83xwlc2gqhlmfgs4tmwad" + }, + { + "enc": "-----BEGIN AGE ENCRYPTED FILE-----\nYWdlLWVuY3J5cHRpb24ub3JnL3YxCi0+IFgyNTUxOSByZENrck42dWJjR2hYUVBl\ncERtRjR6dTdING5nWXlBc3o3eXFhaSs5NkFRCk43QXFUeTBJR0U5dG9YTDRmQ0Yx\naEo2blUvUXNZY3dpbEZRTUx1elNzdkkKLS0tIHJwNjRNM3V6WktWZ1BlUUtLRTNI\nMTVEbCtYbllIbTdxTGozWUluS3pIRXMKZCruDIkD/JofdAHWgPuaaKTDsz408ZkY\n77mhO8J+kd03qwt6qhFC5KF1lyjhwEnqrOE195+R/8Yl7hA/DsL2ZQ==\n-----END AGE ENCRYPTED FILE-----\n", + "recipient": "age1k7d2du5mejsmv5rzavm4xwgpthqvcfsehduquv28nzs53zppa3kqngfxq2" + }, + { + "enc": "-----BEGIN AGE ENCRYPTED FILE-----\nYWdlLWVuY3J5cHRpb24ub3JnL3YxCi0+IFgyNTUxOSBxaC95RjYybzVlU2tYdHdU\naGJ4M2IvNkJwVlNIU0VCZEFUZk5VaksrVnpFCmJXS3luTG9WejR0Rk9DbHA3dngy\nRElFWjU1N2xuc3JaKzQ0L0U2Yktib1kKLS0tIFlrK3F0ZFh5Ync3ejVWMzRKTUx2\nZDhxdEMwa3B4TFZUcWdTdktDeGt1QUEKfgYnK2lW3cZuJGaw+bAKDipLuC4S5vK2\nxK2eJB5TP/xXrp0F3lx9sc2b1FOY9Vt9IQ7zVlBqJFkzJrcw8zYJJw==\n-----END AGE ENCRYPTED FILE-----\n", + "recipient": "age1zhfyuzlq40reuqlr34gf77852nhs3t6mqfzrqmas8z6sxk7tcfhsungrm0" + }, + { + "enc": "-----BEGIN AGE ENCRYPTED FILE-----\nYWdlLWVuY3J5cHRpb24ub3JnL3YxCi0+IFgyNTUxOSBwOGFkSXNxTUIzLzR1Skk5\nMGZveHFDN3YwVmpwT3VTYkppWEU1aGVpdkhRCjZtRC92bVphd0ZFbzFxVzRUcGk4\nMUd1aWdEbFRaM01FT25JSVRoMTRsNUUKLS0tIDAybmcrYjFVWkFYaGY5TFZjcjFO\nYlZoQjJjN2lFNzd4RlJuSHFlRlNCOFEKgUIPnL2/OJgz9oMYt86/llHa7adTkhs6\n8yGYGV1wtU9aYtUMIR907SfYyZ6M4z8jH2wwzpQLbwQQMLgkejl1jg==\n-----END AGE ENCRYPTED FILE-----\n", + "recipient": "age1f7usptjx9rv4rxauasve200gxtdt9jkqhhdqstlf20wvlm7u75rsjfw50m" + } + ], + "lastmodified": "2026-07-27T23:14:51Z", + "mac": "ENC[AES256_GCM,data:CYhzR0Y29GXvWUBbb13s16v9hDQ4k4Xmd4FUpcyNtHe0L/IrDGkx1WHzAohNGZjGMNB9W3BgiEH85OoOo8r1F82El4/8s2prEJi8AARvQU3+2cmRjjhNCCYQWmJkoF/cZNpw6nVyWzZdfUpPvHjbuf6utlI3rtR0qiCpSo/32S0=,iv:XLKTU2Ute4jMkfRAbXiVGxqP9+fjSs6HwRv1JfTTe7w=,tag:oIqS/1HWQZ7mLWaO7GwLFA==,type:str]", + "version": "3.13.2" + } +}