docs: refresh deploy/nixos/README + flag obsolete flow docs
deploy/nixos/README.md was the most-stale doc in the tree: it still
talked about a `lamassu-atm` systemd unit, `/opt/lamassu-atm` paths,
nixos-install with a non-existent `lamassu-atm` flake output, and an
scp-the-built-electron-bundle workflow that hasn't been the deploy
path for many months. Replaced with a rewrite that documents the
actual current pipeline:
- File layout: bitspire-atm.nix (not lamassu-atm.nix), live.nix,
hardware/{douro,batm3,upboard}.nix, and the udev / helper scripts
- Build pipeline: `nix build .#disk-image-<model>` and the four
flake-output flavours per model (live config, installed config,
iso, disk-image)
- Full Sintra walkthrough end-to-end: prep a flashing USB on the
dev box, boot Alpine live on the Sintra, identify the eMMC,
dd with count= to skip the trailing USB padding, repair the
GPT secondary header + grow root with parted, poweroff, boot,
provision via provision-atm.sh. Every quirk we hit during the
first real flash is now baked in (mdev for /dev nodes, parted
Fix prompt, lbu-style notes).
- Runtime layout cheat-sheet: /var/lib/bitspire/.env (0600
lamassu:lamassu), state.db, /etc/bitspire/config.env, etc.
- Common-operations playbook: re-provision, nixos-rebuild switch
over SSH with --use-remote-sudo (much faster than reflashing),
journalctl filtering, hardware-side health checks.
- NixOS module reference for services.bitspire, including the
LNbits-flavoured options (relayUrl, lnbitsServerPubkey,
lnbitsHttpUrl) instead of the retired lightningPubUrl.
- Sintra-specific gotchas section: eMMC-via-sdhci-acpi, the
ttyS4 dispenser placement, the ttyS1..3 phantom-node issue.
- Security-notes section updated to reflect passwordless sudo
enabled for nixos-rebuild deploys, and the implications.
Auto-upgrade behaviour explained explicitly (the ?ref=dev pin) so
contributors understand why production ATMs on main don't pick up
dev branch changes.
docs/ndebit-cash-in-flow.md: added a header banner flagging the
document as historical — cash-in on dev is LNURL-withdraw +
subscribe_payments push, not ndebit. Original content kept as a
reference for any future revival of nostr-native cash-in.
docs/clink-protocol.md: same treatment — flagged as dormant on dev,
explaining which pieces still apply (kind-21003 management) and
which are unused (kinds 21001/21002). Protocol reference content
left intact since the wire format is unchanged upstream.
Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
This commit is contained in:
parent
bac130dbf1
commit
0b94bef4be
3 changed files with 234 additions and 122 deletions
|
|
@ -1,81 +1,235 @@
|
||||||
# bitSpire NixOS Deployment
|
# bitSpire NixOS Deployment
|
||||||
|
|
||||||
NixOS configuration for deploying Lamassu Next ATM software on UP Board hardware.
|
NixOS module + tooling for deploying bitSpire to ATM hardware (Sintra, tejo, douro, batm3). The deploy pipeline produces a dd-able raw disk image; you flash it onto the ATM's internal storage and provision the runtime `.env` with LNbits credentials via SSH.
|
||||||
|
|
||||||
## Quick Start
|
> The production cutover lives on `main`; this README documents `dev` reality. Production ATMs (`batm3`, `douro`) still run from `main` with the Lightning.Pub backend until cutover.
|
||||||
|
|
||||||
### 1. Build Installation ISO
|
## File layout
|
||||||
|
|
||||||
```bash
|
```
|
||||||
cd deploy/nixos
|
deploy/nixos/
|
||||||
nix build .#iso
|
├── bitspire-atm.nix # NixOS module: services.bitspire option tree + systemd unit + udev rules
|
||||||
|
├── configuration.nix # Base system (NixOS 24.05, locale, kernel, packages, lamassu user)
|
||||||
|
├── live.nix # Live USB variant (squashfs + tmpfs root) — used by mkLiveConfig
|
||||||
|
├── hardware/
|
||||||
|
│ ├── douro.nix # Dell OptiPlex 9030 AIO (batm3 sibling; SATA SSD, eGalax touch)
|
||||||
|
│ ├── batm3.nix # GeneralBytes BATM3 (Dell board, WireGuard wired in)
|
||||||
|
│ └── upboard.nix # Aaeon UP Board (Sintra + tejo; eMMC root via sdhci-acpi + mmc_block)
|
||||||
|
├── udev/
|
||||||
|
│ └── 99-lamassu-hardware.rules # additional udev rules (loaded via configuration.nix)
|
||||||
|
├── provision-atm.sh # Push LNbits credentials to a deployed ATM via SSH
|
||||||
|
├── atm-transactions.sh # Operator query tool — reads /var/lib/bitspire/state.db
|
||||||
|
├── flash-douro-usb.sh # Helper for flashing a douro live USB
|
||||||
|
└── build-iso.sh # Convenience wrapper for `nix build .#iso-<model>`
|
||||||
```
|
```
|
||||||
|
|
||||||
The ISO will be in `result/iso/`.
|
## Build pipeline
|
||||||
|
|
||||||
### 2. Install on UP Board
|
Each ATM model has two flake outputs:
|
||||||
|
|
||||||
1. Write ISO to USB drive:
|
| Output (flake.nix) | Type | Purpose |
|
||||||
|
|---|---|---|
|
||||||
|
| `nixosConfigurations.<model>` | live | squashfs live USB, tmpfs root, no persistence — for first-boot testing |
|
||||||
|
| `nixosConfigurations.<model>-installed` | installed | full GPT + systemd-boot install, ext4 root, supports `nixos-rebuild switch` |
|
||||||
|
| `packages.x86_64-linux.iso-<model>` | ISO | ISO image of the live variant |
|
||||||
|
| `packages.x86_64-linux.disk-image-<model>` | raw image | dd-able full disk image of the installed variant |
|
||||||
|
|
||||||
|
Models: `douro`, `tejo`, `sintra`, `batm3`.
|
||||||
|
|
||||||
```bash
|
```bash
|
||||||
sudo dd if=result/iso/*.iso of=/dev/sdX bs=4M status=progress
|
# Build a Sintra disk image
|
||||||
|
nix build .#disk-image-sintra
|
||||||
|
# → result/nixos.img (~8.5 GB sparse, 6 GB actual, GPT-partitioned)
|
||||||
|
|
||||||
|
# Build a live ISO for tejo
|
||||||
|
nix build .#iso-tejo
|
||||||
```
|
```
|
||||||
|
|
||||||
2. Boot UP Board from USB
|
## Deploying to Sintra (full walkthrough)
|
||||||
|
|
||||||
3. Run the 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.
|
||||||
|
|
||||||
|
### 1. Prep a flashing USB stick
|
||||||
|
|
||||||
|
On your dev box:
|
||||||
|
|
||||||
```bash
|
```bash
|
||||||
sudo nixos-install --flake .#lamassu-atm
|
nix build .#disk-image-sintra
|
||||||
|
sudo dd if=result/nixos.img of=/dev/sdX bs=4M status=progress conv=fsync && sync
|
||||||
```
|
```
|
||||||
|
|
||||||
4. Reboot and remove USB
|
`/dev/sdX` is the USB stick you'll carry to the Sintra. **Verify the target is the stick, not your workstation's main disk** — `lsblk -f /dev/sdX` should show `Flash Drive` or similar.
|
||||||
|
|
||||||
### 3. Post-Install Configuration
|
### 2. Boot Sintra into Alpine live
|
||||||
|
|
||||||
SSH into the machine and configure:
|
You need a separate USB stick with a minimal Alpine ISO. Boot it on the Sintra, get to a shell, bring up networking:
|
||||||
|
|
||||||
|
```sh
|
||||||
|
ip link set eth0 up
|
||||||
|
udhcpc -i eth0
|
||||||
|
ver=$(cat /etc/alpine-release | cut -d. -f1-2)
|
||||||
|
cat > /etc/apk/repositories <<EOF
|
||||||
|
http://dl-cdn.alpinelinux.org/alpine/v${ver}/main
|
||||||
|
http://dl-cdn.alpinelinux.org/alpine/v${ver}/community
|
||||||
|
EOF
|
||||||
|
apk update
|
||||||
|
apk add util-linux coreutils gptfdisk parted e2fsprogs e2fsprogs-extra dosfstools openssh
|
||||||
|
```
|
||||||
|
|
||||||
|
### 3. Identify the internal eMMC
|
||||||
|
|
||||||
|
```sh
|
||||||
|
lsblk -f
|
||||||
|
# look for: mmcblk0 with `removable=0`, ~14-32 GB
|
||||||
|
```
|
||||||
|
|
||||||
|
The bitSpire-flashed USB will show up as another disk (`sdb` or similar) — note both device paths.
|
||||||
|
|
||||||
|
### 4. dd the bitSpire image to the eMMC
|
||||||
|
|
||||||
|
```sh
|
||||||
|
# Limit count to ~8.8 GB (the actual image size + small margin) to avoid
|
||||||
|
# spending 30 minutes copying empty USB tail
|
||||||
|
dd if=/dev/sdb of=/dev/mmcblk0 bs=4M count=2200 status=progress conv=fsync && sync
|
||||||
|
```
|
||||||
|
|
||||||
|
### 5. Repair the GPT secondary header
|
||||||
|
|
||||||
|
Because the source disk (60 GB USB) is larger than the target (14 GB eMMC), the backup GPT header that was placed at the end of the USB is now off the end of the eMMC. Fix with parted (which also lets us resize root in one go):
|
||||||
|
|
||||||
|
```sh
|
||||||
|
parted /dev/mmcblk0 resizepart 2 100%
|
||||||
|
# When prompted "Fix/Ignore?" answer Fix.
|
||||||
|
# When prompted "Partition number?" answer 2.
|
||||||
|
# When prompted "End?" answer 100%.
|
||||||
|
|
||||||
|
e2fsck -f /dev/mmcblk0p2
|
||||||
|
resize2fs /dev/mmcblk0p2
|
||||||
|
```
|
||||||
|
|
||||||
|
### 6. Boot from eMMC
|
||||||
|
|
||||||
|
```sh
|
||||||
|
poweroff
|
||||||
|
```
|
||||||
|
|
||||||
|
Pull both USB sticks. Power Sintra back on. systemd-boot loads from the eMMC's ESP, kernel + initrd come up, you reach a kiosk screen showing "ATM unavailable — needs provisioning" (the `.env` template lands empty by design).
|
||||||
|
|
||||||
|
### 7. Provision LNbits credentials from the dev box
|
||||||
|
|
||||||
```bash
|
```bash
|
||||||
# Set up the ATM application
|
LNBITS_SERVER_PUBKEY=$(docker logs <lnbits-container> 2>&1 | \
|
||||||
sudo mkdir -p /opt/lamassu-atm
|
grep -oP 'Public key \(share this\):\s*\K[a-f0-9]{64}' | tail -1)
|
||||||
sudo chown lamassu:lamassu /opt/lamassu-atm
|
|
||||||
|
|
||||||
# Copy the built Electron app
|
LNBITS_HTTP_URL=http://<dev-lan-ip>:5001 \
|
||||||
scp -r apps/machine/dist/* lamassu@<atm-ip>:/opt/lamassu-atm/
|
RELAY_URL=ws://<dev-lan-ip>:5001/nostrrelay/test \
|
||||||
|
LNBITS_SERVER_PUBKEY="$LNBITS_SERVER_PUBKEY" \
|
||||||
# Configure the ATM
|
ATM_PRIVATE_KEY=$(openssl rand -hex 32) \
|
||||||
sudo nano /etc/lamassu-atm/config.env
|
bash deploy/nixos/provision-atm.sh <sintra-lan-ip> 22
|
||||||
```
|
```
|
||||||
|
|
||||||
## Configuration Options
|
The script SSHes to `lamassu@<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.
|
||||||
|
|
||||||
Edit `/etc/nixos/configuration.nix` to customize:
|
> **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.
|
||||||
|
|
||||||
|
## Auto-upgrade behaviour
|
||||||
|
|
||||||
|
The `dev`-branch `flake.nix` pins the auto-upgrade source to `?ref=dev` so any ATM flashed from `dev` stays on `dev`:
|
||||||
|
|
||||||
|
```nix
|
||||||
|
system.autoUpgrade = {
|
||||||
|
enable = true;
|
||||||
|
flake = "git+ssh://forgejo@git.atitlan.io/aiolabs/lamassu-next.git?ref=dev#${machineModel}-installed";
|
||||||
|
dates = "04:00";
|
||||||
|
allowReboot = false;
|
||||||
|
};
|
||||||
|
```
|
||||||
|
|
||||||
|
Daily at 04:00 local time the ATM runs `nixos-rebuild switch` against the latest commit on `dev`. If the build fails (e.g., binary cache miss + local kernel compile failure), the existing system keeps running; nothing destructive happens. `allowReboot = false` means a kernel update lands but doesn't take effect until the next operator-initiated reboot.
|
||||||
|
|
||||||
|
Production ATMs on `main` continue to read `main`'s flake (no `?ref=` pin → resolves to the repo default branch), so they keep pulling `main` and stay on the LP backend.
|
||||||
|
|
||||||
|
## Quick reference — runtime layout on a deployed ATM
|
||||||
|
|
||||||
|
| Path | Owner | Purpose |
|
||||||
|
|------|-------|---------|
|
||||||
|
| `/var/lib/bitspire/` | lamassu:lamassu, 0750 | Service data directory |
|
||||||
|
| `/var/lib/bitspire/.env` | lamassu:lamassu, 0600 | Runtime config — `VITE_RELAY_URL`, `VITE_LNBITS_SERVER_PUBKEY`, `VITE_LNBITS_HTTP_URL`, `VITE_ATM_PRIVATE_KEY`, … |
|
||||||
|
| `/var/lib/bitspire/state.db` | lamassu:lamassu | SQLite — cassette inventory, cashbox state, transaction history |
|
||||||
|
| `/var/lib/bitspire/logs/` | lamassu:lamassu, 0750 | Service logs (if app writes them) |
|
||||||
|
| `/opt/bitspire/` | lamassu:lamassu | Optional override drop for app assets (mostly unused — app comes from `/nix/store`) |
|
||||||
|
| `/etc/bitspire/config.env` | root:root | Static config emitted by the NixOS module (RELAY_URL, LNBITS_HTTP_URL — informational; the renderer reads `/var/lib/bitspire/.env` instead) |
|
||||||
|
|
||||||
|
## Common operations
|
||||||
|
|
||||||
|
### Service status
|
||||||
|
|
||||||
|
```bash
|
||||||
|
sudo systemctl status bitspire
|
||||||
|
sudo journalctl -u bitspire -f
|
||||||
|
sudo journalctl -u bitspire --since "5 minutes ago" | grep -E '\[' # filter to renderer logs
|
||||||
|
```
|
||||||
|
|
||||||
|
### Re-provision (rotate credentials, fix wrong relay URL, etc.)
|
||||||
|
|
||||||
|
Re-run `provision-atm.sh` with new env vars. The script overwrites `/var/lib/bitspire/.env` and restarts the service.
|
||||||
|
|
||||||
|
### Push code without re-flashing
|
||||||
|
|
||||||
|
From the dev box:
|
||||||
|
|
||||||
|
```bash
|
||||||
|
nixos-rebuild switch --flake .#sintra-installed \
|
||||||
|
--target-host lamassu@<sintra-lan-ip> --use-remote-sudo
|
||||||
|
```
|
||||||
|
|
||||||
|
Locally builds the new closure (binary-cache where possible), copies it to the ATM over SSH, activates the new generation. A kernel-or-initrd change still requires a reboot to take effect — `sudo systemctl reboot` over SSH afterwards.
|
||||||
|
|
||||||
|
### Inspect transactions
|
||||||
|
|
||||||
|
```bash
|
||||||
|
sudo bash /etc/nixos/atm-transactions.sh
|
||||||
|
# → reads /var/lib/bitspire/state.db and prints recent transactions
|
||||||
|
```
|
||||||
|
|
||||||
|
### Check hardware-side health
|
||||||
|
|
||||||
|
```bash
|
||||||
|
# udev symlinks expected by upboard.nix
|
||||||
|
ls -la /dev/ttyJ4 /dev/ttyJ5 /dev/ttyJ7
|
||||||
|
|
||||||
|
# Real UART layout
|
||||||
|
sudo dmesg | grep -E 'ttyS[0-9]'
|
||||||
|
|
||||||
|
# All USB serial bridges
|
||||||
|
ls -la /dev/serial/by-id/
|
||||||
|
```
|
||||||
|
|
||||||
|
## NixOS module reference
|
||||||
|
|
||||||
|
`services.bitspire` options (defined in `bitspire-atm.nix`):
|
||||||
|
|
||||||
```nix
|
```nix
|
||||||
{
|
{
|
||||||
services.bitspire = {
|
services.bitspire = {
|
||||||
enable = true;
|
enable = true;
|
||||||
|
relayUrl = "wss://relay.aiolabs.dev"; # ATM ↔ LNbits relay
|
||||||
|
lnbitsServerPubkey = "<64-hex>"; # LNbits transport pubkey
|
||||||
|
lnbitsHttpUrl = "https://lnbits.aiolabs.dev"; # LNURL callback URL prefix
|
||||||
|
appDir = "/opt/bitspire"; # rarely overridden — defaults via flake
|
||||||
|
dataDir = "/var/lib/bitspire"; # rarely overridden
|
||||||
|
logLevel = "info"; # error | warn | info | debug
|
||||||
|
|
||||||
# Nostr relay both the ATM and LNbits subscribe on
|
|
||||||
relayUrl = "wss://relay.aiolabs.dev";
|
|
||||||
|
|
||||||
# LNbits nostr-transport server pubkey (hex, 64 chars)
|
|
||||||
lnbitsServerPubkey = "<hex pubkey from `docker logs lnbits | grep nostr_transport`>";
|
|
||||||
|
|
||||||
# LNbits HTTP origin — only used to compose LNURL-withdraw callback URLs
|
|
||||||
lnbitsHttpUrl = "https://lnbits.aiolabs.dev";
|
|
||||||
|
|
||||||
# Hardware configuration
|
|
||||||
billValidator = {
|
billValidator = {
|
||||||
enable = true;
|
enable = true;
|
||||||
device = "/dev/ttyUSB0";
|
device = "/dev/ttyJ5"; # symlink emitted by upboard.nix udev rules
|
||||||
type = "id003"; # or "mei", "ccnet"
|
type = "id003"; # id003 | mei | ccnet
|
||||||
};
|
};
|
||||||
|
|
||||||
billDispenser = {
|
billDispenser = {
|
||||||
enable = false; # Enable for two-way machines
|
enable = true;
|
||||||
device = "/dev/ttyUSB1";
|
device = "/dev/ttyJ7"; # symlink for the SoC MMIO UART on Sintra (was ttyS4)
|
||||||
type = "puloon";
|
type = "f56"; # puloon | genmega | f56
|
||||||
};
|
};
|
||||||
|
|
||||||
camera = {
|
camera = {
|
||||||
|
|
@ -86,110 +240,26 @@ Edit `/etc/nixos/configuration.nix` to customize:
|
||||||
}
|
}
|
||||||
```
|
```
|
||||||
|
|
||||||
## Hardware Support
|
Most of these are set automatically by the `mkInstalledConfig` helper in the root `flake.nix`. You typically only override them in a one-off NixOS config or for hardware different from what `flake.nix` knows about.
|
||||||
|
|
||||||
### Bill Validators
|
## Hardware support
|
||||||
|
|
||||||
- **ID-003** (JCM) - Most common in Lamassu machines
|
| Component | Drivers in `packages/hal/` | Tested on |
|
||||||
- **MEI** (Mars Electronics)
|
|---|---|---|
|
||||||
- **CCNET** (CashCode)
|
| Bill validator | id003, ccnet, cashflow_sc, bnr_advance, genmega, hcm2, gsr50 | iVIZION (id003) on Sintra |
|
||||||
|
| Bill dispenser | puloon, f56, genmega, hcm2, gsr50 | Fujitsu F56 on Sintra |
|
||||||
|
| Camera | any V4L2 USB device | Z-Star 0ac8:0345 on Sintra |
|
||||||
|
| Touchscreen | any libinput-compatible device | ILI 222a:0001 on Sintra, eGalax on douro |
|
||||||
|
|
||||||
### Bill Dispensers
|
### Sintra-specific gotchas
|
||||||
|
|
||||||
- **Puloon** - LCDM series
|
- **eMMC controller is ACPI-enumerated.** `upboard.nix` force-loads `sdhci-acpi` and `mmc_block` in `initrd.kernelModules` so root-by-label resolves in stage 1.
|
||||||
- **Genmega**
|
- **Dispenser is on `ttyS4`, the SoC MMIO UART.** This is the only on-carrier RS-232 besides the legacy 8250 at `ttyS0`. The kernel console must **not** be routed through `ttyS4` (use `console=tty0` only); routing it through `ttyS4` blocks userspace from opening the port for HAL.
|
||||||
|
- **`ttyS1`, `ttyS2`, `ttyS3` are placeholder kernel nodes.** Opening them returns `EIO`. Only `ttyS0` (legacy 16550A at I/O 0x3f8) and `ttyS4` (MMIO 16550A at 0xa171b000) are real UARTs on this hardware.
|
||||||
|
|
||||||
### Cameras
|
## Security notes
|
||||||
|
|
||||||
- Any V4L2-compatible USB camera
|
- **`lamassu` user has `wheel`/passwordless-sudo** to allow remote `nixos-rebuild switch` via `--use-remote-sudo`. This is acceptable for a kiosk on a network you control. Remove `security.sudo.wheelNeedsPassword = false` if you want to require a password.
|
||||||
|
- **SSH password auth is enabled by default** to allow initial provisioning. Once you've baked your dev box's pubkey into `/home/lamassu/.ssh/authorized_keys`, you can disable password auth: `services.openssh.settings.PasswordAuthentication = false`.
|
||||||
## File Structure
|
- **`/var/lib/bitspire/.env` contains the ATM's nostr private key.** It's mode 0600, owned by `lamassu:lamassu`. Don't `scp` it off the device; if you need to rotate the key, generate fresh and re-provision.
|
||||||
|
- **No firewall is configured by default.** The ATM is meant to be on an operator-controlled network. If you expose it to a wider network, add a `networking.firewall` rule set restricting inbound to SSH from the operator's IPs only.
|
||||||
```
|
|
||||||
deploy/nixos/
|
|
||||||
├── flake.nix # Nix flake entry point
|
|
||||||
├── configuration.nix # Base system configuration
|
|
||||||
├── lamassu-atm.nix # ATM service module
|
|
||||||
├── hardware/
|
|
||||||
│ └── upboard.nix # UP Board hardware config
|
|
||||||
├── udev/
|
|
||||||
│ └── 99-lamassu-hardware.rules # Hardware device rules
|
|
||||||
└── README.md # This file
|
|
||||||
```
|
|
||||||
|
|
||||||
## Troubleshooting
|
|
||||||
|
|
||||||
### Check ATM service status
|
|
||||||
|
|
||||||
```bash
|
|
||||||
sudo systemctl status lamassu-atm
|
|
||||||
sudo journalctl -u lamassu-atm -f
|
|
||||||
```
|
|
||||||
|
|
||||||
### Check hardware detection
|
|
||||||
|
|
||||||
```bash
|
|
||||||
# List serial devices
|
|
||||||
ls -la /dev/ttyUSB* /dev/ttyACM*
|
|
||||||
|
|
||||||
# Check for bill validator symlink
|
|
||||||
ls -la /dev/bill-validator
|
|
||||||
|
|
||||||
# Test camera
|
|
||||||
v4l2-ctl --list-devices
|
|
||||||
```
|
|
||||||
|
|
||||||
### Manual service control
|
|
||||||
|
|
||||||
```bash
|
|
||||||
sudo systemctl restart lamassu-atm
|
|
||||||
sudo systemctl stop lamassu-atm
|
|
||||||
```
|
|
||||||
|
|
||||||
### Debug mode
|
|
||||||
|
|
||||||
```bash
|
|
||||||
# Run manually with verbose output
|
|
||||||
sudo -u lamassu DISPLAY=:0 LOG_LEVEL=debug electron /opt/lamassu-atm
|
|
||||||
```
|
|
||||||
|
|
||||||
## Updating
|
|
||||||
|
|
||||||
### Update system
|
|
||||||
|
|
||||||
```bash
|
|
||||||
sudo nixos-rebuild switch --flake /etc/nixos#lamassu-atm
|
|
||||||
```
|
|
||||||
|
|
||||||
### Update ATM application
|
|
||||||
|
|
||||||
```bash
|
|
||||||
# Build new version
|
|
||||||
cd bitSpire/apps/machine
|
|
||||||
pnpm run build
|
|
||||||
|
|
||||||
# Copy to ATM
|
|
||||||
scp -r dist/* lamassu@<atm-ip>:/opt/lamassu-atm/
|
|
||||||
|
|
||||||
# Restart service
|
|
||||||
ssh lamassu@<atm-ip> "sudo systemctl restart lamassu-atm"
|
|
||||||
```
|
|
||||||
|
|
||||||
## Development vs Production
|
|
||||||
|
|
||||||
For development/testing, you can use the regtest docker environment:
|
|
||||||
|
|
||||||
```bash
|
|
||||||
cd bitSpire
|
|
||||||
./docker/dev.sh up --fund
|
|
||||||
./docker/dev.sh atm
|
|
||||||
```
|
|
||||||
|
|
||||||
For production, deploy this NixOS configuration and point to your production Nostr relay and Lightning.Pub instance.
|
|
||||||
|
|
||||||
## Security Notes
|
|
||||||
|
|
||||||
- The default `lamassu` user has `wheel` access for initial setup
|
|
||||||
- Remove wheel access after configuration: `sudo gpasswd -d lamassu wheel`
|
|
||||||
- SSH is enabled by default - configure key-based auth and disable password auth
|
|
||||||
- Firewall blocks all incoming connections by default
|
|
||||||
|
|
|
||||||
|
|
@ -1,5 +1,28 @@
|
||||||
# CLINK Protocol
|
# CLINK Protocol
|
||||||
|
|
||||||
|
> **Status on the `dev` branch: dormant.** The `@bitSpire/clink` package
|
||||||
|
> is still in the workspace, but `apps/machine/src/services/lightning.ts`
|
||||||
|
> no longer wires its offer/debit/management handlers — those were
|
||||||
|
> Lightning.Pub-paired and were removed when the backend switched to
|
||||||
|
> LNbits over the nostr-native-transport. The cash-out flow on dev uses
|
||||||
|
> BOLT11 + `subscribe_payments({payment_hash})`; the cash-in flow uses
|
||||||
|
> LNURL-withdraw + `subscribe_payments({tag, link_id})`. Both subsume
|
||||||
|
> CLINK's role for the ATM use case.
|
||||||
|
>
|
||||||
|
> This doc remains as the **protocol reference** — the wire format,
|
||||||
|
> event kinds, and encoding conventions are unchanged from the upstream
|
||||||
|
> [CLINK spec](https://github.com/shocknet/clink). Read it if you want
|
||||||
|
> to understand what kinds 21001-21003 mean, or if you're considering
|
||||||
|
> re-introducing CLINK flows on dev (e.g., a nostr-native cash-in path
|
||||||
|
> that doesn't go through LNURL).
|
||||||
|
>
|
||||||
|
> The `kind-21003` management surface (operator commands like "manual
|
||||||
|
> dispense") is the one piece of CLINK still actively wired on dev —
|
||||||
|
> `clink.onManagement` listens for those events and they have no LP
|
||||||
|
> dependency, so they survived the migration.
|
||||||
|
|
||||||
|
---
|
||||||
|
|
||||||
CLINK (Custodial Lightning Keys) is a Nostr-based protocol for Lightning payments. It enables wallets and services to communicate payment requests and authorizations through Nostr relays.
|
CLINK (Custodial Lightning Keys) is a Nostr-based protocol for Lightning payments. It enables wallets and services to communicate payment requests and authorizations through Nostr relays.
|
||||||
|
|
||||||
## Overview
|
## Overview
|
||||||
|
|
|
||||||
|
|
@ -1,5 +1,24 @@
|
||||||
# NDebit Cash-In Flow Implementation Guide
|
# NDebit Cash-In Flow Implementation Guide
|
||||||
|
|
||||||
|
> **Historical reference — NOT the cash-in flow on the `dev` branch.**
|
||||||
|
>
|
||||||
|
> Cash-in on `dev` is **LNURL-withdraw + LNbits `subscribe_payments({tag:"withdraw", link_id})` push**, implemented in
|
||||||
|
> `apps/machine/src/services/lightning.ts → generateLnurlWithdraw()`.
|
||||||
|
> The ATM no longer renders ndebit URIs; `CashInView.vue` ignores
|
||||||
|
> `generateNdebit`'s output and shows the LNURL QR instead. The CLINK
|
||||||
|
> debit-approval listener and all kind-21002 handling were removed in
|
||||||
|
> commit `3c14eea` (the 3b.4 cleanup of LP-paired infrastructure).
|
||||||
|
>
|
||||||
|
> This doc is retained because it explains *why* the previous flow
|
||||||
|
> existed and what the ndebit/CLINK protocol surface looks like — useful
|
||||||
|
> if the project ever wants to reintroduce nostr-native cash-in that
|
||||||
|
> bypasses LNURL. The protocol itself (kinds 21001-21003) is unchanged;
|
||||||
|
> only our wiring of it has been removed. The `@bitSpire/clink` package
|
||||||
|
> still ships the encode/decode helpers if a future implementation needs
|
||||||
|
> them.
|
||||||
|
|
||||||
|
---
|
||||||
|
|
||||||
This document describes how to implement the ndebit scanning flow for ATM cash-in, where a user scans an ndebit QR code from an ATM to withdraw sats to their wallet.
|
This document describes how to implement the ndebit scanning flow for ATM cash-in, where a user scans an ndebit QR code from an ATM to withdraw sats to their wallet.
|
||||||
|
|
||||||
## Overview
|
## Overview
|
||||||
|
|
|
||||||
Loading…
Add table
Add a link
Reference in a new issue