bitspire/deploy/nixos/provision-atm.sh
Padreug 264cc47e0c refactor(deploy): rename system user lamassu → bitspire
System-level half of the lamassu → bitspire rebrand the rest of dev
already did at the path / service / package layers. Touches user/group
declarations, every systemd `User=` block, the udev rules filename, all
chown calls in flake.nix + live.nix, the displayManager autoLogin user,
the trusted-users nix entry, provision-atm.sh's ATM_USER, plus README +
CLAUDE.md doc references.

In-place migration for the Sintra dev unit (which auto-pulls dev at
04:00) lives in `system.activationScripts.bitspire-user-migration` and:
- copies `/home/lamassu/.ssh/authorized_keys` → `/home/bitspire/` once,
  so SSH access survives the rename
- recursively chowns `/var/lib/bitspire` to the new bitspire UID on
  every boot — cheap no-op once done, but covers the case where the
  data dir was written by the now-removed lamassu UID
- leaves `/home/lamassu/` in place as evidence; operator can `rm -rf`
  after confirming bitspire login works

Recovery path if the migration breaks SSH access: root key is still in
configuration.nix:142-144 (padreug@gizmo), so ssh root@<host> works.

Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
2026-06-01 19:11:32 +02:00

118 lines
4.5 KiB
Bash
Executable file

#!/usr/bin/env bash
# Provision a running bitSpire ATM (live USB, QEMU VM, or installed Sintra)
# with LNbits nostr-transport credentials. The ATM speaks to LNbits over
# kind-21000 NIP-44 v2 events on a relay — there is no out-of-band token,
# the ATM's nostr private key IS the credential. # pragma: allowlist secret
#
# Required environment variables (or edit defaults below):
# LNBITS_SERVER_PUBKEY Hex pubkey published by the LNbits server at startup.
# From the LNbits compose:
# docker logs lnbits | grep 'nostr_transport pubkey'
# LNBITS_HTTP_URL Origin LNbits is reachable at over HTTP, used only
# to compose the LNURL-withdraw callback URL that
# customer wallets dereference. Default: http://10.0.2.2:5000
# RELAY_URL Nostr relay LNbits subscribes on. Default uses host gateway.
# ATM_PRIVATE_KEY 32-byte hex key, ATM's nostr identity. If unset, a
# fresh key is generated and saved in the .env.
#
# 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="bitspire"
# Machine model + fiat. Model is operator-set; fiat defaults per-model to
# match the flake's fiatCodeForModel table (sintra=EUR, douro/tejo=GTQ,
# batm3=USD). Operators can override either via env var.
MODEL="${MODEL:-sintra}"
case "${FIAT_CODE:-}" in
"")
case "$MODEL" in
sintra) FIAT_CODE=EUR ;;
douro|tejo) FIAT_CODE=GTQ ;;
batm3) FIAT_CODE=USD ;;
*) FIAT_CODE=USD ;;
esac
;;
esac
echo "=== Provisioning bitSpire ATM at $ATM_HOST:$ATM_SSH_PORT ==="
# Step 1: Discover the host IP as seen from the ATM.
# QEMU user-mode networking puts the host at 10.0.2.2; on real LAN ATMs
# use the dev machine's outbound LAN address.
if [ "$ATM_HOST" = "localhost" ]; then
HOST_IP="10.0.2.2"
echo ""
echo "--- QEMU detected: using $HOST_IP as host gateway ---"
else
HOST_IP=$(ip -4 route get 1 | awk '{print $7; exit}')
echo ""
echo "--- LAN ATM: using $HOST_IP as dev machine address ---"
fi
# Step 2: Resolve the LNbits server pubkey. Prefer the env override; else
# fall back to scraping the local docker compose stack.
if [ -z "${LNBITS_SERVER_PUBKEY:-}" ]; then
echo ""
echo "--- Step 1: Extracting LNbits nostr-transport pubkey from docker logs ---"
LNBITS_SERVER_PUBKEY=$(docker logs lnbits 2>&1 \
| grep -oP 'nostr_transport pubkey:?\s*\K[a-f0-9]{64}' \
| tail -1 || true)
if [ -z "$LNBITS_SERVER_PUBKEY" ]; then
echo "ERROR: Could not extract LNbits pubkey. Set LNBITS_SERVER_PUBKEY explicitly"
echo "or start the LNbits stack first (docker compose -f docker/docker-compose.dev.yml up lnbits)."
exit 1
fi
fi
echo "LNbits server pubkey: ${LNBITS_SERVER_PUBKEY:0:16}..."
# Step 3: Pin LNbits HTTP origin.
LNBITS_HTTP_URL="${LNBITS_HTTP_URL:-http://$HOST_IP:5000}"
# Step 4: Relay URL.
RELAY_URL="${RELAY_URL:-ws://$HOST_IP:7777}"
# Step 5: ATM identity. Generate if unset.
if [ -z "${ATM_PRIVATE_KEY:-}" ]; then
ATM_PRIVATE_KEY=$(openssl rand -hex 32)
echo ""
echo "--- Generated fresh ATM_PRIVATE_KEY (save this if you want it persisted) ---"
fi
# Step 6: Write .env to the ATM via SSH.
echo ""
echo "--- Step 2: Writing .env to ATM ---"
ENV_CONTENT="# bitSpire Configuration
# Auto-generated by provision-atm.sh on $(date -Iseconds)
# LNbits nostr-transport connection
VITE_RELAY_URL=$RELAY_URL
VITE_LNBITS_SERVER_PUBKEY=$LNBITS_SERVER_PUBKEY
VITE_LNBITS_HTTP_URL=$LNBITS_HTTP_URL
# ATM identity (signing key IS the credential under nostr-transport)
VITE_ATM_PRIVATE_KEY=$ATM_PRIVATE_KEY
# Machine configuration
VITE_LAMASSU_MACHINE_MODEL=$MODEL
VITE_LAMASSU_FIAT_CODE=$FIAT_CODE
# 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/bitspire/.env > /dev/null && sudo systemctl restart bitspire"
echo ""
echo "=== ATM provisioned successfully ==="
echo ""
echo "Credentials written to /var/lib/bitspire/.env"
echo "ATM service restarted. It should connect to LNbits via relay $RELAY_URL."
echo ""
echo "To check status: ssh -p $ATM_SSH_PORT $ATM_USER@$ATM_HOST 'sudo journalctl -u bitspire -f'"