refactor(deploy): expose batm3-usb as a named nixosConfiguration
Lift the USB-variant config (distinct fs labels, nofail /boot, no growPartition, autoUpgrade off) out of the inline disk-image-batm3-usb `let` into `nixosConfigurations.batm3-usb`, and build the disk-image from that same config. Enables in-place app deploys to a running stick via `nix copy` + `switch-to-configuration` (build the toplevel, copy the closure, activate) — no reflash, preserving pairing + /var/lib state. Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
This commit is contained in:
parent
6a833d357e
commit
f8f2037100
1 changed files with 35 additions and 33 deletions
68
flake.nix
68
flake.nix
|
|
@ -292,6 +292,37 @@
|
||||||
# at ttyJ5, dispenser at ttyJ7 layout) — reuse the same hw module.
|
# at ttyJ5, dispenser at ttyJ7 layout) — reuse the same hw module.
|
||||||
sintra-installed = mkInstalledConfig "sintra" ./deploy/nixos/hardware/upboard.nix;
|
sintra-installed = mkInstalledConfig "sintra" ./deploy/nixos/hardware/upboard.nix;
|
||||||
batm3-installed = mkInstalledConfig "batm3" ./deploy/nixos/hardware/batm3.nix;
|
batm3-installed = mkInstalledConfig "batm3" ./deploy/nixos/hardware/batm3.nix;
|
||||||
|
|
||||||
|
# USB-bootable variant of batm3-installed. This is the config the
|
||||||
|
# flashed USB stick actually runs — distinct fs labels so stage-1 can't
|
||||||
|
# latch the internal drive, nofail /boot, no growPartition, autoUpgrade
|
||||||
|
# off. Exposed as a named config (not just inline in the disk-image
|
||||||
|
# target) so its system closure can be built here and deployed in-place
|
||||||
|
# with `nix copy` + `switch-to-configuration` — updating the app on a
|
||||||
|
# running stick WITHOUT reflashing (preserves pairing + /var/lib state).
|
||||||
|
# disk-image-batm3-usb builds its filesystem image from this same config.
|
||||||
|
batm3-usb = self.nixosConfigurations.batm3-installed.extendModules {
|
||||||
|
modules = [
|
||||||
|
({ lib, ... }: {
|
||||||
|
fileSystems."/".device = lib.mkForce "/dev/disk/by-label/nixos-usb";
|
||||||
|
fileSystems."/boot".device = lib.mkForce "/dev/disk/by-label/ESP-USB";
|
||||||
|
# /boot must NOT be a hard boot dependency on the USB image. The
|
||||||
|
# firmware already loaded the bootloader before Linux; without
|
||||||
|
# nofail, a slow/late ESP-USB enumeration (BOT is slower than UAS)
|
||||||
|
# blows past systemd's 90s device-timeout into emergency mode with
|
||||||
|
# root locked — a dead end. nofail + short timeout lets the
|
||||||
|
# already-mounted root carry the boot; /boot mounts if/when it shows.
|
||||||
|
fileSystems."/boot".options = [ "nofail" "x-systemd.device-timeout=10s" ];
|
||||||
|
# NO growPartition/autoResize: sfdisk rewriting the partition table
|
||||||
|
# on first boot is the single most bus-stressing write, and flaky
|
||||||
|
# USB bridges drop off the bus mid-rewrite (sfdisk wedges in D-state
|
||||||
|
# and ESP-USB vanishes with the device). Persistent state is a few
|
||||||
|
# MB and the image ships ~2GB free. The internal-SATA disk-image-
|
||||||
|
# batm3 keeps growPartition (a real AHCI SSD won't drop the bus).
|
||||||
|
system.autoUpgrade.enable = lib.mkForce false;
|
||||||
|
})
|
||||||
|
];
|
||||||
|
};
|
||||||
};
|
};
|
||||||
|
|
||||||
# ── Standalone NixOS module ───────────────────────────────────
|
# ── Standalone NixOS module ───────────────────────────────────
|
||||||
|
|
@ -443,41 +474,12 @@
|
||||||
# internal drive's ESP).
|
# internal drive's ESP).
|
||||||
disk-image-batm3-usb =
|
disk-image-batm3-usb =
|
||||||
let
|
let
|
||||||
cfg = self.nixosConfigurations.batm3-installed.extendModules {
|
# Filesystem image of the batm3-usb config (defined in
|
||||||
modules = [
|
# nixosConfigurations). Same config that in-place deploys target, so
|
||||||
({ lib, ... }: {
|
# a reflash and a `switch-to-configuration` converge on one system.
|
||||||
fileSystems."/".device = lib.mkForce "/dev/disk/by-label/nixos-usb";
|
|
||||||
fileSystems."/boot".device = lib.mkForce "/dev/disk/by-label/ESP-USB";
|
|
||||||
# /boot must NOT be a hard boot dependency on the USB test
|
|
||||||
# image. The firmware already loaded the bootloader from the
|
|
||||||
# ESP before Linux started; /boot is only remounted so the OS
|
|
||||||
# can *update* the bootloader — which this image never does
|
|
||||||
# (autoUpgrade off, no nixos-rebuild on the stick). Without
|
|
||||||
# nofail, a slow/late ESP-USB enumeration (BOT is slower than
|
|
||||||
# UAS) blows past systemd's 90s device-timeout and drops to
|
|
||||||
# emergency mode — with root locked, an unrecoverable dead end.
|
|
||||||
# nofail + a short timeout lets the (already-mounted) root carry
|
|
||||||
# the boot to completion; /boot mounts if/when the ESP shows up.
|
|
||||||
fileSystems."/boot".options = [ "nofail" "x-systemd.device-timeout=10s" ];
|
|
||||||
# DELIBERATELY NO growPartition/autoResize on the USB image.
|
|
||||||
# growPartition runs sfdisk to rewrite the stick's partition
|
|
||||||
# table on first boot — the single most bus-stressing write of
|
|
||||||
# the boot. Flaky USB bridges drop off the bus mid-rewrite
|
|
||||||
# (sfdisk hangs forever as an uninterruptible D-state task) and,
|
|
||||||
# worse, partition 1 (ESP-USB) vanishes with the device, so
|
|
||||||
# /boot times out too. The kiosk's persistent state (state.db,
|
|
||||||
# .env, wifi.conf, logs) is a few MB and the built image already
|
|
||||||
# carries ~2GB free inside root — growing to fill the stick buys
|
|
||||||
# nothing and costs reliability. The internal-SATA target
|
|
||||||
# (disk-image-batm3) keeps growPartition: a real AHCI SSD won't
|
|
||||||
# drop the bus and there filling the disk is worth it.
|
|
||||||
system.autoUpgrade.enable = lib.mkForce false;
|
|
||||||
})
|
|
||||||
];
|
|
||||||
};
|
|
||||||
baseImage = import (nixpkgs + "/nixos/lib/make-disk-image.nix") {
|
baseImage = import (nixpkgs + "/nixos/lib/make-disk-image.nix") {
|
||||||
inherit pkgs lib;
|
inherit pkgs lib;
|
||||||
config = cfg.config;
|
config = self.nixosConfigurations.batm3-usb.config;
|
||||||
format = "raw";
|
format = "raw";
|
||||||
partitionTableType = "efi";
|
partitionTableType = "efi";
|
||||||
diskSize = "auto";
|
diskSize = "auto";
|
||||||
|
|
|
||||||
Loading…
Add table
Add a link
Reference in a new issue