diff --git a/deploy/nixos/README.md b/deploy/nixos/README.md index 794c471..af00ed6 100644 --- a/deploy/nixos/README.md +++ b/deploy/nixos/README.md @@ -59,7 +59,7 @@ scp bitspire@:/var/lib/bitspire/.env ~/sintra-backup-$(date +%Y scp bitspire@:/var/lib/bitspire/state.db ~/sintra-backup-$(date +%Y%m%d)/ ``` -The `.env` is the load-bearing one — it contains `VITE_ATM_PRIVATE_KEY` plus the LNbits / relay URLs. `state.db` is transaction history (cheap to keep, fine to drop on dev units). Reuse these in step 7 instead of regenerating. +The `.env` is the load-bearing one — it contains `VITE_SPIRE_SEED` (the NIP-46 bunker pairing seed; or the dev-only `VITE_ATM_PRIVATE_KEY` fallback) plus the LNbits / relay URLs. Note the persisted bunker binding (the ATM's transport key) lives in `state.db` once paired — so on a bunker-backed unit, keep `state.db` too or you'll need to re-pair. `state.db` also holds transaction history. Reuse these in step 7 instead of regenerating. Also before powering off the Sintra: make sure any unpushed commits on `dev` have been pushed AND `./deploy/push-cache.sh sintra` has run. Otherwise the next 04:00 auto-upgrade on the freshly-flashed unit will fail to substitute the new closure (or silently downgrade to whatever `origin/dev` HEAD points at). @@ -202,7 +202,7 @@ Production ATMs on `main` continue to read `main`'s flake (no `?ref=` pin → re | Path | Owner | Purpose | |------|-------|---------| | `/var/lib/bitspire/` | bitspire:bitspire, 0750 | Service data directory | -| `/var/lib/bitspire/.env` | bitspire:bitspire, 0600 | Runtime config — `VITE_RELAY_URL`, `VITE_LNBITS_SERVER_PUBKEY`, `VITE_ATM_PRIVATE_KEY`, … | +| `/var/lib/bitspire/.env` | bitspire:bitspire, 0600 | Runtime config — `VITE_RELAY_URL`, `VITE_LNBITS_SERVER_PUBKEY`, `VITE_SPIRE_SEED` (or dev `VITE_ATM_PRIVATE_KEY`), … | | `/var/lib/bitspire/state.db` | bitspire:bitspire | SQLite — cassette inventory, cashbox state, transaction history | | `/var/lib/bitspire/logs/` | bitspire:bitspire, 0750 | Service logs (if app writes them) | | `/var/lib/bitspire/branding/` | bitspire:bitspire, 0755 | Operator branding override (logo.png + branding.json) — see issue #47 | diff --git a/deploy/nixos/live.nix b/deploy/nixos/live.nix index 6b72fbc..07fe161 100644 --- a/deploy/nixos/live.nix +++ b/deploy/nixos/live.nix @@ -22,16 +22,15 @@ let }.${machineModel} or "USD"; # .env template — runtime secrets are provisioned later via provision-atm.sh. - # Only non-secret defaults and display vars go here. + # Only non-secret defaults and display vars go here. VITE_SPIRE_SEED (the + # NIP-46 bunker pairing seed) is written at provision time; the dev-only + # VITE_ATM_PRIVATE_KEY fallback is omitted here on purpose. envTemplate = pkgs.writeText "bitspire-env" '' VITE_RELAY_URL= - VITE_LIGHTNING_PUB_PUBKEY= - VITE_LIGHTNING_PUB_API_URL= - VITE_ADMIN_TOKEN= - VITE_ATM_PRIVATE_KEY= - VITE_EXTENSION_API_URL= + VITE_LNBITS_SERVER_PUBKEY= + VITE_SPIRE_SEED= VITE_APP_ID= - VITE_LNDCONNECT_URL= + VITE_OPERATOR_PUBKEYS= VITE_LAMASSU_MACHINE_MODEL=${machineModel} VITE_LAMASSU_FIAT_CODE=${fiatCodeForModel} ELECTRON_FORCE_PROD=1 diff --git a/deploy/nixos/provision-atm.sh b/deploy/nixos/provision-atm.sh index 5b4c55b..74f4229 100755 --- a/deploy/nixos/provision-atm.sh +++ b/deploy/nixos/provision-atm.sh @@ -11,9 +11,15 @@ # 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. +# RELAY_URL Nostr relay LNbits + the bunker subscribe on. +# Default: ws://$HOST_IP:5001/nostrrelay/test (LNbits +# bundled nostrrelay). Override for a separate relay. +# SPIRE_SEED The spire pairing seed (`spire-seed:v1:`) +# minted by spirekeeper. THIS is the production +# identity under the NIP-46 bunker (aiolabs/bitspire#52). +# ATM_PRIVATE_KEY DEV-ONLY 32-byte hex nsec fallback, used only when +# SPIRE_SEED is unset (no bunker). Generated if unset +# AND no SPIRE_SEED is provided. # # Usage: # bash provision-atm.sh # defaults: SSH to localhost:2222 (QEMU) @@ -74,14 +80,28 @@ 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 4: Relay URL. Defaults to the LNbits bundled nostrrelay. +RELAY_URL="${RELAY_URL:-ws://$HOST_IP:5001/nostrrelay/test}" -# Step 5: ATM identity. Generate if unset. -if [ -z "${ATM_PRIVATE_KEY:-}" ]; then - ATM_PRIVATE_KEY=$(openssl rand -hex 32) +# Step 5: Signing identity. Prefer the spire pairing seed (bunker). Only fall +# back to a generated dev nsec when no seed is supplied. +if [ -n "${SPIRE_SEED:-}" ]; then echo "" - echo "--- Generated fresh ATM_PRIVATE_KEY (save this if you want it persisted) ---" + echo "--- Using spire pairing seed (bunker-backed identity) ---" + case "$SPIRE_SEED" in + spire-seed:v1:*) : ;; + *) echo "ERROR: SPIRE_SEED must start with 'spire-seed:v1:'"; exit 1 ;; + esac + IDENTITY_LINES="# Spire pairing seed — bunker-backed identity (aiolabs/bitspire#52) +VITE_SPIRE_SEED=$SPIRE_SEED" +else + if [ -z "${ATM_PRIVATE_KEY:-}" ]; then + ATM_PRIVATE_KEY=$(openssl rand -hex 32) + echo "" + echo "--- No SPIRE_SEED; generated a DEV-ONLY ATM_PRIVATE_KEY (no bunker) ---" + fi + IDENTITY_LINES="# DEV-ONLY local nsec (no bunker pairing) # pragma: allowlist secret +VITE_ATM_PRIVATE_KEY=$ATM_PRIVATE_KEY" fi # Step 6: Write .env to the ATM via SSH. @@ -95,8 +115,7 @@ 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 +$IDENTITY_LINES # Machine configuration VITE_LAMASSU_MACHINE_MODEL=$MODEL diff --git a/flake.nix b/flake.nix index dc69891..9ceb5dd 100644 --- a/flake.nix +++ b/flake.nix @@ -200,7 +200,7 @@ cp ${pkgs.writeText "bitspire-env-default" '' VITE_RELAY_URL=${config.services.bitspire.relayUrl} VITE_LNBITS_SERVER_PUBKEY= - VITE_ATM_PRIVATE_KEY= + VITE_SPIRE_SEED= VITE_APP_ID= VITE_OPERATOR_PUBKEYS= VITE_LAMASSU_MACHINE_MODEL=${machineModel}