Compare commits

...

4 Commits

Author SHA1 Message Date
Emma Thorpe b01fc13234 docs(t400,macpro31): add per-machine install-note READMEs
Add system/machine/{T400,MacPro31}/README.md covering the placeholder
hardware-configuration regeneration, partition labels, bootloader selection
(T400 boot variants; Mac Pro EFI quirks), and GPU notes. Link each from its
configuration.nix header, and refresh the top-level README host table (T400
replaces X1, Mac Pro 3,1 added) with links to both.

Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
2026-06-04 15:38:23 +01:00
Emma Thorpe b3fa34f431 feat(t400): add coreboot GRUB/UEFI boot variants and discrete ATI GPU
Split the T400 bootloader into self-contained, importable modules so the host
can match whatever firmware is flashed (switch by changing one import):
- boot-bios.nix       stock BIOS / coreboot+SeaBIOS -> GRUB on the MBR (default)
- boot-coreboot-grub.nix  coreboot GRUB payload -> config-only GRUB (device=nodev)
- boot-coreboot-uefi.nix  coreboot Tianocore/UEFI payload -> systemd-boot; carries
                          its own ESP (/boot vfat) so it travels with the mode

Cover the optional discrete ATI Mobility Radeon HD 3470 (RV620): load the open
`radeon` KMS driver in the initrd for early modesetting (firmware via
enableRedistributableFirmware), with a note on the T400's switchable graphics.

All three boot variants evaluate; nixfmt clean.

Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
2026-06-04 15:35:31 +01:00
Emma Thorpe ebff5aeba6 feat(nixos): replace X1 with ThinkPad T400; add Mac Pro 3,1 desktop
- lyrathorpe-t400 replaces lyrathorpe-x1c: ThinkPad T400 (legacy BIOS -> GRUB,
  Intel microcode + redistributable firmware for iwlwifi, pipewire, sshd).
- lyrathorpe-macpro31: new desktop host (portable = false) importing
  desktop.nix. Mac Pro 3,1 has 64-bit EFI -> systemd-boot; wired NetworkManager
  via desktop.nix; desktop status bar (temperature + net, no battery).

