diff --git a/deploy/nixos/README.md b/deploy/nixos/README.md index 250913d..44b04af 100644 --- a/deploy/nixos/README.md +++ b/deploy/nixos/README.md @@ -49,6 +49,20 @@ nix build .#iso-tejo The Sintra ships from the factory with whatever its previous OS was — Android, vendor Linux, or wiped. You need an Alpine live USB to act as your installer. +### 0. (Re-flash only) Preserve state from the existing Sintra + +If you're re-flashing a Sintra that's already in service, `dd` will wipe `/var/lib/bitspire/`. Back up the parts you care about first, **especially the ATM's nostr private key**. Without it, LNbits will treat the reflashed ATM as a brand-new unit and spawn a fresh wallet — the old wallet's balance becomes inaccessible. + +```bash +mkdir -p ~/sintra-backup-$(date +%Y%m%d) +scp bitspire@:/var/lib/bitspire/.env ~/sintra-backup-$(date +%Y%m%d)/ +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. + +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). + ### 1. Prep a flashing USB stick On your dev box: @@ -108,6 +122,21 @@ e2fsck -f /dev/mmcblk0p2 resize2fs /dev/mmcblk0p2 ``` +**If `e2fsck` complains `No such file or directory ... Possibly non-existent device?`:** the partition table was re-read by the kernel (so `lsblk` shows `mmcblk0p2` correctly), but Alpine's udev didn't create the `/dev/` node. `partprobe` and `blockdev --rereadpt` won't fix this — they refresh the kernel's view, not `/dev/`. Two ways out: + +```sh +# Cleaner: nudge udev to re-emit the add events +udevadm trigger --action=add --subsystem-match=block +udevadm settle + +# Brute force: read the major:minor off lsblk and mknod by hand +# (mmcblk0 partitions are always major 179; minor matches partition number) +mknod /dev/mmcblk0p1 b 179 1 +mknod /dev/mmcblk0p2 b 179 2 +``` + +Then re-run `e2fsck -f /dev/mmcblk0p2 && resize2fs /dev/mmcblk0p2`. Caught on the 25.11 reflash 2026-05-26. + ### 6. Boot from eMMC ```sh @@ -118,6 +147,8 @@ Pull both USB sticks. Power Sintra back on. systemd-boot loads from the eMMC's E ### 7. Provision LNbits credentials from the dev box +**First-time deploy** — generate everything fresh: + ```bash LNBITS_SERVER_PUBKEY=$(docker logs 2>&1 | \ grep -oP 'Public key \(share this\):\s*\K[a-f0-9]{64}' | tail -1) @@ -129,9 +160,27 @@ ATM_PRIVATE_KEY=$(openssl rand -hex 32) \ bash deploy/nixos/provision-atm.sh 22 ``` -The script SSHes to `bitspire@:22`, writes `/var/lib/bitspire/.env`, and restarts `bitspire.service`. After a few seconds the kiosk should connect to LNbits over nostr-transport and show the live UI. +**Re-flash** — source the values straight from your step-0 backup so the ATM keeps its LNbits wallet identity: -> **Save the generated `ATM_PRIVATE_KEY`.** LNbits identifies this ATM by its public key; if you regenerate the key on a re-provision, LNbits will auto-create a fresh wallet and the old wallet's balance becomes inaccessible. +```bash +set -a; source ~/sintra-backup-/.env; set +a +ATM_PRIVATE_KEY=$VITE_ATM_PRIVATE_KEY \ +LNBITS_SERVER_PUBKEY=$VITE_LNBITS_SERVER_PUBKEY \ +LNBITS_HTTP_URL=$VITE_LNBITS_HTTP_URL \ +RELAY_URL=$VITE_RELAY_URL \ +bash deploy/nixos/provision-atm.sh 22 +``` + +Either way the script SSHes to `bitspire@:22`, writes `/var/lib/bitspire/.env`, and restarts `bitspire.service`. After a few seconds the kiosk should connect to LNbits over nostr-transport and show the live UI. + +Optional re-flash follow-up — restore transaction history: + +```bash +scp ~/sintra-backup-/state.db bitspire@:/tmp/state.db +ssh bitspire@ 'sudo install -o bitspire -g bitspire -m 600 /tmp/state.db /var/lib/bitspire/state.db && sudo systemctl restart bitspire' +``` + +> **First-time deploys only: save the generated `ATM_PRIVATE_KEY`.** LNbits identifies this ATM by its public key; if you regenerate the key on a re-provision, LNbits will auto-create a fresh wallet and the old wallet's balance becomes inaccessible. (Re-flashes preserve the key via the step-0 backup.) ## Auto-upgrade behaviour