This commit is contained in:
2025-12-28 15:49:18 -05:00
parent b5d2e3188d
commit a549b01111
15 changed files with 19 additions and 19 deletions

64
modules/age-secrets.nix Normal file
View File

@@ -0,0 +1,64 @@
{
config,
lib,
pkgs,
...
}:
{
# Configure all agenix secrets
age.secrets = {
# ZFS encryption key
zfs-key = {
file = ../secrets/zfs-key.age;
mode = "0400";
owner = "root";
group = "root";
};
# Secureboot keys archive
secureboot-tar = {
file = ../secrets/secureboot.tar.age;
mode = "0400";
owner = "root";
group = "root";
};
# System passwords
hashedPass = {
file = ../secrets/hashedPass.age;
mode = "0400";
owner = "root";
group = "root";
};
# Service authentication
caddy_auth = {
file = ../secrets/caddy_auth.age;
mode = "0400";
owner = "caddy";
group = "caddy";
};
jellyfin-api-key = {
file = ../secrets/jellyfin-api-key.age;
mode = "0400";
owner = "root";
group = "root";
};
slskd_env = {
file = ../secrets/slskd_env.age;
mode = "0400";
owner = "root";
group = "root";
};
# Network configuration
wg0-conf = {
file = ../secrets/wg0.conf.age;
mode = "0400";
owner = "root";
group = "root";
};
};
}

24
modules/hardware.nix Normal file
View File

@@ -0,0 +1,24 @@
{
config,
lib,
pkgs,
service_configs,
...
}:
{
boot.initrd.availableKernelModules = [
"xhci_pci"
"ahci"
"usb_storage"
"usbhid"
"sd_mod"
];
boot.initrd.kernelModules = [ "dm-snapshot" ];
boot.kernelModules = [ "kvm-amd" ];
boot.extraModulePackages = [ ];
swapDevices = [ ];
hardware.cpu.amd.updateMicrocode = true;
hardware.enableRedistributableFirmware = true;
}

31
modules/home.nix Normal file
View File

@@ -0,0 +1,31 @@
{
pkgs,
lib,
...
}:
{
home.stateVersion = "24.11";
programs.fish = {
enable = true;
interactiveShellInit = ''
# disable greeting
set fish_greeting
# pfetch on shell start (disable pkgs because of execution time)
PF_INFO="ascii title os host kernel uptime memory editor wm" ${lib.getExe pkgs.pfetch-rs}
'';
shellAliases =
let
eza = "${lib.getExe pkgs.eza} --color=always --group-directories-first";
in
{
# from DistroTube's dot files: Changing "ls" to "eza"
ls = "${eza} -al";
la = "${eza} -a";
ll = "${eza} -l";
lt = "${eza} -aT";
};
};
}

52
modules/impermanence.nix Normal file
View File

@@ -0,0 +1,52 @@
{
config,
lib,
pkgs,
username,
service_configs,
...
}:
{
environment.persistence."/persistent" = {
hideMounts = true;
directories = [
"/var/log"
"/var/lib/systemd/coredump"
"/var/lib/nixos"
"/var/lib/systemd/timers"
];
files = [
# SSH host keys
"/etc/ssh/ssh_host_ed25519_key"
"/etc/ssh/ssh_host_ed25519_key.pub"
"/etc/ssh/ssh_host_rsa_key"
"/etc/ssh/ssh_host_rsa_key.pub"
# Machine ID
"/etc/machine-id"
# ZFS cache
"/etc/zfs/zpool.cache"
];
users.${username} = {
files = [
".local/share/fish/fish_history"
];
};
users.root = {
home = "/root";
files = [
".local/share/fish/fish_history"
];
};
};
systemd.tmpfiles.rules = [
"d /etc 755 root"
];
}

158
modules/lib.nix Normal file
View File