Both ship hand-written placeholder hardware-configuration.nix (root/swap/ESP by
label, GRUB device /dev/sda) to be regenerated with nixos-generate-config and
committed at install time. All five host configs evaluate; nixfmt clean.

Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
2026-06-04 15:22:07 +01:00
Emma Thorpe dfc436802d refactor(nixos): declare bootloader per-host, not in workstation.nix
The bootloader is firmware-specific, not form-factor: UEFI hosts use
systemd-boot, BIOS hosts use GRUB. Drop boot.loader.systemd-boot.enable from
workstation.nix and declare it on the MBP instead, so the incoming BIOS-only
T400 (GRUB) doesn't have to force it off.

Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
2026-06-04 15:22:07 +01:00
15 changed files with 369 additions and 84 deletions
+3 -2
View File
@@ -10,9 +10,10 @@ Defined in the host table in [`flake.nix`](./flake.nix):
| Configuration | System | Machine |
| ------------------- | --------------- | ---------------------------------------- |
| `lyrathorpe-mbp` | `aarch64-linux` | MacBook Pro (Apple Silicon, Asahi) |
| `lyrathorpe-x1c` | `x86_64-linux` | ThinkPad X1 |
| `lyrathorpe-t400` | `x86_64-linux` | ThinkPad T400 — [install notes](./system/machine/T400/README.md) |
| `lyrathorpe-macpro31` | `x86_64-linux` | Mac Pro 3,1, desktop — [install notes](./system/machine/MacPro31/README.md) |
| `emmathorpe-edaas` | `x86_64-linux` | Work WSL box (NixOS-WSL) |
| `lyrathorpe-mac` | `aarch64-darwin`| macOS (nix-darwin) |
| `lyrathorpe-mac` | `aarch64-darwin` | macOS (nix-darwin) |
Shared layers: `lyrathorpe/home` (home-manager: shell, git, editor),
`system/modules/common-nixos.nix` (all NixOS hosts), and
+18 -2
View File
@@ -192,12 +192,12 @@
];
};
lyrathorpe-x1c = {
lyrathorpe-t400 = {
system = "x86_64-linux";
username = "lyrathorpe";
fullName = "Lyra Thorpe";
modules = [
./system/machine/X1/configuration.nix
./system/machine/T400/configuration.nix
./system/modules/laptop.nix
./lyrathorpe/swaywm.nix
];
@@ -207,6 +207,22 @@
];
};
lyrathorpe-macpro31 = {
system = "x86_64-linux";
username = "lyrathorpe";
fullName = "Lyra Thorpe";
portable = false;
modules = [
./system/machine/MacPro31/configuration.nix
./system/modules/desktop.nix
./lyrathorpe/swaywm.nix
];
homeModules = [
./lyrathorpe/home
./lyrathorpe/home/desktop.nix
];
};
emmathorpe-edaas = {
system = "x86_64-linux";
username = "emmathorpe";
+3 -1
View File
@@ -7,7 +7,9 @@
./hardware-configuration.nix
];
# Asahi manages the EFI vars from macOS; do not touch them from NixOS.
# UEFI boot via systemd-boot. Asahi manages the EFI vars from macOS, so do not
# touch them from NixOS.
boot.loader.systemd-boot.enable = true;
boot.loader.efi.canTouchEfiVariables = false;
networking.hostName = "Emma-Asahi";
+51
View File
@@ -0,0 +1,51 @@
# Mac Pro 3,1 (Early 2008) — install notes
Flake host: `lyrathorpe-macpro31`. Desktop (`portable = false`, imports
`../../modules/desktop.nix`). Files: `configuration.nix`,
`hardware-configuration.nix`.
## 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.
## Bootloader
The Mac Pro 3,1 has **64-bit EFI**, so it uses **systemd-boot** (no GRUB/CSM
shim). `canTouchEfiVariables = false` because Apple's firmware does not reliably
accept `efibootmgr` NVRAM writes.
Apple-EFI quirk: if the firmware boot picker does not show NixOS after install,
either
- uncomment `boot.loader.efi.efiInstallAsRemovable = true;` in
`configuration.nix` (installs the fallback `\EFI\BOOT\BOOTX64.EFI`), and/or
- "bless" the ESP from macOS.
Partition the disk GPT with an ESP (vfat).
## Graphics
The stock card varies between units — **ATI Radeon HD 2600 XT** or **NVIDIA
GeForce 8800 GT**. No proprietary driver is hardcoded; Sway relies on in-tree KMS:
- ATI Radeon HD 2600 XT → `radeon` (or `amdgpu`) KMS
- NVIDIA GeForce 8800 GT → `nouveau` KMS
These come up automatically. If a card needs forcing, set
`services.xserver.videoDrivers` and/or add the module to
`boot.initrd.kernelModules` for early KMS (see the comment in
`configuration.nix`).
## Networking
Wired Ethernet via NetworkManager (from `desktop.nix`) — the Mac Pro has two
gigabit ports.
## Apply
```sh
sudo nixos-rebuild switch --flake .#lyrathorpe-macpro31
```
+58
View File
@@ -0,0 +1,58 @@
# Apple Mac Pro 3,1 (Early 2008, dual Xeon Harpertown, x86_64). Desktop host:
# shared graphical/wired options live in ../../modules/desktop.nix; only
# host-specific settings are here. Install notes (EFI booting, GPU, partitions):
# see ./README.md.
{ ... }:
{
imports = [
./hardware-configuration.nix
];
# The Mac Pro 3,1 has 64-bit EFI (confirmed by the owner), so boot via
# systemd-boot like the MBP -- no GRUB/BIOS shim needed.
boot.loader.systemd-boot.enable = true;
# Apple's EFI does not reliably support efibootmgr NVRAM writes; leave the
# firmware vars untouched.
boot.loader.efi.canTouchEfiVariables = false;
# Apple-EFI quirk: if the Mac does not pick up the bootloader at the boot
# picker, install it to the fallback path \EFI\BOOT\BOOTX64.EFI and/or
# "bless" the ESP from macOS. Uncomment to write the removable fallback path:
# boot.loader.efi.efiInstallAsRemovable = true;
networking.hostName = "MacPro31-NixOS";
# This host accepts SSH, so open 22 (the firewall itself is enabled in
# workstation.nix with a default-deny policy).
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).
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
# install a proprietary blob here. Depending on the installed card, rely on
# the open kernel driver:
# - ATI Radeon HD 2600 XT -> "radeon" (older) or "amdgpu" KMS
# - NVIDIA GeForce 8800 GT -> "nouveau" KMS
# These come up automatically via the in-tree drivers + KMS, and the graphics
# stack itself is enabled by swaywm.nix. If a card needs to be forced, add it
# here, e.g. `services.xserver.videoDrivers = [ "radeon" ];` (or "nouveau"),
# and/or `boot.initrd.kernelModules = [ "radeon" ];` in
# hardware-configuration.nix for early KMS.
# See `man configuration.nix` / the stateVersion docs before changing.
system.stateVersion = "26.05";
}
@@ -0,0 +1,52 @@
# PLACEHOLDER -- hand-written, not machine-generated. Regenerate on the real
# Mac Pro 3,1 with `nixos-generate-config` and commit the result. The device
# labels below are guesses; replace them with the generated UUIDs (or label the
# partitions accordingly at install time).
{
config,
lib,
modulesPath,
...
}:
{
imports = [
(modulesPath + "/installer/scan/not-detected.nix")
];
boot.initrd.availableKernelModules = [
"ahci"
"ata_piix"
"ehci_pci"
"uhci_hcd"
"firewire_ohci"
"usb_storage"
"sd_mod"
"sr_mod"
];
boot.initrd.kernelModules = [ ];
boot.kernelModules = [ "kvm-intel" ];
boot.extraModulePackages = [ ];
# EFI System Partition for systemd-boot. Label the ESP `ESP` at install, or
# replace with the generated UUID.
fileSystems."/boot" = {
device = "/dev/disk/by-label/ESP";
fsType = "vfat";
};
# Label your root partition `nixos` at install, or replace with the generated UUID.
fileSystems."/" = {
device = "/dev/disk/by-label/nixos";
fsType = "ext4";
};
swapDevices = [
{ device = "/dev/disk/by-label/swap"; }
];
networking.useDHCP = lib.mkDefault true;
nixpkgs.hostPlatform = lib.mkDefault "x86_64-linux";
hardware.cpu.intel.updateMicrocode = lib.mkDefault config.hardware.enableRedistributableFirmware;
}
+39
View File
@@ -0,0 +1,39 @@
# ThinkPad T400 — install notes
Flake host: `lyrathorpe-t400`. Files: `configuration.nix`, the `boot-*.nix`
variants, and `hardware-configuration.nix`.
## 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 — root `nixos` (ext4) and `swap` — so either label them at
install time or swap in the generated UUIDs.
## Bootloader — import the module matching the flashed firmware
`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). |
## Graphics
This unit has the optional **discrete ATI Mobility Radeon HD 3470 (RV620)**. The
open `radeon` KMS driver is loaded in the initrd for early modesetting; firmware
comes from `enableRedistributableFirmware`.
The T400 has switchable graphics (discrete ATI + Intel GMA 4500MHD). Select
**Discrete** in the firmware's graphics setting so only the ATI is live. If you
run **Integrated** instead, the Intel `i915` driver takes over with no config
change and `radeon` stays idle.
## Apply
```sh
sudo nixos-rebuild switch --flake .#lyrathorpe-t400
```
+11
View File
@@ -0,0 +1,11 @@
# Boot via legacy BIOS -- the stock Lenovo BIOS, or coreboot with the SeaBIOS
# payload (both present a legacy BIOS interface). GRUB is installed to the MBR of
# the boot disk. This is the default.
{ ... }:
{
boot.loader.grub = {
enable = true;
# Must point at the actual install disk -- adjust if it is not /dev/sda.
device = "/dev/sda";
};
}
@@ -0,0 +1,13 @@
# Boot via coreboot's GRUB payload (e.g. libreboot default). The GRUB in the
# flash chip reads the grub.cfg that NixOS generates on disk, so GRUB here is
# config-only -- it is NOT installed to any disk MBR (`device = "nodev"`).
#
# Your coreboot grub.cfg must locate and load the on-disk config, e.g. search
# for and `configfile` /boot/grub/grub.cfg (or chainload the disk's GRUB).
{ ... }:
{
boot.loader.grub = {
enable = true;
device = "nodev";
};
}
@@ -0,0 +1,17 @@
# Boot via coreboot's Tianocore/edk2 (UEFI) payload. This turns the T400 into a
# real UEFI machine, so use systemd-boot. Unlike Apple's firmware, coreboot's
# UEFI honours EFI variable writes, so canTouchEfiVariables is on.
#
# Requires an EFI System Partition. It is declared here so it travels with this
# boot mode; the generated hardware-configuration.nix should NOT also define
# /boot. Label the ESP `ESP` at install, or replace with the generated UUID.
{ ... }:
{
boot.loader.systemd-boot.enable = true;
boot.loader.efi.canTouchEfiVariables = true;
fileSystems."/boot" = {
device = "/dev/disk/by-label/ESP";
fsType = "vfat";
};
}
+54
View File
@@ -0,0 +1,54 @@
# ThinkPad T400 (NixOS). Shared laptop options live in ../../modules/laptop.nix;
# only host-specific settings are here. Install notes (boot variants, GPU,
# partitions): see ./README.md.
{ ... }:
{
imports = [
./hardware-configuration.nix
# Boot: import exactly ONE, matching the firmware currently flashed.
# Stock Lenovo BIOS and coreboot+SeaBIOS both use boot-bios.nix.
./boot-bios.nix
# ./boot-coreboot-grub.nix # coreboot with the GRUB payload (config-only GRUB)
# ./boot-coreboot-uefi.nix # coreboot with the Tianocore/edk2 UEFI payload
# # (systemd-boot; carries its own ESP mount)
];
networking.hostName = "T400-NixOS";
console.font = "Lat2-Terminus16";
services.pipewire = {
enable = true;
pulse.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.
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
# for early modesetting (clean Sway/Wayland start); firmware comes from
# enableRedistributableFirmware above.
#
# The T400 has switchable graphics (this discrete GPU + the Intel GMA
# 4500MHD). Select "Discrete" in the firmware's graphics setting so only the
# ATI is live; if you instead run "Integrated", the Intel i915 driver takes
# over with no extra config and `radeon` simply stays idle.
boot.initrd.kernelModules = [ "radeon" ];
# See `man configuration.nix` / the stateVersion docs before changing.
system.stateVersion = "26.05";
}
@@ -0,0 +1,44 @@
# PLACEHOLDER -- hand-written, not machine-generated. Regenerate on the real
# T400 with `nixos-generate-config` and commit the result. The device labels
# below are guesses; replace them with the generated UUIDs (or label the
# partitions accordingly at install time).
{
config,
lib,
modulesPath,
...
}:
{
imports = [
(modulesPath + "/installer/scan/not-detected.nix")
];
boot.initrd.availableKernelModules = [
"ahci"
"ata_piix"
"ehci_pci"
"uhci_hcd"
"usb_storage"
"sd_mod"
"sr_mod"
];
boot.initrd.kernelModules = [ ];
boot.kernelModules = [ "kvm-intel" ];
boot.extraModulePackages = [ ];
# Label your root partition `nixos` at install, or replace with the generated UUID.
fileSystems."/" = {
device = "/dev/disk/by-label/nixos";
fsType = "ext4";
};
swapDevices = [
{ device = "/dev/disk/by-label/swap"; }
];
networking.useDHCP = lib.mkDefault true;
nixpkgs.hostPlatform = lib.mkDefault "x86_64-linux";
hardware.cpu.intel.updateMicrocode = lib.mkDefault config.hardware.enableRedistributableFirmware;
}
-33
View File
@@ -1,33 +0,0 @@
# ThinkPad X1 (NixOS). Shared laptop options live in ../../modules/laptop.nix;
# only host-specific settings are here.
{ ... }:
{
imports = [
./hardware-configuration.nix
];
boot.loader.efi.canTouchEfiVariables = true;
networking.hostName = "X1-NixOS";
networking.domain = "client.cbg.emmaisvery.gay";
console.font = "Lat2-Terminus16";
services.pipewire = {
enable = true;
pulse.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 ];
# Fingerprint reader: allow swaylock to authenticate via fprintd.
services.fprintd.enable = true;
security.pam.services.swaylock.fprintAuth = true;
# See `man configuration.nix` / the stateVersion docs before changing.
system.stateVersion = "24.11";
}
@@ -1,42 +0,0 @@
# Do not modify this file! It was generated by nixos-generate-config
# and may be overwritten by future invocations. Please make changes
# to /etc/nixos/configuration.nix instead.
{ config, lib, pkgs, modulesPath, ... }:
{
imports =
[ (modulesPath + "/installer/scan/not-detected.nix")
];
boot.initrd.availableKernelModules = [ "xhci_pci" "nvme" "usb_storage" "sd_mod" ];
boot.initrd.kernelModules = [ ];
boot.kernelModules = [ "kvm-intel" ];
boot.extraModulePackages = [ ];
fileSystems."/" =
{ device = "/dev/disk/by-uuid/a7145534-b122-4899-a75a-3d2e78474d6b";
fsType = "ext4";
};
fileSystems."/boot" =
{ device = "/dev/disk/by-uuid/1338-3D4F";
fsType = "vfat";
options = [ "fmask=0077" "dmask=0077" ];
};
swapDevices =
[ { device = "/dev/disk/by-uuid/e553c8dc-9d5a-48ec-87bc-9c86ce5932a4"; }
];
# Enables DHCP on each ethernet and wireless interface. In case of scripted networking
# (the default) this is the recommended approach. When using systemd-networkd it's
# still possible to use this option, but it's recommended to use it in conjunction
# with explicit per-interface declarations with `networking.interfaces.<interface>.useDHCP`.
networking.useDHCP = lib.mkDefault true;
# networking.interfaces.enp0s31f6.useDHCP = lib.mkDefault true;
# networking.interfaces.wlp0s20f3.useDHCP = lib.mkDefault true;
# networking.interfaces.wwan0.useDHCP = lib.mkDefault true;
nixpkgs.hostPlatform = lib.mkDefault "x86_64-linux";
hardware.cpu.intel.updateMicrocode = lib.mkDefault config.hardware.enableRedistributableFirmware;
}
+4 -2
View File
@@ -1,10 +1,12 @@
# Form-factor-agnostic base for the physical graphical NixOS machines. Imported
# by both ./laptop.nix and ./desktop.nix; those add only the bits that differ
# between portable and desktop hosts (chiefly the networking backend).
#
# The bootloader is NOT set here -- it is firmware-specific, not form-factor:
# UEFI hosts (MBP, Mac Pro 3,1) use systemd-boot, the BIOS-only T400 uses GRUB.
# Each machine config declares its own.
{ ... }:
{
boot.loader.systemd-boot.enable = true;
features.swayDesktop.enable = true;
console.keyMap = "dvorak";