Compare commits

...

3 Commits

Author SHA1 Message Date
Alexander acd16ebc14 Nixos update 15-10-2026 2026-10-15 20:00:27 +02:00
Alexander b9db20d45c Nixos updates 11-10-2026 2026-10-15 19:22:18 +02:00
Alexander d8f2392f80 Point fujin DNS at OPNsense
Old 192.168.1.x Pi-hole/router nameservers returned NXDOMAIN for the
homelab.lan zone; use the OPNsense Unbound resolver (192.168.100.1)
with 1.1.1.1 fallback. Bare http://karate.homelab.lan now resolves and
serves on port 80.

Ultraworked with [Sisyphus](https://github.com/code-yeongyu/oh-my-openagent)
Co-authored-by: Sisyphus <clio-agent@sisyphuslabs.ai>
2026-09-05 12:45:03 +02:00
19 changed files with 279 additions and 206 deletions
Generated
+124 -114
View File
@@ -20,11 +20,11 @@
] ]
}, },
"locked": { "locked": {
"lastModified": 1788016784, "lastModified": 1791041429,
"narHash": "sha256-RO90Fk+Rn2Yy+I8oL4ePTLLKLgOAr8hrTx7tlpwdLaA=", "narHash": "sha256-Y/Q4JtMo6nHB6XS1LPSfK7Y4AnuNl9jci/5sCps1MRc=",
"owner": "hyprwm", "owner": "hyprwm",
"repo": "aquamarine", "repo": "aquamarine",
"rev": "783bfd9ae441d1d0519b979ac68b73ddd6e81df0", "rev": "52ea11f06dd492f34b3cc0b39a9c805beecafcff",
"type": "github" "type": "github"
}, },
"original": { "original": {
@@ -127,11 +127,11 @@
"nixpkgs": "nixpkgs_3" "nixpkgs": "nixpkgs_3"
}, },
"locked": { "locked": {
"lastModified": 1787524125, "lastModified": 1792020613,
"narHash": "sha256-P48TOQdIbB0PKMn4FTk6X0utbf0LemNlJ+bFcSbveGA=", "narHash": "sha256-31skutSMYGBAvGK5vs6wPGXAV4s0ietf1doMynL9FfI=",
"owner": "9001", "owner": "9001",
"repo": "copyparty", "repo": "copyparty",
"rev": "9de090265f8d063056320f41d984830839017a2f", "rev": "8b4593c9a286791eb5dc40862fa24198cea4def7",
"type": "github" "type": "github"
}, },
"original": { "original": {
@@ -147,11 +147,11 @@
] ]
}, },
"locked": { "locked": {
"lastModified": 1781152676, "lastModified": 1789770686,
"narHash": "sha256-RxWs5ND31KzTG7wvMM+PMfUjyNpmIEr999lqNARaM5o=", "narHash": "sha256-uZkBR7yHdIKUFB5SZdfgh1qkGfI3XmYmI/lTiquxbck=",
"owner": "nix-community", "owner": "nix-community",
"repo": "disko", "repo": "disko",
"rev": "ff8702b4de27f72b4c78573dfb89ec74e36abdf1", "rev": "725ea35e410ad83be4931d1bff7e090eacaf3563",
"type": "github" "type": "github"
}, },
"original": { "original": {
@@ -166,11 +166,11 @@
"nixpkgs-stable": "nixpkgs-stable" "nixpkgs-stable": "nixpkgs-stable"
}, },
"locked": { "locked": {
"lastModified": 1788150896, "lastModified": 1792072733,
"narHash": "sha256-suPEqotkAM4UyRxFk6VjWg1E/yBRrpom2E9lr0vnT+8=", "narHash": "sha256-Q+c4fV/OShePs5FdPldh00mywqU0Wl1y8zF8ss07aRM=",
"owner": "nix-community", "owner": "nix-community",
"repo": "emacs-overlay", "repo": "emacs-overlay",
"rev": "f6229276417aa356ae16dfd3b21b51525f55083f", "rev": "08c72b09663805de26057dfed80b7153846336ca",
"type": "github" "type": "github"
}, },
"original": { "original": {
@@ -401,11 +401,11 @@
] ]
}, },
"locked": { "locked": {
"lastModified": 1786719456, "lastModified": 1790819692,
"narHash": "sha256-B74DLQs/VjlqyhnnX3tguWwghqJHWSJX30TKZuAljIg=", "narHash": "sha256-rvubAPbh3QCliic3sAK+CXTrPCGgJstY52OTs/5H1J4=",
"owner": "nix-community", "owner": "nix-community",
"repo": "home-manager", "repo": "home-manager",
"rev": "83b7606dcf44abe3a94b86e8bb2b3355d22e8797", "rev": "c8ecc29e5175452bee4a2aa1ba2383856d795338",
"type": "github" "type": "github"
}, },
"original": { "original": {
@@ -459,11 +459,11 @@
] ]
}, },
"locked": { "locked": {
"lastModified": 1786464367, "lastModified": 1791066858,
"narHash": "sha256-k58p4wbzIXWyRWrW84pP8tD+iaZSSYiiM+fr0Auk4oU=", "narHash": "sha256-hLh6ALHrGpgYm8viWCo1pO+ErC22YDGdAvVPcfYsXA8=",
"owner": "hyprwm", "owner": "hyprwm",
"repo": "hyprgraphics", "repo": "hyprgraphics",
"rev": "7c895c44e3ca6d28ed68ddd80ec02b02b925e7fc", "rev": "80c7d00f2236732853e390019ff8d79d17fa3612",
"type": "github" "type": "github"
}, },
"original": { "original": {
@@ -480,6 +480,7 @@
"hyprland-guiutils": "hyprland-guiutils", "hyprland-guiutils": "hyprland-guiutils",
"hyprland-protocols": "hyprland-protocols", "hyprland-protocols": "hyprland-protocols",
"hyprlang": "hyprlang", "hyprlang": "hyprlang",
"hyprtoolkit": "hyprtoolkit",
"hyprutils": "hyprutils", "hyprutils": "hyprutils",
"hyprwayland-scanner": "hyprwayland-scanner", "hyprwayland-scanner": "hyprwayland-scanner",
"hyprwire": "hyprwire", "hyprwire": "hyprwire",
@@ -489,11 +490,11 @@
"xdph": "xdph" "xdph": "xdph"
}, },
"locked": { "locked": {
"lastModified": 1788100302, "lastModified": 1792003461,
"narHash": "sha256-21MFGYEl3m5SjN9kZGKb+gELVLlMCF1DkbwHqHzSK1w=", "narHash": "sha256-sqWBYgjkJd5xTJKd9Jz/SbtrJfY3eTqxyqn1xfH6O00=",
"ref": "refs/heads/main", "ref": "refs/heads/main",
"rev": "86c24e2e079aa62214421c76f01b603fc8178125", "rev": "e2ad066c9ffd45ddfbe4dc76d2de16b382fbe3eb",
"revCount": 7779, "revCount": 7911,
"type": "git", "type": "git",
"url": "https://github.com/hyprwm/Hyprland" "url": "https://github.com/hyprwm/Hyprland"
}, },
@@ -516,7 +517,10 @@
"hyprland", "hyprland",
"hyprlang" "hyprlang"
], ],
"hyprtoolkit": "hyprtoolkit", "hyprtoolkit": [
"hyprland",
"hyprtoolkit"
],
"hyprutils": [ "hyprutils": [
"hyprland", "hyprland",
"hyprutils" "hyprutils"
@@ -535,11 +539,11 @@
] ]
}, },
"locked": { "locked": {
"lastModified": 1786464504, "lastModified": 1791805511,
"narHash": "sha256-7sHwM86KILQyHDHDuE2SDBlQ2jvZ0EW3hY7sW009/cg=", "narHash": "sha256-p7R3xnbJf6MqvgWAmR86PkHUba97Fotm8RR16tYDF9I=",
"owner": "hyprwm", "owner": "hyprwm",
"repo": "hyprland-guiutils", "repo": "hyprland-guiutils",
"rev": "4c30cf3097ea963c0e250749ee0c59f8b08816d6", "rev": "204f39d6c7a4aca7042587d4638e19cdeccf63bc",
"type": "github" "type": "github"
}, },
"original": { "original": {
@@ -565,11 +569,11 @@
] ]
}, },
"locked": { "locked": {
"lastModified": 1788037253, "lastModified": 1791378645,
"narHash": "sha256-QSGOM0IFpp45DwmtIwcih8+kKuSgAoQal9QkVVSRNew=", "narHash": "sha256-9Eix+ZUcI9IUklrtJAD9l/nTcS/Byz7fi94Y3InxS2Y=",
"owner": "hyprwm", "owner": "hyprwm",
"repo": "hyprland-plugins", "repo": "hyprland-plugins",
"rev": "67c3a4c019f223c27b5bdc6bb656ce891a60861a", "rev": "428bfcd1c9ee34965400bb359349f518140c9920",
"type": "github" "type": "github"
}, },
"original": { "original": {
@@ -590,11 +594,11 @@
] ]
}, },
"locked": { "locked": {
"lastModified": 1772460177, "lastModified": 1791277361,
"narHash": "sha256-/6G/MsPvtn7bc4Y32pserBT/Z4SUUdBd4XYJpOEKVR4=", "narHash": "sha256-+dv/mMnrw+uBgY+WW3KpoKQ8Nl3bVLS3lknXsbJ03zQ=",
"owner": "hyprwm", "owner": "hyprwm",
"repo": "hyprland-protocols", "repo": "hyprland-protocols",
"rev": "1cb6db5fd6bb8aee419f4457402fa18293ace917", "rev": "4c27ba9ce104782bf718aabf59df3f503afe7caa",
"type": "github" "type": "github"
}, },
"original": { "original": {
@@ -636,46 +640,39 @@
"inputs": { "inputs": {
"aquamarine": [ "aquamarine": [
"hyprland", "hyprland",
"hyprland-guiutils",
"aquamarine" "aquamarine"
], ],
"hyprgraphics": [ "hyprgraphics": [
"hyprland", "hyprland",
"hyprland-guiutils",
"hyprgraphics" "hyprgraphics"
], ],
"hyprlang": [ "hyprlang": [
"hyprland", "hyprland",
"hyprland-guiutils",
"hyprlang" "hyprlang"
], ],
"hyprutils": [ "hyprutils": [
"hyprland", "hyprland",
"hyprland-guiutils",
"hyprutils" "hyprutils"
], ],
"hyprwayland-scanner": [ "hyprwayland-scanner": [
"hyprland", "hyprland",
"hyprland-guiutils",
"hyprwayland-scanner" "hyprwayland-scanner"
], ],
"nixpkgs": [ "nixpkgs": [
"hyprland", "hyprland",
"hyprland-guiutils",
"nixpkgs" "nixpkgs"
], ],
"systems": [ "systems": [
"hyprland", "hyprland",
"hyprland-guiutils",
"systems" "systems"
] ]
}, },
"locked": { "locked": {
"lastModified": 1785930473, "lastModified": 1791849226,
"narHash": "sha256-DitTu625BhEYpZjtjxtGpjrEJwPwW+X/+jJvhSZNSJM=", "narHash": "sha256-q9Kgz/ZSo6ftVliPGQuRZYWYp3eK4vggO0IR6LcsWl0=",
"owner": "hyprwm", "owner": "hyprwm",
"repo": "hyprtoolkit", "repo": "hyprtoolkit",
"rev": "af515b69dfbe366dc7873aa1475cb2f4db3ebad7", "rev": "2907e0d1f8a3a540737a0e738acc40d48ad7ba0d",
"type": "github" "type": "github"
}, },
"original": { "original": {
@@ -696,11 +693,11 @@
] ]
}, },
"locked": { "locked": {
"lastModified": 1786903207, "lastModified": 1789968180,
"narHash": "sha256-QTwMqLLONRhv9iz6CVeuX6BqQNQCIqI8hL/cPYlR/24=", "narHash": "sha256-YGRfhw+fJW7oKW3IspoceD34jeokN1KXNxKU6APlFH4=",
"owner": "hyprwm", "owner": "hyprwm",
"repo": "hyprutils", "repo": "hyprutils",
"rev": "6cf50415e06dc6bd9f1252f1b745eac6b4a1cc39", "rev": "95983ee836ff205e615bba67d1f67098e1231941",
"type": "github" "type": "github"
}, },
"original": { "original": {
@@ -768,11 +765,11 @@
"nixpkgs": "nixpkgs_6" "nixpkgs": "nixpkgs_6"
}, },
"locked": { "locked": {
"lastModified": 1787822983, "lastModified": 1791490285,
"narHash": "sha256-wusELfq9vxbkbZy8cPprcOldqoqSbKltxt++EW9gQ9g=", "narHash": "sha256-JPu+WSXX4TaQnue+UKGMmv2YYCbM5t9Bwwm0fp6lJXc=",
"owner": "Lxtharia", "owner": "Lxtharia",
"repo": "minegrub-theme", "repo": "minegrub-theme",
"rev": "89f9e24f44cbe06b11d69068e39f534666e4d3d3", "rev": "cdd067ebc31ac59e24ae3c99e5b0f05a18eb8a1d",
"type": "github" "type": "github"
}, },
"original": { "original": {
@@ -803,11 +800,11 @@
] ]
}, },
"locked": { "locked": {
"lastModified": 1788166029, "lastModified": 1791190188,
"narHash": "sha256-+hgpdq6rXpbBHhB5Pbu80kq7UTZhVpbZZtJXePs9ufE=", "narHash": "sha256-d+5+d7r62PZcHc4UFA5HkjxnzBDfVIixsdJX+dwQsyI=",
"owner": "Mic92", "owner": "Mic92",
"repo": "nix-ld", "repo": "nix-ld",
"rev": "2cced31ac171b55dd6ab8cc04502cb1ad012d7cf", "rev": "2ba7201c2db8a49b9bd745d240430282f67bbe39",
"type": "github" "type": "github"
}, },
"original": { "original": {
@@ -857,11 +854,11 @@
"nixpkgs": "nixpkgs_7" "nixpkgs": "nixpkgs_7"
}, },
"locked": { "locked": {
"lastModified": 1788044418, "lastModified": 1791721963,
"narHash": "sha256-cmOd3iGoE140M2GidgQMQbyxHZ4dT7C0QZq2+CrXQyA=", "narHash": "sha256-BYhx89XJltnRyQeuDKHVL5eSqbbfAcOKuDts7QRsrxQ=",
"owner": "NixOS", "owner": "NixOS",
"repo": "nixos-hardware", "repo": "nixos-hardware",
"rev": "dc3f0cfde2050172abf6c3cdb684f735c15a57c5", "rev": "60a624466c08787ee8303393b7d4752d1826f14f",
"type": "github" "type": "github"
}, },
"original": { "original": {
@@ -919,11 +916,11 @@
}, },
"nixpkgs-stable": { "nixpkgs-stable": {
"locked": { "locked": {
"lastModified": 1787962033, "lastModified": 1791883866,
"narHash": "sha256-u6z9VTZA4Kf3RkHQo9sQI7NI4Ei/uiU9vrMqOiwWP1Y=", "narHash": "sha256-yvkDdToRZ4IgPc9tSBzzCYJvTLf8n5eE3rgUkpCuD5A=",
"owner": "NixOS", "owner": "NixOS",
"repo": "nixpkgs", "repo": "nixpkgs",
"rev": "c5c4a43b0e8056328ec4529f735cabdb8f1942bb", "rev": "a033e66ab94a6bedf2c3d58d93a36319d3cbbbaf",
"type": "github" "type": "github"
}, },
"original": { "original": {
@@ -935,11 +932,11 @@
}, },
"nixpkgs_10": { "nixpkgs_10": {
"locked": { "locked": {
"lastModified": 1786599213, "lastModified": 1790689126,
"narHash": "sha256-yNJd40f11EzXBjSByCB7IPpeFFAdeoSKKM67dGkfFoU=", "narHash": "sha256-ilerN1WLSvF+HMjziC/Wv99J5y02maDH+6hZPwsORKg=",
"owner": "nixos", "owner": "nixos",
"repo": "nixpkgs", "repo": "nixpkgs",
"rev": "0e251e24a4f24e036a084b6b4b2d2491af4167f4", "rev": "b4fd65b198c599cbe814fcb9f42d25d021595ec9",
"type": "github" "type": "github"
}, },
"original": { "original": {
@@ -981,11 +978,11 @@
}, },
"nixpkgs_4": { "nixpkgs_4": {
"locked": { "locked": {
"lastModified": 1788039129, "lastModified": 1791956154,
"narHash": "sha256-pa4Q0qErvCvzCaaUph7Sm37RhR4xvPrYI8Lgz6k85+A=", "narHash": "sha256-jBYGPi4udQ9uo4KQp9m2J0546nJVQitG15gvZSaVVAs=",
"owner": "NixOS", "owner": "NixOS",
"repo": "nixpkgs", "repo": "nixpkgs",
"rev": "d2f67949798825fe853f7c5d0492b8bf016d3f88", "rev": "55bfb4d7437bd4e09ab7cba58a43bd68eb310044",
"type": "github" "type": "github"
}, },
"original": { "original": {
@@ -997,11 +994,11 @@
}, },
"nixpkgs_5": { "nixpkgs_5": {
"locked": { "locked": {
"lastModified": 1787736819, "lastModified": 1791734076,
"narHash": "sha256-cV5xEJJK3BvhU8rEd4mC9UsmDi5qscv/kzGPhBRC5WA=", "narHash": "sha256-i5qk1kLiit98rRbh1AXmWBNT9QXC/y4l5Wk/u5EdpDQ=",
"owner": "NixOS", "owner": "NixOS",
"repo": "nixpkgs", "repo": "nixpkgs",
"rev": "9fbb54b33e91ee4ca368e35a78e0613c720600b3", "rev": "7fd4004d0511991fff3a0524856a9be09e28c5f0",
"type": "github" "type": "github"
}, },
"original": { "original": {
@@ -1029,11 +1026,11 @@
}, },
"nixpkgs_7": { "nixpkgs_7": {
"locked": { "locked": {
"lastModified": 1767892417, "lastModified": 1789546076,
"narHash": "sha256-8bW3q88CEg2u4hSP66Vf4lpbLonHz7hqDNBMcCY7E9U=", "narHash": "sha256-vWkSk5bbfTqdtMoSgD9FshACO8JCvXTFi+3cqEp0mH0=",
"rev": "3497aa5c9457a9d88d71fa93a4a8368816fbeeba", "rev": "b1b875982b17dabde9b4a37f3e229e74913e6db3",
"type": "tarball", "type": "tarball",
"url": "https://releases.nixos.org/nixos/unstable/nixos-26.05pre924538.3497aa5c9457/nixexprs.tar.xz" "url": "https://releases.nixos.org/nixos/unstable/nixos-26.11pre1074753.b1b875982b17/nixexprs.tar.xz"
}, },
"original": { "original": {
"type": "tarball", "type": "tarball",
@@ -1058,11 +1055,11 @@
}, },
"nixpkgs_9": { "nixpkgs_9": {
"locked": { "locked": {
"lastModified": 1775036866, "lastModified": 1789149629,
"narHash": "sha256-ZojAnPuCdy657PbTq5V0Y+AHKhZAIwSIT2cb8UgAz/U=", "narHash": "sha256-H6GwaZzZf+4npqv0tph94w9tZddSjFjmQrVsW0z78uk=",
"owner": "NixOS", "owner": "NixOS",
"repo": "nixpkgs", "repo": "nixpkgs",
"rev": "6201e203d09599479a3b3450ed24fa81537ebc4e", "rev": "eaad089433ca2bb662274377d33df3d0e51ef28b",
"type": "github" "type": "github"
}, },
"original": { "original": {
@@ -1079,11 +1076,11 @@
] ]
}, },
"locked": { "locked": {
"lastModified": 1788154427, "lastModified": 1792070304,
"narHash": "sha256-nCzmnj3rk60iznPMoDBg09b3wsDzEoGAjQj81QlsUTo=", "narHash": "sha256-gCF1P9r0UzPah0fqBTg2nVuxuuNnRxnYYHklvq8VKZI=",
"owner": "noctalia-dev", "owner": "noctalia-dev",
"repo": "noctalia", "repo": "noctalia",
"rev": "bee126157205f9e686e4f3f98d2cc3be1c1bf252", "rev": "a33122c4208a385e19c9a252e65e2751b2c44fbb",
"type": "github" "type": "github"
}, },
"original": { "original": {
@@ -1126,11 +1123,11 @@
] ]
}, },
"locked": { "locked": {
"lastModified": 1787424939, "lastModified": 1791909798,
"narHash": "sha256-O2tBn84NNuHrnqNVxx/XqsXwfYvS1YwBh+7CBnbCYsk=", "narHash": "sha256-VAhpCOmrun/KXimYfR8NM88bciKCui7CqHHhThSzgag=",
"owner": "cachix", "owner": "cachix",
"repo": "git-hooks.nix", "repo": "git-hooks.nix",
"rev": "809414f0cdadf82cf11b06c2b29ba9b3168b3297", "rev": "1ba1dbfe28738c9a71c266be6efa5b89e75491a9",
"type": "github" "type": "github"
}, },
"original": { "original": {
@@ -1155,11 +1152,11 @@
] ]
}, },
"locked": { "locked": {
"lastModified": 1773870109, "lastModified": 1788149501,
"narHash": "sha256-ZoTdqZP03DcdoyxvpFHCAek4bkPUTUPUF3oCCgc3dP4=", "narHash": "sha256-XKJP4KvhawV3pyVfraX3sflz05Rp7KP74gRt6QqKjNE=",
"owner": "pyproject-nix", "owner": "pyproject-nix",
"repo": "build-system-pkgs", "repo": "build-system-pkgs",
"rev": "b6e74f433b02fa4b8a7965ee24680f4867e2926f", "rev": "150839ac67b5a34db56a55e8f6b7099a4e7878ab",
"type": "github" "type": "github"
}, },
"original": { "original": {
@@ -1176,11 +1173,11 @@
] ]
}, },
"locked": { "locked": {
"lastModified": 1775439158, "lastModified": 1788394333,
"narHash": "sha256-NHY9SJNU019n+8NCabBDtmuzRFeE2gZlYKHowp9bV24=", "narHash": "sha256-xYOP0Xym1eVGUaHFx+eJEaycFGoiCbst3fZf0xFHP78=",
"owner": "pyproject-nix", "owner": "pyproject-nix",
"repo": "pyproject.nix", "repo": "pyproject.nix",
"rev": "fb6b728260f3f32761367e9fd1e1a25b4245bcd0", "rev": "6a8a7881d75b6f98967e7b8069f4ead331384301",
"type": "github" "type": "github"
}, },
"original": { "original": {
@@ -1221,11 +1218,11 @@
] ]
}, },
"locked": { "locked": {
"lastModified": 1786629091, "lastModified": 1792056300,
"narHash": "sha256-gkig4nPi1CWc4Z50GBsjE4ygSE7hMpl/TwID2an2Cck=", "narHash": "sha256-YU1LjDe1o2Ymg5zEiCHbmMXLkDCtxHQRiVqZ3nC5GGk=",
"owner": "Mic92", "owner": "Mic92",
"repo": "sops-nix", "repo": "sops-nix",
"rev": "a8627b21b9107c5711c96b84f32a9a4b3d45295f", "rev": "44931708c62937c2b1bf7953902989fa5bb9ee1b",
"type": "github" "type": "github"
}, },
"original": { "original": {
@@ -1242,11 +1239,11 @@
"nix-filter": "nix-filter" "nix-filter": "nix-filter"
}, },
"locked": { "locked": {
"lastModified": 1787489216, "lastModified": 1790431438,
"narHash": "sha256-VE1o0B6GPHrwmYANfGIEm/hDz2u4IhG0Gdj+ZkEV2uY=", "narHash": "sha256-D0pKfzVlRz8VnLIZVaPtr2d+LHYspICllgIz+oQlw98=",
"owner": "zjeffer", "owner": "zjeffer",
"repo": "split-monitor-workspaces", "repo": "split-monitor-workspaces",
"rev": "47b22971e3a21d228882ca1e2509fdac26f2d5b2", "rev": "f26d624c2638d0661f3e0352a634650bfd08296d",
"type": "github" "type": "github"
}, },
"original": { "original": {
@@ -1275,15 +1272,16 @@
"tinted-zed": "tinted-zed" "tinted-zed": "tinted-zed"
}, },
"locked": { "locked": {
"lastModified": 1787771653, "lastModified": 1790322631,
"narHash": "sha256-DkkJSBOXWV/mja5Vy8az5g1KpZlsbUwlmH0BsQhowaQ=", "narHash": "sha256-/EDdHSkJwOQUNDdlLXhC1FyMuERiL/fkPAF/LWZy+HY=",
"owner": "nix-community", "owner": "Azd325",
"repo": "stylix", "repo": "stylix",
"rev": "5e3809851f486e7fc7e84b40f174c74b60ecc784", "rev": "a1198612edba320a39c5cc5c4ab30dbee6fd66ea",
"type": "github" "type": "github"
}, },
"original": { "original": {
"owner": "nix-community", "owner": "Azd325",
"ref": "rofi-settings-font",
"repo": "stylix", "repo": "stylix",
"type": "github" "type": "github"
} }
@@ -1343,11 +1341,11 @@
"uv2nix": "uv2nix" "uv2nix": "uv2nix"
}, },
"locked": { "locked": {
"lastModified": 1776248910, "lastModified": 1791196392,
"narHash": "sha256-MrwY8D48uZMTI/D6TEBmG1osklyAlqdtYeH+1cBeRNU=", "narHash": "sha256-BQ2f4gEtc2An1t9xac66C+ZIPEopJotoH2OhNcm5eLg=",
"owner": "LichHunter", "owner": "LichHunter",
"repo": "thefuck", "repo": "thefuck",
"rev": "7cac5ac8709dade676264af51afbe7a4d3c84582", "rev": "7a102bb398407e57aaf64f4e5123f47256b11c04",
"type": "github" "type": "github"
}, },
"original": { "original": {
@@ -1422,11 +1420,11 @@
}, },
"unstable": { "unstable": {
"locked": { "locked": {
"lastModified": 1788039129, "lastModified": 1791956154,
"narHash": "sha256-pa4Q0qErvCvzCaaUph7Sm37RhR4xvPrYI8Lgz6k85+A=", "narHash": "sha256-jBYGPi4udQ9uo4KQp9m2J0546nJVQitG15gvZSaVVAs=",
"owner": "nixos", "owner": "nixos",
"repo": "nixpkgs", "repo": "nixpkgs",
"rev": "d2f67949798825fe853f7c5d0492b8bf016d3f88", "rev": "55bfb4d7437bd4e09ab7cba58a43bd68eb310044",
"type": "github" "type": "github"
}, },
"original": { "original": {
@@ -1443,11 +1441,11 @@
] ]
}, },
"locked": { "locked": {
"lastModified": 1788146656, "lastModified": 1792082440,
"narHash": "sha256-XmJmvk9rytTb7dCotO/aqR+YysB8HOqnprlOdv+LAF4=", "narHash": "sha256-TppYgfBkqAs4IaO3AV+t4zlH9FZIL/AdJFI+PagXwVw=",
"owner": "nix-community", "owner": "nix-community",
"repo": "home-manager", "repo": "home-manager",
"rev": "82c265faf4e3161d6015db07c9b0f1ee36a9029b", "rev": "6d9c00bad9a3c763f842c2b08193e5844bdcedfa",
"type": "github" "type": "github"
}, },
"original": { "original": {
@@ -1469,11 +1467,11 @@
] ]
}, },
"locked": { "locked": {
"lastModified": 1775386139, "lastModified": 1788001239,
"narHash": "sha256-n82p7WF+dYxf5r01pXlqbk8CAF7xX0Tk7wAcmMjkuhc=", "narHash": "sha256-AELmsXPI546MhbC/ZXC7WRUkCz7d4rqKTHUmliIgPpI=",
"owner": "pyproject-nix", "owner": "pyproject-nix",
"repo": "uv2nix", "repo": "uv2nix",
"rev": "3cffcee173635d553e213d11418690b5290ff1c9", "rev": "7f9c6b613d2e749e54854b1d60ab6a2192db889e",
"type": "github" "type": "github"
}, },
"original": { "original": {
@@ -1502,6 +1500,14 @@
}, },
"xdph": { "xdph": {
"inputs": { "inputs": {
"aquamarine": [
"hyprland",
"aquamarine"
],
"hyprgraphics": [
"hyprland",
"hyprgraphics"
],
"hyprland-protocols": [ "hyprland-protocols": [
"hyprland", "hyprland",
"hyprland-protocols" "hyprland-protocols"
@@ -1510,6 +1516,10 @@
"hyprland", "hyprland",
"hyprlang" "hyprlang"
], ],
"hyprtoolkit": [
"hyprland",
"hyprtoolkit"
],
"hyprutils": [ "hyprutils": [
"hyprland", "hyprland",
"hyprutils" "hyprutils"
@@ -1528,11 +1538,11 @@
] ]
}, },
"locked": { "locked": {
"lastModified": 1786988229, "lastModified": 1791822904,
"narHash": "sha256-frEFLVRj8xXvBBDs44IRiqHo6R2PxsRpluygL7abjjI=", "narHash": "sha256-gsxPblA9YV+By4SxXWkj2HGGk7MKGxiNj/T9bU4q31U=",
"owner": "hyprwm", "owner": "hyprwm",
"repo": "xdg-desktop-portal-hyprland", "repo": "xdg-desktop-portal-hyprland",
"rev": "59d429bf45aed4e2209043c0c36565ad8e2859a5", "rev": "0121b2e3f85c7ebf6280173f1054f7e5606262d1",
"type": "github" "type": "github"
}, },
"original": { "original": {
@@ -1547,11 +1557,11 @@
"nixpkgs": "nixpkgs_10" "nixpkgs": "nixpkgs_10"
}, },
"locked": { "locked": {
"lastModified": 1788149125, "lastModified": 1792047775,
"narHash": "sha256-GueAv4789rOV70hixnL9+uN4tiDKJm7s92DnTejdpuE=", "narHash": "sha256-Ks46+ZukSOvdgmextucbLykzpAmygNZ2I+HWxCe03ok=",
"owner": "0xc000022070", "owner": "0xc000022070",
"repo": "zen-browser-flake", "repo": "zen-browser-flake",
"rev": "5fe00f38d41ced9a5c0ba1cbf2127d7e8b3e3d56", "rev": "9342d127aa8c585e82f3f57ddb25800fd546029f",
"type": "github" "type": "github"
}, },
"original": { "original": {
+33 -13
View File
@@ -41,7 +41,11 @@
emacs-overlay.url = "github:nix-community/emacs-overlay/master"; emacs-overlay.url = "github:nix-community/emacs-overlay/master";
stylix = { stylix = {
url = "github:nix-community/stylix"; # TODO: revert to github:nix-community/stylix once
# https://github.com/nix-community/stylix/pull/2501 is merged;
# stylix master still sets `programs.rofi.font`, which
# home-manager renamed to `programs.rofi.settings.font`.
url = "github:Azd325/stylix/rofi-settings-font";
inputs.nixpkgs.follows = "unstable"; inputs.nixpkgs.follows = "unstable";
}; };
@@ -213,19 +217,35 @@
"fujin"; "fujin";
}; };
packages.x86_64-linux = { packages.x86_64-linux =
nixos-lxc = (nixpkgs.lib.nixosSystem { let
system = "x86_64-linux"; builderSystem = nixpkgs.lib.nixosSystem {
modules = [ system = "x86_64-linux";
./machines/builder modules = [
({ modulesPath, ... }: { ./machines/builder
imports = [ (modulesPath + "/virtualisation/proxmox-lxc.nix") ]; ({ modulesPath, ... }: {
}) imports = [ (modulesPath + "/virtualisation/proxmox-lxc.nix") ];
]; })
specialArgs = { ];
inherit inputs; specialArgs = {
inherit inputs;
};
}; };
}).config.system.build.image; in {
# pve-build keys template identity on this output's outPath: the
# store-path hash (covers nixpkgs pin + builder config) becomes the
# template filename on PVE. overrideAttrs only names the derivation
# so the filename reads <hash>-nixos-lxc-builder.tar.xz instead of
# <hash>-tarball.tar.xz.
nixos-lxc = builderSystem.config.system.build.image.overrideAttrs (_: {
name = "nixos-lxc-builder";
});
# Toplevel the builder image boots. pve-build compares it against
# /run/current-system inside a running disposable to detect clones
# of stale templates (pct config drops the ostemplate field after
# creation, so it cannot be used for this).
nixos-lxc-toplevel = builderSystem.config.system.build.toplevel;
izanami-proxmox = nixos-generators.nixosGenerate { izanami-proxmox = nixos-generators.nixosGenerate {
system = "x86_64-linux"; system = "x86_64-linux";
+1 -1
View File
@@ -70,7 +70,7 @@ in
config = mkIf cfg.enable { config = mkIf cfg.enable {
programs.noctalia = { programs.noctalia = {
enable = true; enable = true;
package = inputs.noctalia.packages.${pkgs.system}.default; package = inputs.noctalia.packages.${pkgs.stdenv.hostPlatform.system}.default;
systemd.enable = true; systemd.enable = true;
customPalettes.stylix = { customPalettes.stylix = {
+2 -2
View File
@@ -8,8 +8,8 @@ in {
options.dov.browser.zen.enable = mkEnableOption "zen config"; options.dov.browser.zen.enable = mkEnableOption "zen config";
config = mkIf cfg.enable { config = mkIf cfg.enable {
home.packages = with pkgs; [ home.packages = [
inputs.zen-browser.packages."${system}".default inputs.zen-browser.packages."${pkgs.stdenv.hostPlatform.system}".default
]; ];
}; };
} }
+1
View File
@@ -215,6 +215,7 @@ in {
stylix = { stylix = {
enable = true; enable = true;
autoEnable = true; autoEnable = true;
overlays.enable = false;
# Base scheme/polarity; overridable per specialisation below. # Base scheme/polarity; overridable per specialisation below.
base16Scheme = mkDefault themeVariants.${baseVariant}.scheme; base16Scheme = mkDefault themeVariants.${baseVariant}.scheme;
polarity = mkDefault themeVariants.${baseVariant}.polarity; polarity = mkDefault themeVariants.${baseVariant}.polarity;
+1 -1
View File
@@ -19,7 +19,7 @@ in {
nix = { nix = {
settings = { settings = {
# Enable flakes and new 'nix' command # Enable flakes and new 'nix' command
experimental-features = "nix-command flakes"; experimental-features = [ "nix-command" "flakes" ];
# Opinionated: disable global registry # Opinionated: disable global registry
flake-registry = ""; flake-registry = "";
# Workaround for https://github.com/NixOS/nix/issues/9574 # Workaround for https://github.com/NixOS/nix/issues/9574
+1 -1
View File
@@ -19,7 +19,7 @@ in {
nix = { nix = {
settings = { settings = {
# Enable flakes and new 'nix' command # Enable flakes and new 'nix' command
experimental-features = "nix-command flakes"; experimental-features = [ "nix-command" "flakes" ];
# Opinionated: disable global registry # Opinionated: disable global registry
flake-registry = ""; flake-registry = "";
# Workaround for https://github.com/NixOS/nix/issues/9574 # Workaround for https://github.com/NixOS/nix/issues/9574
+1 -1
View File
@@ -26,7 +26,7 @@ in {
nix = { nix = {
settings = { settings = {
# Enable flakes and new 'nix' command # Enable flakes and new 'nix' command
experimental-features = "nix-command flakes"; experimental-features = [ "nix-command" "flakes" ];
# Opinionated: disable global registry # Opinionated: disable global registry
flake-registry = ""; flake-registry = "";
# Workaround for https://github.com/NixOS/nix/issues/9574 # Workaround for https://github.com/NixOS/nix/issues/9574
+1 -1
View File
@@ -33,7 +33,7 @@ in
nix = { nix = {
settings = { settings = {
# Enable flakes and new 'nix' command # Enable flakes and new 'nix' command
experimental-features = "nix-command flakes"; experimental-features = [ "nix-command" "flakes" ];
# Opinionated: disable global registry # Opinionated: disable global registry
flake-registry = ""; flake-registry = "";
# Workaround for https://github.com/NixOS/nix/issues/9574 # Workaround for https://github.com/NixOS/nix/issues/9574
+1 -1
View File
@@ -41,7 +41,7 @@ in {
nix = { nix = {
settings = { settings = {
experimental-features = "nix-command flakes"; experimental-features = [ "nix-command" "flakes" ];
flake-registry = ""; flake-registry = "";
nix-path = config.nix.nixPath; nix-path = config.nix.nixPath;
+4 -2
View File
@@ -66,9 +66,11 @@
}; };
networking = { networking = {
# OPNsense (192.168.100.1) runs Unbound with the homelab.lan overrides;
# the old 192.168.1.x Pi-hole/router are gone and returned NXDOMAIN for
# the local zone. 1.1.1.1 stays as a fallback if the firewall is down.
nameservers = [ nameservers = [
"192.168.1.2" # PyHole "192.168.100.1" # OPNsense Unbound
"192.168.1.1" # Router
"1.1.1.1" "1.1.1.1"
]; ];
dhcpcd.extraConfig = '' dhcpcd.extraConfig = ''
+1 -1
View File
@@ -159,7 +159,7 @@
#mpd #mpd
#mpv #mpv
#mpc-cli #mpc-cli
] ++ [ inputs.thefuck.packages.${pkgs.system}.default ]; ] ++ [ inputs.thefuck.packages.${pkgs.stdenv.hostPlatform.system}.default ];
# Stylix theming is driven by `dov.dynamic-theme` (hm-modules/theme), # Stylix theming is driven by `dov.dynamic-theme` (hm-modules/theme),
# which sets `enable`, `base16Scheme` and `polarity` + specialisations. # which sets `enable`, `base16Scheme` and `polarity` + specialisations.
+1 -1
View File
@@ -26,7 +26,7 @@ in {
nix = { nix = {
settings = { settings = {
# Enable flakes and new 'nix' command # Enable flakes and new 'nix' command
experimental-features = "nix-command flakes"; experimental-features = [ "nix-command" "flakes" ];
# Opinionated: disable global registry # Opinionated: disable global registry
flake-registry = ""; flake-registry = "";
# Workaround for https://github.com/NixOS/nix/issues/9574 # Workaround for https://github.com/NixOS/nix/issues/9574
+1 -1
View File
@@ -33,7 +33,7 @@ in {
nix = { nix = {
settings = { settings = {
# Enable flakes and new 'nix' command # Enable flakes and new 'nix' command
experimental-features = "nix-command flakes"; experimental-features = [ "nix-command" "flakes" ];
# Opinionated: disable global registry # Opinionated: disable global registry
flake-registry = ""; flake-registry = "";
# Workaround for https://github.com/NixOS/nix/issues/9574 # Workaround for https://github.com/NixOS/nix/issues/9574
+1 -1
View File
@@ -51,7 +51,7 @@ in {
nix = { nix = {
settings = { settings = {
# Enable flakes and new 'nix' command # Enable flakes and new 'nix' command
experimental-features = "nix-command flakes"; experimental-features = [ "nix-command" "flakes" ];
# Opinionated: disable global registry # Opinionated: disable global registry
flake-registry = ""; flake-registry = "";
+1 -1
View File
@@ -43,7 +43,7 @@ in
nix = { nix = {
settings = { settings = {
# Enable flakes and new 'nix' command # Enable flakes and new 'nix' command
experimental-features = "nix-command flakes"; experimental-features = [ "nix-command" "flakes" ];
# Opinionated: disable global registry # Opinionated: disable global registry
flake-registry = ""; flake-registry = "";
# Workaround for https://github.com/NixOS/nix/issues/9574 # Workaround for https://github.com/NixOS/nix/issues/9574
+1 -1
View File
@@ -42,7 +42,7 @@ in
nix = { nix = {
settings = { settings = {
# Enable flakes and new 'nix' command # Enable flakes and new 'nix' command
experimental-features = "nix-command flakes"; experimental-features = [ "nix-command" "flakes" ];
# Opinionated: disable global registry # Opinionated: disable global registry
flake-registry = ""; flake-registry = "";
# Workaround for https://github.com/NixOS/nix/issues/9574 # Workaround for https://github.com/NixOS/nix/issues/9574
+2 -2
View File
@@ -39,13 +39,13 @@ in {
## Module dependencies ## Module dependencies
# :checkers spell # :checkers spell
(aspellWithDicts (ds: with ds; [ en en-computers en-science ])) (aspellWithDicts (ds: with ds; [ en ]))
# :tools editorconfig # :tools editorconfig
editorconfig-core-c # per-project style config editorconfig-core-c # per-project style config
# :tools lookup & :lang org +roam # :tools lookup & :lang org +roam
sqlite sqlite
# :lang latex & :lang org (latex previews) # :lang latex & :lang org (latex previews)
texlive.combined.scheme-medium texliveMedium
# :lang nix # :lang nix
nixfmt nixfmt
#nixd #nixd
+101 -61
View File
@@ -8,8 +8,8 @@
# #
# Stage Step command Effect # Stage Step command Effect
# ------ ------------------------- -------------------------------------- # ------ ------------------------- --------------------------------------
# 1 check-image Read-only: is a NixOS LXC ostemplate on PVE? # 1 check-image Read-only: is the ostemplate matching the current flake on PVE?
# deploy-image Idempotent: build+upload if missing, no-op if present. # deploy-image Idempotent: build+upload if missing/stale, no-op if current.
# update-image Force: rebuild locally + replace on PVE. # update-image Force: rebuild locally + replace on PVE.
# 2 start-builder deploy-image + clone a fresh CT under a free # 2 start-builder deploy-image + clone a fresh CT under a free
# VMID + start it + wait for DHCP. # VMID + start it + wait for DHCP.
@@ -90,6 +90,7 @@ PVE_BRIDGE="${PVE_BRIDGE:-vmbr0}" # network bridge
VMID_START="${VMID_START:-9999}" # scan downward from here for a free VMID VMID_START="${VMID_START:-9999}" # scan downward from here for a free VMID
VMID_FLOOR="${VMID_FLOOR:-100}" # lowest VMID to consider (PVE minimum) VMID_FLOOR="${VMID_FLOOR:-100}" # lowest VMID to consider (PVE minimum)
TEMPLATE_OUTPUT="${TEMPLATE_OUTPUT:-nixos-lxc}" # flake output to build TEMPLATE_OUTPUT="${TEMPLATE_OUTPUT:-nixos-lxc}" # flake output to build
TEMPLATE_TOPLEVEL_OUTPUT="${TEMPLATE_TOPLEVEL_OUTPUT:-nixos-lxc-toplevel}" # flake output a disposable must be running
CT_HOSTNAME_PREFIX="${CT_HOSTNAME_PREFIX:-nixos-builder}" # disposables' hostname prefix CT_HOSTNAME_PREFIX="${CT_HOSTNAME_PREFIX:-nixos-builder}" # disposables' hostname prefix
BUILD_SSH_USER="${BUILD_SSH_USER:-builder}" # user nixos-rebuild SSHes as on the CT BUILD_SSH_USER="${BUILD_SSH_USER:-builder}" # user nixos-rebuild SSHes as on the CT
CT_BOOT_TIMEOUT="${CT_BOOT_TIMEOUT:-120}" # seconds to wait for DHCP lease CT_BOOT_TIMEOUT="${CT_BOOT_TIMEOUT:-120}" # seconds to wait for DHCP lease
@@ -244,9 +245,9 @@ Composite commands (chain all stages):
+ destroy-builder. Disposable destroyed on success. + destroy-builder. Disposable destroyed on success.
Step commands (run one stage — VMID auto-discovered from PVE if omitted): Step commands (run one stage — VMID auto-discovered from PVE if omitted):
check-image Read-only: exit 0 if a NixOS LXC ostemplate is on PVE, 1 if not. check-image Read-only: exit 0 if the ostemplate matching the current flake is on PVE.
deploy-image Idempotent: build+upload if missing, no-op if present. deploy-image Idempotent: build+upload if missing/stale, no-op if current.
update-image Force: rebuild .$TEMPLATE_OUTPUT locally + replace on PVE. update-image Force: rebuild .$TEMPLATE_OUTPUT + upload. Old templates are kept.
start-builder deploy-image + clone a fresh CT + start. start-builder deploy-image + clone a fresh CT + start.
build-on [VMID] Build closure on an existing disposable. build-on [VMID] Build closure on an existing disposable.
activate <test|switch|boot> activate <test|switch|boot>
@@ -279,7 +280,8 @@ Options:
Environment: Environment:
PVE_HOST, PVE_STORAGE, PVE_ROOTFS_STORAGE, PVE_BRIDGE, PVE_HOST, PVE_STORAGE, PVE_ROOTFS_STORAGE, PVE_BRIDGE,
VMID_START, VMID_FLOOR, BUILD_SSH_USER, VMID_START, VMID_FLOOR, BUILD_SSH_USER,
CT_BOOT_TIMEOUT, CT_ROOTFS_GIB, TEMPLATE_OUTPUT, CT_HOSTNAME_PREFIX CT_BOOT_TIMEOUT, CT_ROOTFS_GIB, TEMPLATE_OUTPUT, TEMPLATE_TOPLEVEL_OUTPUT,
CT_HOSTNAME_PREFIX
Examples: Examples:
# Full happy path — build + activate susano permanently, auto-destroy CT. # Full happy path — build + activate susano permanently, auto-destroy CT.
@@ -481,17 +483,33 @@ resolve_vmid() {
## --------------------------------------------------------------------------- ## ---------------------------------------------------------------------------
# Stage 1: image management (check / deploy / update). # Stage 1: image management (check / deploy / update).
# All three operate on the NixOS LXC ostemplate stored in PVE's # All three operate on the NixOS LXC ostemplate stored in PVE's
# /var/lib/vz/template/cache/. The "latest" template is whichever # /var/lib/vz/template/cache/.
# nixos-lxc-*.tar.xz sorts last alphabetically (matches the helpers below). #
# Template identity: .$TEMPLATE_OUTPUT's store path is evaluated (no build);
# its basename embeds the full derivation hash — nixpkgs pin AND NixOS
# config — and becomes the uploaded filename. Matching against PVE is exact:
# a template matches the current flake iff its name equals the evaluated
# one. This catches both "missing" and "stale" images. (The previous
# "alphabetically last nixos*lxc*.tar.xz" pick was wrong: unstable version
# strings like 26.05pre-git sort above dated stable ones like 25.05.2026…,
# so a stale image could win over the current one.)
# --------------------------------------------------------------------------- # ---------------------------------------------------------------------------
# Echo the storage-relative path of the newest nixos-lxc template on PVE, or # Evaluate the image derivation's store path WITHOUT building it, and derive
# empty if none. Read-only. # the canonical template filename from it. Sets TEMPLATE_FILENAME and
find_template_on_pve() { # OSTEMPLATE. Because the store-path hash covers the flake lock and the
debug "find_template_on_pve: pveam list $PVE_STORAGE" # whole NixOS config, any edit to machines/builder/ or nixpkgs pin bump
pve pveam list "$PVE_STORAGE" 2>/dev/null \ # changes the filename — "same name, older build" becomes impossible.
| awk '/nixos.*lxc.*\.tar\.xz/ {print $1}' \ resolve_template_identity() {
| sort | tail -n1 || true step "Evaluating .$TEMPLATE_OUTPUT image identity (nix eval, no build) ..."
local out_path
out_path=$(cd "$FLAKE_ROOT" && nix eval --raw ".#$TEMPLATE_OUTPUT.outPath") \
|| die "Failed to eval .$TEMPLATE_OUTPUT.outPath — is the flake evaluable?"
TEMPLATE_FILENAME="$(basename "$out_path").tar.xz"
OSTEMPLATE="$PVE_STORAGE:vztmpl/$TEMPLATE_FILENAME"
debug "image outPath: $out_path"
debug "template on PVE: $OSTEMPLATE"
ok "Current flake image: $TEMPLATE_FILENAME"
} }
# Build .$TEMPLATE_OUTPUT locally and scp the tarball to PVE's template cache. # Build .$TEMPLATE_OUTPUT locally and scp the tarball to PVE's template cache.
@@ -505,80 +523,60 @@ build_and_upload_image() {
|| die "nix build .$TEMPLATE_OUTPUT produced no output path." || die "nix build .$TEMPLATE_OUTPUT produced no output path."
log " nix output: $result_dir" log " nix output: $result_dir"
# nixos-generators proxmox-lxc format lays the file under result/tarball/*.tar.xz # Identity first, so the upload target is the canonical hash-embedded
# filename even when called without a prior check_image (update-image).
resolve_template_identity
# nixos-generators / proxmox-lxc image lays the file under result/tarball/*.tar.xz
local tarball local tarball
tarball=$(find "$result_dir/tarball" -maxdepth 1 -type f -name '*.tar.xz' -print -quit | head -n1) tarball=$(find "$result_dir/tarball" -maxdepth 1 -type f -name '*.tar.xz' -print -quit | head -n1)
[[ -n "$tarball" ]] \ [[ -n "$tarball" ]] \
|| die "No .tar.xz found under $result_dir/tarball/. Did nixos-generators output layout change?" || die "No .tar.xz found under $result_dir/tarball/. Did the image output layout change?"
local tname; tname=$(basename "$tarball")
debug "tarball path: $tarball" debug "tarball path: $tarball"
debug "tarball name: $tname" ok "Built image: $(basename "$tarball")"
ok "Built image: $tname"
step "Uploading to $PVE_HOST:/var/lib/vz/template/cache/ ..." step "Uploading to $PVE_HOST:/var/lib/vz/template/cache/ ..."
local size_human local size_human
size_human=$(du -h "$tarball" | cut -f1) size_human=$(du -h "$tarball" | cut -f1)
log " scp $tarball ($size_human) -> $PVE_HOST:/var/lib/vz/template/cache/$tname" log " scp $tarball ($size_human) -> $PVE_HOST:/var/lib/vz/template/cache/$TEMPLATE_FILENAME"
pve_scp "$tarball" "$PVE_HOST:/var/lib/vz/template/cache/$tname" pve_scp "$tarball" "$PVE_HOST:/var/lib/vz/template/cache/$TEMPLATE_FILENAME"
OSTEMPLATE="$PVE_STORAGE:vztmpl/$tname"
} }
# Remove old nixos-lxc templates from PVE, keeping $1. Must be called after # Read-only check. Sets OSTEMPLATE and returns 0 if the template matching
# the new image is uploaded so a build/upload failure leaves the previous # the CURRENT flake build is on PVE; clears OSTEMPLATE and returns 1 if it
# template intact. # is missing or stale (a differently-named nixos-lxc template may exist).
purge_old_templates_on_pve() {
local keep="${1:-}"
step "Purging old nixos-lxc templates from $PVE_HOST (keeping ${keep:-none}) ..."
local all
all=$(pve pveam list "$PVE_STORAGE" 2>/dev/null \
| awk '/nixos.*lxc.*\.tar\.xz/ {print $1}' || true)
local removed=0
while IFS= read -r t; do
[[ -n "$t" ]] || continue
if [[ -n "$keep" && "$t" == "$keep" ]]; then
debug "keeping: $t"
continue
fi
local filename="${t##*/}"
log " removing: $t"
pve rm -f "/var/lib/vz/template/cache/$filename" 2>/dev/null || true
removed=$((removed + 1))
done <<<"$all"
ok "Purged $removed old template(s)"
}
# Read-only check. Sets OSTEMPLATE and returns 0 if a template exists;
# clears OSTEMPLATE and returns 1 if missing.
check_image() { check_image() {
step "Checking for nixos-lxc ostemplate on $PVE_HOST (storage: $PVE_STORAGE) ..." resolve_template_identity
step "Checking for $OSTEMPLATE on $PVE_HOST (storage: $PVE_STORAGE) ..."
local existing local existing
existing=$(find_template_on_pve) existing=$(pve pveam list "$PVE_STORAGE" 2>/dev/null | awk -v t="$OSTEMPLATE" '$1 == t {print $1}')
if [[ -n "$existing" ]]; then if [[ -n "$existing" ]]; then
OSTEMPLATE="$existing" ok "Image present (matches current flake build): $OSTEMPLATE"
ok "Image present: $OSTEMPLATE"
return 0 return 0
fi fi
OSTEMPLATE="" OSTEMPLATE=""
warn "No nixos-lxc ostemplate found." warn "No template matching the current flake build on $PVE_HOST."
return 1 return 1
} }
# Idempotent deploy: build + upload only if no template exists. # Idempotent deploy: ensure PVE holds the template matching the CURRENT
# flake build. No-op when it matches; build + upload otherwise. Historical
# templates are deliberately left in place — other tooling (e.g. the
# terraform handler) may pin containers to them.
deploy_image() { deploy_image() {
if check_image; then if check_image; then
log "Nothing to do — image already on PVE." log "Nothing to do — image on PVE matches current flake build."
return return
fi fi
build_and_upload_image build_and_upload_image
ok "Image deployed: $OSTEMPLATE" ok "Image deployed: $OSTEMPLATE"
} }
# Force update: build + upload first, then purge old. If the build or upload # Force update: rebuild + upload even if the current template is present.
# fails, the previous template remains on PVE. # Old templates are never deleted (terraform may pin them); prune manually
# with `pveam remove` if really desired.
update_image() { update_image() {
build_and_upload_image build_and_upload_image
purge_old_templates_on_pve "$OSTEMPLATE"
ok "Image updated: $OSTEMPLATE" ok "Image updated: $OSTEMPLATE"
} }
@@ -640,11 +638,27 @@ create_and_start_ct() {
# Echo the current IPv4 of a running container's eth0, or empty if unavailable. # Echo the current IPv4 of a running container's eth0, or empty if unavailable.
get_ct_ip() { get_ct_ip() {
local vmid="$1" local vmid="$1"
pve pct exec "$vmid" -- ip -j -4 addr show eth0 2>/dev/null \ # NixOS containers have no standard /bin|/sbin — lxc-attach needs the
# full path or exec fails with "No such file or directory".
pve pct exec "$vmid" -- /run/current-system/sw/bin/ip -j -4 addr show eth0 2>/dev/null \
| jq -r '.[0].addr_info[]? | select(.scope=="global") | .local' 2>/dev/null \ | jq -r '.[0].addr_info[]? | select(.scope=="global") | .local' 2>/dev/null \
| head -n1 || true | head -n1 || true
} }
# Echo the NixOS toplevel a running disposable actually booted, or empty.
# pct config drops the ostemplate field after creation, so the container's
# own /run/current-system is the only reliable record of what it runs.
ct_toplevel() {
local vmid="$1"
pve pct exec "$vmid" -- /run/current-system/sw/bin/readlink /run/current-system 2>/dev/null || true
}
# Echo the toplevel the current flake's builder image boots, or empty on
# eval failure (callers treat empty as "cannot tell, skip the check").
expected_toplevel() {
(cd "$FLAKE_ROOT" && nix eval --raw ".#$TEMPLATE_TOPLEVEL_OUTPUT.outPath" 2>/dev/null) || true
}
# Wait for a disposable to become SSH-reachable via its hostname. Echos the # Wait for a disposable to become SSH-reachable via its hostname. Echos the
# hostname on success (so the caller can pass it to do_build / probe_ssh). # hostname on success (so the caller can pass it to do_build / probe_ssh).
# We deliberately do NOT use the IP here — the script's contract is that # We deliberately do NOT use the IP here — the script's contract is that
@@ -832,6 +846,21 @@ cmd_composite() {
step "Container $vmid is stopped — starting ..." step "Container $vmid is stopped — starting ..."
pve pct start "$vmid" pve pct start "$vmid"
fi fi
local running_top want_top
running_top=$(ct_toplevel "$vmid")
want_top=$(expected_toplevel)
if [[ -n "$running_top" && -n "$want_top" && "$running_top" != "$want_top" ]]; then
warn "Disposable $vmid runs a stale image:"
warn " running: $running_top"
warn " current: $want_top"
step "Destroying $vmid and recreating from current image ..."
pve pct destroy "$vmid" --purge --force
vmid=$(find_free_vmid)
hostname="$CT_HOSTNAME_PREFIX-$vmid"
log "Created fresh disposable: $hostname"
create_and_start_ct "$vmid"
fi
fi fi
hostname=$(wait_for_ready "$vmid") hostname=$(wait_for_ready "$vmid")
@@ -867,6 +896,7 @@ cmd_composite() {
# --------------------------------------------------------------------------- # ---------------------------------------------------------------------------
cmd_check_image() { cmd_check_image() {
require ssh "drive PVE" require ssh "drive PVE"
require nix "evaluate the image identity"
require_pve require_pve
phase "check-image — read-only probe of ostemplate on PVE" phase "check-image — read-only probe of ostemplate on PVE"
if check_image; then if check_image; then
@@ -970,6 +1000,16 @@ cmd_build_on() {
die "Start it on PVE first ('pct start $vmid') or pick another VMID." die "Start it on PVE first ('pct start $vmid') or pick another VMID."
fi fi
# Guard: a disposable cloned from a stale template boots without
# sshd/networkd config and hangs the build — refuse instead of hanging.
local running_top want_top
running_top=$(ct_toplevel "$vmid")
want_top=$(expected_toplevel)
if [[ -n "$running_top" && -n "$want_top" && "$running_top" != "$want_top" ]]; then
fail "Disposable $vmid runs a stale image: $running_top"
die "Current flake boots: $want_top — recreate with: $0 destroy-builder $vmid && $0 start-builder"
fi
probe_ssh "$hostname" || { print_debug_info "$vmid" "$hostname"; die "Aborting build-on."; } probe_ssh "$hostname" || { print_debug_info "$vmid" "$hostname"; die "Aborting build-on."; }
do_build "$vmid" "$hostname" && rc=0 || rc=$? do_build "$vmid" "$hostname" && rc=0 || rc=$?