docs(deploy): capture re-flash workflow gotchas from 25.11 reflash
Tonight's Sintra re-flash surfaced two procedure gaps the doc didn't cover. Burn them in so future-us doesn't rediscover them: 1. Step 0 (re-flash only): preserve .env + state.db before powering off. The .env carries VITE_ATM_PRIVATE_KEY — without it LNbits treats the reflashed unit as new and spawns a fresh wallet, stranding the old wallet's balance. Also: push origin/dev + push-cache.sh BEFORE flashing, or the 04:00 auto-upgrade either fails to substitute or silently downgrades. 2. Step 5: e2fsck "No such file or directory" after parted resize. Kernel re-read the partition table (lsblk shows mmcblk0p2) but Alpine's udev didn't create the /dev/ node. partprobe and blockdev --rereadpt don't fix it — they refresh the kernel's view, not /dev/. Fix is udevadm trigger + settle, or mknod 179:N by hand. Caught tonight, cost ~4 round-trips of confusion. Step 7 split into first-time vs re-flash provisioning paths — the re-flash path sources from the step-0 backup so the ATM keeps its wallet identity. Also added optional state.db restore command. Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
This commit is contained in:
parent
9bbe2a8aef
commit
0af2a9bb29
1 changed files with 51 additions and 2 deletions
|
|
@ -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.
|
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@<sintra-ip>:/var/lib/bitspire/.env ~/sintra-backup-$(date +%Y%m%d)/
|
||||||
|
scp bitspire@<sintra-ip>:/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
|
### 1. Prep a flashing USB stick
|
||||||
|
|
||||||
On your dev box:
|
On your dev box:
|
||||||
|
|
@ -108,6 +122,21 @@ e2fsck -f /dev/mmcblk0p2
|
||||||
resize2fs /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
|
### 6. Boot from eMMC
|
||||||
|
|
||||||
```sh
|
```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
|
### 7. Provision LNbits credentials from the dev box
|
||||||
|
|
||||||
|
**First-time deploy** — generate everything fresh:
|
||||||
|
|
||||||
```bash
|
```bash
|
||||||
LNBITS_SERVER_PUBKEY=$(docker logs <lnbits-container> 2>&1 | \
|
LNBITS_SERVER_PUBKEY=$(docker logs <lnbits-container> 2>&1 | \
|
||||||
grep -oP 'Public key \(share this\):\s*\K[a-f0-9]{64}' | tail -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 <sintra-lan-ip> 22
|
bash deploy/nixos/provision-atm.sh <sintra-lan-ip> 22
|
||||||
```
|
```
|
||||||
|
|
||||||
The script SSHes to `bitspire@<sintra-lan-ip>: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-<date>/.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 <sintra-lan-ip> 22
|
||||||
|
```
|
||||||
|
|
||||||
|
Either way the script SSHes to `bitspire@<sintra-lan-ip>: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-<date>/state.db bitspire@<sintra-ip>:/tmp/state.db
|
||||||
|
ssh bitspire@<sintra-ip> '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
|
## Auto-upgrade behaviour
|
||||||
|
|
||||||
|
|
|
||||||
Loading…
Add table
Add a link
Reference in a new issue