Wire sops-nix into the shared base config as unconditional plumbing, with a two-tier age identity model: an admin identity held outside the repo, and a per-host identity generated on the machine and kept on its encrypted root. Both `sshKeyPaths` defaults are cleared so the SSH host keys stay out of the decryption path and remain free to become secrets in their own right. The primary user's password hash moves into a shared secrets file encrypted to admin plus neogaia, consumed through `hashedPasswordFile` and decrypted before accounts are created. This needs `users.mutableUsers = false`: NixOS applies a declared hash to an already-existing account only when that flag is false, so at the default the hand-set password would have been kept and the change would have been inert. Root consequently has no password and is locked; sudo from wheel is the way in, and generation rollback remains the recovery path.
77 lines
1.7 KiB
Nix
77 lines
1.7 KiB
Nix
{
|
|
lib,
|
|
inputs,
|
|
self,
|
|
}:
|
|
let
|
|
inherit (lib)
|
|
attrNames
|
|
filterAttrs
|
|
genAttrs
|
|
flatten
|
|
hasSuffix
|
|
mapAttrsToList
|
|
;
|
|
|
|
# Recursively collect every `.nix` file under `dir` as a flat list, for a
|
|
# module's `imports`.
|
|
collectNixFiles =
|
|
dir:
|
|
flatten (
|
|
mapAttrsToList (
|
|
name: type:
|
|
let
|
|
path = dir + "/${name}";
|
|
in
|
|
if type == "directory" then
|
|
collectNixFiles path
|
|
else if type == "regular" && hasSuffix ".nix" name then
|
|
[ path ]
|
|
else
|
|
[ ]
|
|
) (builtins.readDir dir)
|
|
);
|
|
|
|
# Build one host: every module is imported unconditionally (inert until its
|
|
# `enable` flag is set), alongside home-manager, chaotic, the shared base, and
|
|
# the host's own directory.
|
|
mkHost =
|
|
{
|
|
hostName,
|
|
system ? "x86_64-linux",
|
|
}:
|
|
inputs.nixpkgs.lib.nixosSystem {
|
|
inherit system;
|
|
specialArgs = {
|
|
inherit inputs;
|
|
my = self.lib;
|
|
};
|
|
modules =
|
|
(collectNixFiles (self + "/modules"))
|
|
++ [
|
|
inputs.home-manager.nixosModules.home-manager
|
|
inputs.chaotic.nixosModules.default
|
|
inputs.disko.nixosModules.disko
|
|
inputs.sops-nix.nixosModules.sops
|
|
(self + "/system")
|
|
(self + "/hosts/${hostName}")
|
|
{ networking.hostName = hostName; }
|
|
];
|
|
};
|
|
|
|
# Discover every host (a subdirectory of `hostsDir`) and build each one.
|
|
mkHosts =
|
|
hostsDir:
|
|
let
|
|
hostNames = attrNames (filterAttrs (_name: type: type == "directory") (builtins.readDir hostsDir));
|
|
in
|
|
genAttrs hostNames (hostName: mkHost { inherit hostName; });
|
|
in
|
|
{
|
|
inherit
|
|
collectNixFiles
|
|
mkHost
|
|
mkHosts
|
|
;
|
|
}
|