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

99
deploy/nixos/provision-atm.sh Executable file
View file

@ -0,0 +1,99 @@
#!/usr/bin/env bash
# Provision a running ATM (live USB or QEMU VM) with Lightning.Pub credentials.
# Extracts credentials from the dev docker stack and writes them to the ATM's .env via SSH.
#
# Usage:
# bash provision-atm.sh # defaults: SSH to localhost:2222 (QEMU)
# bash provision-atm.sh 192.168.1.50 # SSH to a real ATM on the LAN
# bash provision-atm.sh 192.168.1.50 22 # custom SSH port
set -euo pipefail
ATM_HOST="${1:-localhost}"
ATM_SSH_PORT="${2:-2222}"
ATM_USER="lamassu"
LP_API="http://localhost:1776"
ADMIN_TOKEN="lamassu-dev-admin-token"
ATM_PRIVATE_KEY="f391a2c3fc734f443b0f685688a0441b5fb9805853c0023f570c5a3c6412b136"
echo "=== Provisioning ATM at $ATM_HOST:$ATM_SSH_PORT ==="
# Step 1: Extract Lightning.Pub pubkey from docker logs
echo ""
echo "--- Step 1: Getting Lightning.Pub pubkey ---"
PUBKEY=$(docker logs lamassu-lightning-pub 2>&1 | grep -oP 'pubkey:\s*\K[a-f0-9]+' | tail -1)
if [ -z "$PUBKEY" ]; then
echo "ERROR: Could not extract pubkey from lamassu-lightning-pub logs."
echo "Is the docker stack running? Try: docker ps | grep lightning-pub"
exit 1
fi
echo "Pubkey: ${PUBKEY:0:16}..."
# Step 2: Create ATM app via admin API
echo ""
echo "--- Step 2: Creating ATM app ---"
RESPONSE=$(curl -s -X POST "$LP_API/api/admin/app/add" \
-H "Content-Type: application/json" \
-H "Authorization: Bearer $ADMIN_TOKEN" \
-d '{"name":"lamassu-atm-live","allow_user_creation":true}' 2>/dev/null)
if echo "$RESPONSE" | grep -q '"status":"OK"'; then
APP_ID=$(echo "$RESPONSE" | grep -oP '"id":"\K[^"]+')
APP_TOKEN=$(echo "$RESPONSE" | grep -oP '"auth_token":"\K[^"]+')
echo "Created app: ${APP_ID:0:16}..."
else
echo "WARN: Could not create app (may already exist). Response:"
echo "$RESPONSE"
echo ""
echo "If the app already exists, check docker/dev-state/ for cached credentials."
exit 1
fi
# Step 3: Determine the host IP as seen from the ATM
# For QEMU user-mode networking, the host is at 10.0.2.2
# For real hardware on LAN, use the dev machine's LAN IP
if [ "$ATM_HOST" = "localhost" ]; then
HOST_IP="10.0.2.2"
echo ""
echo "--- QEMU detected: using $HOST_IP as host gateway ---"
else
HOST_IP=$(hostname -I | awk '{print $1}')
echo ""
echo "--- LAN ATM: using $HOST_IP as dev machine address ---"
fi
# Step 4: Write .env to the ATM via SSH
echo ""
echo "--- Step 3: Writing .env to ATM ---"
ENV_CONTENT="# Lamassu ATM Configuration
# Auto-generated by provision-atm.sh on $(date -Iseconds)
# Lightning.Pub connection
VITE_RELAY_URL=ws://$HOST_IP:7777
VITE_LIGHTNING_PUB_PUBKEY=$PUBKEY
VITE_LIGHTNING_PUB_API_URL=http://$HOST_IP:1776
VITE_EXTENSION_API_URL=http://$HOST_IP:1777
# Credentials
VITE_ADMIN_TOKEN=$ADMIN_TOKEN
VITE_ATM_PRIVATE_KEY=$ATM_PRIVATE_KEY
VITE_APP_ID=$APP_ID
VITE_APP_TOKEN=$APP_TOKEN
# Machine configuration
VITE_LAMASSU_MACHINE_MODEL=sintra
VITE_LAMASSU_FIAT_CODE=USD
# Force production mode
ELECTRON_FORCE_PROD=1
DISPLAY=:0"
ssh -o StrictHostKeyChecking=no -p "$ATM_SSH_PORT" "$ATM_USER@$ATM_HOST" \
"echo '$ENV_CONTENT' | sudo tee /var/lib/lamassu-atm/.env > /dev/null && sudo systemctl restart lamassu-atm"
echo ""
echo "=== ATM provisioned successfully ==="
echo ""
echo "Credentials written to /var/lib/lamassu-atm/.env"
echo "ATM service restarted. It should connect to Lightning.Pub at $HOST_IP."
echo ""
echo "To check status: ssh -p $ATM_SSH_PORT $ATM_USER@$ATM_HOST 'sudo journalctl -u lamassu-atm -f'"