Compare commits
2 Commits
e9ac72d162
...
37d6977223
| Author | SHA1 | Date | |
|---|---|---|---|
| 37d6977223 | |||
| 20963732a5 |
+150
@@ -61,6 +61,7 @@ This guide documents methods for installing NixOS on a Proxmox virtual machine a
|
||||
- [[#rebuildsh---enhanced-nixos-rebuild-wrapper][rebuild.sh - Enhanced NixOS Rebuild Wrapper]]
|
||||
- [[#backupsh---automated-backup-script][backup.sh - Automated Backup Script]]
|
||||
- [[#hash-utilsh---file-hash-verification][hash-util.sh - File Hash Verification]]
|
||||
- [[#pve-buildsh---disposable-lxc-builder-on-proxmox-ve][pve-build.sh - Disposable LXC Builder on Proxmox VE]]
|
||||
- [[#optional-nixos-modules][Optional NixOS Modules]]
|
||||
- [[#reverse-proxies][Reverse Proxies]]
|
||||
- [[#file-servers][File Servers]]
|
||||
@@ -335,6 +336,155 @@ Verifies file integrity using SHA256 checksums.
|
||||
./bin/hash-util.sh --path configuration.nix --hash $(sha256sum configuration.nix | cut -d' ' -f1)
|
||||
#+end_src
|
||||
|
||||
** pve-build.sh - Disposable LXC Builder on Proxmox VE
|
||||
Builds a NixOS configuration on a throwaway LXC container running on the Proxmox VE node, then activates the result on the requester (= the machine invoking the script, by default). Offloads the heavy compilation work from the requester to a disposable builder; the closure is shipped back over =nix copy= and activated locally.
|
||||
|
||||
The disposable is cloned from a NixOS LXC ostemplate (=nixos-lxc= flake output, =proxmox-lxc= format). The template is built locally and uploaded to PVE on first use, then reused.
|
||||
|
||||
*** Prerequisites
|
||||
- An SSH alias =pve= in =~/.ssh/config= pointing at the PVE node (the script defers all connection details — HostName, User, Port, IdentityFile — to SSH config). Override with =PVE_HOST= or =--pve-host= if your alias differs.
|
||||
- The operator's pubkey must be in the =adminKeys= list in =machines/builder/default.nix=. The disposable's =builder= user trusts whatever keys are listed there.
|
||||
- The caller must resolve disposable hostnames (=nixos-builder-<VMID>=) — typically via dnsmasq or split-DNS that reads from PVE. The script never uses IPs for SSH.
|
||||
- =jq= on the caller (to parse =pvesh= JSON output).
|
||||
|
||||
*** Flow
|
||||
1. Ensure a NixOS LXC ostemplate exists on PVE; build =.#nixos-lxc= locally and =scp= it if missing.
|
||||
2. Clone a fresh container under a free VMID (scanning downward from 9999), start it, wait for SSH on its hostname.
|
||||
3. Build phase (runs as the calling user, no =sudo=):
|
||||
#+begin_example
|
||||
nixos-rebuild build --flake .#<requester> --build-host root@<ct-ip>
|
||||
#+end_example
|
||||
builds the closure on the disposable and copies it back to the local Nix store.
|
||||
4. Activate phase (only for =test= / =switch= / =boot=; runs locally with =sudo=, no =--build-host=):
|
||||
#+begin_example
|
||||
sudo nixos-rebuild <cmd> --flake .#<requester>
|
||||
#+end_example
|
||||
the closure is already local, so this only activates.
|
||||
5. Destroy the disposable (=pct destroy --purge --force=).
|
||||
|
||||
The build/activate split avoids needing the requester's root user to SSH to the disposable — only the calling user does.
|
||||
|
||||
*** Composite vs. step commands
|
||||
Each stage can be invoked on its own, or chained via the composite commands:
|
||||
|
||||
| Composite | Stages chained | Disposable on success |
|
||||
|-----------+-----------------------------------------------------------------+-----------------------|
|
||||
| =build= | deploy-image + start-builder + build-on | left running |
|
||||
| =test= | deploy-image + start-builder + build-on + activate(test) | left running |
|
||||
| =switch= | deploy-image + start-builder + build-on + activate(switch) + destroy-builder | destroyed |
|
||||
| =boot= | deploy-image + start-builder + build-on + activate(boot) + destroy-builder | destroyed |
|
||||
|
||||
| Step command | Stage | Effect |
|
||||
|---------------------------+-------+-----------------------------------------------------------------------|
|
||||
| =check-image= | 1 | Read-only: exit 0 if a NixOS LXC ostemplate is on PVE, 1 if not. |
|
||||
| =deploy-image= | 1 | Idempotent: build =.#nixos-lxc= locally + scp to PVE if missing. |
|
||||
| =update-image= | 1 | Force: rebuild =.#nixos-lxc= and replace the ostemplate on PVE. |
|
||||
| =start-builder= | 2 | deploy-image + clone a fresh CT + start. |
|
||||
| =build-on [VMID]= | 3 | Build closure on an existing disposable. |
|
||||
| =activate <test\|switch\|boot>= | 4 | Activate LOCALLY (closure must already be in the local store). |
|
||||
| =destroy-builder [VMID]= | 5 | =pct destroy --purge --force=. |
|
||||
| =info [VMID]= | - | List disposables, or show detail for one. |
|
||||
|
||||
*** Stateless design
|
||||
The script writes no state files. Each step discovers prior steps' artifacts dynamically from PVE:
|
||||
|
||||
- Disposables are identified by hostname pattern =nixos-builder-<VMID>= (override via =CT_HOSTNAME_PREFIX=). When a step needs a target VMID and none is passed explicitly, it queries =pvesh get /cluster/resources= for LXC containers matching the prefix.
|
||||
- Exactly one match :: used automatically.
|
||||
- Zero matches :: the step errors out and points at =create=.
|
||||
- Multiple matches :: the step errors out, lists the matches, and asks for an explicit VMID.
|
||||
- VMID allocation starts at =9999= and scans downward (configurable via =--vmid-start= / =--vmid-floor=) so disposables sit clearly above regular VM IDs.
|
||||
- The built closure lives in the caller's local Nix store; =nixos-rebuild= finds it naturally during =activate=, so no IPC between =build-on= and =activate= is needed.
|
||||
|
||||
*** Hostname-based SSH
|
||||
All SSH to disposables targets their hostname (=nixos-builder-<VMID>=), never their IP. The caller's resolver must be able to look up PVE container hostnames — typically via dnsmasq or split-DNS that reads from PVE. The script never resolves IPs for SSH; =get_ct_ip= is used only for =info= display and diagnostic logging.
|
||||
|
||||
This makes the script safe to re-run, interrupt, or split across shell sessions — there is no =latest-vmid= file to drift out of sync with reality.
|
||||
|
||||
*** Basic Usage
|
||||
#+begin_src sh
|
||||
# Full happy path — build + activate susano permanently, auto-destroy CT.
|
||||
pve-build switch --machine susano
|
||||
|
||||
# Step-by-step (each step discovers the prior step's artifacts from PVE):
|
||||
pve-build deploy-image # build + upload the LXC ostemplate (no-op if present)
|
||||
pve-build start-builder # clones a fresh disposable CT
|
||||
pve-build build-on # discovers the CT on PVE, builds on it
|
||||
pve-build activate switch # activates locally (no SSH)
|
||||
pve-build destroy-builder # discovers the CT on PVE, destroys it
|
||||
|
||||
# Rebuild the LXC image after editing machines/builder/default.nix.
|
||||
pve-build update-image
|
||||
|
||||
# Read-only check (exit 0 if image is already on PVE, 1 otherwise).
|
||||
pve-build check-image && echo ready || echo missing
|
||||
|
||||
# Operate on a specific CT (skips discovery — needed when multiple exist).
|
||||
pve-build build-on 305
|
||||
#+end_src
|
||||
|
||||
*** Advanced Examples
|
||||
#+begin_src sh
|
||||
# Build + activate temporarily without persisting to the bootloader.
|
||||
pve-build test --machine fujin
|
||||
|
||||
# Use a non-default PVE node and a higher starting VMID.
|
||||
pve-build switch --pve-host root@10.0.0.5 --vmid-start 9999
|
||||
|
||||
# Keep the disposable even after a successful switch (for inspection).
|
||||
pve-build switch --keep
|
||||
|
||||
# List every disposable currently on PVE.
|
||||
pve-build info
|
||||
|
||||
# Inspect a specific disposable in detail.
|
||||
pve-build info 307
|
||||
|
||||
# Destroy a specific disposable by VMID.
|
||||
pve-build destroy-builder 307
|
||||
#+end_src
|
||||
|
||||
*** Command Reference
|
||||
**** Composite commands
|
||||
- =build= - deploy-image + start-builder + build-on.
|
||||
- =test= - build + activate temporarily (reverts on reboot).
|
||||
- =switch= - build + activate permanently. Disposable destroyed on success.
|
||||
- =boot= - build + set as boot default. Disposable destroyed on success.
|
||||
|
||||
**** Step commands
|
||||
- =check-image= - Read-only: exit 0 if ostemplate is on PVE, 1 if missing.
|
||||
- =deploy-image= - Idempotent: build =.#nixos-lxc= locally + scp to PVE if missing.
|
||||
- =update-image= - Force rebuild + replace the ostemplate on PVE.
|
||||
- =start-builder= - deploy-image + clone a fresh CT + start.
|
||||
- =build-on [VMID]= - Build closure on an existing disposable (default: discovered).
|
||||
- =activate <test|switch|boot>= - Activate LOCALLY (closure must already be built).
|
||||
- =destroy-builder [VMID]= - =pct destroy --purge --force= (default: discovered).
|
||||
- =info [VMID]= - List disposables, or show detail for one.
|
||||
|
||||
**** Aliases
|
||||
The old command names still work as aliases:
|
||||
- =ensure-template= → =deploy-image=
|
||||
- =create= → =start-builder=
|
||||
|
||||
**** Options
|
||||
- =--machine NAME= - Requester machine name (default: current hostname).
|
||||
- =--pve-host HOST= - PVE SSH alias or target (default: =pve=).
|
||||
- =--pve-storage NAME= - Ostemplate storage (default: =local=).
|
||||
- =--rootfs-storage NAME= - Rootfs storage (default: =local-lvm=).
|
||||
- =--bridge NAME= - Network bridge (default: =vmbr0=).
|
||||
- =--vmid-start N= - Highest VMID to consider (default: =9999=); scanned downward.
|
||||
- =--vmid-floor N= - Lowest VMID to consider (default: =100=).
|
||||
- =--rootfs-gib N= - Rootfs size in GiB (default: =20=).
|
||||
- =--keep= - Keep the disposable even on successful =switch= / =boot=.
|
||||
- =--show-trace= , =--verbose= - Passed through to =nixos-rebuild=.
|
||||
|
||||
**** Environment
|
||||
= PVE_HOST= , = PVE_STORAGE= , = PVE_ROOTFS_STORAGE= , = PVE_BRIDGE= , = VMID_START= , = VMID_FLOOR= , = BUILD_SSH_USER= , = CT_BOOT_TIMEOUT= , = CT_ROOTFS_GIB= .
|
||||
|
||||
*** Notes
|
||||
- Disposables are matched by hostname prefix (=nixos-builder-= by default). If you want a parallel run with multiple builders, pass explicit VMIDs to =build-on= / =destroy-builder= / =info=.
|
||||
- =destroy-builder= calls =pct destroy <vmid> --purge --force=, so it stops and removes a running container in one step.
|
||||
- To rebuild the LXC template after editing =machines/builder/default.nix=, remove the old tarball from =root@<pve>:/var/lib/vz/template/cache/= — the script always picks the alphabetically last =nixos-lxc-*.tar.xz= it finds.
|
||||
|
||||
* Optional NixOS Modules
|
||||
** Reverse Proxies
|
||||
The following modules can be enabled to provide a reverse proxy.
|
||||
|
||||
Generated
+89
-88
@@ -20,11 +20,11 @@
|
||||
]
|
||||
},
|
||||
"locked": {
|
||||
"lastModified": 1784368054,
|
||||
"narHash": "sha256-zF1iJkBQSDWmRO4/LEeHR1SpKY0lqZaxkoQJpPS9K9U=",
|
||||
"lastModified": 1785877886,
|
||||
"narHash": "sha256-H2CrAlJD9FsUbSEIhPVK3IyVjnK0vSxPruBef17GcBs=",
|
||||
"owner": "hyprwm",
|
||||
"repo": "aquamarine",
|
||||
"rev": "9b5f14d9483445e766294eb8fbe0b8f370269ed0",
|
||||
"rev": "1a10fe26a9f7d989c359e6a9ea61aa2e44d06c36",
|
||||
"type": "github"
|
||||
},
|
||||
"original": {
|
||||
@@ -127,11 +127,11 @@
|
||||
"nixpkgs": "nixpkgs_3"
|
||||
},
|
||||
"locked": {
|
||||
"lastModified": 1784907296,
|
||||
"narHash": "sha256-UYyGETnsSfPDTFIq/+1Uwe0C5fhqE2cgFXpYHnv8cUc=",
|
||||
"lastModified": 1786054218,
|
||||
"narHash": "sha256-frbTEfqt6fAOcQ4Xk9o1cR5Eq//XhlmqS+3M86ZH1hY=",
|
||||
"owner": "9001",
|
||||
"repo": "copyparty",
|
||||
"rev": "10db4236bf864a2f57b3cb2db42eb93a456ea698",
|
||||
"rev": "fbcb7733071560bac490ca60b0bb982a00bbe343",
|
||||
"type": "github"
|
||||
},
|
||||
"original": {
|
||||
@@ -166,11 +166,11 @@
|
||||
"nixpkgs-stable": "nixpkgs-stable"
|
||||
},
|
||||
"locked": {
|
||||
"lastModified": 1785062976,
|
||||
"narHash": "sha256-3PQYC0Gm9NfAJbko6JTtFBlujtXWm7L5VZpUVJRu04c=",
|
||||
"lastModified": 1786356557,
|
||||
"narHash": "sha256-d3FqeM5bfyCvMmdygrQ+stj0MKq/T8O1+NdIHMsspzs=",
|
||||
"owner": "nix-community",
|
||||
"repo": "emacs-overlay",
|
||||
"rev": "ecf4a1a2d40f5cf118e7ffa255212ffba6036151",
|
||||
"rev": "c450874f05714ba7229a4c4e7b9a80da1dafc3c2",
|
||||
"type": "github"
|
||||
},
|
||||
"original": {
|
||||
@@ -183,11 +183,11 @@
|
||||
"firefox-gnome-theme": {
|
||||
"flake": false,
|
||||
"locked": {
|
||||
"lastModified": 1782007937,
|
||||
"narHash": "sha256-PbnJr+eB+9Czol3ReI83dUgEhcn0sDK6TSy6ODTQm88=",
|
||||
"lastModified": 1783570805,
|
||||
"narHash": "sha256-ptl5aRlCv9/uRSv2u8Hq8UFVFeZ6Q/bT049bpqNgc3w=",
|
||||
"owner": "rafaelmardojai",
|
||||
"repo": "firefox-gnome-theme",
|
||||
"rev": "981bd332015397fb1ca033fa982bd61635160c78",
|
||||
"rev": "5602ed62d638142c1ab31dccd01dfbfb28841225",
|
||||
"type": "github"
|
||||
},
|
||||
"original": {
|
||||
@@ -424,11 +424,11 @@
|
||||
]
|
||||
},
|
||||
"locked": {
|
||||
"lastModified": 1783963347,
|
||||
"narHash": "sha256-r376E2XpakiXwModDHIxlvB6qLq4iFVEq730vxOO4JY=",
|
||||
"lastModified": 1785531816,
|
||||
"narHash": "sha256-vkMnV0JIyw+g/NmcfoajlGaAO+9a0ezia+FZohQJrik=",
|
||||
"owner": "nix-community",
|
||||
"repo": "home-manager",
|
||||
"rev": "a45a7c451455a51ae740ec3bce4024b312809c29",
|
||||
"rev": "bf9ce9fec78f95f374e8dd3b503863a3ec128ebe",
|
||||
"type": "github"
|
||||
},
|
||||
"original": {
|
||||
@@ -482,11 +482,11 @@
|
||||
]
|
||||
},
|
||||
"locked": {
|
||||
"lastModified": 1782566056,
|
||||
"narHash": "sha256-haEZcHzYrePnjFOYSWTbxm/Nrla0aPslJfmvdCvqtVc=",
|
||||
"lastModified": 1785855875,
|
||||
"narHash": "sha256-dpW3UKG2NTboxxYGzOX4nZiH8YI++CpgosHmVaquOEI=",
|
||||
"owner": "hyprwm",
|
||||
"repo": "hyprgraphics",
|
||||
"rev": "c6e7b9f673f4360bc813d3dc75028f75ee88d3f8",
|
||||
"rev": "8699c38f0e4a1ca3bfc84f84ba020509ced1f133",
|
||||
"type": "github"
|
||||
},
|
||||
"original": {
|
||||
@@ -512,11 +512,11 @@
|
||||
"xdph": "xdph"
|
||||
},
|
||||
"locked": {
|
||||
"lastModified": 1784980432,
|
||||
"narHash": "sha256-MZQi0zqZ8c7eIxhhQzC5z7PHh8LWGRRjYqkX0GYbYBg=",
|
||||
"lastModified": 1786298417,
|
||||
"narHash": "sha256-nJZCCA1YXQqnLQSNVrtY+IxK0pnVLV5qJSw79axtpCo=",
|
||||
"ref": "refs/heads/main",
|
||||
"rev": "453d96e92739a2a0b865cf9166d48ba14ec14b7b",
|
||||
"revCount": 7646,
|
||||
"rev": "f7daeb7f79d48745a2894367e9e73229ac162abe",
|
||||
"revCount": 7721,
|
||||
"type": "git",
|
||||
"url": "https://github.com/hyprwm/Hyprland"
|
||||
},
|
||||
@@ -558,11 +558,11 @@
|
||||
]
|
||||
},
|
||||
"locked": {
|
||||
"lastModified": 1784196523,
|
||||
"narHash": "sha256-ahtKMGXFJdlQNhatQm1+BBU/pGfGYnAqQt3vWvq4p8s=",
|
||||
"lastModified": 1784533903,
|
||||
"narHash": "sha256-Ee78BRFi+MrmgHmmW+2dZUEI1R3cssEzza0ar3fsNX8=",
|
||||
"owner": "hyprwm",
|
||||
"repo": "hyprland-guiutils",
|
||||
"rev": "a6ccb6cb112ed5a244c0191fb972347ecfa893e0",
|
||||
"rev": "a16ad89ed5fb4192c966018a80c652de8d96f748",
|
||||
"type": "github"
|
||||
},
|
||||
"original": {
|
||||
@@ -588,11 +588,11 @@
|
||||
]
|
||||
},
|
||||
"locked": {
|
||||
"lastModified": 1784102347,
|
||||
"narHash": "sha256-piRpwar7VZI3YviYo0a/UMFz9+rLesfv3nRLGKxjVGg=",
|
||||
"lastModified": 1786227627,
|
||||
"narHash": "sha256-bc4jNVx0agB40xwxJ0r7hAAk5tk5Lm0uKtwP5rNyvZQ=",
|
||||
"owner": "hyprwm",
|
||||
"repo": "hyprland-plugins",
|
||||
"rev": "7644cecdb947060682891a0db2a0cdc5c0b9e704",
|
||||
"rev": "faf5ef1bd5916051ed3252463697dd2ae479f629",
|
||||
"type": "github"
|
||||
},
|
||||
"original": {
|
||||
@@ -719,11 +719,11 @@
|
||||
]
|
||||
},
|
||||
"locked": {
|
||||
"lastModified": 1784323413,
|
||||
"narHash": "sha256-XnAVV+H4f8Xdv0yZcSwJ5kCjLyE8fHxPeLX6a3HSrAU=",
|
||||
"lastModified": 1785843795,
|
||||
"narHash": "sha256-DFc543bQN94Kt+RsD3Hiu7qCA1uKdqaFJKPMjzANKGU=",
|
||||
"owner": "hyprwm",
|
||||
"repo": "hyprutils",
|
||||
"rev": "5f03477ab3a005ff27c527486f551883535aea2f",
|
||||
"rev": "5a7b8cf221914ce4714407950e4ffbdddcd8b66f",
|
||||
"type": "github"
|
||||
},
|
||||
"original": {
|
||||
@@ -773,11 +773,11 @@
|
||||
]
|
||||
},
|
||||
"locked": {
|
||||
"lastModified": 1778410714,
|
||||
"narHash": "sha256-o6RzFj4nJXaPRY7EM01siuCQeT41RfwwmcmFQqwFJJg=",
|
||||
"lastModified": 1784465130,
|
||||
"narHash": "sha256-ak5fWEmWZyax8trkV4aphdvjrbUiSyl6qS+y5GwBS7Y=",
|
||||
"owner": "hyprwm",
|
||||
"repo": "hyprwire",
|
||||
"rev": "85148a8e612808cf5ddb25d0b3c5840f3498a7dc",
|
||||
"rev": "7d935bb54674aa0fbd327d2a6888bd0630079ed0",
|
||||
"type": "github"
|
||||
},
|
||||
"original": {
|
||||
@@ -826,11 +826,11 @@
|
||||
]
|
||||
},
|
||||
"locked": {
|
||||
"lastModified": 1784537139,
|
||||
"narHash": "sha256-cfJ+PdNNx++NukHKATYBNBnNdIudcDt/BJ7VbFhXx9Q=",
|
||||
"lastModified": 1785141927,
|
||||
"narHash": "sha256-vaPZJgjFL13DlDZcO25XNuAfsOPQm2i9Jmg42dj4wj4=",
|
||||
"owner": "Mic92",
|
||||
"repo": "nix-ld",
|
||||
"rev": "9fef86f17a711a04399b0f0bf5d8fb7680d5f13b",
|
||||
"rev": "1267405dbb13b1b664445ff3654da3a33ee272e4",
|
||||
"type": "github"
|
||||
},
|
||||
"original": {
|
||||
@@ -880,11 +880,11 @@
|
||||
"nixpkgs": "nixpkgs_7"
|
||||
},
|
||||
"locked": {
|
||||
"lastModified": 1784723954,
|
||||
"narHash": "sha256-1CfD8ZUjCkTgjsneLZ/lxCHhgDfqxxE7/GX0MmsgiqA=",
|
||||
"lastModified": 1785232496,
|
||||
"narHash": "sha256-65EQYIRRpTdpH8lUiB6Mvo5uBkG60aBIzAJuALfx+O0=",
|
||||
"owner": "NixOS",
|
||||
"repo": "nixos-hardware",
|
||||
"rev": "a017f5b72210026af5b3ac5949f08d94380a6fbd",
|
||||
"rev": "2e790b0a6be8ec2b76174ac0931b8ff11919ec98",
|
||||
"type": "github"
|
||||
},
|
||||
"original": {
|
||||
@@ -942,11 +942,11 @@
|
||||
},
|
||||
"nixpkgs-stable": {
|
||||
"locked": {
|
||||
"lastModified": 1784856561,
|
||||
"narHash": "sha256-J+Bx1Z6Oeoj2FgnBhRMKyUhhtDoOpTgXYaVLZpDjW4A=",
|
||||
"lastModified": 1786201459,
|
||||
"narHash": "sha256-CiOTEjmwAmG2AWnaIno9YaCJJmpca2FXPhMAsnrolCg=",
|
||||
"owner": "NixOS",
|
||||
"repo": "nixpkgs",
|
||||
"rev": "597283ad8aa0b331c788e97c4c262d58877074ef",
|
||||
"rev": "8b8c811c7c2541c30382c5de7ed26be055569c60",
|
||||
"type": "github"
|
||||
},
|
||||
"original": {
|
||||
@@ -958,11 +958,11 @@
|
||||
},
|
||||
"nixpkgs_10": {
|
||||
"locked": {
|
||||
"lastModified": 1784007870,
|
||||
"narHash": "sha256-djcLt/JJphyNt4eDY9XTly+/WbCK5lqWq9lSgCmJkkQ=",
|
||||
"lastModified": 1785454630,
|
||||
"narHash": "sha256-LQy14TZp77TwbQf40gg1V3jo8FwJG0jGDkAH+zRHqg8=",
|
||||
"owner": "nixos",
|
||||
"repo": "nixpkgs",
|
||||
"rev": "18b9261cb3294b6d2a06d03f96872827b8fe2698",
|
||||
"rev": "1559d3daa3ecc813a650b79375ea61b6741b8746",
|
||||
"type": "github"
|
||||
},
|
||||
"original": {
|
||||
@@ -1004,11 +1004,11 @@
|
||||
},
|
||||
"nixpkgs_4": {
|
||||
"locked": {
|
||||
"lastModified": 1784796856,
|
||||
"narHash": "sha256-wWFrV5/Qbm+lyt5x20E/bSbfJiGKMo4RCxZV8cl/WZI=",
|
||||
"lastModified": 1786106723,
|
||||
"narHash": "sha256-zDSUbpoeo/9ZmD2+wXnzxoo1+uhL8vxc0b8yuYMKYq0=",
|
||||
"owner": "NixOS",
|
||||
"repo": "nixpkgs",
|
||||
"rev": "e2587caef70cea85dd97d7daab492899902dbf5d",
|
||||
"rev": "f13ff45afd1bb73e640eaa08a7066dbed07e3238",
|
||||
"type": "github"
|
||||
},
|
||||
"original": {
|
||||
@@ -1020,11 +1020,11 @@
|
||||
},
|
||||
"nixpkgs_5": {
|
||||
"locked": {
|
||||
"lastModified": 1784356753,
|
||||
"narHash": "sha256-12KrbMiWLcf8m7pCvAtZh1ZrgF85ZXDXvfR/fWTKy84=",
|
||||
"lastModified": 1786106723,
|
||||
"narHash": "sha256-zDSUbpoeo/9ZmD2+wXnzxoo1+uhL8vxc0b8yuYMKYq0=",
|
||||
"owner": "NixOS",
|
||||
"repo": "nixpkgs",
|
||||
"rev": "61b7c44c4073f0b827768aff0049561b5110ea5a",
|
||||
"rev": "f13ff45afd1bb73e640eaa08a7066dbed07e3238",
|
||||
"type": "github"
|
||||
},
|
||||
"original": {
|
||||
@@ -1102,11 +1102,11 @@
|
||||
]
|
||||
},
|
||||
"locked": {
|
||||
"lastModified": 1785062220,
|
||||
"narHash": "sha256-p3Wxo+5p0Y6E3LwA3DdwMMse/GtcaPUmqLilPVfJPe4=",
|
||||
"lastModified": 1786338498,
|
||||
"narHash": "sha256-qy3Cheg/FQ9ZaBPTIgdq4IkmkNtC6XBpmtC8nT+wU/Y=",
|
||||
"owner": "noctalia-dev",
|
||||
"repo": "noctalia",
|
||||
"rev": "e1a4d27f2f2494db2c6e7636b514d1770b16c776",
|
||||
"rev": "45e721ba0fb47d6efc00ca47e156237954037c99",
|
||||
"type": "github"
|
||||
},
|
||||
"original": {
|
||||
@@ -1127,11 +1127,11 @@
|
||||
]
|
||||
},
|
||||
"locked": {
|
||||
"lastModified": 1783439237,
|
||||
"narHash": "sha256-WUr8JF2v3n4Y30E5dxv4sAgNJXpVDBoCQNoQ/V4+n4o=",
|
||||
"lastModified": 1785549842,
|
||||
"narHash": "sha256-DCwBZmGsySF7oKGTRgEv2HvpxVXkHT+38VhTM76k0B4=",
|
||||
"owner": "nix-community",
|
||||
"repo": "NUR",
|
||||
"rev": "b70bb66c7bcd162642f3a609bc16843c7059f503",
|
||||
"rev": "a9f987b57594e845e3e5cdd423b9a70846d70308",
|
||||
"type": "github"
|
||||
},
|
||||
"original": {
|
||||
@@ -1265,11 +1265,11 @@
|
||||
"nix-filter": "nix-filter"
|
||||
},
|
||||
"locked": {
|
||||
"lastModified": 1784576463,
|
||||
"narHash": "sha256-XVm8Bi8XasjMP2VOisrPAuJvrB6+rQZW+/TL9kr2Ogs=",
|
||||
"lastModified": 1786046605,
|
||||
"narHash": "sha256-+ROT5vBruI7d0B2RKbpl2dT76Zf90urrOxfrhzfaVr4=",
|
||||
"owner": "zjeffer",
|
||||
"repo": "split-monitor-workspaces",
|
||||
"rev": "c8a03d993f71a3ae73179ce354e7a54859055f02",
|
||||
"rev": "3c2020a1f574aaec17ffe39e73468b73643990e3",
|
||||
"type": "github"
|
||||
},
|
||||
"original": {
|
||||
@@ -1298,11 +1298,11 @@
|
||||
"tinted-zed": "tinted-zed"
|
||||
},
|
||||
"locked": {
|
||||
"lastModified": 1784676123,
|
||||
"narHash": "sha256-ndyanKzw90yX2nUVFmTuYqXidUNymtMfgmIHyNdhht0=",
|
||||
"lastModified": 1786216702,
|
||||
"narHash": "sha256-fOOmw9tUYeqWVnK2w2NiuMTmGIbluj8xiBFTTFDCcEE=",
|
||||
"owner": "nix-community",
|
||||
"repo": "stylix",
|
||||
"rev": "66714e5ce44269ecc58c20d9196da8dbe1b27a31",
|
||||
"rev": "b67debfd2db1eb1f0fd8740b950f598bbaf74b8f",
|
||||
"type": "github"
|
||||
},
|
||||
"original": {
|
||||
@@ -1328,15 +1328,16 @@
|
||||
},
|
||||
"systems_2": {
|
||||
"locked": {
|
||||
"lastModified": 1681028828,
|
||||
"narHash": "sha256-Vy1rq5AaRuLzOxct8nz4T6wlgyUR7zLU309k9mBC768=",
|
||||
"lastModified": 1774449309,
|
||||
"narHash": "sha256-brhZ8DmuGtzkCYHJg4HEd602amKm89Y9ytsFZ5uWD1w=",
|
||||
"owner": "nix-systems",
|
||||
"repo": "default",
|
||||
"rev": "da67096a3b9bf56a91d16901293e51ba5b49a27e",
|
||||
"rev": "c29398b59d2048c4ab79345812849c9bd15e9150",
|
||||
"type": "github"
|
||||
},
|
||||
"original": {
|
||||
"owner": "nix-systems",
|
||||
"ref": "future-26.11",
|
||||
"repo": "default",
|
||||
"type": "github"
|
||||
}
|
||||
@@ -1397,11 +1398,11 @@
|
||||
"tinted-schemes": {
|
||||
"flake": false,
|
||||
"locked": {
|
||||
"lastModified": 1781968807,
|
||||
"narHash": "sha256-yYO3Vw2M0y3TAUqt+9+Mj0zwP3XDTF5/PXcPhhFQ1ZM=",
|
||||
"lastModified": 1785153830,
|
||||
"narHash": "sha256-fNdfCTeCXU3tZG3TMincd+u68qBHQgCr2Ljr/M1mWP0=",
|
||||
"owner": "tinted-theming",
|
||||
"repo": "schemes",
|
||||
"rev": "2ccef2f4b22e3cab5a9292811f7133a07eeba4a7",
|
||||
"rev": "9bd28ed313560db3c5b605c63bc4e309e78e3fc8",
|
||||
"type": "github"
|
||||
},
|
||||
"original": {
|
||||
@@ -1413,11 +1414,11 @@
|
||||
"tinted-tmux": {
|
||||
"flake": false,
|
||||
"locked": {
|
||||
"lastModified": 1782012462,
|
||||
"narHash": "sha256-2iDiD8DQLwS1lGuD9TS8WlvNyDoTs6krWntJbtB2zGo=",
|
||||
"lastModified": 1785031658,
|
||||
"narHash": "sha256-mZp9O2LjzdMzlqQF3l3fjqsuPBzXy+1qTfBEUGjTlpk=",
|
||||
"owner": "tinted-theming",
|
||||
"repo": "tinted-tmux",
|
||||
"rev": "8c4e750f738a742bd73377ee41d3dadedebedef4",
|
||||
"rev": "5d2c67f61ea7af36f16865ab6d541cdba41dc257",
|
||||
"type": "github"
|
||||
},
|
||||
"original": {
|
||||
@@ -1429,11 +1430,11 @@
|
||||
"tinted-zed": {
|
||||
"flake": false,
|
||||
"locked": {
|
||||
"lastModified": 1782009766,
|
||||
"narHash": "sha256-VUhBjpGvWqHI7rWeyMYb/u87YJSXHKfVV6S+IelWeO8=",
|
||||
"lastModified": 1785030526,
|
||||
"narHash": "sha256-klZf8UviewRkxuu74Bhbq6tqy7oxebQC7UVRWbbtQxU=",
|
||||
"owner": "tinted-theming",
|
||||
"repo": "base16-zed",
|
||||
"rev": "5e8350bcd354e3241ab681a265fa6ef060c40be1",
|
||||
"rev": "16f5a8adf4a6b1310d0a61ab172de963e8f76a02",
|
||||
"type": "github"
|
||||
},
|
||||
"original": {
|
||||
@@ -1444,11 +1445,11 @@
|
||||
},
|
||||
"unstable": {
|
||||
"locked": {
|
||||
"lastModified": 1784796856,
|
||||
"narHash": "sha256-wWFrV5/Qbm+lyt5x20E/bSbfJiGKMo4RCxZV8cl/WZI=",
|
||||
"lastModified": 1786106723,
|
||||
"narHash": "sha256-zDSUbpoeo/9ZmD2+wXnzxoo1+uhL8vxc0b8yuYMKYq0=",
|
||||
"owner": "nixos",
|
||||
"repo": "nixpkgs",
|
||||
"rev": "e2587caef70cea85dd97d7daab492899902dbf5d",
|
||||
"rev": "f13ff45afd1bb73e640eaa08a7066dbed07e3238",
|
||||
"type": "github"
|
||||
},
|
||||
"original": {
|
||||
@@ -1465,11 +1466,11 @@
|
||||
]
|
||||
},
|
||||
"locked": {
|
||||
"lastModified": 1784913159,
|
||||
"narHash": "sha256-JWq0BfjO4ktpH5USfQNQzdvHpIDT8fSKD5K7LvdMRFs=",
|
||||
"lastModified": 1786356609,
|
||||
"narHash": "sha256-ou8fYz5w9yhXC8YbvvExybFIa19MyW5G/8dEPqa90hM=",
|
||||
"owner": "nix-community",
|
||||
"repo": "home-manager",
|
||||
"rev": "079a3b5d1aa6a719920a51316253b7d6dd22738d",
|
||||
"rev": "c30c7955cec30d664a9baced6bc0112e263d4647",
|
||||
"type": "github"
|
||||
},
|
||||
"original": {
|
||||
@@ -1550,11 +1551,11 @@
|
||||
]
|
||||
},
|
||||
"locked": {
|
||||
"lastModified": 1784371182,
|
||||
"narHash": "sha256-S8A1lezEalltWcCp3gAic5lssS0xTSISK6fKODefhOk=",
|
||||
"lastModified": 1786032767,
|
||||
"narHash": "sha256-C5K27sF/jaQe1BgB1/575r01oTAvw6mrDWPS1qUl6X0=",
|
||||
"owner": "hyprwm",
|
||||
"repo": "xdg-desktop-portal-hyprland",
|
||||
"rev": "08d99f727944dd15e4740090305e31c5fb92a50a",
|
||||
"rev": "688feb3d88404598f12440a668136e74044391de",
|
||||
"type": "github"
|
||||
},
|
||||
"original": {
|
||||
@@ -1569,11 +1570,11 @@
|
||||
"nixpkgs": "nixpkgs_10"
|
||||
},
|
||||
"locked": {
|
||||
"lastModified": 1785039979,
|
||||
"narHash": "sha256-vZjuRK0UgvChYGMeQ8daxiETJ5KQyGx+8u8YHdw5e/g=",
|
||||
"lastModified": 1786347712,
|
||||
"narHash": "sha256-yH+jWXH2TVd5h3J5KoZiE8/4O4HqoggfB0zl9uVj39w=",
|
||||
"owner": "0xc000022070",
|
||||
"repo": "zen-browser-flake",
|
||||
"rev": "6f5e680db7d105ecf02b4e0d752d48d9083da6c9",
|
||||
"rev": "945efbc704b7f8c1731a922aabbc5d95edc9eb74",
|
||||
"type": "github"
|
||||
},
|
||||
"original": {
|
||||
|
||||
@@ -1,5 +1,5 @@
|
||||
{
|
||||
description = "Susano NixOS Homelab";
|
||||
description = "Alex's NixOS";
|
||||
|
||||
inputs = {
|
||||
# Nixpkgs
|
||||
@@ -214,6 +214,19 @@
|
||||
};
|
||||
|
||||
packages.x86_64-linux = {
|
||||
nixos-lxc = (nixpkgs.lib.nixosSystem {
|
||||
system = "x86_64-linux";
|
||||
modules = [
|
||||
./machines/builder
|
||||
({ modulesPath, ... }: {
|
||||
imports = [ (modulesPath + "/virtualisation/proxmox-lxc.nix") ];
|
||||
})
|
||||
];
|
||||
specialArgs = {
|
||||
inherit inputs;
|
||||
};
|
||||
}).config.system.build.image;
|
||||
|
||||
izanami-proxmox = nixos-generators.nixosGenerate {
|
||||
system = "x86_64-linux";
|
||||
modules = [
|
||||
|
||||
@@ -0,0 +1,152 @@
|
||||
# Minimal NixOS configuration for a disposable LXC builder on Proxmox VE.
|
||||
#
|
||||
# Built via the `nixos-lxc` flake output using nixos-generators with
|
||||
# format = "proxmox-lxc". The resulting tarball is uploaded to PVE's
|
||||
# /var/lib/vz/template/cache/ and cloned by pve-build each time a
|
||||
# disposable builder is needed.
|
||||
#
|
||||
# Responsibilities of this image:
|
||||
# * Run nix with flakes as the `builder` user so nixos-rebuild
|
||||
# --build-host builder@<hostname> works against it.
|
||||
# * Be a competent builder: all cores, hardlink dedup, keep-derivations
|
||||
# and keep-outputs, keep-going on failure, idle CPU scheduling.
|
||||
# * Accept SSH from the operator (`builder` user + admin keys shared
|
||||
# across the rest of the homelab). Root SSH is disabled.
|
||||
# * Stay tiny — no bootloader, no kernel, no home-manager. The proxmox-lxc
|
||||
# format module from nixpkgs already sets boot.isContainer = true and
|
||||
# handles the LXC-specific bits.
|
||||
{
|
||||
config,
|
||||
pkgs,
|
||||
inputs,
|
||||
lib,
|
||||
...
|
||||
}:
|
||||
|
||||
let
|
||||
flakeInputs = lib.filterAttrs (_: lib.isType "flake") inputs;
|
||||
|
||||
# Operator keys — same ones baked into every other machine in this flake.
|
||||
# Whoever runs pve-build must hold a matching private key. Add more
|
||||
# keys here as needed; the authorized_keys list mirrors this exactly.
|
||||
adminKeys = [
|
||||
"ssh-ed25519 AAAAC3NzaC1lZDI1NTE5AAAAIBcGhVpjmWEw1GEw0y/ysJPa2v3+u/Rt/iES/Se2huH2 alexander0derevianko@gmail.com"
|
||||
"sk-ssh-ed25519@openssh.com AAAAGnNrLXNzaC1lZDI1NTE5QG9wZW5zc2guY29tAAAAIGXvmStLAC4f+D9/b3/eKl6lb8xLQOfDqwu3Piocrr7ZAAAABHNzaDo= yubikey@fujin"
|
||||
];
|
||||
in {
|
||||
nixpkgs = {
|
||||
hostPlatform = "x86_64-linux";
|
||||
config.allowUnfree = true;
|
||||
};
|
||||
|
||||
nix = {
|
||||
settings = {
|
||||
experimental-features = "nix-command flakes";
|
||||
flake-registry = "";
|
||||
nix-path = config.nix.nixPath;
|
||||
|
||||
# Parallelism — use every core the container can see.
|
||||
cores = 0; # 0 = use all visible cores per build job
|
||||
max-jobs = "auto"; # auto = one local build job per core
|
||||
|
||||
# Store hygiene — hardlink identical files so the store stays compact
|
||||
# across many sequential builds.
|
||||
auto-optimise-store = true;
|
||||
|
||||
# Cache reuse — keep derivation files and their outputs around even
|
||||
# when no current generation references them. Massively speeds up
|
||||
# repeated builds of the same flakes and lets you inspect what a
|
||||
# prior build actually pulled in.
|
||||
gc-keep-derivations = true;
|
||||
gc-keep-outputs = true;
|
||||
|
||||
# Don't abort the whole build on the first failing derivation — let
|
||||
# nix continue so the caller sees every failure in one pass.
|
||||
keep-going = true;
|
||||
|
||||
# `builder` drives builds via nixos-rebuild --build-host. Trust it so
|
||||
# `nix copy --to ssh://builder@<ct>` from the caller works without
|
||||
# extra configuration.
|
||||
trusted-users = [ "builder" ];
|
||||
allowed-users = [ "builder" ];
|
||||
|
||||
# Keep the default cache so flake inputs and build outputs resolve
|
||||
# without having to build them from source.
|
||||
substituters = lib.mkForce [ "https://cache.nixos.org/" ];
|
||||
trusted-public-keys = lib.mkForce [
|
||||
"cache.nixos.org-1:6NCHdD59X431o0gWypbMrAURkbJ16ZPMQFGspcDShjY="
|
||||
];
|
||||
};
|
||||
channel.enable = false;
|
||||
|
||||
# Be polite to other tenants on the PVE node when no builds are running.
|
||||
daemonCPUSchedPolicy = "idle";
|
||||
|
||||
registry = lib.mapAttrs (_: flake: { inherit flake; }) flakeInputs;
|
||||
nixPath = lib.mapAttrsToList (n: _: "${n}=flake:${n}") flakeInputs;
|
||||
};
|
||||
|
||||
# Networking: PVE creates the veth pair and attaches it to the bridge, but
|
||||
# because NixOS is not a recognised PVE ostype (no setup plugin exists),
|
||||
# PVE cannot write the guest-side network config. We configure eth0 DHCP
|
||||
# ourselves via systemd-networkd. The proxmox-lxc module already enables
|
||||
# networking.useNetworkd; this block provides the matching .network file.
|
||||
systemd.network = {
|
||||
enable = true;
|
||||
networks."10-eth0" = {
|
||||
matchConfig.Name = "eth0";
|
||||
networkConfig.DHCP = "yes";
|
||||
};
|
||||
};
|
||||
|
||||
time.timeZone = "Europe/Warsaw";
|
||||
i18n.defaultLocale = "en_US.UTF-8";
|
||||
|
||||
# `builder` is the only SSH-reachable account on this disposable. It is a
|
||||
# normal user (no root login via SSH — see services.openssh.settings below)
|
||||
# but has passwordless sudo for the rare case a build needs it. Build
|
||||
# traffic itself goes through nix-daemon, which trusts `builder`.
|
||||
users.users.builder = {
|
||||
isNormalUser = true;
|
||||
description = "Disposable LXC builder";
|
||||
extraGroups = [ "wheel" ];
|
||||
openssh.authorizedKeys.keys = adminKeys;
|
||||
};
|
||||
|
||||
security.sudo = {
|
||||
enable = true;
|
||||
extraRules = [{
|
||||
users = [ "builder" ];
|
||||
commands = [{
|
||||
command = "ALL";
|
||||
options = [ "NOPASSWD" ];
|
||||
}];
|
||||
}];
|
||||
};
|
||||
|
||||
environment.systemPackages = with pkgs; [
|
||||
vim
|
||||
wget
|
||||
curl
|
||||
ripgrep
|
||||
jq
|
||||
git
|
||||
tmux
|
||||
htop
|
||||
ncdu
|
||||
file
|
||||
iproute2
|
||||
nix-output-monitor # `nom build` for friendlier nix build output
|
||||
];
|
||||
|
||||
services.openssh = {
|
||||
enable = true;
|
||||
settings = {
|
||||
PermitRootLogin = "no"; # only `builder` may log in
|
||||
PasswordAuthentication = false;
|
||||
};
|
||||
};
|
||||
|
||||
# This is a disposable image; do NOT change.
|
||||
system.stateVersion = "25.05";
|
||||
}
|
||||
+2
-1
@@ -1,4 +1,4 @@
|
||||
{ config, lib, pkgs, ... }:
|
||||
{ ... }:
|
||||
|
||||
{
|
||||
imports = [
|
||||
@@ -16,5 +16,6 @@
|
||||
./jenkins
|
||||
./gaming
|
||||
./yubikey
|
||||
./scripts
|
||||
];
|
||||
}
|
||||
|
||||
@@ -0,0 +1,52 @@
|
||||
{
|
||||
config,
|
||||
lib,
|
||||
pkgs,
|
||||
username,
|
||||
...
|
||||
}:
|
||||
{
|
||||
environment.systemPackages = [
|
||||
(pkgs.writeShellScriptBin "pve-build" ''
|
||||
export PATH="${
|
||||
lib.makeBinPath [
|
||||
pkgs.jq
|
||||
pkgs.openssh
|
||||
]
|
||||
}:$PATH"
|
||||
${builtins.readFile ./pve-build.sh}
|
||||
'')
|
||||
];
|
||||
|
||||
home-manager.users.${username} = {
|
||||
programs.nushell.extraConfig =
|
||||
lib.mkIf config.home-manager.users.${username}.programs.nushell.enable
|
||||
''
|
||||
def "nu-complete pve-build-cmds" [] {
|
||||
[build test switch boot check-image deploy-image update-image start-builder build-on activate destroy-builder info]
|
||||
}
|
||||
|
||||
def "nu-complete pve-build-activate" [] {
|
||||
[test switch boot]
|
||||
}
|
||||
|
||||
extern pve-build [
|
||||
command?: string@"nu-complete pve-build-cmds"
|
||||
--machine: string
|
||||
--pve-host: string
|
||||
--pve-storage: string
|
||||
--rootfs-storage: string
|
||||
--bridge: string
|
||||
--vmid-start: int
|
||||
--vmid-floor: int
|
||||
--rootfs-gib: int
|
||||
--keep
|
||||
--local-build
|
||||
--show-trace
|
||||
--verbose
|
||||
--debug
|
||||
--help(-h)
|
||||
]
|
||||
'';
|
||||
};
|
||||
}
|
||||
Executable
+1103
File diff suppressed because it is too large
Load Diff
Reference in New Issue
Block a user