feat: USDA-dash now uses encrypted .env files
All checks were successful
CI / Format Check (push) Successful in 2s
CI / Flake Check (push) Successful in 1m42s
CI / Evaluate Key Configurations (nix-builder) (push) Successful in 14s
CI / Evaluate Key Configurations (nix-desktop1) (push) Successful in 8s
CI / Evaluate Key Configurations (nix-laptop1) (push) Successful in 9s
CI / Evaluate Artifacts (installer-iso-nix-laptop1) (push) Successful in 20s
CI / Evaluate Artifacts (lxc-nix-builder) (push) Successful in 13s
CI / Build and Publish Documentation (push) Successful in 10s

This commit is contained in:
UGA Innovation Factory
2026-01-30 23:19:38 +00:00
parent 7e6e8d5e0f
commit 7c07727150
4 changed files with 53 additions and 81 deletions

View File

@@ -27,42 +27,44 @@ in
}; };
filesystem = { filesystem = {
device = lib.mkOption { device = lib.mkOption {
type = lib.types.nullOr lib.types.str; type = lib.types.nullOr lib.types.str;
default = null; default = null;
description = '' description = ''
The main disk device to use for automated partitioning and installation. The main disk device to use for automated partitioning and installation.
When set, enables disko for declarative disk management with: When set, enables disko for declarative disk management with:
- 1GB EFI boot partition - 1GB EFI boot partition
- Optional swap partition (see swapSize) - Optional swap partition (see swapSize)
- Root partition using remaining space - Root partition using remaining space
Leave null for systems that don't need disk partitioning (containers, WSL). Leave null for systems that don't need disk partitioning (containers, WSL).
''; '';
example = "/dev/nvme0n1"; example = "/dev/nvme0n1";
}; };
useSwap = lib.mkOption { useSwap = lib.mkOption {
type = lib.types.bool; type = lib.types.bool;
default = true; default = true;
description = '' description = ''
Whether to create and use a swap partition. Whether to create and use a swap partition.
Disable for systems with ample RAM or SSDs where swap is undesirable. Disable for systems with ample RAM or SSDs where swap is undesirable.
''; '';
}; };
swapSize = lib.mkOption { swapSize = lib.mkOption {
type = lib.types.nullOr lib.types.str; type = lib.types.nullOr lib.types.str;
default = null; default = null;
description = '' description = ''
Size of the swap partition (e.g., "16G", "32G"). Size of the swap partition (e.g., "16G", "32G").
Recommended sizes: Recommended sizes:
- 8-16GB for desktops with 16GB+ RAM - 8-16GB for desktops with 16GB+ RAM
- 32GB for laptops (enables hibernation) - 32GB for laptops (enables hibernation)
- Match RAM size for systems <8GB RAM - Match RAM size for systems <8GB RAM
''; '';
example = "32G"; example = "32G";
};
}; };
}; }; }; };
};
config = lib.mkMerge [ config = lib.mkMerge [
{ {

View File

@@ -54,27 +54,10 @@ let
in in
lenStr >= lenSuffix && lib.substring (lenStr - lenSuffix) lenSuffix str == suffix; lenStr >= lenSuffix && lib.substring (lenStr - lenSuffix) lenSuffix str == suffix;
hasPrefix =
prefix: str:
let
lenPrefix = lib.stringLength prefix;
in
lib.stringLength str >= lenPrefix && lib.substring 0 lenPrefix str == prefix;
nameValuePair = name: value: { inherit name value; }; nameValuePair = name: value: { inherit name value; };
secretsPath = ./secrets; secretsPath = ./secrets;
# Helper to convert SSH public key content to age public key
sshToAge =
sshPubKey:
let
# This is a simple check - in practice, use ssh-to-age tool
# For now, we'll just use the keys as-is if they look like age keys
trimmed = lib.replaceStrings [ "\n" ] [ "" ] sshPubKey;
in
if lib.substring 0 4 trimmed == "age1" then trimmed else null; # Will need manual conversion with ssh-to-age
# Read all directories in secrets/ # Read all directories in secrets/
secretDirs = if lib.pathExists secretsPath then lib.readDir secretsPath else { }; secretDirs = if lib.pathExists secretsPath then lib.readDir secretsPath else { };
@@ -181,22 +164,23 @@ let
# Generate wildcard rules for each directory to allow creating new secrets # Generate wildcard rules for each directory to allow creating new secrets
wildcardRules = lib.listToAttrs ( wildcardRules = lib.listToAttrs (
lib.concatMap ( lib.concatMap (dir: [
dir: # Match with and without .age extension for ragenix compatibility
[ (nameValuePair "secrets/${dir}/*" {
# Match with and without .age extension for ragenix compatibility publicKeys =
(nameValuePair "secrets/${dir}/*" { let
publicKeys = let
recipients = getRecipients "secrets/${dir}/dummy.age"; recipients = getRecipients "secrets/${dir}/dummy.age";
in unique (lib.filter (k: k != null && k != "") recipients); in
}) unique (lib.filter (k: k != null && k != "") recipients);
(nameValuePair "secrets/${dir}/*.age" { })
publicKeys = let (nameValuePair "secrets/${dir}/*.age" {
publicKeys =
let
recipients = getRecipients "secrets/${dir}/dummy.age"; recipients = getRecipients "secrets/${dir}/dummy.age";
in unique (lib.filter (k: k != null && k != "") recipients); in
}) unique (lib.filter (k: k != null && k != "") recipients);
] })
) (lib.filter (d: d != "admins") directories) ]) (lib.filter (d: d != "admins") directories)
); );
in in

View File

@@ -54,27 +54,10 @@ let
in in
lenStr >= lenSuffix && lib.substring (lenStr - lenSuffix) lenSuffix str == suffix; lenStr >= lenSuffix && lib.substring (lenStr - lenSuffix) lenSuffix str == suffix;
hasPrefix =
prefix: str:
let
lenPrefix = lib.stringLength prefix;
in
lib.stringLength str >= lenPrefix && lib.substring 0 lenPrefix str == prefix;
nameValuePair = name: value: { inherit name value; }; nameValuePair = name: value: { inherit name value; };
secretsPath = ./secrets; secretsPath = ./secrets;
# Helper to convert SSH public key content to age public key
sshToAge =
sshPubKey:
let
# This is a simple check - in practice, use ssh-to-age tool
# For now, we'll just use the keys as-is if they look like age keys
trimmed = lib.replaceStrings [ "\n" ] [ "" ] sshPubKey;
in
if lib.substring 0 4 trimmed == "age1" then trimmed else null; # Will need manual conversion with ssh-to-age
# Read all directories in secrets/ # Read all directories in secrets/
secretDirs = if lib.pathExists secretsPath then lib.readDir secretsPath else { }; secretDirs = if lib.pathExists secretsPath then lib.readDir secretsPath else { };

View File

@@ -195,7 +195,10 @@ in
# This is needed because age can't reliably use OpenSSH private keys directly # This is needed because age can't reliably use OpenSSH private keys directly
# Must run before agenix tries to decrypt secrets # Must run before agenix tries to decrypt secrets
system.activationScripts.convertSshToAge = { system.activationScripts.convertSshToAge = {
deps = [ "users" "groups" ]; deps = [
"users"
"groups"
];
text = '' text = ''
mkdir -p /etc/age mkdir -p /etc/age
if [ -f /etc/ssh/ssh_host_ed25519_key ]; then if [ -f /etc/ssh/ssh_host_ed25519_key ]; then