Procházet zdrojové kódy

feat(odin): doesn't work with mac

Zander Hawke před 9 měsíci
rodič
revize
d5249739b7

+ 59 - 1
flake.lock

@@ -77,6 +77,26 @@
         "type": "github"
       }
     },
+    "disko": {
+      "inputs": {
+        "nixpkgs": [
+          "nixpkgs"
+        ]
+      },
+      "locked": {
+        "lastModified": 1756115622,
+        "narHash": "sha256-iv8xVtmLMNLWFcDM/HcAPLRGONyTRpzL9NS09RnryRM=",
+        "owner": "nix-community",
+        "repo": "disko",
+        "rev": "bafad29f89e83b2d861b493aa23034ea16595560",
+        "type": "github"
+      },
+      "original": {
+        "owner": "nix-community",
+        "repo": "disko",
+        "type": "github"
+      }
+    },
     "flake-compat": {
       "flake": false,
       "locked": {
@@ -223,6 +243,21 @@
         "type": "github"
       }
     },
+    "impermanence": {
+      "locked": {
+        "lastModified": 1737831083,
+        "narHash": "sha256-LJggUHbpyeDvNagTUrdhe/pRVp4pnS6wVKALS782gRI=",
+        "owner": "nix-community",
+        "repo": "impermanence",
+        "rev": "4b3e914cdf97a5b536a889e939fb2fd2b043a170",
+        "type": "github"
+      },
+      "original": {
+        "owner": "nix-community",
+        "repo": "impermanence",
+        "type": "github"
+      }
+    },
     "ixx": {
       "inputs": {
         "flake-utils": [
@@ -387,11 +422,34 @@
       "inputs": {
         "darwin": "darwin",
         "devenv": "devenv",
+        "disko": "disko",
         "home-manager": "home-manager",
+        "impermanence": "impermanence",
         "nixpkgs": "nixpkgs",
         "nixpkgs-darwin": "nixpkgs-darwin",
         "nixpkgs-unstable": "nixpkgs-unstable",
-        "nixvim": "nixvim"
+        "nixvim": "nixvim",
+        "sops-nix": "sops-nix"
+      }
+    },
+    "sops-nix": {
+      "inputs": {
+        "nixpkgs": [
+          "nixpkgs"
+        ]
+      },
+      "locked": {
+        "lastModified": 1754988908,
+        "narHash": "sha256-t+voe2961vCgrzPFtZxha0/kmFSHFobzF00sT8p9h0U=",
+        "owner": "mic92",
+        "repo": "sops-nix",
+        "rev": "3223c7a92724b5d804e9988c6b447a0d09017d48",
+        "type": "github"
+      },
+      "original": {
+        "owner": "mic92",
+        "repo": "sops-nix",
+        "type": "github"
       }
     },
     "systems": {

+ 13 - 4
flake.nix

@@ -15,6 +15,15 @@
 
     nixvim.url = "github:nix-community/nixvim/nixos-25.05?shallow=true";
     nixvim.inputs.nixpkgs.follows = "nixpkgs";
+
+    impermanence.url = "github:nix-community/impermanence";
+    # impermanence.inputs.nixpkgs.follows = "nixpkgs";
+
+    sops-nix.url = "github:mic92/sops-nix?shallow=true";
+    sops-nix.inputs.nixpkgs.follows = "nixpkgs";
+
+    disko.url = "github:nix-community/disko?shallow=true";
+    disko.inputs.nixpkgs.follows = "nixpkgs";
   };
 
   outputs = { self, ... } @ inputs: rec {
@@ -46,10 +55,10 @@
       #   modules = [ ./hosts/modgud ];
       # };
 
-      # odin = lib.mkSystem {
-      #   system = "x86_64-linux";
-      #   modules = [ ./hosts/odin ];
-      # };
+      odin = lib.mkSystem {
+        system = "x86_64-linux";
+        modules = [ ./hosts/odin ];
+      };
     };
 
     darwinConfigurations = {

+ 351 - 0
hosts/odin/default.nix

@@ -0,0 +1,351 @@
+{ inputs, pkgs, lib, ... }:
+{
+  imports = [
+    # inputs.impermanence.nixosModules.impermanence
+    inputs.disko.nixosModules.disko
+
+    ./hardware-configuration.nix
+    ./disko.nix
+    # ./secrets.nix
+    # ./services
+  ];
+
+  # System identification
+  networking = {
+    hostName = "odin";
+    # Generate a unique host ID (you need to replace this with an actual string)
+    # hostId = "12345678"; # Generate with `head -c 8 /etc/machine-id` and place result here
+    useDHCP = lib.mkDefault true;
+
+    # Firewall configuration for home server
+    # firewall = {
+    #   enable = true;
+    #   allowedTCPPorts = [ 
+    #     22    # SSH
+    #     80    # HTTP
+    #     443   # HTTPS  
+    #     2283  # Immich
+    #   ];
+    # };
+  };
+
+  # # Boot configuration
+  # boot = {
+  #   # Use systemd-boot for UEFI systems
+  #   loader = {
+  #     systemd-boot.enable = true;
+  #     efi.canTouchEfiVariables = true;
+  #     timeout = 3;
+  #   };
+  #
+  #   # Kernel parameters for server workload
+  #   kernelParams = [ "rootflags=compress=zstd:1,noatime" ];
+  #
+  #   # 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 ''
+  #     # Get device from disko config
+  #     DEVICE=/dev/disk/by-id/nvme-KINGSTON_SNV3S1000G_50026B7383CC0908-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 optimizations
+  # hardware = {
+  #   enableRedistributableFirmware = true;
+  #   cpu.amd.updateMicrocode = true;
+  #
+  #   # Enable hardware acceleration for media processing
+  #   opengl = {
+  #     enable = true;
+  #     extraPackages = with pkgs; [
+  #       amdvlk
+  #       rocm-opencl-icd
+  #     ];
+  #   };
+  # };
+  #
+  # # Power management for home server
+  # powerManagement = {
+  #   enable = true;
+  #   cpuFreqGovernor = "ondemand";
+  # };
+
+  # Services configuration
+  services = {
+    # SSH configuration is managed in secrets.nix
+    openssh = {
+      enable = true;
+      settings = {
+        PasswordAuthentication = false;
+        PermitRootLogin = "no";
+        X11Forwarding = false;
+      };
+      # hostKeys = [ ];
+    };
+
+    # System monitoring
+    # smartd = {
+    #   enable = true;
+    #   autodetect = true;
+    #   notifications.mail.enable = false; # Configure if you want email alerts
+    # };
+
+    # # Time synchronization
+    # timesyncd.enable = true;
+    #
+    # # Btrfs maintenance
+    # btrfs.autoScrub = {
+    #   enable = true;
+    #   interval = "monthly";
+    #   fileSystems = [ "/" ];
+    # };
+    #
+    # # Drive power management and fan control
+    # hddfancontrol = {
+    #   enable = false;
+    #   settings = {
+    #     harddrives = {
+    #       disks = [
+    #         "/dev/disk/by-id/ata-ST8000VN002-2ZM188_WPV023WG"
+    #         "/dev/disk/by-id/ata-ST8000VN002-2ZM188_WPV07RMA"
+    #         "/dev/disk/by-id/ata-ST8000VN002-2ZM188_WPV020CG"
+    #       ];
+    #       pwmPaths = [
+    #         "/sys/class/hwmon/hwmon5/pwm1:25:10"
+    #       ];
+    #       logVerbosity = "DEBUG";
+    #     };
+    #   };
+    # };
+
+    # Drive spin-down management
+    # hdparm.devices = [
+    #   {
+    #     device = "/dev/disk/by-id/ata-ST8000VN002-2ZM188_WPV023WG";
+    #     spindownTime = 120; # 10 minutes
+    #     apmLevel = 127;
+    #   }
+    #   {
+    #     device = "/dev/disk/by-id/ata-ST8000VN002-2ZM188_WPV07RMA";
+    #     spindownTime = 120;
+    #     apmLevel = 127;
+    #   }
+    #   {
+    #     device = "/dev/disk/by-id/ata-ST8000VN002-2ZM188_WPV020CG";
+    #     spindownTime = 120;
+    #     apmLevel = 127;
+    #   }
+    # ];
+  };
+
+  # # Automatic garbage collection
+  # nix = {
+  #   gc = {
+  #     automatic = true;
+  #     dates = "weekly";
+  #     options = "--delete-older-than 30d";
+  #   };
+  #   optimise.automatic = true;
+  # };
+
+  # # Container runtime
+  # virtualisation = {
+  #   docker = {
+  #     enable = true;
+  #     storageDriver = "btrfs";
+  #     autoPrune = {
+  #       enable = true;
+  #       dates = "weekly";
+  #       flags = [ "--all" "--force" "--volumes" ];
+  #     };
+  #   };
+  # };
+
+  # System packages
+  environment.systemPackages = with pkgs; [
+    # System utilities
+    htop
+    btop
+    iotop
+    lsof
+    pciutils
+    usbutils
+
+    # Network tools
+    curl
+    wget
+    rsync
+
+    # File system tools
+    btrfs-progs
+    xfsprogs
+    smartmontools
+    hdparm
+
+    # # Container tools
+    # docker-compose
+
+    # Storage management
+    snapraid
+    mergerfs
+
+    # Monitoring
+    lm_sensors
+    nvme-cli
+  ];
+
+  # User configuration
+  users = {
+    mutableUsers = false; # Declarative user management
+    users = {
+      # Main user account
+      thomas = {
+        isNormalUser = true;
+        extraGroups = [ "wheel" "users" ];
+        hashedPassword = "$6$jO/t4PtMb4Ky.goy$2diW2qZjswUAVAzRQqOJ7wfGwD9QInJtUfQYEOOp8hkdhAy6wcccYfIG.gEQniStx7ZkxADNQxQ7pyfUiOqll.";
+        openssh.authorizedKeys.keys = [
+          "ssh-rsa AAAAB3NzaC1yc2EAAAADAQABAAACAQC5o7LT5wPYWgI8Mvr6RKOv+BcsbQgU7PCw2hheVu17alwF1uFUsAYV5BVQu+uv9uEm/UDsCNhfM6TwI0A1prdmtBz4pKiwXbj7fcdp6DcVOgTsPfawbXEpivtJvlhEatyTsR26MjHKnqpT0BxPvj6Ug6pvRkCYW5d2bWXiY9murmAX6Q5kSyNunkB8PdRTH+S47f7eOdCJY63VBOkkiG8M7XyPwFCDTYiHhbMZcejIdY9mB6kYnMQVRHDznQWiQxrcaE1fD/TY3db9GDcOVoo2aDBOZX7WT2+me67sU8dEK9+nSyhWDzBbEs8knu87ZlKPFwhl4slenRniKhbf22OpicXArtEcjEj0GyDJH5e+ZCIQ4eSQanA7TxnKFlDuaf+Qqx55UT+ya4vJJeik7nkzbRHaE9IoWhhiOaOnaN6kHIxuxB6z7EL3Gk7f78+I/qBaj5df6fgnXM3JBXKa5bRH2wqoSetJAo6EGpEgmU2huB1ktiGlO7BlF5XwSw6cb/KT7NSIXhncgLkCzsDVXxecVQv1FnPISBcp3+ti01ADVf2trgpPDbNTWV40Rgiefie0o2fc6KWAFfum1j5N3WWU+XVVmRjDmKKHiEJBLNKDAe0rQf+tryPW4c5GIN7aFoB+8dYFAuUyLd7Fu3vhZdmcckN5ryHunEc0dKPIiuoVZw=="
+        ];
+      };
+    };
+  };
+
+  # File system mounts for impermanence
+  fileSystems = {
+    # Boot partition
+    "/boot" = {
+      device = "/dev/disk/by-id/nvme-KINGSTON_SNV3S1000G_50026B7383CC0908-part1";
+      fsType = "vfat";
+    };
+
+    # Root filesystem
+    "/" = {
+      device = "/dev/disk/by-id/nvme-KINGSTON_SNV3S1000G_50026B7383CC0908-part2";
+      fsType = "btrfs";
+      options = [ "subvol=@root" "compress=zstd:1" "noatime" ];
+    };
+
+    # Nix store
+    "/nix" = {
+      device = "/dev/disk/by-id/nvme-KINGSTON_SNV3S1000G_50026B7383CC0908-part2";
+      fsType = "btrfs";
+      options = [ "subvol=@nix" "compress=zstd:1" "noatime" ];
+    };
+
+    # Home directory
+    "/home" = {
+      device = "/dev/disk/by-id/nvme-KINGSTON_SNV3S1000G_50026B7383CC0908-part2";
+      fsType = "btrfs";
+      options = [ "subvol=@home" "compress=zstd:1" "noatime" ];
+    };
+
+    # Persistent data
+    "/persist" = {
+      device = "/dev/disk/by-id/nvme-KINGSTON_SNV3S1000G_50026B7383CC0908-part2";
+      fsType = "btrfs";
+      options = [ "subvol=@persist" "compress=zstd:1" "noatime" ];
+      neededForBoot = true;
+    };
+
+    # Logs
+    "/logs" = {
+      device = "/dev/disk/by-id/nvme-KINGSTON_SNV3S1000G_50026B7383CC0908-part2";
+      fsType = "btrfs";
+      options = [ "subvol=@logs" "compress=zstd:1" "noatime" ];
+    };
+
+    # Services data
+    "/services" = {
+      device = "/dev/disk/by-id/nvme-KINGSTON_SNV3S1000G_50026B7383CC0908-part2";
+      fsType = "btrfs";
+      options = [ "subvol=@services" "compress=zstd:1" "noatime" ];
+    };
+
+    # Database storage - nodatacow for performance
+    "/databases" = {
+      device = "/dev/disk/by-id/nvme-KINGSTON_SNV3S1000G_50026B7383CC0908-part2";
+      fsType = "btrfs";
+      options = [ "subvol=@databases" "compress=zstd:1" "noatime" "nodatacow" ];
+    };
+
+    # Cache storage - nodatacow for performance
+    "/cache" = {
+      device = "/dev/disk/by-id/nvme-KINGSTON_SNV3S1000G_50026B7383CC0908-part2";
+      fsType = "btrfs";
+      options = [ "subvol=@cache" "compress=zstd:1" "noatime" "nodatacow" ];
+    };
+
+    # Container storage - nodatacow for performance
+    "/containers" = {
+      device = "/dev/disk/by-id/nvme-KINGSTON_SNV3S1000G_50026B7383CC0908-part2";
+      fsType = "btrfs";
+      options = [ "subvol=@containers" "compress=zstd:1" "noatime" "nodatacow" ];
+    };
+  };
+
+  # # Persistent directories for impermanence
+  # environment.persistence."/persist" = {
+  #   hideMounts = true;
+  #   directories = [
+  #     "/etc/nixos"
+  #     "/etc/ssh"
+  #     "/var/lib/nixos"
+  #     "/var/lib/systemd"
+  #     "/srv"
+  #   ];
+  #   files = [
+  #     "/etc/machine-id"
+  #   ];
+  #   users.thomas = {
+  #     directories = [
+  #       ".ssh"
+  #       ".config"
+  #     ];
+  #   };
+  # };
+
+  # System state version
+  system.stateVersion = "25.05";
+}

+ 90 - 0
hosts/odin/disko.nix

@@ -0,0 +1,90 @@
+{ 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
+
+{
+  disko.devices = {
+    disk = {
+      # Root system drive (1TB NVMe)
+      main = {
+        type = "disk";
+        device = "/dev/disk/by-id/${mainDiskId}";
+        content = {
+          type = "gpt";
+          partitions = {
+            # EFI boot partition
+            efi = {
+              size = "1G";
+              type = "EF00";
+              content = {
+                type = "filesystem";
+                format = "vfat";
+                mountpoint = "/boot";
+              };
+            };
+
+            # Main Btrfs partition
+            root = {
+              end = "-0";
+              content = {
+                type = "btrfs";
+                extraArgs = [ "-f" ];
+                subvolumes = {
+                  # Blank root template for ephemeral setup
+                  "@root-blank" = { };
+                } // lib.listToAttrs (map mkSubvolume (regular ++ noDataCow));
+              };
+            };
+          };
+        };
+      };
+
+    } // lib.listToAttrs (lib.imap1
+      (i: diskId: {
+        name = "storage${toString i}";
+        value = {
+          type = "disk";
+          device = "/dev/disk/by-id/${diskId}";
+          content = {
+            type = "gpt";
+            partitions = {
+              primary = {
+                size = "100%";
+                content = {
+                  type = "filesystem";
+                  format = "xfs";
+                  mountpoint = "/mnt/disk${toString i}";
+                  mountOptions = [ "defaults" "noatime" ];
+                };
+              };
+            };
+          };
+        };
+      })
+      storageDisks);
+  };
+}

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

@@ -0,0 +1,18 @@
+{ 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;
+}

+ 50 - 0
hosts/odin/services/default.nix

@@ -0,0 +1,50 @@
+# { config, pkgs, ... }:
+
+{
+  imports = [
+    # ./immich.nix
+    # ./snapraid.nix
+    # ./mergerfs.nix
+    # Add more services as you create them
+    # ./jellyfin.nix
+    # ./nextcloud.nix
+    # ./traefik.nix
+  ];
+
+  # # Common service setup
+  # systemd.tmpfiles.rules = [
+  #   # Service directories
+  #   "d /srv 0755 root root -"
+  #   "d /srv/immich 0755 root root -"
+  #   "d /srv/media 0755 root root -"
+  #   "d /srv/web 0755 root root -"
+  #   "d /srv/monitoring 0755 root root -"
+  #
+  #   # Database directories
+  #   "d /databases 0755 root root -"
+  #   "d /databases/postgresql 0755 postgres postgres -"
+  #   "d /databases/redis 0755 redis redis -"
+  #
+  #   # Cache directories
+  #   "d /cache 0755 root root -"
+  #   "d /cache/immich 0755 root root -"
+  #
+  #   # Log directories
+  #   "d /logs 0755 root root -"
+  #   "d /logs/services 0755 root root -"
+  #
+  #   # Storage array structure
+  #   "d /storage 0755 root root -"
+  #   "d /storage/media 0755 root root -"
+  #   "d /storage/backups 0755 root root -"
+  #   "d /storage/photos 0755 root root -"
+  # ];
+  #
+  # # MergerFS for unified storage view
+  # services.mergerfs.mounts = {
+  #   "/storage" = {
+  #     branches = [ "/mnt/disk1" "/mnt/disk2" "/mnt/disk3" ];
+  #     options = "defaults,allow_other,use_ino,cache.files=partial,dropcacheonclose=true,category.create=mfs";
+  #   };
+  # };
+}

+ 1 - 2
lib/default.nix

@@ -19,12 +19,11 @@ in
 rec {
   mkSystem =
     { system
-    , nixpkgs ? nixpkgs
     , modules ? [ ]
     ,
     }:
     lib.nixosSystem {
-      inherit system modules nixpkgs;
+      inherit system modules;
       specialArgs = { inherit inputs outputs; };
     };