@@ -0,0 +1,158 @@
{
inputs,
pkgs,
...
}:
inputs.nixpkgs.lib.extend (
final: prev:
let
lib = prev;
in
{
# stolen from: https://stackoverflow.com/a/42398526
optimizeWithFlags =
pkg: flags:
lib.overrideDerivation pkg (
old:
let
newflags = lib.foldl' (acc: x: "${acc} ${x}") "" flags;
oldflags = if (lib.hasAttr "NIX_CFLAGS_COMPILE" old) then "${old.NIX_CFLAGS_COMPILE}" else "";
in
{
NIX_CFLAGS_COMPILE = "${oldflags} ${newflags}";
# stdenv = pkgs.clang19Stdenv;
}
);
optimizePackage =
pkg:
final.optimizeWithFlags pkg [
"-O3"
"-march=znver3"
"-mtune=znver3"
];
vpnNamespaceOpenPort =
port: service:
{ ... }:
{
vpnNamespaces.wg = {
portMappings = [
{
from = port;
to = port;
}
];
openVPNPorts = [
{
port = port;
protocol = "both";
}
];
};
systemd.services.${service}.vpnConfinement = {
enable = true;
vpnNamespace = "wg";
};
};
serviceMountWithZpool =
serviceName: zpool: dirs:
{ pkgs, config, ... }:
{
systemd.services."${serviceName}-mounts" = {
wants = [ "zfs.target" ] ++ lib.optionals (zpool != "") [ "zfs-import-${zpool}.service" ];
after = lib.optionals (zpool != "") [ "zfs-import-${zpool}.service" ];
before = [ "${serviceName}.service" ];
serviceConfig = {
Type = "oneshot";
RemainAfterExit = true;
ExecStart = [
(lib.getExe (
pkgs.writeShellApplication {
name = "ensure-zfs-mounts-with-pool-${serviceName}-${zpool}";
runtimeInputs = with pkgs; [
gawk
coreutils
config.boot.zfs.package
];
text = ''
set -euo pipefail
echo "Ensuring ZFS mounts for service: ${serviceName} (pool: ${zpool})"
echo "Directories: ${lib.strings.concatStringsSep ", " dirs}"
# Validate mounts exist (ensureZfsMounts already has proper PATH)
${lib.getExe pkgs.ensureZfsMounts} ${lib.strings.concatStringsSep " " dirs}
# Additional runtime check: verify paths are on correct zpool
${lib.optionalString (zpool != "") ''
echo "Verifying ZFS mountpoints are on pool '${zpool}'..."
if ! zfs_list_output=$(zfs list -H -o name,mountpoint 2>&1); then
echo "ERROR: Failed to query ZFS datasets: $zfs_list_output" >&2
exit 1
fi
# shellcheck disable=SC2043
for target in ${lib.strings.concatStringsSep " " dirs}; do
echo "Checking: $target"
# Find dataset that has this mountpoint
dataset=$(echo "$zfs_list_output" | awk -v target="$target" '$2 == target {print $1; exit}')
if [ -z "$dataset" ]; then
echo "ERROR: No ZFS dataset found for mountpoint: $target" >&2
exit 1
fi
# Extract pool name from dataset (first part before /)
actual_pool=$(echo "$dataset" | cut -d'/' -f1)
if [ "$actual_pool" != "${zpool}" ]; then
echo "ERROR: ZFS pool mismatch for $target" >&2
echo " Expected pool: ${zpool}" >&2
echo " Actual pool: $actual_pool" >&2
echo " Dataset: $dataset" >&2
exit 1
fi
echo "$target is on $dataset (pool: $actual_pool)"
done
echo "All paths verified successfully on pool '${zpool}'"
''}
echo "Mount validation completed for ${serviceName} (pool: ${zpool})"
'';
}
))
];
};
};
systemd.services.${serviceName} = {
wants = [
"${serviceName}-mounts.service"
];
after = [
"${serviceName}-mounts.service"
];
requires = [
"${serviceName}-mounts.service"
];
};
# assert that the pool is even enabled
#assertions = lib.optionals (zpool != "") [
# {
# assertion = builtins.elem zpool config.boot.zfs.extraPools;
# message = "${zpool} is not enabled in `boot.zfs.extraPools`";
# }
#];
};
}
)

49
modules/no-rgb.nix Normal file
View File

@@ -0,0 +1,49 @@
{
config,
lib,
pkgs,
...
}:
{
systemd.services.no-rgb =
let
no-rgb = (
pkgs.writeShellApplication {
name = "no-rgb";
runtimeInputs = with pkgs; [
openrgb
coreutils
gnugrep
];
text = ''
#!/bin/sh
set -e
NUM_DEVICES=$(openrgb --noautoconnect --list-devices | grep -cE '^[0-9]+: ')
for i in $(seq 0 $((NUM_DEVICES - 1))); do
openrgb --noautoconnect --device "$i" --mode direct --color 000000
done
'';
}
);
in
{
description = "disable rgb";
serviceConfig = {
ExecStart = lib.getExe no-rgb;
Type = "oneshot";
};
wantedBy = [ "multi-user.target" ];
};
services.hardware.openrgb = {
enable = true;
package = pkgs.openrgb-with-all-plugins;
motherboard = "amd";
};
services.udev.packages = [ pkgs.openrgb-with-all-plugins ];
hardware.i2c.enable = true;
}

46
modules/overlays.nix Normal file
View File

