diff --git a/README.md b/README.md index bd88a3b..a89b8f0 100644 --- a/README.md +++ b/README.md @@ -5,46 +5,78 @@ Flake-based NixOS config. Host: `jupiter` (ZimaBlade, NAS + services). ## Structure ``` -flake.nix # inputs + nixosConfigurations.jupiter -jupiter/configuration.nix # system, users, ssh, samba, containers, caddy -jupiter/hardware-configuration.nix # PLACEHOLDER — regenerate on real machine +flake.nix # inputs (nixpkgs, disko) + nixosConfigurations +jupiter/configuration.nix # real host: imports + bootloader + data mount +jupiter/disk-config.nix # disko: OS-disk partitions + filesystems +jupiter/hardware-configuration.nix # PLACEHOLDER — kernel modules, regenerate on target +jupiter/services.nix # shared: users, ssh, samba, containers, caddy +jupiter/vm.nix # VirtualBox test image (jupiter-vbox) ``` -## First install (on the ZimaBlade) +Two configs from one service definition: `jupiter` (real host, disko-partitioned) +and `jupiter-vbox` (test OVA). Both import `services.nix`. -1. Boot NixOS minimal ISO, partition + mount disks at `/mnt`. -2. Generate hardware config: - ``` - sudo nixos-generate-config --root /mnt - ``` - Copy `/mnt/etc/nixos/hardware-configuration.nix` into `jupiter/`. -3. Add your SSH public key to `users.users.erik.openssh.authorizedKeys.keys`. -4. Install: - ``` - sudo nixos-install --flake .#jupiter - ``` - -## Rebuild after changes +## Test in VirtualBox (no hardware needed) ``` -sudo nixos-rebuild switch --flake .#jupiter +nix build .#nixosConfigurations.jupiter-vbox.config.system.build.virtualBoxOVA +VBoxManage import result/*.ova --vsys 0 --vmname jupiter-vbox +VBoxManage startvm jupiter-vbox --type headless ``` +Login `darman` / `test`. Forward ports with `VBoxManage modifyvm ... --natpf1`. + +## First install on the ZimaBlade — nixos-anywhere + disko + +Wipes the OS disk and installs the flake over SSH. No USB needed if the box +already runs Linux (ZimaOS) reachable by root SSH — nixos-anywhere kexecs into +an installer, partitions via disko, installs. + +> ⚠️ The OS disk in `disk-config.nix` is WIPED. Set `device` to the OS disk +> ONLY (by-id). Back up / physically identify the NAS data disk first — it must +> NOT appear in disko. `lsblk -o NAME,SERIAL,SIZE,MODEL` to identify. + +1. Set the real OS disk id in `jupiter/disk-config.nix` + (`ls -l /dev/disk/by-id`), and the data-disk mount in `configuration.nix`. +2. Add your SSH pubkey to `users.users.darman.openssh.authorizedKeys.keys`. +3. Wire the samba secret (see Notes) — real password, not the VM's plaintext. +4. Run from your laptop: + ``` + nix run github:nix-community/nixos-anywhere -- \ + --flake .#jupiter \ + --generate-hardware-config nixos-generate-config ./jupiter/hardware-configuration.nix \ + --target-host root@ + ``` + `--generate-hardware-config` pulls the target's real kernel modules into the + placeholder for you. Commit the result. Reboot into NixOS. + +Manual alternative (USB ISO): boot installer, `disko` the disk, then +`nixos-install --flake .#jupiter`. + +## Rebuild after changes (the daily loop) -Remote from laptop: ``` +# from laptop, build + activate on jupiter over SSH: nixos-rebuild switch --flake .#jupiter \ - --target-host erik@jupiter --use-remote-sudo + --target-host darman@jupiter --use-remote-sudo ``` +Rollback: `nixos-rebuild switch --rollback`, or pick a prior generation at boot. ## Adding a service Copy the `whoami` block in `oci-containers.containers`, swap image/ports/volumes. Native NixOS module exists for many apps (Nextcloud, Jellyfin, Grafana...) — -prefer `services.` over a container when available. +prefer `services.` over a container when available. Add a `caddy` +`virtualHosts` block to expose it. ## Notes - Backend is Podman with `dockerCompat` — `docker` CLI works, no daemon. -- Set correct `time.timeZone` and Samba `path` for your data mount. +- Samba keeps its own password DB. `services.samba` never sets it; a systemd + oneshot (`samba-smbpasswd`) provisions it from `/etc/samba/smb-password`. + Real host: supply that file via **sops-nix / agenix**, never commit plaintext. +- Data disk: plain `fileSystems."/mnt/data"` in configuration.nix — kept out of + disko so it is never formatted. Reference by `by-id` / `by-uuid`. - `system.stateVersion` = `26.05`, install-time schema. Do NOT bump on upgrades. +- Terraform is not used: a single bare-metal box has no provider API. disko + + nixos-anywhere cover provisioning natively. ``` diff --git a/flake.lock b/flake.lock index 5e3254b..b4fd525 100644 --- a/flake.lock +++ b/flake.lock @@ -1,5 +1,25 @@ { "nodes": { + "disko": { + "inputs": { + "nixpkgs": [ + "nixpkgs" + ] + }, + "locked": { + "lastModified": 1781152676, + "narHash": "sha256-RxWs5ND31KzTG7wvMM+PMfUjyNpmIEr999lqNARaM5o=", + "owner": "nix-community", + "repo": "disko", + "rev": "ff8702b4de27f72b4c78573dfb89ec74e36abdf1", + "type": "github" + }, + "original": { + "owner": "nix-community", + "repo": "disko", + "type": "github" + } + }, "nixpkgs": { "locked": { "lastModified": 1783703440, @@ -18,6 +38,7 @@ }, "root": { "inputs": { + "disko": "disko", "nixpkgs": "nixpkgs" } } diff --git a/flake.nix b/flake.nix index 3221c77..082f141 100644 --- a/flake.nix +++ b/flake.nix @@ -3,23 +3,32 @@ inputs = { nixpkgs.url = "github:NixOS/nixpkgs/nixos-26.05"; + disko = { + url = "github:nix-community/disko"; + inputs.nixpkgs.follows = "nixpkgs"; + }; }; - outputs = { self, nixpkgs, ... }@inputs: + outputs = { self, nixpkgs, disko, ... }@inputs: let system = "x86_64-linux"; in { nixosConfigurations = { # Real host — install on the ZimaBlade. + # disko owns the OS-disk partitioning + filesystems (see disk-config.nix). jupiter = nixpkgs.lib.nixosSystem { inherit system; specialArgs = { inherit inputs; }; - modules = [ ./jupiter/configuration.nix ]; + modules = [ + disko.nixosModules.disko + ./jupiter/configuration.nix + ]; }; # VirtualBox test image. Build the OVA with: # nix build .#nixosConfigurations.jupiter-vbox.config.system.build.virtualBoxOVA + # NOTE: no disko here — the virtualbox-image module supplies the disk. jupiter-vbox = nixpkgs.lib.nixosSystem { inherit system; specialArgs = { inherit inputs; }; diff --git a/jupiter/configuration.nix b/jupiter/configuration.nix index 3c04458..a29aad8 100644 --- a/jupiter/configuration.nix +++ b/jupiter/configuration.nix @@ -1,9 +1,10 @@ { config, pkgs, lib, ... }: -# Real-host config: hardware + bootloader + shared services. +# Real-host config: hardware + disk layout + bootloader + shared services. { imports = [ ./hardware-configuration.nix + ./disk-config.nix # disko: OS-disk partitions + filesystems ./services.nix ]; @@ -11,4 +12,12 @@ # systemd-boot for UEFI. If ZimaBlade boots legacy/BIOS, switch to grub. boot.loader.systemd-boot.enable = true; boot.loader.efi.canTouchEfiVariables = true; + + # ---- NAS data disk ---- + # Existing data filesystem — mounted, NOT formatted (kept out of disko). + # Set the id from `ls -l /dev/disk/by-id` (or by-uuid). Adjust fsType. + # fileSystems."/mnt/data" = { + # device = "/dev/disk/by-id/CHANGE-ME-data-disk"; + # fsType = "ext4"; + # }; } diff --git a/jupiter/disk-config.nix b/jupiter/disk-config.nix new file mode 100644 index 0000000..efc2833 --- /dev/null +++ b/jupiter/disk-config.nix @@ -0,0 +1,42 @@ +{ ... }: + +# Declarative OS-disk layout (disko). UEFI: GPT with an ESP + ext4 root. +# disko both PARTITIONS/FORMATS this disk and generates the NixOS +# `fileSystems.*` entries, so hardware-configuration.nix must NOT define +# fileSystems for "/" or "/boot". +# +# ⚠️ This disk is WIPED on install. Set `device` to the OS disk ONLY. +# Your NAS data disk is NOT listed here — keep it out of disko so it is +# never formatted; mount it as a plain read-write fileSystem instead +# (see configuration.nix, /mnt/data). +# +# Find the stable id: ls -l /dev/disk/by-id (use by-id, never /dev/sdX) +{ + disko.devices.disk.os = { + type = "disk"; + device = "/dev/disk/by-id/CHANGE-ME-os-disk"; + content = { + type = "gpt"; + partitions = { + ESP = { + size = "512M"; + type = "EF00"; + content = { + type = "filesystem"; + format = "vfat"; + mountpoint = "/boot"; + mountOptions = [ "umask=0077" ]; + }; + }; + root = { + size = "100%"; + content = { + type = "filesystem"; + format = "ext4"; + mountpoint = "/"; + }; + }; + }; + }; + }; +} diff --git a/jupiter/hardware-configuration.nix b/jupiter/hardware-configuration.nix index 2d571d7..98f5e29 100644 --- a/jupiter/hardware-configuration.nix +++ b/jupiter/hardware-configuration.nix @@ -1,14 +1,13 @@ -# PLACEHOLDER — do not use as-is. +# PLACEHOLDER — replace on the real machine. # -# Generate the real file ON the ZimaBlade after booting the NixOS installer: +# disko (disk-config.nix) owns the OS-disk filesystems, so this file should +# only carry kernel modules + platform. Get the real values from the target: # -# sudo nixos-generate-config --root /mnt +# # during install, or via nixos-anywhere --generate-hardware-config: +# sudo nixos-generate-config --no-filesystems --root /mnt # -# then copy /mnt/etc/nixos/hardware-configuration.nix over this file. -# It contains machine-specific disk UUIDs, filesystems, and kernel modules. -# -# The block below is a minimal example so `nix flake check` does not fail on a -# workstation. REPLACE it entirely with the generated output. +# `--no-filesystems` omits the fileSystems.* blocks (disko provides them). +# Copy the generated file over this one. Keep the imports/kernel-module lines. { config, lib, pkgs, modulesPath, ... }: { @@ -19,22 +18,8 @@ boot.kernelModules = [ ]; boot.extraModulePackages = [ ]; - # Example root — replace UUID with real value from generated config. - fileSystems."/" = { - device = "/dev/disk/by-label/nixos"; - fsType = "ext4"; - }; - - fileSystems."/boot" = { - device = "/dev/disk/by-label/BOOT"; - fsType = "vfat"; - }; - - # Example NAS data mount. Point at your storage disk/pool. - # fileSystems."/mnt/data" = { - # device = "/dev/disk/by-label/data"; - # fsType = "ext4"; - # }; + # NO fileSystems here — disko defines "/" and "/boot" (see disk-config.nix). + # The NAS data mount lives in configuration.nix. swapDevices = [ ];