Improve usage of roles. It should be much easier to read and use now.

This commit is contained in:
Zuckerberg 2025-03-29 22:48:14 -07:00
parent 1f9fbd87ac
commit 8c4dc9cb74
8 changed files with 152 additions and 128 deletions

View File

@ -100,7 +100,5 @@
security.acme.defaults.email = "zuckerberg@neet.dev"; security.acme.defaults.email = "zuckerberg@neet.dev";
# Enable Desktop Environment if this is a PC (machine role is "personal") # Enable Desktop Environment if this is a PC (machine role is "personal")
de.enable = ( de.enable = lib.mkDefault (config.thisMachine.hasRole."personal");
builtins.elem config.networking.hostName config.machines.roles.personal
);
} }

View File

@ -5,20 +5,9 @@
let let
machines = config.machines.hosts; machines = config.machines.hosts;
in
{
imports = [
./ssh.nix
./roles.nix
];
options.machines = { hostOptionsSubmoduleType = lib.types.submodule {
hosts = lib.mkOption {
type = lib.types.attrsOf
(lib.types.submodule {
options = { options = {
hostNames = lib.mkOption { hostNames = lib.mkOption {
type = lib.types.listOf lib.types.str; type = lib.types.listOf lib.types.str;
description = '' description = ''
@ -26,21 +15,18 @@ in
Used for automatically trusting hosts for ssh connections. Used for automatically trusting hosts for ssh connections.
''; '';
}; };
arch = lib.mkOption { arch = lib.mkOption {
type = lib.types.enum [ "x86_64-linux" "aarch64-linux" ]; type = lib.types.enum [ "x86_64-linux" "aarch64-linux" ];
description = '' description = ''
The architecture of this machine. The architecture of this machine.
''; '';
}; };
systemRoles = lib.mkOption { systemRoles = lib.mkOption {
type = lib.types.listOf lib.types.str; # TODO: maybe use an enum? type = lib.types.listOf lib.types.str; # TODO: maybe use an enum?
description = '' description = ''
The set of roles this machine holds. Affects secrets available. (TODO add service config as well using this info) The set of roles this machine holds. Affects secrets available. (TODO add service config as well using this info)
''; '';
}; };
hostKey = lib.mkOption { hostKey = lib.mkOption {
type = lib.types.str; type = lib.types.str;
description = '' description = ''
@ -48,7 +34,6 @@ in
and for decrypting secrets with agenix. and for decrypting secrets with agenix.
''; '';
}; };
remoteUnlock = lib.mkOption { remoteUnlock = lib.mkOption {
default = null; default = null;
type = lib.types.nullOr (lib.types.submodule { type = lib.types.nullOr (lib.types.submodule {
@ -80,7 +65,6 @@ in
}; };
}); });
}; };
userKeys = lib.mkOption { userKeys = lib.mkOption {
default = [ ]; default = [ ];
type = lib.types.listOf lib.types.str; type = lib.types.listOf lib.types.str;
@ -90,7 +74,6 @@ in
TODO: consider auto populating other programs that use ssh keys such as gitea TODO: consider auto populating other programs that use ssh keys such as gitea
''; '';
}; };
deployKeys = lib.mkOption { deployKeys = lib.mkOption {
default = [ ]; default = [ ];
type = lib.types.listOf lib.types.str; type = lib.types.listOf lib.types.str;
@ -98,17 +81,30 @@ in
The list of deployment keys. Each key here can be used to log into all other systems as `root`. The list of deployment keys. Each key here can be used to log into all other systems as `root`.
''; '';
}; };
configurationPath = lib.mkOption { configurationPath = lib.mkOption {
type = lib.types.path; type = lib.types.path;
description = '' description = ''
The path to this machine's configuration directory. The path to this machine's configuration directory.
''; '';
}; };
};
};
in
{
imports = [
./ssh.nix
./roles.nix
];
options.machines = {
hosts = lib.mkOption {
type = lib.types.attrsOf hostOptionsSubmoduleType;
}; };
});
}; };
options.thisMachine.config = lib.mkOption {
# For ease of use, a direct copy of the host config from machines.hosts.${hostName}
type = hostOptionsSubmoduleType;
}; };
config = { config = {
@ -196,5 +192,12 @@ in
builtins.map (p: { "${dirName p}" = p; }) propFiles; builtins.map (p: { "${dirName p}" = p; }) propFiles;
in in
properties ../../machines; properties ../../machines;
# Don't try to evaluate "thisMachine" when reflecting using moduleless.nix.
# When evaluated by moduleless.nix this will fail due to networking.hostName not
# existing. This is because moduleless.nix is not intended for reflection from the
# perspective of a perticular machine but is instead intended for reflecting on
# the properties of all machines as a whole system.
thisMachine.config = config.machines.hosts.${config.networking.hostName};
}; };
} }

View File

@ -1,19 +1,55 @@
{ config, lib, ... }: { config, lib, ... }:
# Maps roles to their hosts # Maps roles to their hosts.
# machines.withRole = {
# personal = [
# "machine1" "machine3"
# ];
# cache = [
# "machine2"
# ];
# };
#
# A list of all possible roles
# machines.allRoles = [
# "personal"
# "cache"
# ];
#
# For each role has true or false if the current machine has that role
# thisMachine.hasRole = {
# personal = true;
# cache = false;
# };
{ {
options.machines.roles = lib.mkOption { options.machines.withRole = lib.mkOption {
type = lib.types.attrsOf (lib.types.listOf lib.types.str); type = lib.types.attrsOf (lib.types.listOf lib.types.str);
}; };
options.machines.allRoles = lib.mkOption {
type = lib.types.listOf lib.types.str;
};
options.thisMachine.hasRole = lib.mkOption {
type = lib.types.attrsOf lib.types.bool;
};
config = { config = {
machines.roles = lib.zipAttrs machines.withRole = lib.zipAttrs
(lib.mapAttrsToList (lib.mapAttrsToList
(host: cfg: (host: cfg:
lib.foldl (lib.mergeAttrs) { } lib.foldl (lib.mergeAttrs) { }
(builtins.map (role: { ${role} = host; }) (builtins.map (role: { ${role} = host; })
cfg.systemRoles)) cfg.systemRoles))
config.machines.hosts); config.machines.hosts);
machines.allRoles = lib.attrNames config.machines.withRole;
thisMachine.hasRole = lib.mapAttrs
(role: cfg:
builtins.elem config.networking.hostName config.machines.withRole.${role}
)
config.machines.withRole;
}; };
} }

