Преглед на файлове

feat(odin): fix a lot of stuff

Zander Hawke преди 9 месеца
родител
ревизия
89438bb725
променени са 11 файла, в които са добавени 348 реда и са изтрити 240 реда
  1. 0 10
      .sops.yaml
  2. 96 19
      flake.lock
  3. 5 3
      flake.nix
  4. 7 0
      hosts/odin/README.md
  5. 35 161
      hosts/odin/default.nix
  6. 31 23
      hosts/odin/disko.nix
  7. 0 18
      hosts/odin/hardware-configuration.nix
  8. 102 0
      hosts/odin/impermanence.nix
  9. 0 5
      hosts/odin/secrets.yaml
  10. 69 0
      hosts/odin/system.nix
  11. 3 1
      lib/default.nix

+ 0 - 10
.sops.yaml

@@ -1,10 +0,0 @@
-keys:
-  - &thomas 7A53D4C6B481F7711588D34FDE749C31D060A160
-  - &odin age17fg06ssdz089k7fhl5rkmkszj0we3an9frp9q6hdp5uuamxwhc4syzy02l
-creation_rules:
-  - path_regex: hosts/odin/secrets.yaml
-    key_groups:
-    - pgp:
-      - *thomas
-      age:
-      - *odin

+ 96 - 19
flake.lock

