From 20dbc8ca80cd20b630d5717ec3541f2cab8d4054 Mon Sep 17 00:00:00 2001 From: Padreug Date: Thu, 2 Jul 2026 15:38:14 +0200 Subject: [PATCH] fix(deploy): provision-atm.sh writes relay/pubkey only on explicit override (#70) MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit The script unconditionally wrote VITE_RELAY_URL + VITE_LNBITS_SERVER_PUBKEY (and hard-exited if it couldn't scrape the pubkey), env-pinning every provisioned machine and defeating the seed — the same bug as the activation default. Make it seed-first: with a SPIRE_SEED, relay + pubkey come from the seed and are written only when the operator explicitly passes RELAY_URL / LNBITS_SERVER_PUBKEY as a deliberate pin. The no-seed dev-nsec path still scrapes/defaults them. Also drops the unused VITE_LNBITS_HTTP_URL line. Co-Authored-By: Claude Opus 4.8 --- deploy/nixos/provision-atm.sh | 100 +++++++++++++++++++--------------- 1 file changed, 57 insertions(+), 43 deletions(-) diff --git a/deploy/nixos/provision-atm.sh b/deploy/nixos/provision-atm.sh index 74f4229..31e08e8 100755 --- a/deploy/nixos/provision-atm.sh +++ b/deploy/nixos/provision-atm.sh @@ -4,19 +4,22 @@ # 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 + 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). +# The primary input is SPIRE_SEED — the pairing seed carries the relay, the +# LNbits server pubkey AND the signing identity, so a seed-provisioned machine +# needs nothing else (aiolabs/bitspire#70). +# +# Environment variables: +# SPIRE_SEED RECOMMENDED. The spire pairing seed +# (`spire-seed:v1:`) minted by spirekeeper. +# Carries relay + LNbits server pubkey + the production +# identity under the NIP-46 bunker (aiolabs/bitspire#52 / #70). +# RELAY_URL OPTIONAL override — pins VITE_RELAY_URL and WINS over the +# seed's relay (env-first precedence). Leave unset to let the +# seed drive it. Required only on the no-seed dev path +# (default there: ws://$HOST_IP:5001/nostrrelay/test). +# LNBITS_SERVER_PUBKEY OPTIONAL override (hex). Leave unset with a seed. On the +# no-seed dev path it's scraped from +# `docker logs lnbits | grep 'nostr_transport pubkey'`. # 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. @@ -61,40 +64,51 @@ else 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}..." +# Steps 2-4: transport config (relay + LNbits server pubkey) + signing identity. +# +# Under aiolabs/bitspire#70 the relay + server pubkey come from the pairing SEED, +# so a seed-provisioned machine needs NEITHER in .env. We only pin them when the +# operator EXPLICITLY passes RELAY_URL / LNBITS_SERVER_PUBKEY (a deliberate +# override that WINS over the seed via env-first precedence), or when there is no +# seed (the dev-nsec fallback has nothing else to supply them, so we scrape/default). +TRANSPORT_LINES="" -# Step 3: Pin LNbits HTTP origin. -LNBITS_HTTP_URL="${LNBITS_HTTP_URL:-http://$HOST_IP:5000}" - -# Step 4: Relay URL. Defaults to the LNbits bundled nostrrelay. -RELAY_URL="${RELAY_URL:-ws://$HOST_IP:5001/nostrrelay/test}" - -# 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 "--- 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 + echo "" + echo "--- Spire pairing seed: relay + LNbits pubkey come from the seed ---" + if [ -n "${RELAY_URL:-}" ]; then + echo " (pinning VITE_RELAY_URL=$RELAY_URL — overrides the seed's relay)" + TRANSPORT_LINES="VITE_RELAY_URL=$RELAY_URL" + fi + if [ -n "${LNBITS_SERVER_PUBKEY:-}" ]; then + TRANSPORT_LINES="${TRANSPORT_LINES:+$TRANSPORT_LINES +}VITE_LNBITS_SERVER_PUBKEY=$LNBITS_SERVER_PUBKEY" + fi IDENTITY_LINES="# Spire pairing seed — bunker-backed identity (aiolabs/bitspire#52) VITE_SPIRE_SEED=$SPIRE_SEED" else + # No seed → DEV-ONLY nsec fallback. Nothing else supplies the relay + pubkey, + # so scrape/default them. + if [ -z "${LNBITS_SERVER_PUBKEY:-}" ]; then + echo "" + echo "--- No seed: 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: no SPIRE_SEED, and could not extract the LNbits pubkey." + echo "Provide a SPIRE_SEED (recommended — the seed carries relay + pubkey)," + echo "or set LNBITS_SERVER_PUBKEY explicitly." + exit 1 + fi + fi + RELAY_URL="${RELAY_URL:-ws://$HOST_IP:5001/nostrrelay/test}" + TRANSPORT_LINES="VITE_RELAY_URL=$RELAY_URL +VITE_LNBITS_SERVER_PUBKEY=$LNBITS_SERVER_PUBKEY" if [ -z "${ATM_PRIVATE_KEY:-}" ]; then ATM_PRIVATE_KEY=$(openssl rand -hex 32) echo "" @@ -110,10 +124,10 @@ 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 +# LNbits nostr-transport. Relay + server pubkey come from the pairing seed +# (aiolabs/bitspire#70); present below only as an explicit override or the +# no-seed dev fallback. +$TRANSPORT_LINES $IDENTITY_LINES @@ -132,6 +146,6 @@ 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 "ATM service restarted. Relay: ${RELAY_URL:-from the pairing seed}." echo "" echo "To check status: ssh -p $ATM_SSH_PORT $ATM_USER@$ATM_HOST 'sudo journalctl -u bitspire -f'"