diff --git a/.gitea/workflows/iso-builder.yml b/.gitea/workflows/iso-builder.yml new file mode 100644 index 0000000..2483da5 --- /dev/null +++ b/.gitea/workflows/iso-builder.yml @@ -0,0 +1,60 @@ +name: Build NixOS ISOs + +on: + push: + paths: + - hosts/eva-01/** + - hosts/armaros/** + - flake.nix + - flake.lock + - .gitea/workflows/iso-builder.yml + workflow_dispatch: + inputs: + upload-artifact: + description: "Upload the ISOs as artifacts" + type: boolean + default: true + +jobs: + build-iso: + strategy: + matrix: + host: + - eva-01 + - armaros + runs-on: x86_64-linux + steps: + - name: Checkout repository + uses: actions/checkout@v4 + + - name: Install Nix + uses: cachix/install-nix-action@v27 + with: + nix_path: nixpkgs=channel:nixos-unstable + extra_nix_config: | + experimental-features = nix-command flakes + download-buffer-size = 200000000 + auto-optimise-store = true + + - name: Build ${{ matrix.host }} ISO + run: | + nix build \ + .#nixosConfigurations.${{ matrix.host }}-iso.config.system.build.isoImage \ + --print-build-logs \ + --out-link iso-result + + - name: Show ${{ matrix.host }} ISO info + run: | + echo "ISO built successfully:" + ls -lh iso-result/iso/ + echo "" + echo "SHA256:" + sha256sum iso-result/iso/*.iso + + - name: Upload ${{ matrix.host }} ISO artifact + if: ${{ github.event_name != 'workflow_dispatch' || inputs.upload-artifact }} + uses: actions/upload-artifact@v4 + with: + name: ${{ matrix.host }}-installer-iso + path: iso-result/iso/*.iso + retention-days: 7 diff --git a/flake.lock b/flake.lock index 8bede17..004557b 100644 --- a/flake.lock +++ b/flake.lock @@ -19,6 +19,26 @@ "type": "github" } }, + "disko": { + "inputs": { + "nixpkgs": [ + "nixpkgs" + ] + }, + "locked": { + "lastModified": 1780048612, + "narHash": "sha256-Md/eOK5OjmvvHc2H52pLZe4zpP4XyfiS5vHqfRCz2HU=", + "owner": "nix-community", + "repo": "disko", + "rev": "caa775cf67bfdc47f940edd96c975b5016df9059", + "type": "github" + }, + "original": { + "owner": "nix-community", + "repo": "disko", + "type": "github" + } + }, "flake-compat": { "locked": { "lastModified": 1733328505, @@ -77,11 +97,11 @@ ] }, "locked": { - "lastModified": 1768135262, - "narHash": "sha256-PVvu7OqHBGWN16zSi6tEmPwwHQ4rLPU9Plvs8/1TUBY=", + "lastModified": 1778716662, + "narHash": "sha256-m1Yf0wZ8j1OHjTc2UwHwyQRSnNeSgLJOd7q5Y45hzi4=", "owner": "hercules-ci", "repo": "flake-parts", - "rev": "80daad04eddbbf5a4d883996a73f3f542fa437ac", + "rev": "f7c1a2d347e4c52d5fb8d10cb4d94b5884e546fb", "type": "github" }, "original": { @@ -90,24 +110,6 @@ "type": "github" } }, - "flake-utils": { - "inputs": { - "systems": "systems" - }, - "locked": { - "lastModified": 1731533236, - "narHash": "sha256-l0KFg5HjrsfsO/JpG+r7fRrqm12kzFHyUHqHCVpMMbI=", - "owner": "numtide", - "repo": "flake-utils", - "rev": "11707dc2f618dd54ca8739b309ec4fc024de578b", - "type": "github" - }, - "original": { - "owner": "numtide", - "repo": "flake-utils", - "type": "github" - } - }, "home-manager": { "inputs": { "nixpkgs": [ @@ -115,16 +117,16 @@ ] }, "locked": { - "lastModified": 1779506708, - "narHash": "sha256-QOD/CNm196nCJRheux/URi4/HE66fthdOMqCJoPP1Y0=", + "lastModified": 1779726825, + "narHash": "sha256-RUkMrREjKDQrA+dA9+xZviGAxM5W1aVdyOr/bSYpHrE=", "owner": "nix-community", "repo": "home-manager", - "rev": "3ee51fbdac8c8bdfe1e7e1fcaba6520a563f394f", + "rev": "b179bde238977f7d4454fc770b1a727eaf55111c", "type": "github" }, "original": { "owner": "nix-community", - "ref": "release-25.11", + "ref": "release-26.05", "repo": "home-manager", "type": "github" } @@ -136,51 +138,24 @@ ] }, "locked": { - "lastModified": 1779726696, - "narHash": "sha256-/p37CB5n6Wpw250b0Lq0CYwNq2D8uGKzDoBulyLcQqA=", + "lastModified": 1780099287, + "narHash": "sha256-efIPwVGtIWIjWcznhaop6XN6HxnOL8800hF6CBNvlqQ=", "owner": "nix-community", "repo": "home-manager", - "rev": "1a95e2efb477959b70b4a14c51035975c0481df6", + "rev": "7d8127d308c3fb9664f7e643eec944be74ebb37d", "type": "github" }, "original": { "owner": "nix-community", + "ref": "master", "repo": "home-manager", "type": "github" } }, - "ixx": { - "inputs": { - "flake-utils": [ - "nixvim", - "nuschtosSearch", - "flake-utils" - ], - "nixpkgs": [ - "nixvim", - "nuschtosSearch", - "nixpkgs" - ] - }, - "locked": { - "lastModified": 1754860581, - "narHash": "sha256-EM0IE63OHxXCOpDHXaTyHIOk2cNvMCGPqLt/IdtVxgk=", - "owner": "NuschtOS", - "repo": "ixx", - "rev": "babfe85a876162c4acc9ab6fb4483df88fa1f281", - "type": "github" - }, - "original": { - "owner": "NuschtOS", - "ref": "v0.1.1", - "repo": "ixx", - "type": "github" - } - }, "nix-darwin": { "inputs": { "nixpkgs": [ - "nixpkgs-unstable" + "nixpkgs" ] }, "locked": { @@ -193,7 +168,7 @@ }, "original": { "owner": "nix-darwin", - "ref": "master", + "ref": "nix-darwin-26.05", "repo": "nix-darwin", "type": "github" } @@ -219,12 +194,15 @@ } }, "nixos-hardware": { + "inputs": { + "nixpkgs": "nixpkgs_3" + }, "locked": { - "lastModified": 1779258371, - "narHash": "sha256-j1iZsLy6oFApqR1oiDmHhvkwxXqcNi0aoSJj643LuwU=", + "lastModified": 1780065812, + "narHash": "sha256-SCSLUKBmwlSLGQ8Xbr8PjRFtiHNk0l9ktqkcmqdBkfE=", "owner": "NixOS", "repo": "nixos-hardware", - "rev": "c97bc4d15bd3473dd095e8e8ba57330ab1943a77", + "rev": "b76b5639c0593e0aeb0b5879ad62d4b30596c144", "type": "github" }, "original": { @@ -313,16 +291,45 @@ }, "nixpkgs_3": { "locked": { - "lastModified": 1779467186, - "narHash": "sha256-nOesoDCiXcUftqbRBMz9tt4blI5PvljMWbm3kuCA+0s=", + "lastModified": 1767892417, + "narHash": "sha256-8bW3q88CEg2u4hSP66Vf4lpbLonHz7hqDNBMcCY7E9U=", + "rev": "3497aa5c9457a9d88d71fa93a4a8368816fbeeba", + "type": "tarball", + "url": "https://releases.nixos.org/nixos/unstable/nixos-26.05pre924538.3497aa5c9457/nixexprs.tar.xz" + }, + "original": { + "type": "tarball", + "url": "https://channels.nixos.org/nixos-unstable/nixexprs.tar.xz" + } + }, + "nixpkgs_4": { + "locked": { + "lastModified": 1779971959, + "narHash": "sha256-R5nauXyqyfRUFiZycFFZdkF7wl6eaUpPLst35+2nJQY=", "owner": "nixos", "repo": "nixpkgs", - "rev": "b77b3de8775677f84492abe84635f87b0e153f0f", + "rev": "ec942ba042dad5ef097e2ef3a3effc034241f011", "type": "github" }, "original": { "owner": "nixos", - "ref": "nixos-25.11", + "ref": "nixos-26.05", + "repo": "nixpkgs", + "type": "github" + } + }, + "nixpkgs_5": { + "locked": { + "lastModified": 1779259093, + "narHash": "sha256-7DKWmH23hL2eYdkxCKeqj2i+yljTKuU+3Nk1UPHOnxc=", + "owner": "NixOS", + "repo": "nixpkgs", + "rev": "d99b013d5d1931ad77fe3912ed218170dec5d9a4", + "type": "github" + }, + "original": { + "owner": "NixOS", + "ref": "nixpkgs-unstable", "repo": "nixpkgs", "type": "github" } @@ -330,59 +337,34 @@ "nixvim": { "inputs": { "flake-parts": "flake-parts_3", - "nixpkgs": [ - "nixpkgs" - ], - "nuschtosSearch": "nuschtosSearch", - "systems": "systems_2" + "nixpkgs": "nixpkgs_5", + "systems": "systems" }, "locked": { - "lastModified": 1769049374, - "narHash": "sha256-h0Os2qqNyycDY1FyZgtbn28VF1ySP74/n0f+LDd8j+w=", + "lastModified": 1780169111, + "narHash": "sha256-XDlj8d20NnLcQLaG8JW7hgEQbwBVTtjh/Qs6e6IGAyU=", "owner": "nix-community", "repo": "nixvim", - "rev": "b8f76bf5751835647538ef8784e4e6ee8deb8f95", + "rev": "ac4e5d370f55e2c3e9a27eaad9d6923fdff41b53", "type": "github" }, "original": { "owner": "nix-community", - "ref": "nixos-25.11", + "ref": "nixos-26.05", "repo": "nixvim", "type": "github" } }, - "nuschtosSearch": { - "inputs": { - "flake-utils": "flake-utils", - "ixx": "ixx", - "nixpkgs": [ - "nixvim", - "nixpkgs" - ] - }, - "locked": { - "lastModified": 1768249818, - "narHash": "sha256-ANfn5OqIxq3HONPIXZ6zuI5sLzX1sS+2qcf/Pa0kQEc=", - "owner": "NuschtOS", - "repo": "search", - "rev": "b6f77b88e9009bfde28e2130e218e5123dc66796", - "type": "github" - }, - "original": { - "owner": "NuschtOS", - "repo": "search", - "type": "github" - } - }, "root": { "inputs": { "comfyui-nix": "comfyui-nix", + "disko": "disko", "home-manager": "home-manager", "home-manager-unstable": "home-manager-unstable", "nix-darwin": "nix-darwin", "nix-snapd": "nix-snapd", "nixos-hardware": "nixos-hardware", - "nixpkgs": "nixpkgs_3", + "nixpkgs": "nixpkgs_4", "nixpkgs-unstable": "nixpkgs-unstable", "nixvim": "nixvim" } @@ -401,21 +383,6 @@ "repo": "default", "type": "github" } - }, - "systems_2": { - "locked": { - "lastModified": 1681028828, - "narHash": "sha256-Vy1rq5AaRuLzOxct8nz4T6wlgyUR7zLU309k9mBC768=", - "owner": "nix-systems", - "repo": "default", - "rev": "da67096a3b9bf56a91d16901293e51ba5b49a27e", - "type": "github" - }, - "original": { - "owner": "nix-systems", - "repo": "default", - "type": "github" - } } }, "root": "root", diff --git a/flake.nix b/flake.nix index b8b5b18..68cf283 100644 --- a/flake.nix +++ b/flake.nix @@ -2,33 +2,37 @@ description = "Nixos Config Flake"; inputs = { - nixpkgs.url = "github:nixos/nixpkgs/nixos-25.11"; + nixpkgs.url = "github:nixos/nixpkgs/nixos-26.05"; nixpkgs-unstable.url = "github:nixos/nixpkgs/nixos-unstable"; - nix-darwin.url = "github:nix-darwin/nix-darwin/master"; - nix-darwin.inputs.nixpkgs.follows = "nixpkgs-unstable"; + nix-darwin.url = "github:nix-darwin/nix-darwin/nix-darwin-26.05"; + nix-darwin.inputs.nixpkgs.follows = "nixpkgs"; nix-snapd.url = "github:nix-community/nix-snapd"; comfyui-nix.url = "github:utensils/comfyui-nix"; #nix-snapd.inputs.pkgs-unstable.follows = "nixpkgs"; home-manager = { - url = "github:nix-community/home-manager/release-25.11"; + url = "github:nix-community/home-manager/release-26.05"; inputs.nixpkgs.follows = "nixpkgs"; }; home-manager-unstable = { - url = "github:nix-community/home-manager/"; + url = "github:nix-community/home-manager/master"; inputs.nixpkgs.follows = "nixpkgs-unstable"; }; nixvim = { - url = "github:nix-community/nixvim/nixos-25.11"; - inputs.nixpkgs.follows = "nixpkgs"; + url = "github:nix-community/nixvim/nixos-26.05"; }; nixos-hardware = { url = "github:NixOS/nixos-hardware/master"; #inputs.nixpkgs.follows = "nixpkgs"; }; + + disko = { + url = "github:nix-community/disko"; + inputs.nixpkgs.follows = "nixpkgs"; + }; }; outputs = { @@ -42,6 +46,7 @@ nixpkgs, nixpkgs-unstable, nixvim, + disko, ... } @ inputs: let system = "x86_64-linux"; @@ -71,6 +76,27 @@ then "macos" else "linux-desktop"; }; + + # Hosts that have rescue/installer ISOs + isoHosts = ["acheron" "armaros" "buildbox" "eva-01" "eva-03"]; + + # Build a rescue/installer ISO configuration for a host + mkIso = hostname: { + specialArgs = { + inherit inputs configPath hostTypes; + pkgs-unstable = import nixpkgs-unstable { + inherit system; + config.allowUnfree = true; + }; + hostname = "${hostname}-iso"; + }; + inherit system; + modules = [ + "${nixpkgs}/nixos/modules/installer/cd-dvd/installation-cd-minimal.nix" + ./hosts/${hostname}/iso.nix + inputs.disko.nixosModules.disko + ]; + }; in { nixosConfigurations = { acheron = nixpkgs.lib.nixosSystem { @@ -82,6 +108,7 @@ modules = [ ./hosts/acheron/configuration.nix inputs.home-manager.nixosModules.default + inputs.disko.nixosModules.disko ]; }; @@ -94,6 +121,7 @@ modules = [ ./hosts/armaros/configuration.nix inputs.home-manager.nixosModules.default + inputs.disko.nixosModules.disko ]; }; @@ -106,6 +134,7 @@ modules = [ ./hosts/buildbox/configuration.nix inputs.home-manager.nixosModules.default + inputs.disko.nixosModules.disko ]; }; @@ -119,6 +148,7 @@ ./hosts/ender-ml/configuration.nix inputs.home-manager.nixosModules.default comfyui-nix.nixosModules.default + inputs.disko.nixosModules.disko ]; }; @@ -134,6 +164,7 @@ nixos-hardware.nixosModules.lenovo-thinkpad-x1-nano-gen1 nix-snapd.nixosModules.default {services.snap.enable = true;} + inputs.disko.nixosModules.disko ]; }; @@ -147,9 +178,15 @@ ./hosts/eva-03/configuration.nix inputs.home-manager.nixosModules.default comfyui-nix.nixosModules.default + inputs.disko.nixosModules.disko ]; }; - }; + } + # ── Rescue / installer ISOs (generated) ────────────────────── + // builtins.listToAttrs (map (name: { + name = "${name}-iso"; + value = nixpkgs.lib.nixosSystem (mkIso name); + }) isoHosts); darwinConfigurations = { eva-02 = nix-darwin.lib.darwinSystem { @@ -165,7 +202,7 @@ system = "aarch64-darwin"; modules = [ ./hosts/eva-02/configuration.nix - inputs.home-manager-unstable.darwinModules.home-manager + inputs.home-manager.darwinModules.home-manager ]; }; }; diff --git a/home-manager/commands/commands.nix b/home-manager/commands/commands.nix index bca407c..0e4171b 100644 --- a/home-manager/commands/commands.nix +++ b/home-manager/commands/commands.nix @@ -196,13 +196,11 @@ ssh = { enable = true; enableDefaultConfig = false; - matchBlocks = + settings = { "*" = { - setEnv = { - TERM = "xterm-256color"; - }; + setEnv = "TERM=xterm-256color"; forwardAgent = false; forwardX11 = false; serverAliveInterval = 0; diff --git a/home-manager/commands/fastfetch/fastfetch.nix b/home-manager/commands/fastfetch/fastfetch.nix index 48e4148..d97aa28 100644 --- a/home-manager/commands/fastfetch/fastfetch.nix +++ b/home-manager/commands/fastfetch/fastfetch.nix @@ -7,6 +7,7 @@ # Map hostnames to their image files hostImages = { "acheron" = "${configPath}/assets/pfp/nerv-color.png"; + "armaros" = "${configPath}/assets/pfp/nerv-color.png"; "buildbox" = "${configPath}/assets/pfp/nerv-color.png"; "ender-ml" = "${configPath}/assets/pfp/nerv-color.png"; "eva-01" = "${configPath}/assets/pfp/eva-01.jpg"; diff --git a/home-manager/home.nix b/home-manager/home.nix index 7d4099d..25fb6be 100644 --- a/home-manager/home.nix +++ b/home-manager/home.nix @@ -28,7 +28,7 @@ # You should not change this value, even if you update Home Manager. If you do # want to update the value, then make sure to first check the Home Manager # release notes. - home.stateVersion = "25.05"; # Please read the comment before changing. + home.stateVersion = "26.05"; # Please read the comment before changing. nixpkgs.config.allowUnfree = true; diff --git a/hosts/acheron/configuration.nix b/hosts/acheron/configuration.nix index f854bbb..e3a18ac 100644 --- a/hosts/acheron/configuration.nix +++ b/hosts/acheron/configuration.nix @@ -56,6 +56,13 @@ algorithm = "zstd"; }; + # Btrfs auto-scrub + services.btrfs.autoScrub = { + enable = true; + interval = "weekly"; + fileSystems = ["/" "/home" "/nix"]; + }; + # Set your time zone. time.timeZone = "America/Los_Angeles"; @@ -134,6 +141,7 @@ # $ nix search wget environment.systemPackages = with pkgs; [ # System-level only — CLI tools moved to home-manager + btrfs-progs ]; home-manager = { @@ -152,5 +160,5 @@ backupFileExtension = "backup"; }; - system.stateVersion = "25.11"; + system.stateVersion = "26.05"; } diff --git a/hosts/acheron/disko-config.nix b/hosts/acheron/disko-config.nix new file mode 100644 index 0000000..57252f9 --- /dev/null +++ b/hosts/acheron/disko-config.nix @@ -0,0 +1,65 @@ +# ── acheron disk layout ───────────────────────────────────────── +# Server/VM: Btrfs with subvolumes for snapshot-capable root, home, +# nix store, logs, and snapshot directory. +# +# Run from rescue ISO: +# disko --mode disko /etc/disko-config.nix +{ + disko.devices = { + disk = { + main = { + type = "disk"; + device = "/dev/vda"; + content = { + type = "gpt"; + partitions = { + root = { + size = "100%"; + content = { + type = "btrfs"; + extraArgs = [ "-f" ]; + subvolumes = { + "/root" = { + mountpoint = "/"; + mountOptions = [ + "compress=zstd" + "noatime" + ]; + }; + "/home" = { + mountpoint = "/home"; + mountOptions = [ + "compress=zstd" + "noatime" + ]; + }; + "/nix" = { + mountpoint = "/nix"; + mountOptions = [ + "compress=zstd" + "noatime" + ]; + }; + "/var-log" = { + mountpoint = "/var/log"; + mountOptions = [ + "compress=zstd" + "noatime" + ]; + }; + "/snapshots" = { + mountpoint = "/.snapshots"; + mountOptions = [ + "compress=zstd" + "noatime" + ]; + }; + }; + }; + }; + }; + }; + }; + }; + }; +} diff --git a/hosts/acheron/hardware-configuration.nix b/hosts/acheron/hardware-configuration.nix new file mode 100644 index 0000000..e27e852 --- /dev/null +++ b/hosts/acheron/hardware-configuration.nix @@ -0,0 +1,62 @@ +# Do not modify this file! It was generated by 'nixos-generate-config' +# and may be overwritten by future invocations. Please make changes +# to /etc/nixos/configuration.nix instead. +{ + config, + lib, + pkgs, + modulesPath, + ... +}: { + imports = [ + (modulesPath + "/profiles/qemu-guest.nix") + ]; + + boot.initrd.availableKernelModules = ["virtio_pci" "virtio_scsi" "ahci" "sd_mod"]; + boot.initrd.kernelModules = ["btrfs"]; + boot.kernelModules = []; + boot.extraModulePackages = []; + + fileSystems."/" = { + device = "/dev/disk/by-partuuid/REPLACE-ME"; + fsType = "btrfs"; + options = [ "subvol=root" "compress=zstd" "noatime" ]; + }; + + fileSystems."/home" = { + device = "/dev/disk/by-partuuid/REPLACE-ME"; + fsType = "btrfs"; + options = [ "subvol=home" "compress=zstd" "noatime" ]; + }; + + fileSystems."/nix" = { + device = "/dev/disk/by-partuuid/REPLACE-ME"; + fsType = "btrfs"; + options = [ "subvol=nix" "compress=zstd" "noatime" ]; + }; + + fileSystems."/var/log" = { + device = "/dev/disk/by-partuuid/REPLACE-ME"; + fsType = "btrfs"; + options = [ "subvol=var-log" "compress=zstd" "noatime" ]; + neededForBoot = false; + }; + + fileSystems."/.snapshots" = { + device = "/dev/disk/by-partuuid/REPLACE-ME"; + fsType = "btrfs"; + options = [ "subvol=snapshots" "compress=zstd" "noatime" ]; + neededForBoot = false; + }; + + swapDevices = [ + { + device = "/var/lib/swapfile"; + size = 2 * 1024; + } + ]; + + networking.useDHCP = lib.mkDefault true; + + nixpkgs.hostPlatform = lib.mkDefault "x86_64-linux"; +} diff --git a/hosts/acheron/iso.nix b/hosts/acheron/iso.nix new file mode 100644 index 0000000..6b90c93 --- /dev/null +++ b/hosts/acheron/iso.nix @@ -0,0 +1,20 @@ +# ── acheron rescue / installer ISO ───────────────────────────── +{ + config, + pkgs, + pkgs-unstable, + lib, + ... +}: { + imports = [ + ./hardware-configuration.nix + ../iso/default.nix + ]; + + boot.loader.grub.enable = lib.mkDefault true; + boot.loader.grub.devices = ["nodev"]; + + iso.extraPackages = with pkgs; [ btrfs-progs ]; + iso.diskoConfig = ./disko-config.nix; + iso.description = "acheron Rescue ISO"; +} diff --git a/hosts/armaros/configuration.nix b/hosts/armaros/configuration.nix index 3075c8c..92ae14c 100644 --- a/hosts/armaros/configuration.nix +++ b/hosts/armaros/configuration.nix @@ -50,6 +50,13 @@ algorithm = "zstd"; }; + # Btrfs auto-scrub + services.btrfs.autoScrub = { + enable = true; + interval = "weekly"; + fileSystems = ["/" "/home" "/nix"]; + }; + # Set your time zone. time.timeZone = "America/Los_Angeles"; @@ -148,6 +155,7 @@ # GUI tools firefox putty + btrfs-progs ]; fonts.packages = with pkgs; [ @@ -171,5 +179,5 @@ backupFileExtension = "backup"; }; - system.stateVersion = "25.11"; + system.stateVersion = "26.05"; } diff --git a/hosts/armaros/disko-config.nix b/hosts/armaros/disko-config.nix new file mode 100644 index 0000000..18ca81a --- /dev/null +++ b/hosts/armaros/disko-config.nix @@ -0,0 +1,65 @@ +# ── armaros disk layout ───────────────────────────────────────── +# QEMU VM: Btrfs with subvolumes for snapshot-capable root, home, +# nix store, logs, and snapshot directory. +# +# Run from rescue ISO: +# disko --mode disko /etc/disko-config.nix +{ + disko.devices = { + disk = { + main = { + type = "disk"; + device = "/dev/vda"; + content = { + type = "gpt"; + partitions = { + root = { + size = "100%"; + content = { + type = "btrfs"; + extraArgs = [ "-f" ]; + subvolumes = { + "/root" = { + mountpoint = "/"; + mountOptions = [ + "compress=zstd" + "noatime" + ]; + }; + "/home" = { + mountpoint = "/home"; + mountOptions = [ + "compress=zstd" + "noatime" + ]; + }; + "/nix" = { + mountpoint = "/nix"; + mountOptions = [ + "compress=zstd" + "noatime" + ]; + }; + "/var-log" = { + mountpoint = "/var/log"; + mountOptions = [ + "compress=zstd" + "noatime" + ]; + }; + "/snapshots" = { + mountpoint = "/.snapshots"; + mountOptions = [ + "compress=zstd" + "noatime" + ]; + }; + }; + }; + }; + }; + }; + }; + }; + }; +} diff --git a/hosts/armaros/hardware-configuration.nix b/hosts/armaros/hardware-configuration.nix index ead1053..f2653c9 100644 --- a/hosts/armaros/hardware-configuration.nix +++ b/hosts/armaros/hardware-configuration.nix @@ -13,25 +13,50 @@ ]; boot.initrd.availableKernelModules = ["virtio_pci" "virtio_scsi" "ahci" "sd_mod"]; - boot.initrd.kernelModules = []; + boot.initrd.kernelModules = ["btrfs"]; boot.kernelModules = ["uinput"]; boot.extraModulePackages = []; fileSystems."/" = { - device = "/dev/disk/by-uuid/277eaf87-728c-4ebc-80f2-dcb7f915acff"; - fsType = "ext4"; + device = "/dev/disk/by-partuuid/REPLACE-ME"; + fsType = "btrfs"; + options = [ "subvol=root" "compress=zstd" "noatime" ]; + }; + + fileSystems."/home" = { + device = "/dev/disk/by-partuuid/REPLACE-ME"; + fsType = "btrfs"; + options = [ "subvol=home" "compress=zstd" "noatime" ]; + }; + + fileSystems."/nix" = { + device = "/dev/disk/by-partuuid/REPLACE-ME"; + fsType = "btrfs"; + options = [ "subvol=nix" "compress=zstd" "noatime" ]; + }; + + fileSystems."/var/log" = { + device = "/dev/disk/by-partuuid/REPLACE-ME"; + fsType = "btrfs"; + options = [ "subvol=var-log" "compress=zstd" "noatime" ]; + neededForBoot = false; + }; + + fileSystems."/.snapshots" = { + device = "/dev/disk/by-partuuid/REPLACE-ME"; + fsType = "btrfs"; + options = [ "subvol=snapshots" "compress=zstd" "noatime" ]; + neededForBoot = false; }; swapDevices = [ { device = "/var/lib/swapfile"; - size = 2 * 1024; # 2GB swap for lightweight VM + size = 2 * 1024; } ]; - # Enables DHCP on each ethernet and wireless interface. networking.useDHCP = lib.mkDefault true; nixpkgs.hostPlatform = lib.mkDefault "x86_64-linux"; - hardware.cpu.intel.updateMicrocode = lib.mkDefault config.hardware.enableRedistributableFirmware; } diff --git a/hosts/armaros/iso.nix b/hosts/armaros/iso.nix new file mode 100644 index 0000000..3a88a5a --- /dev/null +++ b/hosts/armaros/iso.nix @@ -0,0 +1,20 @@ +# ── armaros rescue / installer ISO ───────────────────────────── +{ + config, + pkgs, + pkgs-unstable, + lib, + ... +}: { + imports = [ + ./hardware-configuration.nix + ../iso/default.nix + ]; + + boot.loader.grub.enable = lib.mkDefault true; + boot.loader.grub.devices = ["nodev"]; + + iso.extraPackages = with pkgs; [ btrfs-progs ]; + iso.diskoConfig = ./disko-config.nix; + iso.description = "armaros Rescue ISO"; +} diff --git a/hosts/buildbox/configuration.nix b/hosts/buildbox/configuration.nix index 1270bfb..1437210 100644 --- a/hosts/buildbox/configuration.nix +++ b/hosts/buildbox/configuration.nix @@ -50,6 +50,13 @@ algorithm = "zstd"; }; + # Btrfs auto-scrub + services.btrfs.autoScrub = { + enable = true; + interval = "weekly"; + fileSystems = ["/" "/home" "/nix"]; + }; + # Set your time zone. time.timeZone = "America/Los_Angeles"; @@ -155,6 +162,7 @@ # $ nix search wget environment.systemPackages = with pkgs; [ # System-level only — CLI tools moved to home-manager + btrfs-progs ]; home-manager = { @@ -174,5 +182,5 @@ backupFileExtension = "backup"; }; - system.stateVersion = "25.11"; + system.stateVersion = "26.05"; } diff --git a/hosts/buildbox/disko-config.nix b/hosts/buildbox/disko-config.nix new file mode 100644 index 0000000..8cc8122 --- /dev/null +++ b/hosts/buildbox/disko-config.nix @@ -0,0 +1,65 @@ +# ── buildbox disk layout ──────────────────────────────────────── +# QEMU VM: Btrfs with subvolumes for snapshot-capable root, home, +# nix store, logs, and snapshot directory. +# +# Run from rescue ISO: +# disko --mode disko /etc/disko-config.nix +{ + disko.devices = { + disk = { + main = { + type = "disk"; + device = "/dev/vda"; + content = { + type = "gpt"; + partitions = { + root = { + size = "100%"; + content = { + type = "btrfs"; + extraArgs = [ "-f" ]; + subvolumes = { + "/root" = { + mountpoint = "/"; + mountOptions = [ + "compress=zstd" + "noatime" + ]; + }; + "/home" = { + mountpoint = "/home"; + mountOptions = [ + "compress=zstd" + "noatime" + ]; + }; + "/nix" = { + mountpoint = "/nix"; + mountOptions = [ + "compress=zstd" + "noatime" + ]; + }; + "/var-log" = { + mountpoint = "/var/log"; + mountOptions = [ + "compress=zstd" + "noatime" + ]; + }; + "/snapshots" = { + mountpoint = "/.snapshots"; + mountOptions = [ + "compress=zstd" + "noatime" + ]; + }; + }; + }; + }; + }; + }; + }; + }; + }; +} diff --git a/hosts/buildbox/hardware-configuration.nix b/hosts/buildbox/hardware-configuration.nix index 8c30787..65bc07f 100644 --- a/hosts/buildbox/hardware-configuration.nix +++ b/hosts/buildbox/hardware-configuration.nix @@ -1,4 +1,4 @@ -# Do not modify this file! It was generated by ‘nixos-generate-config’ +# Do not modify this file! It was generated by 'nixos-generate-config' # and may be overwritten by future invocations. Please make changes # to /etc/nixos/configuration.nix instead. { @@ -13,13 +13,40 @@ ]; boot.initrd.availableKernelModules = ["xhci_pci" "thunderbolt" "nvme" "uas" "sd_mod"]; - boot.initrd.kernelModules = []; + boot.initrd.kernelModules = ["btrfs"]; boot.kernelModules = []; boot.extraModulePackages = []; fileSystems."/" = { - device = "/dev/disk/by-uuid/2387c615-e566-44ed-a708-ebd407ee16f6"; - fsType = "ext4"; + device = "/dev/disk/by-partuuid/REPLACE-ME"; + fsType = "btrfs"; + options = [ "subvol=root" "compress=zstd" "noatime" ]; + }; + + fileSystems."/home" = { + device = "/dev/disk/by-partuuid/REPLACE-ME"; + fsType = "btrfs"; + options = [ "subvol=home" "compress=zstd" "noatime" ]; + }; + + fileSystems."/nix" = { + device = "/dev/disk/by-partuuid/REPLACE-ME"; + fsType = "btrfs"; + options = [ "subvol=nix" "compress=zstd" "noatime" ]; + }; + + fileSystems."/var/log" = { + device = "/dev/disk/by-partuuid/REPLACE-ME"; + fsType = "btrfs"; + options = [ "subvol=var-log" "compress=zstd" "noatime" ]; + neededForBoot = false; + }; + + fileSystems."/.snapshots" = { + device = "/dev/disk/by-partuuid/REPLACE-ME"; + fsType = "btrfs"; + options = [ "subvol=snapshots" "compress=zstd" "noatime" ]; + neededForBoot = false; }; swapDevices = [ @@ -29,10 +56,6 @@ } ]; - # Enables DHCP on each ethernet and wireless interface. In case of scripted networking - # (the default) this is the recommended approach. When using systemd-networkd it's - # still possible to use this option, but it's recommended to use it in conjunction - # with explicit per-interface declarations with `networking.interfaces..useDHCP`. networking.useDHCP = lib.mkDefault true; # networking.interfaces.wlp0s20f3.useDHCP = lib.mkDefault true; diff --git a/hosts/buildbox/iso.nix b/hosts/buildbox/iso.nix new file mode 100644 index 0000000..43eb620 --- /dev/null +++ b/hosts/buildbox/iso.nix @@ -0,0 +1,20 @@ +# ── buildbox rescue / installer ISO ──────────────────────────── +{ + config, + pkgs, + pkgs-unstable, + lib, + ... +}: { + imports = [ + ./hardware-configuration.nix + ../iso/default.nix + ]; + + boot.loader.grub.enable = lib.mkDefault true; + boot.loader.grub.devices = ["nodev"]; + + iso.extraPackages = with pkgs; [ btrfs-progs ]; + iso.diskoConfig = ./disko-config.nix; + iso.description = "buildbox Rescue ISO"; +} diff --git a/hosts/ender-ml/configuration.nix b/hosts/ender-ml/configuration.nix index c0843ab..0d7f359 100644 --- a/hosts/ender-ml/configuration.nix +++ b/hosts/ender-ml/configuration.nix @@ -242,5 +242,5 @@ backupFileExtension = "backup"; }; - system.stateVersion = "25.11"; + system.stateVersion = "26.05"; } diff --git a/hosts/eva-01/configuration.nix b/hosts/eva-01/configuration.nix index 74245bc..a9c96c1 100644 --- a/hosts/eva-01/configuration.nix +++ b/hosts/eva-01/configuration.nix @@ -75,7 +75,33 @@ services.btrfs.autoScrub = { enable = true; interval = "weekly"; - fileSystems = ["/"]; + fileSystems = ["/" "/home" "/nix"]; + }; + + # Snapper — automatic btrfs snapshots so you can roll back + services.snapper = { + enable = true; + # Snapshot / every hour, keep 10 hourly and 7 daily + rootConfig = '' + TIMELINE_CREATE="yes" + TIMELINE_CLEANUP="yes" + TIMELINE_MIN_AGE="1800" + TIMELINE_LIMIT_HOURLY="10" + TIMELINE_LIMIT_DAILY="7" + TIMELINE_LIMIT_MONTHLY="3" + TIMELINE_LIMIT_YEARLY="0" + ''; + # Snapshot /home every 4 hours + homeConfig = '' + SUBVOLUME="/home" + TIMELINE_CREATE="yes" + TIMELINE_CLEANUP="yes" + TIMELINE_MIN_AGE="14400" + TIMELINE_LIMIT_HOURLY="6" + TIMELINE_LIMIT_DAILY="14" + TIMELINE_LIMIT_MONTHLY="3" + TIMELINE_LIMIT_YEARLY="0" + ''; }; boot.kernel.sysctl = { @@ -304,5 +330,5 @@ backupFileExtension = "backup"; }; - system.stateVersion = "25.11"; # Did you read the comment? + system.stateVersion = "26.05"; # Did you read the comment? } diff --git a/hosts/eva-01/disko-config.nix b/hosts/eva-01/disko-config.nix new file mode 100644 index 0000000..286f0af --- /dev/null +++ b/hosts/eva-01/disko-config.nix @@ -0,0 +1,83 @@ +# ── eva-01 disk layout ────────────────────────────────────────── +# NVMe SSD with Btrfs subvolumes for snapshot-capable root, home, +# nix store, logs, and snapshot directory. +# +# Run from rescue ISO: +# disko --mode disko /etc/nixos/hosts/eva-01/disko-config.nix +{ + disko.devices = { + disk = { + main = { + type = "disk"; + device = "/dev/nvme0n1"; + content = { + type = "gpt"; + partitions = { + ESP = { + size = "1G"; + type = "EF00"; + content = { + type = "filesystem"; + format = "vfat"; + mountpoint = "/boot"; + mountOptions = [ + "fmask=0077" + "dmask=0077" + ]; + }; + }; + root = { + size = "100%"; + content = { + type = "btrfs"; + extraArgs = [ "-f" ]; + subvolumes = { + "/root" = { + mountpoint = "/"; + mountOptions = [ + "compress=zstd" + "discard=async" + "noatime" + ]; + }; + "/home" = { + mountpoint = "/home"; + mountOptions = [ + "compress=zstd" + "discard=async" + "noatime" + ]; + }; + "/nix" = { + mountpoint = "/nix"; + mountOptions = [ + "compress=zstd" + "discard=async" + "noatime" + ]; + }; + "/var-log" = { + mountpoint = "/var/log"; + mountOptions = [ + "compress=zstd" + "discard=async" + "noatime" + ]; + }; + "/snapshots" = { + mountpoint = "/.snapshots"; + mountOptions = [ + "compress=zstd" + "discard=async" + "noatime" + ]; + }; + }; + }; + }; + }; + }; + }; + }; + }; +} diff --git a/hosts/eva-01/hardware-configuration.nix b/hosts/eva-01/hardware-configuration.nix index 2d88b87..7f51a1f 100644 --- a/hosts/eva-01/hardware-configuration.nix +++ b/hosts/eva-01/hardware-configuration.nix @@ -17,12 +17,51 @@ boot.kernelModules = ["kvm-intel"]; boot.extraModulePackages = []; + # ── btrfs subvolumes ─────────────────────────────────────────────── + # All share the same physical device. Each subvolume can be snapshotted + # and rolled back independently. + # + # IMPORTANT: These subvolumes must exist on disk before this config is + # applied. Create them from a live USB with: + # + # mount /dev/nvme0n1pX /mnt + # btrfs subvolume create /mnt/home + # btrfs subvolume create /mnt/nix + # btrfs subvolume create /mnt/var-log + # btrfs subvolume create /mnt/snapshots + # fileSystems."/" = { device = "/dev/disk/by-uuid/0ec1b4fd-ca0f-4938-a038-37a69ec00b21"; fsType = "btrfs"; options = [ "subvol=root" "compress=zstd" "discard=async" "noatime" ]; }; + fileSystems."/home" = { + device = "/dev/disk/by-uuid/0ec1b4fd-ca0f-4938-a038-37a69ec00b21"; + fsType = "btrfs"; + options = [ "subvol=home" "compress=zstd" "discard=async" "noatime" ]; + }; + + fileSystems."/nix" = { + device = "/dev/disk/by-uuid/0ec1b4fd-ca0f-4938-a038-37a69ec00b21"; + fsType = "btrfs"; + options = [ "subvol=nix" "compress=zstd" "discard=async" "noatime" ]; + }; + + fileSystems."/var/log" = { + device = "/dev/disk/by-uuid/0ec1b4fd-ca0f-4938-a038-37a69ec00b21"; + fsType = "btrfs"; + options = [ "subvol=var-log" "compress=zstd" "discard=async" "noatime" ]; + neededForBoot = false; + }; + + fileSystems."/.snapshots" = { + device = "/dev/disk/by-uuid/0ec1b4fd-ca0f-4938-a038-37a69ec00b21"; + fsType = "btrfs"; + options = [ "subvol=snapshots" "compress=zstd" "discard=async" "noatime" ]; + neededForBoot = false; + }; + fileSystems."/boot" = { device = "/dev/disk/by-uuid/2066-E44D"; fsType = "vfat"; diff --git a/hosts/eva-01/iso.nix b/hosts/eva-01/iso.nix new file mode 100644 index 0000000..171aff9 --- /dev/null +++ b/hosts/eva-01/iso.nix @@ -0,0 +1,26 @@ +# ── eva-01 rescue / installer ISO ────────────────────────────── +{ + config, + pkgs, + pkgs-unstable, + lib, + ... +}: { + imports = [ + ./hardware-configuration.nix + ../iso/default.nix + ]; + + # Boot — EFI + legacy BIOS for broad hardware compatibility + boot.loader.systemd-boot.enable = true; + boot.loader.efi.canTouchEfiVariables = true; + + # Extra tools for Btrfs rescue + iso.extraPackages = with pkgs; [ + btrfs-progs + snapper + ]; + + iso.diskoConfig = ./disko-config.nix; + iso.description = "eva-01 Rescue ISO"; +} diff --git a/hosts/eva-02/configuration.nix b/hosts/eva-02/configuration.nix index f019dce..300caf8 100644 --- a/hosts/eva-02/configuration.nix +++ b/hosts/eva-02/configuration.nix @@ -67,6 +67,7 @@ "ckan" "esptool" "git-lfs" + "imagemagick" "huggingface-cli" "mono" "putty" @@ -90,6 +91,7 @@ "melonds" "moonlight" "obsidian" + "scroll-reverser" "signal" "steam" "vesktop" diff --git a/hosts/eva-03/configuration.nix b/hosts/eva-03/configuration.nix index a7acc33..67d4fb0 100644 --- a/hosts/eva-03/configuration.nix +++ b/hosts/eva-03/configuration.nix @@ -315,5 +315,5 @@ backupFileExtension = "backup"; }; - system.stateVersion = "25.11"; + system.stateVersion = "26.05"; } diff --git a/hosts/eva-03/disko-config.nix b/hosts/eva-03/disko-config.nix new file mode 100644 index 0000000..a8c4523 --- /dev/null +++ b/hosts/eva-03/disko-config.nix @@ -0,0 +1,47 @@ +# ── eva-03 disk layout ────────────────────────────────────────── +# NVMe SSD: EFI system partition, swap partition, ext4 root. +# +# Run from rescue ISO: +# disko --mode disko /etc/nixos/hosts/eva-03/disko-config.nix +{ + disko.devices = { + disk = { + main = { + type = "disk"; + device = "/dev/nvme0n1"; + content = { + type = "gpt"; + partitions = { + ESP = { + size = "1G"; + type = "EF00"; + content = { + type = "filesystem"; + format = "vfat"; + mountpoint = "/boot"; + mountOptions = [ + "fmask=0077" + "dmask=0077" + ]; + }; + }; + swap = { + size = "16G"; + content = { + type = "swap"; + }; + }; + root = { + size = "100%"; + content = { + type = "filesystem"; + format = "ext4"; + mountpoint = "/"; + }; + }; + }; + }; + }; + }; + }; +} diff --git a/hosts/eva-03/iso.nix b/hosts/eva-03/iso.nix new file mode 100644 index 0000000..ae87f53 --- /dev/null +++ b/hosts/eva-03/iso.nix @@ -0,0 +1,19 @@ +# ── eva-03 rescue / installer ISO ────────────────────────────── +{ + config, + pkgs, + pkgs-unstable, + lib, + ... +}: { + imports = [ + ./hardware-configuration.nix + ../iso/default.nix + ]; + + boot.loader.systemd-boot.enable = true; + boot.loader.efi.canTouchEfiVariables = true; + + iso.diskoConfig = ./disko-config.nix; + iso.description = "eva-03 Rescue ISO"; +} diff --git a/hosts/iso/default.nix b/hosts/iso/default.nix new file mode 100644 index 0000000..c4a4424 --- /dev/null +++ b/hosts/iso/default.nix @@ -0,0 +1,79 @@ +# ── Shared rescue / installer ISO module ──────────────────────── +# Import this from a host's iso.nix to get a standard rescue +# environment with: +# - SSH access for remote rescue +# - The host's disko config available at /etc/disko-config.nix +# - Common installer tools +# +# The host's iso.nix should set `iso.diskoConfig` to the path of +# its disko configuration file. +# +# The flake must also include `inputs.disko.nixosModules.disko` in +# each ISO's module list to make the `disko` command available. +{ + config, + lib, + pkgs, + ... +}: let + cfg = config.iso; +in { + options.iso = { + diskoConfig = lib.mkOption { + type = lib.types.path; + description = "Path to the host's disko configuration file"; + }; + + description = lib.mkOption { + type = lib.types.str; + default = "NixOS Rescue ISO"; + description = "Description shown in the ISO boot menu"; + }; + + extraPackages = lib.mkOption { + type = lib.types.listOf lib.types.package; + default = []; + description = "Additional packages to include on the ISO"; + }; + }; + + config = { + # Standard installer tools + environment.systemPackages = with pkgs; + [ + git + neovim + wget + curl + parted + gptfdisk + efibootmgr + ] + ++ cfg.extraPackages; + + # Enable SSH for remote rescue access + systemd.services.sshd.wantedBy = lib.mkOverride 40 ["multi-user.target"]; + services.openssh = { + enable = true; + settings.PasswordAuthentication = false; + }; + + users.users.root = { + openssh.authorizedKeys.keys = [ + "ssh-ed25519 AAAAC3NzaC1lZDI1NTE5AAAAINXqriPZVIuduc/J7GS1mD171LL0gIbgEjlImsxedWVX" + ]; + }; + + # Copy the host's disko config to /etc/disko-config.nix + # Usage during rescue: + # disko --mode disko /etc/disko-config.nix + # nixos-install --flake /etc/nixos#hostname + environment.etc."disko-config.nix".source = cfg.diskoConfig; + + system.activationScripts.diskoConfig = '' + chmod 644 /etc/disko-config.nix + ''; + + system.stateVersion = "26.05"; + }; +}