@@ -1,5 +1,28 @@
 {
   "nodes": {
+    "agenix": {
+      "inputs": {
+        "darwin": "darwin",
+        "home-manager": "home-manager",
+        "nixpkgs": [
+          "nixpkgs"
+        ],
+        "systems": "systems"
+      },
+      "locked": {
+        "lastModified": 1754433428,
+        "narHash": "sha256-NA/FT2hVhKDftbHSwVnoRTFhes62+7dxZbxj5Gxvghs=",
+        "owner": "ryantm",
+        "repo": "agenix",
+        "rev": "9edb1787864c4f59ae5074ad498b6272b3ec308d",
+        "type": "github"
+      },
+      "original": {
+        "owner": "ryantm",
+        "repo": "agenix",
+        "type": "github"
+      }
+    },
     "cachix": {
       "inputs": {
         "devenv": [
@@ -33,6 +56,28 @@
       }
     },
     "darwin": {
+      "inputs": {
+        "nixpkgs": [
+          "agenix",
+          "nixpkgs"
+        ]
+      },
+      "locked": {
+        "lastModified": 1744478979,
+        "narHash": "sha256-dyN+teG9G82G+m+PX/aSAagkC+vUv0SgUw3XkPhQodQ=",
+        "owner": "lnl7",
+        "repo": "nix-darwin",
+        "rev": "43975d782b418ebf4969e9ccba82466728c2851b",
+        "type": "github"
+      },
+      "original": {
+        "owner": "lnl7",
+        "ref": "master",
+        "repo": "nix-darwin",
+        "type": "github"
+      }
+    },
+    "darwin_2": {
       "inputs": {
         "nixpkgs": [
           "nixpkgs-darwin"
@@ -158,7 +203,7 @@
     },
     "flake-utils": {
       "inputs": {
-        "systems": "systems"
+        "systems": "systems_2"
       },
       "locked": {
         "lastModified": 1731533236,
@@ -223,6 +268,27 @@
       }
     },
     "home-manager": {
+      "inputs": {
+        "nixpkgs": [
+          "agenix",
+          "nixpkgs"
+        ]
+      },
+      "locked": {
+        "lastModified": 1745494811,
+        "narHash": "sha256-YZCh2o9Ua1n9uCvrvi5pRxtuVNml8X2a03qIFfRKpFs=",
+        "owner": "nix-community",
+        "repo": "home-manager",
+        "rev": "abfad3d2958c9e6300a883bd443512c55dfeb1be",
+        "type": "github"
+      },
+      "original": {
+        "owner": "nix-community",
+        "repo": "home-manager",
+        "type": "github"
+      }
+    },
+    "home-manager_2": {
       "inputs": {
         "nixpkgs": [
           "nixpkgs"
@@ -393,7 +459,7 @@
           "nixpkgs"
         ],
         "nuschtosSearch": "nuschtosSearch",
-        "systems": "systems_2"
+        "systems": "systems_3"
       },
       "locked": {
         "lastModified": 1755727480,
@@ -435,40 +501,51 @@
     },
     "root": {
       "inputs": {
-        "darwin": "darwin",
+        "agenix": "agenix",
+        "darwin": "darwin_2",
         "devenv": "devenv",
         "disko": "disko",
-        "home-manager": "home-manager",
+        "home-manager": "home-manager_2",
         "impermanence": "impermanence",
         "nixos-facter-modules": "nixos-facter-modules",
         "nixpkgs": "nixpkgs",
         "nixpkgs-darwin": "nixpkgs-darwin",
         "nixpkgs-unstable": "nixpkgs-unstable",
         "nixvim": "nixvim",
-        "sops-nix": "sops-nix"
+        "secrets": "secrets"
       }
     },
-    "sops-nix": {
-      "inputs": {
-        "nixpkgs": [
-          "nixpkgs"
-        ]
+    "secrets": {
+      "locked": {
+        "lastModified": 1756492215,
+        "narHash": "sha256-m1qcuCVWg7JTTvI/vZ3Z/6tq3fNxMyVvTikzDs3bW1M=",
+        "ref": "refs/heads/master",
+        "rev": "11cb4ec3ce820622ee30bd3b11d3e7f585426c63",
+        "revCount": 2,
+        "type": "git",
+        "url": "ssh://[email protected]/control/secrets.git"
       },
+      "original": {
+        "type": "git",
+        "url": "ssh://[email protected]/control/secrets.git"
+      }
+    },
+    "systems": {
       "locked": {
-        "lastModified": 1754988908,
-        "narHash": "sha256-t+voe2961vCgrzPFtZxha0/kmFSHFobzF00sT8p9h0U=",
-        "owner": "mic92",
-        "repo": "sops-nix",
-        "rev": "3223c7a92724b5d804e9988c6b447a0d09017d48",
+        "lastModified": 1681028828,
+        "narHash": "sha256-Vy1rq5AaRuLzOxct8nz4T6wlgyUR7zLU309k9mBC768=",
+        "owner": "nix-systems",
+        "repo": "default",
+        "rev": "da67096a3b9bf56a91d16901293e51ba5b49a27e",
         "type": "github"
       },
       "original": {
-        "owner": "mic92",
-        "repo": "sops-nix",
+        "owner": "nix-systems",
+        "repo": "default",
         "type": "github"
       }
     },
-    "systems": {
+    "systems_2": {
       "locked": {
         "lastModified": 1681028828,
         "narHash": "sha256-Vy1rq5AaRuLzOxct8nz4T6wlgyUR7zLU309k9mBC768=",
@@ -483,7 +560,7 @@
         "type": "github"
       }
     },
-    "systems_2": {
+    "systems_3": {
       "locked": {
         "lastModified": 1681028828,
         "narHash": "sha256-Vy1rq5AaRuLzOxct8nz4T6wlgyUR7zLU309k9mBC768=",

+ 5 - 3
flake.nix

@@ -19,11 +19,13 @@
     nixvim.url = "github:nix-community/nixvim/nixos-25.05?shallow=true";
     nixvim.inputs.nixpkgs.follows = "nixpkgs";
 
-    impermanence.url = "github:nix-community/impermanence";
+    impermanence.url = "github:nix-community/impermanence?shallow=true";
     # impermanence.inputs.nixpkgs.follows = "nixpkgs";
 
-    sops-nix.url = "github:mic92/sops-nix?shallow=true";
-    sops-nix.inputs.nixpkgs.follows = "nixpkgs";
+    agenix.url = "github:ryantm/agenix?shallow=true";
+    agenix.inputs.nixpkgs.follows = "nixpkgs";
+    secrets.url = "git+ssh://[email protected]/control/secrets.git";
+    # secrets.url = "path:/Users/thomas/workspace/control/secrets";
 
     disko.url = "github:nix-community/disko?shallow=true";
     disko.inputs.nixpkgs.follows = "nixpkgs";

+ 7 - 0
hosts/odin/README.md

@@ -11,3 +11,10 @@
 | PWM4 | HDD Bottom |    80 |   60 |
 | PWM2 | CPU Fan    |  150? |   0? |
 | PWM7 | Main Top   |    65 |   60 |
+
+```
+nix run github:nix-community/nixos-anywhere -- \
+  --disko-mode mount \
+  --flake .#odin \
+  --target-host [email protected]
+```

+ 35 - 161
hosts/odin/default.nix

@@ -5,131 +5,19 @@
     { config.facter.reportPath = ./facter.json; }
 
     outputs.modules.global.nix-config
-    inputs.sops-nix.nixosModules.sops
-    inputs.impermanence.nixosModules.impermanence
-    inputs.disko.nixosModules.disko
+    inputs.agenix.nixosModules.default
 
     ./disko.nix
+    ./impermanence.nix
+    ./system.nix
     # ./services
   ];
 
-  # System identification
-  networking.hostName = "odin";
-  networking.useDHCP = lib.mkDefault true;
-
-  sops.defaultSopsFile = ./secrets.yaml;
-  sops.secrets."thomas/password".neededForUsers = true;
-  sops.secrets."nullmailer/remotes".owner = config.services.nullmailer.user;
-
-
-  # Boot configuration
-  boot = {
-    # Use systemd-boot for UEFI systems
-    loader = {
-      systemd-boot.enable = true;
-      efi.canTouchEfiVariables = true;
-      grub.devices = [ config.disko.devices.disk.main.device ];
-      timeout = 3;
-    };
-
-    # Kernel parameters for server workload
-    kernelParams = [ "rootflags=compress=zstd:1,noatime" ];
-    kernelModules = [ "nct6775" ];
-
-    # Enable KSM for memory efficiency with containers
-    kernel.sysctl = {
-      "kernel.sysrq" = 1;
-      "vm.swappiness" = 10;
-      "net.core.default_qdisc" = "cake";
-    };
-
-    # Impermanence: reset root on boot
-    initrd.postDeviceCommands = lib.mkAfter ''
-      DEVICE=${config.disko.devices.disk.main.device}-part2
-
-      mkdir -p /mnt
-      mount -o subvol=/ $DEVICE /mnt
-
-      # Create a directory for old roots if it doesn't exist
-      mkdir -p /mnt/old-roots
-
-      # Move current root to old-roots with timestamp if it exists
-      if [[ -e /mnt/@root && ! -e /mnt/@root-blank ]]; then
-        timestamp=$(date --date="@$(stat -c %Y /mnt/@root)" "+%Y-%m-%d_%H:%M:%S")
-        mv /mnt/@root "/mnt/old-roots/@root-$timestamp"
-      fi
-
-      # Function to recursively delete subvolumes
-      delete_subvolume_recursively() {
-        for i in $(btrfs subvolume list -o "$1" | cut -f 9- -d ' '); do
-          delete_subvolume_recursively "/mnt/$i"
-        done
-        btrfs subvolume delete "$1"
-      }
-
-      # Delete old roots older than 30 days
-      for i in $(find /mnt/old-roots/ -maxdepth 1 -mtime +30); do
-        delete_subvolume_recursively "$i"
-      done
-
-      # Create fresh root from blank if needed or create blank if it doesn't exist
-      if [[ -e /mnt/@root-blank ]]; then
-        btrfs subvolume delete /mnt/@root || true
-        btrfs subvolume snapshot /mnt/@root-blank /mnt/@root
-      else
-        btrfs subvolume create /mnt/@root-blank
-        btrfs subvolume create /mnt/@root
-      fi
-
-      umount /mnt
-    '';
-  };
-
-  hardware = {
-    fancontrol = {
-      enable = true;
-      config = ''
-        INTERVAL=10
-        DEVPATH=hwmon1=devices/pci0000:00/0000:00:02.2/0000:04:00.0/nvme/nvme0 hwmon2=devices/platform/nct6775.656
-        DEVNAME=hwmon1=nvme hwmon2=nct6798
-        FCTEMPS=hwmon2/pwm7=hwmon1/temp1_input hwmon2/pwm2=hwmon1/temp1_input
-        FCFANS=hwmon2/pwm7=hwmon2/fan7_input hwmon2/pwm2=hwmon2/fan2_input
-        MINTEMP=hwmon2/pwm7=30 hwmon2/pwm2=30
-        MAXTEMP=hwmon2/pwm7=60 hwmon2/pwm2=60
-        MINSTART=hwmon2/pwm7=95 hwmon2/pwm2=150
-        MINSTOP=hwmon2/pwm7=75 hwmon2/pwm2=0
-      '';
-    };
-  };
+  security.sudo.wheelNeedsPassword = false;
 
+  age.secrets."odin/nullmailer/remotes".file = inputs.secrets."odin/nullmailer/remotes";
   # Services configuration
   services = {
-    # Drive power management and fan control
-    hddfancontrol = {
-      enable = true;
-      settings = {
-        harddrives =
-          let
-            devices = config.disko.devices.disk;
-          in
-          {
-            disks = [
-              devices.storage1.device
-              devices.storage2.device
-              devices.storage3.device
-            ];
-            pwmPaths = [
-              "/sys/class/hwmon/hwmon2/pwm1:20:0"
-              "/sys/class/hwmon/hwmon2/pwm4:80:60"
-            ];
-            logVerbosity = "DEBUG";
-            extraArgs = [
-              "--min-fan-speed-prct=0"
-            ];
-          };
-      };
-    };
-
     openssh = {
       enable = true;
       openFirewall = true;
@@ -153,7 +41,7 @@
     nullmailer = {
       enable = true;
       setSendmail = true;
-      remotesFile = config.sops.secrets."nullmailer/remotes".path;
+      remotesFile = config.age.secrets."odin/nullmailer/remotes".path;
       config = {
         me = "odin.t5.st";
         defaulthost = "odin.t5.st";
@@ -163,15 +51,6 @@
       };
     };
 
-    # Time synchronization
-    timesyncd.enable = true;
-
-    # Btrfs maintenance
-    btrfs.autoScrub = {
-      enable = true;
-      interval = "monthly";
-      fileSystems = [ "/" ];
-    };
 
     # Drive spin-down management
     # hdparm.devices = [
@@ -206,6 +85,19 @@
   #   };
   # };
 
+  programs.fish = {
+    enable = true;
+    vendor = {
+      completions.enable = true;
+      config.enable = true;
+      functions.enable = true;
+    };
+  };
+
+  environment.shells = [
+    config.programs.fish.package
+  ];
+
   # System packages
   environment.systemPackages = with pkgs; [
     # System utilities
@@ -239,44 +131,26 @@
     nvme-cli
   ];
 
-  # User configuration
-  users = {
-    mutableUsers = false; # Declarative user management
-    users = {
-      # Main user account
-      thomas = {
-        isNormalUser = true;
-        extraGroups = [ "wheel" "users" ];
-        hashedPasswordFile = config.sops.secrets."thomas/password".path;
-        openssh.authorizedKeys.keys = [
-          "ssh-rsa AAAAB3NzaC1yc2EAAAADAQABAAACAQC5o7LT5wPYWgI8Mvr6RKOv+BcsbQgU7PCw2hheVu17alwF1uFUsAYV5BVQu+uv9uEm/UDsCNhfM6TwI0A1prdmtBz4pKiwXbj7fcdp6DcVOgTsPfawbXEpivtJvlhEatyTsR26MjHKnqpT0BxPvj6Ug6pvRkCYW5d2bWXiY9murmAX6Q5kSyNunkB8PdRTH+S47f7eOdCJY63VBOkkiG8M7XyPwFCDTYiHhbMZcejIdY9mB6kYnMQVRHDznQWiQxrcaE1fD/TY3db9GDcOVoo2aDBOZX7WT2+me67sU8dEK9+nSyhWDzBbEs8knu87ZlKPFwhl4slenRniKhbf22OpicXArtEcjEj0GyDJH5e+ZCIQ4eSQanA7TxnKFlDuaf+Qqx55UT+ya4vJJeik7nkzbRHaE9IoWhhiOaOnaN6kHIxuxB6z7EL3Gk7f78+I/qBaj5df6fgnXM3JBXKa5bRH2wqoSetJAo6EGpEgmU2huB1ktiGlO7BlF5XwSw6cb/KT7NSIXhncgLkCzsDVXxecVQv1FnPISBcp3+ti01ADVf2trgpPDbNTWV40Rgiefie0o2fc6KWAFfum1j5N3WWU+XVVmRjDmKKHiEJBLNKDAe0rQf+tryPW4c5GIN7aFoB+8dYFAuUyLd7Fu3vhZdmcckN5ryHunEc0dKPIiuoVZw=="
-        ];
-      };
-    };
-  };
+  age.secrets."odin/thomas".file = inputs.secrets."odin/thomas";
 
-  # Persistent directories for impermanence
-  fileSystems."/persist".neededForBoot = true;
-  environment.persistence."/persist" = {
-    hideMounts = true;
-    directories = [
-      "/etc/nixos"
-      "/etc/ssh"
-      "/var/lib/nixos"
-      "/var/lib/systemd"
-      "/srv"
-    ];
-    files = [
-      "/etc/machine-id"
+  # User configuration
+  users.mutableUsers = false;
+  users.users.thomas = {
+    isNormalUser = true;
+    extraGroups = [ "wheel" "users" ];
+    hashedPasswordFile = config.age.secrets."odin/thomas".path;
+    openssh.authorizedKeys.keys = [
+      "ssh-rsa AAAAB3NzaC1yc2EAAAADAQABAAACAQC5o7LT5wPYWgI8Mvr6RKOv+BcsbQgU7PCw2hheVu17alwF1uFUsAYV5BVQu+uv9uEm/UDsCNhfM6TwI0A1prdmtBz4pKiwXbj7fcdp6DcVOgTsPfawbXEpivtJvlhEatyTsR26MjHKnqpT0BxPvj6Ug6pvRkCYW5d2bWXiY9murmAX6Q5kSyNunkB8PdRTH+S47f7eOdCJY63VBOkkiG8M7XyPwFCDTYiHhbMZcejIdY9mB6kYnMQVRHDznQWiQxrcaE1fD/TY3db9GDcOVoo2aDBOZX7WT2+me67sU8dEK9+nSyhWDzBbEs8knu87ZlKPFwhl4slenRniKhbf22OpicXArtEcjEj0GyDJH5e+ZCIQ4eSQanA7TxnKFlDuaf+Qqx55UT+ya4vJJeik7nkzbRHaE9IoWhhiOaOnaN6kHIxuxB6z7EL3Gk7f78+I/qBaj5df6fgnXM3JBXKa5bRH2wqoSetJAo6EGpEgmU2huB1ktiGlO7BlF5XwSw6cb/KT7NSIXhncgLkCzsDVXxecVQv1FnPISBcp3+ti01ADVf2trgpPDbNTWV40Rgiefie0o2fc6KWAFfum1j5N3WWU+XVVmRjDmKKHiEJBLNKDAe0rQf+tryPW4c5GIN7aFoB+8dYFAuUyLd7Fu3vhZdmcckN5ryHunEc0dKPIiuoVZw=="
     ];
-    users.thomas = {
-      directories = [
-        ".ssh"
-        ".config"
-      ];
-    };
   };
 
+  # System identification
+  networking.hostName = "odin";
+  networking.useDHCP = lib.mkDefault true;
+  # Time synchronization
+  services.timesyncd.enable = true;
+  time.timeZone = "Europe/Vienna";
+
   # System state version
   system.stateVersion = "25.05";
 }

+ 31 - 23
hosts/odin/disko.nix

@@ -1,38 +1,24 @@
-{ lib, ... }:
+{ inputs, lib, ... }:
 
 let
-  mainDiskId = "nvme-KINGSTON_SNV3S1000G_50026B7383CC0908";
   storageDisks = [
     "ata-ST8000VN002-2ZM188_WPV023WG"
     "ata-ST8000VN002-2ZM188_WPV07RMA"
     "ata-ST8000VN002-2ZM188_WPV020CG"
   ];
-
-  # Subvolumes with regular CoW behavior
-  regular = [ "root" "home" "nix" "persist" "logs" "services" ];
-  # Subvolumes that need noDataCow for performance
-  noDataCow = [ "databases" "cache" "containers" ];
-
-  # Function to create subvolume configuration
-  mkSubvolume = name: {
-    name = "@${name}";
-    value = {
-      mountpoint = if name == "root" then "/" else "/${name}";
-      mountOptions = [
-        "compress=zstd:1"
-        "noatime"
-      ] ++ lib.optional (lib.elem name noDataCow) "nodatacow";
-    };
-  };
 in
 
 {
+  imports = [
+    inputs.disko.nixosModules.disko
+  ];
+
   disko.devices = {
     disk = {
       # Root system drive (1TB NVMe)
       main = {
         type = "disk";
-        device = "/dev/disk/by-id/${mainDiskId}";
+        device = "/dev/disk/by-id/nvme-KINGSTON_SNV3S1000G_50026B7383CC0908";
         content = {
           type = "gpt";
           partitions = {
@@ -54,9 +40,31 @@ in
                 type = "btrfs";
                 extraArgs = [ "-f" ];
                 subvolumes = {
-                  # Blank root template for ephemeral setup
-                  "@root-blank" = { };
-                } // lib.listToAttrs (map mkSubvolume (regular ++ noDataCow));
+                  "@root" = {
+                    mountpoint = "/";
+                    mountOptions = [ "compress=zstd1" "noatime" ];
+                  };
+
+                  "@nix" = {
+                    mountpoint = "/nix";
+                    mountOptions = [ "compress=zstd1" "noatime" ];
+                  };
+
+                  "@persist" = {
+                    mountpoint = "/persist";
+                    mountOptions = [ "compress=zstd1" "noatime" ];
+                  };
+
+                  "@services" = {
+                    mountpoint = "/var/lib";
+                    mountOptions = [ "compress=zstd1" "noatime" "space_cache=v2" ];
+                  };
+
+                  "@logs" = {
+                    mountpoint = "/var/log";
+                    mountOptions = [ "compress=zstd1" "noatime" ];
+                  };
+                };
               };
             };
           };

+ 0 - 18
hosts/odin/hardware-configuration.nix

@@ -1,18 +0,0 @@
-{ config, lib, modulesPath, ... }:
-
-{
-  imports = [
-    (modulesPath + "/installer/scan/not-detected.nix")
-  ];
-
-  boot.initrd.availableKernelModules = [ "xhci_pci" "ahci" "nvme" "usbhid" "usb_storage" "sd_mod" "sr_mod" ];
-  boot.initrd.kernelModules = [ ];
-  boot.kernelModules = [ "kvm-amd" "nct6775" ];
-  boot.extraModulePackages = [ ];
-
-  swapDevices = [ ];
-
-  networking.useDHCP = lib.mkDefault true;
-  nixpkgs.hostPlatform = lib.mkDefault "x86_64-linux";
-  hardware.cpu.amd.updateMicrocode = lib.mkDefault config.hardware.enableRedistributableFirmware;
-}

+ 102 - 0
hosts/odin/impermanence.nix

@@ -0,0 +1,102 @@
+{ config, inputs, lib, ... }:
+{
+  imports = [
+    inputs.impermanence.nixosModules.impermanence
+  ];
+
+  boot.initrd.postDeviceCommands = lib.mkAfter ''
+    #!/bin/sh
+    DEVICE=${config.disko.devices.disk.main.device}-part2
+
+    # Mount Btrfs root
+    mkdir -p /mnt
+    if ! mount -o subvol=/ $DEVICE /mnt; then
+      echo "Failed to mount $DEVICE at /mnt"
+      exit 1
+    fi
+
+    # Create directory for old roots
+    mkdir -p /mnt/old-roots
+
+    # Move current root to old-roots with current timestamp
+    if [[ -e /mnt/@root && ! -e /mnt/@root-blank ]]; then
+      timestamp=$(date +%Y-%m-%d_%H:%M:%S)
+      if ! mv /mnt/@root "/mnt/old-roots/@root-$timestamp"; then
+        echo "Failed to move /mnt/@root to old-roots"
+        umount /mnt
+        exit 1
+      fi
+    fi
+
+    # Function to recursively delete subvolumes
+    delete_subvolume_recursively() {
+      for i in $(btrfs subvolume list -o "$1" | cut -f 9- -d ' '); do
+        delete_subvolume_recursively "/mnt/$i"
+      done
+      if ! btrfs subvolume delete "$1"; then
+        echo "Failed to delete subvolume $1"
+      fi
+    }
+
+    # Delete old roots older than 30 days
+    for i in $(btrfs subvolume list /mnt | grep 'old-roots/@root-' | cut -f 9- -d ' '); do
+      subvol_time=$(echo "$i" | grep -o '[0-9]\{4\}-[0-9]\{2\}-[0-9]\{2\}_[0-9]\{2\}:[0-9]\{2\}:[0-9]\{2\}')
+      if [[ -n "$subvol_time" ]]; then
+        subvol_secs=$(date -d "$subvol_time" +%s 2>/dev/null || continue)
+        thirty_days_ago=$(date -d "30 days ago" +%s)
+        if [[ $subvol_secs -lt $thirty_days_ago ]]; then
+          delete_subvolume_recursively "/mnt/$i"
+        fi
+      fi
+    done
+
+    # Create or restore fresh root
+    if [[ -e /mnt/@root-blank ]]; then
+      btrfs subvolume delete /mnt/@root || true
+      if ! btrfs subvolume snapshot /mnt/@root-blank /mnt/@root; then
+        echo "Failed to snapshot @root-blank to @root"
+        umount /mnt
+        exit 1
+      fi
+    else
+      if ! btrfs subvolume create /mnt/@root-blank; then
+        echo "Failed to create @root-blank"
+        umount /mnt
+        exit 1
+      fi
+      if ! btrfs subvolume create /mnt/@root; then
+        echo "Failed to create @root"
+        umount /mnt
+        exit 1
+      fi
+    fi
+
+    # Unmount
+    if ! umount /mnt; then
+      echo "Failed to unmount /mnt"
+      exit 1
+    fi
+  '';
+
+  # Persistent directories for impermanence
+  fileSystems."/persist".neededForBoot = true;
+  fileSystems."/var/lib".neededForBoot = true;
+
+  environment.persistence."/persist" = {
+    hideMounts = true;
+
+    directories = [
+      "/etc/ssh"
+      "/srv"
+    ];
+
+    files = [
+      "/etc/machine-id"
+    ];
+
+    users.thomas.directories = [
+      ".ssh"
+      ".local/share"
+    ];
+  };
+}

Файловите разлики са ограничени, защото са твърде много
+ 0 - 5
hosts/odin/secrets.yaml


+ 69 - 0
hosts/odin/system.nix

@@ -0,0 +1,69 @@
+{ config, ... }:
+{
+  # Boot configuration
+  boot = {
+    # Use systemd-boot for UEFI systems
+    loader.systemd-boot.enable = true;
+    loader.efi.canTouchEfiVariables = true;
+    loader.grub.devices = [
+      config.disko.devices.disk.main.device
+    ];
+    loader.timeout = 3;
+
+    # Kernel parameters for server workload
+    kernelParams = [ "rootflags=compress=zstd:1,noatime" ];
+    kernelModules = [ "nct6775" ];
+
+    # Enable KSM for memory efficiency with containers
+    kernel.sysctl = {
+      "kernel.sysrq" = 1;
+      "vm.swappiness" = 10;
+      "net.core.default_qdisc" = "cake";
+    };
+  };
+
+  hardware.fancontrol = {
+    enable = true;
+    config = ''
+      INTERVAL=10
+      DEVPATH=hwmon1=devices/pci0000:00/0000:00:02.2/0000:04:00.0/nvme/nvme0 hwmon2=devices/platform/nct6775.656
+      DEVNAME=hwmon1=nvme hwmon2=nct6775
+      FCTEMPS=hwmon2/pwm7=hwmon1/temp1_input hwmon2/pwm2=hwmon1/temp1_input
+      FCFANS=hwmon2/pwm7=hwmon2/fan7_input hwmon2/pwm2=hwmon2/fan2_input
+      MINTEMP=hwmon2/pwm7=30 hwmon2/pwm2=30
+      MAXTEMP=hwmon2/pwm7=60 hwmon2/pwm2=60
+      MINSTART=hwmon2/pwm7=95 hwmon2/pwm2=150
+      MINSTOP=hwmon2/pwm7=75 hwmon2/pwm2=0
+    '';
+  };
+
+  services.hddfancontrol.enable = true;
+  services.hddfancontrol.settings = {
+    harddrives =
+      let
+        devices = config.disko.devices.disk;
+      in
+      {
+        disks = [
+          devices.storage1.device
+          devices.storage2.device
+          devices.storage3.device
+        ];
+        pwmPaths = [
+          "/sys/class/hwmon/hwmon2/pwm1:20:0"
+          "/sys/class/hwmon/hwmon2/pwm4:80:60"
+        ];
+        logVerbosity = "DEBUG";
+        extraArgs = [
+          "--min-fan-speed-prct=0"
+        ];
+      };
+  };
+
+  # Btrfs maintenance
+  services.btrfs.autoScrub = {
+    enable = true;
+    interval = "monthly";
+    fileSystems = [ "/" ];
+  };
+}

+ 3 - 1
lib/default.nix

@@ -65,13 +65,15 @@ rec {
         config
     );
 
-  eachSystem = lib.genAttrs [
+  allSystems = [
     "x86_64-linux"
     "x86_64-darwin"
     "aarch64-linux"
     "aarch64-darwin"
   ];
 
+  eachSystem = lib.genAttrs allSystems;
+
   eachSystemWithPkgs = f:
     eachSystem (
       system:

Някои файлове не бяха показани, защото твърде много файлове са промени