fix(deploy): multi-model ISO builds and HAL packaging

- Parameterize live.nix by machineModel (douro/tejo) passed via specialArgs
- Douro: kernel 5.15 LTS for Bay Trail i915 eDP fix, vt.handoff=7
- Fix HAL packaging: copy dist/ into subdirectory (not flattened)
- Add display-reset systemd service for kexec GPU reinitialization
- Add --disable-gpu flag for Electron on headless/GPU-less boots
- flake.nix: mkLiveConfig helper, per-model ISO outputs (iso-douro/iso-tejo)
- build-iso.sh: require model param, write model-specific .env for Vite
- flash-douro-usb.sh: GPT+FAT32 ESP layout for Bay Trail UEFI boot

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
This commit is contained in:
Patrick Mulligan 2026-02-25 17:02:28 -05:00
commit c874d9e2e3
4 changed files with 325 additions and 31 deletions

View file

@ -1,11 +1,16 @@
# Lamassu ATM Live USB Configuration
# Bootable ISO for testing on physical hardware (UpBoard) without installing to disk.
# Builds with: nix build .#iso
# Bootable ISO for testing on physical hardware without installing to disk.
#
# Parameterized by machineModel (passed via specialArgs from flake.nix):
# "douro" - Bay Trail Atom, kernel 5.15 (i915 regression in newer kernels), eDP panel
# "tejo" - UP4000/UPBoard, default kernel 6.6, standard Intel GPU
#
# Builds with: nix build .#iso-douro or nix build .#iso-tejo
#
# Does NOT import hardware/upboard.nix (its fileSystems conflict with live boot).
# Instead, duplicates only the hardware-relevant kernel modules and GPU config.
{ config, lib, pkgs, pkgs-unstable, nixpkgs, ... }:
{ config, lib, pkgs, pkgs-unstable, nixpkgs, machineModel ? "douro", ... }:
let
# Pre-built Electron app copied into the Nix store.
@ -47,8 +52,8 @@ let
cp -rL ${builtins.path { path = fileUriStore + "/file-uri-to-path"; name = "file-uri-to-path"; }} $out/node_modules/file-uri-to-path
# @lamassu/hal (workspace package, dynamically imported for hardware access)
mkdir -p $out/node_modules/@lamassu/hal
cp -rL ${builtins.path { path = halDir + "/dist"; name = "hal-dist"; }}/* $out/node_modules/@lamassu/hal/
mkdir -p $out/node_modules/@lamassu/hal/dist
cp -rL ${builtins.path { path = halDir + "/dist"; name = "hal-dist"; }}/* $out/node_modules/@lamassu/hal/dist/
cp ${builtins.path { path = halDir + "/package.json"; name = "hal-package-json"; }} $out/node_modules/@lamassu/hal/package.json
# serialport and transitive deps (native module chain for RS232 hardware)
@ -99,7 +104,7 @@ in
# ISO image settings
isoImage = {
isoName = "lamassu-atm-live.iso";
isoName = "lamassu-atm-${machineModel}-live.iso";
makeEfiBootable = true;
makeBiosBootable = true;
squashfsCompression = "zstd -Xcompression-level 6";
@ -108,7 +113,10 @@ in
# No fileSystems override needed — iso-image.nix handles squashfs + tmpfs root.
# We don't import hardware/upboard.nix, so there are no conflicting disk mounts.
# Boot: UpBoard-relevant kernel modules (from hardware/upboard.nix) without disk mounts
# Kernel: Douro Bay Trail needs 5.15 LTS (i915 eDP regression in 6.x kernels)
boot.kernelPackages = lib.mkIf (machineModel == "douro") pkgs.linuxPackages_5_15;
# Boot: kernel modules and parameters (model-specific)
boot = {
initrd.availableKernelModules = [
"xhci_pci"
@ -132,10 +140,13 @@ in
"i915.enable_psr=0"
"quiet"
"splash"
] ++ lib.optionals (machineModel == "douro") [
# Bay Trail: preserve BIOS display init (matches working kernel 5.4 config)
"vt.handoff=7"
];
};
# Intel GPU support (from hardware/upboard.nix)
# Intel GPU support
# NB: nixos-24.05 uses hardware.opengl, not hardware.graphics
hardware = {
opengl = {
@ -182,7 +193,7 @@ in
Environment = "LD_LIBRARY_PATH=${pkgs.stdenv.cc.cc.lib}/lib";
# Electron needs --no-sandbox in the live/testing environment
# --enable-logging makes renderer console.log visible in journalctl
ExecStart = lib.mkForce "${pkgs-unstable.electron}/bin/electron --no-sandbox --disable-gpu-sandbox --enable-logging ${atm-app}";
ExecStart = lib.mkForce "${pkgs-unstable.electron}/bin/electron --no-sandbox --disable-gpu-sandbox --disable-gpu --enable-logging ${atm-app}";
# Disable all security hardening that conflicts with Electron
NoNewPrivileges = lib.mkForce false;
ProtectSystem = lib.mkForce false;
@ -201,6 +212,22 @@ in
fi
'';
# Reset display output after X starts (required for kexec boots where
# the GPU wasn't reinitialized by BIOS firmware)
systemd.services.display-reset = {
description = "Reset eDP display output";
after = [ "display-manager.service" ];
requires = [ "display-manager.service" ];
wantedBy = [ "graphical.target" ];
before = [ "lamassu-atm.service" ];
serviceConfig = {
Type = "oneshot";
User = "lamassu";
Environment = "DISPLAY=:0";
ExecStart = "${pkgs.bash}/bin/bash -c '${pkgs.xorg.xrandr}/bin/xrandr --output eDP-1 --off; sleep 1; ${pkgs.xorg.xrandr}/bin/xrandr --output eDP-1 --auto'";
};
};
# Allow SSH with password for initial setup on the live system
services.openssh.settings.PasswordAuthentication = lib.mkForce true;