From 6356e07364370675a572c33b4ae49276e659aec1 Mon Sep 17 00:00:00 2001 From: Emma Thorpe Date: Wed, 10 Jun 2026 14:56:58 +0100 Subject: [PATCH] feat(nixos): disk hygiene, dedupe shared options, fix MacPro docs - common-nixos: nix.settings.auto-optimise-store + larger download buffer. - workstation: fstrim, boot.tmp.cleanOnBoot, and the shared graphical options moved here from the per-host configs (pipewire, swaylock PAM stub, redistributable firmware) -- MBP-Asahi gains audio it lacked. - T400: zramSwap for the low-RAM host. - MBP-Asahi: nixos-apple-silicon binary cache substituter. - MacPro31 README: describe the real (LVM/UUID) hardware config; it is no longer a placeholder. Co-Authored-By: Claude Opus 4.8 (1M context) --- system/machine/MBP-Asahi/configuration.nix | 15 ++++++++++++--- system/machine/MacPro31/README.md | 9 +++++---- system/machine/MacPro31/configuration.nix | 14 ++------------ system/machine/T400/README.md | 10 +++++----- system/machine/T400/configuration.nix | 17 +++++------------ system/modules/common-nixos.nix | 7 +++++++ system/modules/workstation.nix | 20 ++++++++++++++++++++ 7 files changed, 56 insertions(+), 36 deletions(-) diff --git a/system/machine/MBP-Asahi/configuration.nix b/system/machine/MBP-Asahi/configuration.nix index 24dad33..0a1d5f7 100644 --- a/system/machine/MBP-Asahi/configuration.nix +++ b/system/machine/MBP-Asahi/configuration.nix @@ -14,9 +14,18 @@ networking.hostName = "Emma-Asahi"; - # No fingerprint reader on this machine; empty service still lets swaylock - # authenticate via password. - security.pam.services.swaylock = { }; + # Audio (PipeWire) and the swaylock PAM stack are inherited from + # workstation.nix. hardware.enableRedistributableFirmware is also set there; + # it is harmless here since Asahi supplies its own peripheral firmware below. + + # Binary cache for the Asahi kernel/build artifacts, so the MBP pulls prebuilt + # outputs instead of compiling the Asahi kernel locally. + nix.settings = { + substituters = [ "https://nixos-apple-silicon.cachix.org" ]; + trusted-public-keys = [ + "nixos-apple-silicon.cachix.org-1:8psDu5SA5dAD7qA0zMy5UT292TxeEPzIz8VVEr2Js20=" + ]; + }; # Apple peripheral firmware (Wi-Fi/Bluetooth). The directory is gitignored and # populated out-of-band -- see README. diff --git a/system/machine/MacPro31/README.md b/system/machine/MacPro31/README.md index e459b1e..d223e5b 100644 --- a/system/machine/MacPro31/README.md +++ b/system/machine/MacPro31/README.md @@ -6,10 +6,11 @@ Flake host: `lyrathorpe-macpro31`. Desktop (`portable = false`, imports ## Hardware configuration -`hardware-configuration.nix` here is a hand-written **placeholder**. On the real -machine, run `nixos-generate-config`, replace the file, and commit it. It assumes -by-label partitions — ESP `ESP` (vfat, mounted at `/boot`), root `nixos` (ext4), -and `swap` — so either label them at install time or swap in the generated UUIDs. +`hardware-configuration.nix` here is the real config generated by +`nixos-generate-config` on the machine. Root is an **LVM** logical volume +(`/dev/mapper/MacPro-Root`, ext4); the ESP (vfat) and swap are referenced by +UUID. The initrd carries `dm-snapshot` for the LVM root. Regenerate and commit +if the disk layout changes. ## Bootloader diff --git a/system/machine/MacPro31/configuration.nix b/system/machine/MacPro31/configuration.nix index 1d41ad5..6b7d3f7 100644 --- a/system/machine/MacPro31/configuration.nix +++ b/system/machine/MacPro31/configuration.nix @@ -27,19 +27,9 @@ services.openssh.enable = true; networking.firewall.allowedTCPPorts = [ 22 ]; - services.pipewire = { - enable = true; - pulse.enable = true; - }; - - # No fingerprint hardware; empty service still lets swaylock authenticate via - # password. - security.pam.services.swaylock = { }; - - # Dual Harpertown Xeon microcode + redistributable firmware (e.g. GPU/NIC - # blobs). + # Dual Harpertown Xeon microcode. Redistributable firmware (GPU/NIC blobs) is + # enabled in workstation.nix. hardware.cpu.intel.updateMicrocode = true; - hardware.enableRedistributableFirmware = true; # GPU note: the stock card varies between units -- ATI Radeon HD 2600 XT or # NVIDIA GeForce 8800 GT. Sway needs a working KMS/modesetting driver; do NOT diff --git a/system/machine/T400/README.md b/system/machine/T400/README.md index 6f2d1d7..3480f30 100644 --- a/system/machine/T400/README.md +++ b/system/machine/T400/README.md @@ -15,11 +15,11 @@ install time or swap in the generated UUIDs. `configuration.nix` imports exactly one boot module. Default is `boot-bios.nix`; switch by commenting it out and uncommenting the relevant alternative. -| Firmware | Module | Notes | -| --- | --- | --- | -| Stock Lenovo BIOS, or coreboot + **SeaBIOS** payload | `boot-bios.nix` | GRUB on the MBR. Set `device` to the real install disk (`/dev/sda` by default). MBR/legacy layout. | -| coreboot + **GRUB** payload | `boot-coreboot-grub.nix` | GRUB is config-only (`device = "nodev"`); NixOS does **not** write to a disk. Your coreboot `grub.cfg` (in the flash chip) must `search` for and `configfile` the on-disk `/boot/grub/grub.cfg`, or chainload the disk's GRUB. | -| coreboot + **Tianocore/edk2 (UEFI)** payload | `boot-coreboot-uefi.nix` | systemd-boot. `canTouchEfiVariables = true` (coreboot honours NVRAM writes). The module **declares its own ESP** (`/boot` vfat, label `ESP`) — when you regenerate `hardware-configuration.nix`, do **not** let it also define `/boot`. Create + label an `ESP` vfat partition (GPT). | +| Firmware | Module | Notes | +| ---------------------------------------------------- | ------------------------ | ------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- | +| Stock Lenovo BIOS, or coreboot + **SeaBIOS** payload | `boot-bios.nix` | GRUB on the MBR. Set `device` to the real install disk (`/dev/sda` by default). MBR/legacy layout. | +| coreboot + **GRUB** payload | `boot-coreboot-grub.nix` | GRUB is config-only (`device = "nodev"`); NixOS does **not** write to a disk. Your coreboot `grub.cfg` (in the flash chip) must `search` for and `configfile` the on-disk `/boot/grub/grub.cfg`, or chainload the disk's GRUB. | +| coreboot + **Tianocore/edk2 (UEFI)** payload | `boot-coreboot-uefi.nix` | systemd-boot. `canTouchEfiVariables = true` (coreboot honours NVRAM writes). The module **declares its own ESP** (`/boot` vfat, label `ESP`) — when you regenerate `hardware-configuration.nix`, do **not** let it also define `/boot`. Create + label an `ESP` vfat partition (GPT). | ## Graphics diff --git a/system/machine/T400/configuration.nix b/system/machine/T400/configuration.nix index 2ed5d13..361130c 100644 --- a/system/machine/T400/configuration.nix +++ b/system/machine/T400/configuration.nix @@ -18,25 +18,18 @@ console.font = "Lat2-Terminus16"; - services.pipewire = { - enable = true; - pulse.enable = true; - }; + # Low-RAM host (4 GiB max): a compressed RAM swap reduces disk paging. + zramSwap.enable = true; # This host accepts SSH, so open 22 (the firewall itself is enabled in # laptop.nix with a default-deny policy). services.openssh.enable = true; networking.firewall.allowedTCPPorts = [ 22 ]; - # The T400's fingerprint reader differs/may be absent; empty service still - # lets swaylock authenticate via password. - security.pam.services.swaylock = { }; - - # Intel Core 2 (Penryn) microcode + redistributable firmware. The latter also - # supplies the iwlwifi blobs (Intel WiFi Link 5100/5300) and the radeon - # firmware needed by the discrete GPU below. + # Intel Core 2 (Penryn) microcode. Redistributable firmware (enabled in + # workstation.nix) supplies the iwlwifi blobs (Intel WiFi Link 5100/5300) and + # the radeon firmware needed by the discrete GPU below. hardware.cpu.intel.updateMicrocode = true; - hardware.enableRedistributableFirmware = true; # This T400 has the optional discrete GPU fitted: an ATI Mobility Radeon HD # 3470 (RV620), driven by the open `radeon` KMS driver. Load it in the initrd diff --git a/system/modules/common-nixos.nix b/system/modules/common-nixos.nix index 476aa1e..fe87953 100644 --- a/system/modules/common-nixos.nix +++ b/system/modules/common-nixos.nix @@ -6,6 +6,13 @@ time.timeZone = "Europe/London"; i18n.defaultLocale = "en_GB.UTF-8"; + # Store hygiene. auto-optimise-store hard-links identical files in the store + # after each build (cheap dedupe; NOT a garbage collector -- there is + # deliberately no automatic GC timer). The larger download buffer avoids + # "buffer full" stalls when fetching big NARs over a fast link. + nix.settings.auto-optimise-store = true; + nix.settings.download-buffer-size = 134217728; # 128 MiB + # Minimal system-level CLI available before the home-manager profile loads # (e.g. early boot / rescue). User-level tooling lives in home-manager. environment.systemPackages = with pkgs; [ diff --git a/system/modules/workstation.nix b/system/modules/workstation.nix index 96da265..a8e52b1 100644 --- a/system/modules/workstation.nix +++ b/system/modules/workstation.nix @@ -14,4 +14,24 @@ # Default-deny inbound. Hosts that run a listening service open their own # ports next to where the service is enabled (e.g. sshd -> 22 on X1). networking.firewall.enable = true; + + # Disk hygiene for the physical hosts. fstrim reclaims unused SSD blocks on a + # weekly timer; cleanOnBoot wipes /tmp at every boot. + services.fstrim.enable = true; + boot.tmp.cleanOnBoot = true; + + # Audio. PipeWire with the PulseAudio shim covers every graphical host; no + # per-machine audio config is needed. + services.pipewire = { + enable = true; + pulse.enable = true; + }; + + # swaylock PAM stack. None of these machines has working fingerprint auth, so + # an empty service is enough -- swaylock falls back to password. + security.pam.services.swaylock = { }; + + # Redistributable firmware (GPU/Wi-Fi/NIC blobs) for the x86 hosts. Harmless + # on the Asahi MBP, which supplies its own peripheral firmware out-of-band. + hardware.enableRedistributableFirmware = true; }