@@ -0,0 +1,46 @@
final: prev: {
ensureZfsMounts = prev.writeShellApplication {
name = "zfsEnsureMounted";
runtimeInputs = with prev; [
zfs
gawk
coreutils
];
text = ''
#!/bin/sh
if [[ "$#" -eq "0" ]]; then
echo "no arguments passed"
exit 1
fi
MOUNTED=$(zfs list -o mountpoint,mounted -H | awk '$NF == "yes" {NF--; print}')
MISSING=""
for target in "$@"; do
if ! grep -Fxq "$target" <<< "$MOUNTED"; then
MISSING="$MISSING $target"
fi
done
if [[ -n "$MISSING" ]]; then
echo "FAILURE, missing:$MISSING" 1>&2
exit 1
fi
'';
};
reflac = prev.writeShellApplication {
name = "reflac";
runtimeInputs = with prev; [ flac ];
excludeShellChecks = [ "2086" ];
text = builtins.readFile (
prev.fetchurl {
url = "https://raw.githubusercontent.com/chungy/reflac/refs/heads/master/reflac";
sha256 = "61c6cc8be3d276c6714e68b55e5de0e6491f50bbf195233073dbce14a1e278a7";
}
);
};
}

41
modules/secureboot.nix Normal file
View File

@@ -0,0 +1,41 @@
{
config,
lib,
pkgs,
...
}:
{
boot = {
loader.systemd-boot.enable = lib.mkForce false;
lanzaboote = {
enable = true;
# needed to be in `/etc/secureboot` for sbctl to work
pkiBundle = "/etc/secureboot";
};
};
system.activationScripts = {
# extract secureboot keys from agenix-decrypted tar
"secureboot-keys" = {
deps = [ "agenix" ];
text = ''
#!/bin/sh
# Check if keys already exist (e.g., from disko-install)
if [[ -d ${config.boot.lanzaboote.pkiBundle} && -f ${config.boot.lanzaboote.pkiBundle}/db.key ]]; then
echo "Secureboot keys already present, skipping extraction"
chown -R root:wheel ${config.boot.lanzaboote.pkiBundle}
chmod -R 500 ${config.boot.lanzaboote.pkiBundle}
else
echo "Extracting secureboot keys from agenix"
rm -fr ${config.boot.lanzaboote.pkiBundle} || true
mkdir -p ${config.boot.lanzaboote.pkiBundle}
${pkgs.gnutar}/bin/tar xf ${config.age.secrets.secureboot-tar.path} -C ${config.boot.lanzaboote.pkiBundle}
chown -R root:wheel ${config.boot.lanzaboote.pkiBundle}
chmod -R 500 ${config.boot.lanzaboote.pkiBundle}
fi
'';
};
};
}

22
modules/usb-secrets.nix Normal file
View File

@@ -0,0 +1,22 @@
{
config,
lib,
pkgs,
...
}:
{
# Mount USB secrets drive via fileSystems
fileSystems."/mnt/usb-secrets" = {
device = "/dev/disk/by-label/SECRETS";
fsType = "vfat";
options = [
"ro"
"uid=root"
"gid=root"
"umask=377"
];
neededForBoot = true;
};
age.identityPaths = [ "/mnt/usb-secrets/usb-secrets-key" ];
}

92
modules/zfs.nix Normal file
View File

@@ -0,0 +1,92 @@
{
config,
service_configs,
pkgs,
...
}:
let
# DO NOT CHANGE
# path is set via a zfs property
zfs-key = "/etc/zfs-key";
in
{
system.activationScripts = {
# Copy decrypted ZFS key from agenix to expected location
# /etc is on tmpfs due to impermanence, so no persistent storage risk
"zfs-key".text = ''
#!/bin/sh
rm -f ${zfs-key} || true
cp ${config.age.secrets.zfs-key.path} ${zfs-key}
chmod 0400 ${zfs-key}
chown root:root ${zfs-key}
'';
};
boot.zfs.package = pkgs.zfs;
boot.initrd.kernelModules = [ "zfs" ];
boot.kernelParams =
let
gb = 20;
mb = gb * 1000;
kb = mb * 1000;
b = kb * 1000;
in
[
"zfs.zfs_arc_max=${builtins.toString b}"
];
boot.supportedFilesystems = [ "zfs" ];
boot.zfs.extraPools = [
service_configs.zpool_ssds
service_configs.zpool_hdds
];
services.sanoid = {
enable = true;
datasets."${service_configs.zpool_ssds}" = {
recursive = true;
autoprune = true;
autosnap = true;
hourly = 5;
daily = 7;
monthly = 3;
yearly = 0;
};
datasets."${service_configs.zpool_ssds}/services/sql" = {
recursive = true;
autoprune = true;
autosnap = true;
hourly = 12;
daily = 2;
monthly = 0;
yearly = 0;
};
datasets."${service_configs.zpool_ssds}/services/jellyfin_cache" = {
recursive = true;
autoprune = true;
autosnap = true;
hourly = 0;
daily = 0;
monthly = 0;
yearly = 0;
};
datasets."${service_configs.zpool_hdds}" = {
recursive = true;
autoprune = true;
autosnap = true;
hourly = 0;
daily = 0;
monthly = 0;
yearly = 0;
};
};
services.zfs = {
autoScrub.enable = true;
trim.enable = true;
};
}