feat(deploy): add NixOS live USB ISO for ATM hardware testing

Add NixOS configuration to build a bootable live USB ISO that runs the
ATM Electron app in kiosk mode on physical hardware (UpBoard). The ISO
boots from squashfs, auto-starts X11/openbox, and launches Electron in
production mode.

Key changes:
- deploy/nixos/live.nix: Live USB module (squashfs+tmpfs, no disk install)
- deploy/nixos/flake.nix: Nix flake with ISO build output
- deploy/nixos/provision-atm.sh: Auto-provision LP credentials via API
- deploy/nixos/build-iso.sh: End-to-end build workflow script
- apps/machine: Fix Electron production mode (ELECTRON_FORCE_PROD),
  Vue Router hash mode for file:// protocol, relative asset paths

Build: cd deploy/nixos && bash build-iso.sh
Test:  qemu-system-x86_64 -enable-kvm -m 2G -cdrom result/iso/*.iso

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
This commit is contained in:
Patrick Mulligan 2026-02-18 20:11:23 -05:00
commit 19d43c2939
13 changed files with 1203 additions and 3 deletions

View file

@ -0,0 +1,150 @@
# Lamassu ATM NixOS Configuration
# Base system configuration for ATM kiosk
{ config, lib, pkgs, pkgs-unstable, ... }:
{
# System basics
system.stateVersion = "24.05";
# Networking
networking = {
hostName = "lamassu-atm";
# Use NetworkManager for easy WiFi configuration
networkmanager.enable = true;
# Firewall - minimal exposure
firewall = {
enable = true;
allowedTCPPorts = [ ]; # ATM initiates all connections
allowedUDPPorts = [ ];
};
};
# Timezone - set to your location
time.timeZone = "UTC";
# Locale
i18n.defaultLocale = "en_US.UTF-8";
# Users
users.groups.lamassu = { };
users.users.lamassu = {
isNormalUser = true;
group = "lamassu";
description = "Lamassu ATM";
extraGroups = [
"wheel" # For admin access
"video" # GPU access
"audio" # Sound
"dialout" # Serial ports
"plugdev" # USB devices
"networkmanager" # Network config
];
# No password - kiosk mode
initialPassword = "lamassu";
};
# Kiosk display configuration
services.xserver = {
enable = true;
# Display manager - auto-login
displayManager = {
autoLogin = {
enable = true;
user = "lamassu";
};
};
# No desktop environment - just the ATM app
desktopManager.xterm.enable = false;
# Basic window manager for Electron
windowManager.openbox.enable = true;
# Disable screen blanking
serverFlagsSection = ''
Option "BlankTime" "0"
Option "StandbyTime" "0"
Option "SuspendTime" "0"
Option "OffTime" "0"
'';
# Intel driver
videoDrivers = [ "modesetting" ];
};
# Audio (for transaction sounds)
security.rtkit.enable = true;
services.pipewire = {
enable = true;
alsa.enable = true;
pulse.enable = true;
};
# System packages
environment.systemPackages = with pkgs; [
# System utilities
htop
vim
git
curl
wget
# Hardware debugging
usbutils
pciutils
lsof
# Serial port tools
minicom
screen
# For the Electron app
pkgs-unstable.electron
# Node.js for the application
pkgs-unstable.nodejs_22
# Camera support
v4l-utils
fswebcam
];
# Enable SSH for remote administration
services.openssh = {
enable = true;
settings = {
PasswordAuthentication = false;
PermitRootLogin = "no";
};
};
# Auto-updates (optional - disabled by default for stability)
# system.autoUpgrade.enable = false;
# Journal configuration
services.journald = {
extraConfig = ''
SystemMaxUse=100M
MaxRetentionSec=1week
'';
};
# Nix settings
nix = {
settings = {
experimental-features = [ "nix-command" "flakes" ];
auto-optimise-store = true;
};
# Garbage collection
gc = {
automatic = true;
dates = "weekly";
options = "--delete-older-than 7d";
};
};
}