Add secret spec & update host config

- Import secrets modules into main configuration
- Rename and rearrange host specification options
- Introduce new host options: desktop, shell, and pool
- Create secret spec with SSH, API, Docker, user, and firewall submodules
This commit is contained in:
Chris Toph 2025-04-22 21:07:07 -04:00
parent dc8ea6f5a9
commit 2f83f84270
4 changed files with 237 additions and 18 deletions

View file

@ -121,6 +121,12 @@
self.overlays.default
];
}
# Import secrets
./modules/common/secret-spec.nix
./secrets.nix
# Host-specific configuration
./hosts/nixos/${host}
];
};

View file

@ -3,6 +3,7 @@
{
# use path relative to the root of the project
relativeToRoot = lib.path.append ../.;
scanPaths =
path:
builtins.map (f: (path + "/${f}")) (

View file

@ -7,34 +7,36 @@
}:
{
options.hostSpec = {
username = lib.mkOption {
type = lib.types.str;
description = "The username of the host";
};
password = lib.mkOption {
type = lib.types.str;
description = "Password of the host";
};
hostName = lib.mkOption {
type = lib.types.str;
description = "The hostname of the host";
};
username = lib.mkOption {
type = lib.types.str;
description = "The username for the host's user";
};
password = lib.mkOption {
type = lib.types.str;
description = "Hashed password for the host's user";
};
email = lib.mkOption {
type = lib.types.attrsOf lib.types.str;
type = lib.types.str;
description = "The email of the user";
};
domain = lib.mkOption {
type = lib.types.str;
description = "The domain of the host";
};
userFullName = lib.mkOption {
type = lib.types.str;
description = "The full name of the user";
};
handle = lib.mkOption {
type = lib.types.str;
description = "The handle of the user (eg: github user)";
};
userFullName = lib.mkOption {
type = lib.types.str;
description = "The full name of the user";
};
home = lib.mkOption {
type = lib.types.str;
description = "The home directory of the user";
@ -44,20 +46,49 @@
in
if pkgs.stdenv.isLinux then "/home/${user}" else "/Users/${user}";
};
isARM = lib.mkOption {
type = lib.types.bool;
default = false;
description = "Used to indicate a host that is aarch64";
};
isMinimal = lib.mkOption {
type = lib.types.bool;
default = false;
description = "Used to indicate a minimal host";
description = "Used to indicate a minimal configuration host";
};
isServer = lib.mkOption {
type = lib.types.bool;
default = false;
description = "Used to indicate a server host";
};
desktop = lib.mkOption {
type = lib.types.nullOr (
lib.types.enum [
"Gnome"
"Hyprland"
]
);
default = if config.hostSpec.isServer then null else "Gnome";
description = "Desktop environment (Gnome, Hyprland or null)";
};
shell = lib.mkOption {
type = lib.types.enum [
pkgs.fish
pkgs.bash
];
default = pkgs.fish;
description = "Default shell (pkgs.fish or pkgs.bash)";
};
pool = lib.mkOption {
type = lib.types.bool;
default = true;
description = "Whether it mounts pool from PVE";
};
};
}

View file

@ -0,0 +1,181 @@
# Specifications For Secret Data Structures
{
pkgs,
config,
lib,
...
}:
let
# Function to create a private key file in the Nix store with proper permissions
mkSshKeyFile =
name: content:
pkgs.writeTextFile {
name = "ssh-key-${name}";
text = content;
executable = false;
checkPhase = ''
# Verify it's a valid SSH key (optional)
grep -q "BEGIN OPENSSH PRIVATE KEY" "$out" || (echo "Invalid SSH key format"; exit 1)
'';
};
in
{
options.secretsSpec = {
ssh = lib.mkOption {
type = lib.types.submodule {
options = {
# privateKeys are set up automagically 🌠, see config below
privateKeyContents = lib.mkOption {
type = lib.types.attrsOf lib.types.str;
description = "SSH private key contents keyed by name";
default = { };
};
privateKeys = lib.mkOption {
type = lib.types.attrsOf lib.types.path;
description = "SSH private key file paths keyed by name";
# default = { };
readOnly = true;
};
publicKeys = lib.mkOption {
type = lib.types.attrsOf lib.types.str;
description = "SSH public keys keyed by name";
default = { };
};
knownHosts = lib.mkOption {
type = lib.types.attrsOf lib.types.str;
description = "SSH known hosts entries keyed by hostname";
default = { };
};
};
};
default = { };
description = "SSH key related secrets";
};
api = lib.mkOption {
type = lib.types.attrsOf lib.types.str;
description = "API keys keyed by service name";
default = { };
};
docker = lib.mkOption {
type = lib.types.attrsOf (lib.types.attrsOf lib.types.str);
description = "Docker environment variables keyed by container name";
default = { };
};
users = lib.mkOption {
type = lib.types.attrsOf (
lib.types.submodule {
options = {
password = lib.mkOption {
type = lib.types.str;
description = "Hashed password for the user"; # nix-shell -p whois --run 'mkpasswd --method=sha-512 --rounds=656000'
};
email = lib.mkOption {
type = lib.types.str;
description = "Email address for the user";
};
handle = lib.mkOption {
type = lib.types.str;
description = "The handle of the user (eg: github user)";
};
fullName = lib.mkOption {
type = lib.types.str;
description = "Full name of the user";
};
sshKeys = lib.mkOption {
type = lib.types.listOf lib.types.str;
description = "SSH public keys for the user";
default = [ ];
};
};
}
);
description = "User information secrets";
default = { };
};
firewall = lib.mkOption {
type = lib.types.attrsOf (
lib.types.submodule {
options = {
allowedTCPPorts = lib.mkOption {
type = lib.types.listOf lib.types.port;
description = "Allowed TCP ports for this host";
default = [ ];
# example = [
# 22
# 80
# 443
# ];
};
allowedTCPPortRanges = lib.mkOption {
type = lib.types.listOf (
lib.types.submodule {
options = {
from = lib.mkOption {
type = lib.types.port;
description = "Starting port in range";
};
to = lib.mkOption {
type = lib.types.port;
description = "Ending port in range";
};
};
}
);
description = "Allowed TCP port ranges for this host";
default = [ ];
# example = [
# {
# [REDACTED]
# [REDACTED]
# }
# ];
};
allowedUDPPorts = lib.mkOption {
type = lib.types.listOf lib.types.port;
description = "Allowed UDP ports for this host";
default = [ ];
# example = [
# 53
# 123
# ];
};
allowedUDPPortRanges = lib.mkOption {
type = lib.types.listOf (
lib.types.submodule {
options = {
from = lib.mkOption {
type = lib.types.port;
description = "Starting port in range";
};
to = lib.mkOption {
type = lib.types.port;
description = "Ending port in range";
};
};
}
);
description = "Allowed UDP port ranges for this host";
default = [ ];
# example = [
# {
# [REDACTED]
# [REDACTED]
# }
# ];
};
};
}
);
description = "Firewall configuration by host";
default = { };
};
};
config.secretsSpec.ssh.privateKeys = lib.mapAttrs (
name: content: mkSshKeyFile name content
) config.secretsSpec.ssh.privateKeyContents;
}