View File

@ -39,6 +39,6 @@ in
builtins.map builtins.map
(host: machines.hosts.${host}.hostKey) (host: machines.hosts.${host}.hostKey)
hosts) hosts)
machines.roles; machines.withRole;
}; };
} }

View File

@ -1,18 +1,14 @@
{ config, lib, ... }: { config, lib, ... }:
let let
builderRole = "nix-builder";
builderUserName = "nix-builder"; builderUserName = "nix-builder";
machinesByRole = role: lib.filterAttrs (hostname: cfg: builtins.elem role cfg.systemRoles) config.machines.hosts; builderRole = "nix-builder";
otherMachinesByRole = role: lib.filterAttrs (hostname: cfg: hostname != config.networking.hostName) (machinesByRole role); builders = config.machines.withRole.${builderRole};
thisMachineHasRole = role: builtins.hasAttr config.networking.hostName (machinesByRole role); thisMachineIsABuilder = config.thisMachine.hasRole.${builderRole};
builders = machinesByRole builderRole;
thisMachineIsABuilder = thisMachineHasRole builderRole;
# builders don't include themselves as a remote builder # builders don't include themselves as a remote builder
otherBuilders = lib.filterAttrs (hostname: cfg: hostname != config.networking.hostName) builders; otherBuilders = lib.filter (hostname: hostname != config.networking.hostName) builders;
in in
lib.mkMerge [ lib.mkMerge [
# configure builder # configure builder
@ -40,9 +36,9 @@ lib.mkMerge [
nix.distributedBuilds = true; nix.distributedBuilds = true;
nix.buildMachines = builtins.map nix.buildMachines = builtins.map
(builderCfg: { (builderHostname: {
hostName = builtins.elemAt builderCfg.hostNames 0; hostName = builderHostname;
system = builderCfg.arch; system = config.machines.hosts.${builderHostname}.arch;
protocol = "ssh-ng"; protocol = "ssh-ng";
sshUser = builderUserName; sshUser = builderUserName;
sshKey = "/etc/ssh/ssh_host_ed25519_key"; sshKey = "/etc/ssh/ssh_host_ed25519_key";
@ -50,7 +46,7 @@ lib.mkMerge [
speedFactor = 10; speedFactor = 10;
supportedFeatures = [ "nixos-test" "benchmark" "big-parallel" "kvm" ]; supportedFeatures = [ "nixos-test" "benchmark" "big-parallel" "kvm" ];
}) })
(builtins.attrValues otherBuilders); otherBuilders;
# It is very likely that the builder's internet is faster or just as fast # It is very likely that the builder's internet is faster or just as fast
nix.extraOptions = '' nix.extraOptions = ''

View File

@ -9,10 +9,7 @@
# TODO: skipping running inside of nixos container for now because of issues getting docker/podman running # TODO: skipping running inside of nixos container for now because of issues getting docker/podman running
let let
runnerRole = "gitea-actions-runner"; thisMachineIsARunner = config.thisMachine.hasRole."gitea-actions-runner";
runners = config.machines.roles.${runnerRole};
thisMachineIsARunner = builtins.elem config.networking.hostName runners;
containerName = "gitea-runner"; containerName = "gitea-runner";
in in
{ {

View File

@ -84,13 +84,11 @@
outputs = { self, nixpkgs, ... }@inputs: outputs = { self, nixpkgs, ... }@inputs:
let let
machines = (import ./common/machine-info/moduleless.nix machineHosts = (import ./common/machine-info/moduleless.nix
{ {
inherit nixpkgs; inherit nixpkgs;
assertionsModule = "${nixpkgs}/nixos/modules/misc/assertions.nix"; assertionsModule = "${nixpkgs}/nixos/modules/misc/assertions.nix";
}).machines; }).machines.hosts;
machineHosts = machines.hosts;
machineRoles = machines.roles;
in in
{ {
nixosConfigurations = nixosConfigurations =
@ -115,10 +113,7 @@
home-manager.useGlobalPkgs = true; home-manager.useGlobalPkgs = true;
home-manager.useUserPackages = true; home-manager.useUserPackages = true;
home-manager.users.googlebot = import ./home/googlebot.nix { home-manager.users.googlebot = import ./home/googlebot.nix;
inherit hostname;
inherit machineRoles;
};
}; };
# because nixos specialArgs doesn't work for containers... need to pass in inputs a different way # because nixos specialArgs doesn't work for containers... need to pass in inputs a different way

View File

@ -1,9 +1,8 @@
{ hostname, machineRoles }: { config, lib, pkgs, osConfig, ... }:
{ config, lib, pkgs, ... }:
let let
# Check if the current machine has the role "personal" # Check if the current machine has the role "personal"
thisMachineIsPersonal = builtins.elem hostname machineRoles.personal; thisMachineIsPersonal = osConfig.thisMachine.hasRole."personal";
in in
{ {
home.username = "googlebot"; home.username = "googlebot";