wip(rpi4): park the Pi 4 sketch — superseded by the Pi 5 machinery in #87
Never-committed working tree state found in the dev worktree: a Pi 4 hardware module, a setup walkthrough, an upboard-serial refactor, and flake wiring that does not evaluate (aarch64 packages block nested inside packages.x86_64-linux; pkgs-aarch64 built with `inherit aarch64` instead of `system`, so it is really x86; references a nixosConfigurations.rpi4-installed that is never defined). Parked verbatim for reference. The real Pi 4 target is rebuilt on top of #87's mkPiInstalled/mkPiImage shape in feat/rpi4-target. Co-Authored-By: Claude Opus 5 <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_013A6683cCHnQxFUosx1krY4
This commit is contained in:
parent
cb236703d6
commit
7e59951fcc
7 changed files with 533 additions and 4 deletions
|
|
@ -14,7 +14,8 @@ deploy/nixos/
|
|||
├── hardware/
|
||||
│ ├── douro.nix # Dell OptiPlex 9030 AIO (stock Douro motherboard; SATA SSD, eGalax touch)
|
||||
│ ├── batm3.nix # GeneralBytes BATM3 chassis with a Dell OptiPlex 9030 AIO grafted in (custom mod; WireGuard wired in)
|
||||
│ └── upboard.nix # Aaeon UP Board (Sintra + tejo; eMMC root via sdhci-acpi + mmc_block)
|
||||
│ ├── upboard.nix # Aaeon UP Board (Sintra + tejo; eMMC root via sdhci-acpi + mmc_block)
|
||||
│ └── raspberry-pi4.nix # Raspberry Pi 4 (aarch64) hardware configuration
|
||||
├── udev/
|
||||
│ └── 99-bitspire-hardware.rules # additional udev rules (loaded via configuration.nix)
|
||||
├── provision-atm.sh # Push LNbits credentials to a deployed ATM via SSH
|
||||
|
|
@ -34,7 +35,7 @@ Each ATM model has two flake outputs:
|
|||
| `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`.
|
||||
Models: `douro`, `tejo`, `sintra`, `batm3`, `rpi4`.
|
||||
|
||||
```bash
|
||||
# Build a Sintra disk image
|
||||
|
|
@ -43,11 +44,111 @@ nix build .#disk-image-sintra
|
|||
|
||||
# Build a live ISO for tejo
|
||||
nix build .#iso-tejo
|
||||
|
||||
# Build a Raspberry Pi 4 disk image (aarch64)
|
||||
nix build .#disk-image-rpi4
|
||||
# → result/nixos.img (Raspberry Pi firmware bootloader, GPT+ESP)
|
||||
```
|
||||
|
||||
## Deploying to Sintra (full walkthrough)
|
||||
|
||||
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.
|
||||
|
||||
## Deploying to Raspberry Pi 4 (full walkthrough)
|
||||
|
||||
The Raspberry Pi 4 uses an SD card as primary storage and boots via the Raspberry Pi firmware bootloader (rpi-bootloader). Unlike Intel-based ATMs that use systemd-boot, the RPi4 config uses the native Raspberry Pi bootloader.
|
||||
|
||||
### Prerequisites
|
||||
|
||||
- Raspberry Pi 4 board (4GB or 8GB RAM recommended for Electron)
|
||||
- 32GB+ SD card (or external SSD for better reliability)
|
||||
- Network connection (ethernet recommended for stability)
|
||||
- SSH access or a serial console (UART) for first-boot provisioning
|
||||
|
||||
### Build the disk image
|
||||
|
||||
```bash
|
||||
nix build .#disk-image-rpi4
|
||||
# → result/nixos.img (raw disk image, aarch64)
|
||||
```
|
||||
|
||||
### Flash to SD card
|
||||
|
||||
```bash
|
||||
# Replace /dev/sdX with your SD card device
|
||||
sudo dd if=result/nixos.img of=/dev/sdX bs=4M status=progress conv=fsync && sync
|
||||
```
|
||||
|
||||
**Important:** Verify the target is the SD card, not your main disk:
|
||||
```bash
|
||||
lsblk -f /dev/sdX
|
||||
# Should show 'SD_CARD' or similar, not a hard drive name
|
||||
```
|
||||
|
||||
### Boot and provision
|
||||
|
||||
1. Insert the SD card into the Raspberry Pi 4.
|
||||
2. Connect Ethernet and power on.
|
||||
3. Wait for boot (you should see Raspberry Pi firmware loading messages).
|
||||
4. The kiosk screen should show "ATM unavailable — needs provisioning".
|
||||
|
||||
From your dev box, provision LNbits credentials:
|
||||
|
||||
```bash
|
||||
LNBITS_SERVER_PUBKEY=$(docker logs <lnbits-container> 2>&1 | \
|
||||
grep -oP 'Public key \(share this\):\s*\K[a-f0-9]{64}' | tail -1)
|
||||
|
||||
RELAY_URL=ws://<dev-lan-ip>:5001/nostrrelay/test \
|
||||
LNBITS_SERVER_PUBKEY="$LNBITS_SERVER_PUBKEY" \
|
||||
ATM_PRIVATE_KEY=$(openssl rand -hex 32) \
|
||||
bash deploy/nixos/provision-atm.sh <rpi4-ip> 22
|
||||
```
|
||||
|
||||
The script SSHes to `bitspire@<rpi4-ip>:22`, writes `/var/lib/bitspire/.env`, and restarts `bitspire.service`. After a few seconds the kiosk connects to LNbits over nostr-transport and shows the live UI.
|
||||
|
||||
### First-time deploy
|
||||
|
||||
**Save the generated `ATM_PRIVATE_KEY`.** LNbits identifies this ATM by its public key; if you regenerate the key on re-provision, LNbits will auto-create a fresh wallet and the old wallet's balance becomes inaccessible.
|
||||
|
||||
### Re-flash
|
||||
|
||||
To preserve the ATM's identity and transaction history, backup the `.env` and `state.db` from the running Raspberry Pi before reflashing:
|
||||
|
||||
```bash
|
||||
# From the Raspberry Pi
|
||||
mkdir -p ~/rpi4-backup-$(date +%Y%m%d)
|
||||
cp /var/lib/bitspire/.env ~/rpi4-backup-$(date +%Y%m%d)/
|
||||
cp /var/lib/bitspire/state.db ~/rpi4-backup-$(date +%Y%m%d)/
|
||||
|
||||
# Copy to dev box
|
||||
scp bitspire@<rpi4-ip>:~/rpi4-backup-*/.env ~/rpi4-backup-*/
|
||||
scp bitspire@<rpi4-ip>:~/rpi4-backup-*/state.db ~/rpi4-backup-*/
|
||||
```
|
||||
|
||||
On re-flash, source the backup values:
|
||||
|
||||
```bash
|
||||
set -a; source ~/rpi4-backup-<date>/.env; set +a
|
||||
ATM_PRIVATE_KEY=$VITE_ATM_PRIVATE_KEY \
|
||||
LNBITS_SERVER_PUBKEY=$VITE_LNBITS_SERVER_PUBKEY \
|
||||
RELAY_URL=$VITE_RELAY_URL \
|
||||
bash deploy/nixos/provision-atm.sh <rpi4-ip> 22
|
||||
```
|
||||
|
||||
### Hardware-specific notes
|
||||
|
||||
- **Storage:** SD cards are slower and have limited write cycles compared to SSDs. Consider using a high-quality card and avoid frequent rewrites. For production, an external SSD via USB 3.0 is recommended for better reliability.
|
||||
- **Power:** The Raspberry Pi 4 can draw up to 3A at 5V. Use a reliable power supply rated for at least 5V 3A.
|
||||
- **Thermal:** The Pi 4 runs warm. Ensure adequate cooling (passive heatsinks or a fan) for 24/7 operation.
|
||||
- **Console:** The serial console is available at `/dev/ttyAMA0` (PL011 UART) at 115200 baud, useful for debugging.
|
||||
- **Swap:** A 2GB swapfile is enabled by default to prevent hard-freeze under memory pressure. Consider increasing this on 4GB models.
|
||||
|
||||
### Troubleshooting
|
||||
|
||||
- **Boot fails:** Check the SD card is properly flashed and inserted. Try rebuilding the image with a fresh `nix build .#disk-image-rpi4`.
|
||||
- **No network:** Verify the Ethernet cable is connected and the Pi's lights show activity. Check `/etc/resolv.conf` after boot.
|
||||
- **ATM doesn't connect to LNbits:** Verify `VITE_RELAY_URL` and `VITE_LNBITS_SERVER_PUBKEY` are set in `/var/lib/bitspire/.env` via SSH: `ssh bitspire@<rpi4-ip> 'cat /var/lib/bitspire/.env'`.
|
||||
- **Electron fails to start:** Check memory usage (`free -h`). On 4GB models, close other processes to free up RAM. You need an Alpine live USB to act as your installer.
|
||||
|
||||
### 0. (Re-flash only) Preserve state from the existing Sintra
|
||||
|
||||
|
|
|
|||
124
deploy/nixos/hardware/raspberry-pi4.nix
Normal file
124
deploy/nixos/hardware/raspberry-pi4.nix
Normal file
|
|
@ -0,0 +1,124 @@
|
|||
# Raspberry Pi 4 Hardware Configuration
|
||||
# For bitSpire deployments on Raspberry Pi 4
|
||||
# Requires: 4GB+ RAM (8GB recommended for Electron + kiosk)
|
||||
# Storage: SD card or external SSD/eMMC (minimum 32GB)
|
||||
#
|
||||
# Note: Import shared serial peripheral configuration for consistency
|
||||
# with other bitSpire hardware (useful for future extensions).
|
||||
|
||||
{ config, lib, pkgs, ... }:
|
||||
|
||||
{
|
||||
# Import shared serial peripheral configuration (useful for future hardware extensions)
|
||||
imports = [ ./upboard-serial.nix ];
|
||||
|
||||
# Raspberry Pi 4 uses aarch64 architecture
|
||||
boot.kernelPackages = pkgs.linuxPackages_rpi4;
|
||||
|
||||
boot = {
|
||||
loader = {
|
||||
# Raspberry Pi 4 uses the Raspberry Pi firmware bootloader (rpi-bootloader)
|
||||
grub.enable = lib.mkForce false;
|
||||
# raspberryPi.enable has been removed in recent nixpkgs
|
||||
# rpi-bootloader is now built into rpi4 kernel packages
|
||||
};
|
||||
|
||||
initrd.availableKernelModules = [
|
||||
"xhci_pci"
|
||||
"usb_storage"
|
||||
"sdhci_pci"
|
||||
"sdhci"
|
||||
"sd_mod"
|
||||
"brcmmac"
|
||||
"brcmfmac"
|
||||
"mmc_block"
|
||||
"cma"
|
||||
];
|
||||
|
||||
initrd.kernelModules = [
|
||||
"sdhci_pci"
|
||||
"sdhci"
|
||||
"mmc_block"
|
||||
"brcmmac"
|
||||
"brcmfmac"
|
||||
"cma"
|
||||
];
|
||||
|
||||
kernelModules = [
|
||||
"kvm-arm"
|
||||
"uas"
|
||||
];
|
||||
|
||||
kernelParams = [
|
||||
"console=tty1"
|
||||
"console=ttyAMA0,115200n8"
|
||||
"console=ttyS0,115200n8"
|
||||
"root=/dev/mmcblk0p2"
|
||||
"rootfstype=ext4"
|
||||
"rootwait"
|
||||
"rw"
|
||||
# Disable PCIe to save power (optional - uncomment if needed)
|
||||
# "pcie_aspm=off"
|
||||
];
|
||||
};
|
||||
|
||||
# Filesystem layout: SD card with GPT partition table
|
||||
# Partition 1: EFI System Partition (FAT32)
|
||||
# Partition 2: Root filesystem (ext4)
|
||||
fileSystems."/" = {
|
||||
device = "/dev/disk/by-label/nixos";
|
||||
fsType = "ext4";
|
||||
options = [ "noatime" ];
|
||||
};
|
||||
|
||||
fileSystems."/boot" = {
|
||||
device = "/dev/disk/by-label/ESP";
|
||||
fsType = "vfat";
|
||||
options = [ "defaults" "nofail" ];
|
||||
};
|
||||
|
||||
# Swap configuration for better reliability on SD cards
|
||||
swapDevices = [{
|
||||
device = "/swapfile";
|
||||
size = 2048; # 2GB swap
|
||||
}];
|
||||
|
||||
# Power management for Raspberry Pi
|
||||
powerManagement = {
|
||||
enable = true;
|
||||
cpuFreqGovernor = "ondemand";
|
||||
};
|
||||
|
||||
# Disable suspend/hibernate for kiosk stability
|
||||
systemd.targets = {
|
||||
sleep.enable = false;
|
||||
suspend.enable = false;
|
||||
hibernate.enable = false;
|
||||
hybrid-sleep.enable = false;
|
||||
};
|
||||
|
||||
# Hardware-specific settings
|
||||
hardware = {
|
||||
# Raspberry Pi 4 has no discrete GPU (uses VideoCore)
|
||||
graphics = {
|
||||
enable = true;
|
||||
};
|
||||
|
||||
# USB mass storage drivers (not applicable for ARM - handled by kernel modules)
|
||||
# usb.enable = true;
|
||||
# usb.enableUSBHub = true;
|
||||
|
||||
# RPi4-specific tweaks
|
||||
enableRedistributableFirmware = true;
|
||||
# CPU firmware (not applicable for ARM - no x86 microcode)
|
||||
# cpu.amd64.updateMicrocode = false; # Not applicable for ARM
|
||||
};
|
||||
|
||||
# USB configuration (not applicable for ARM)
|
||||
# hardware.usb.enable = true;
|
||||
# hardware.usb.enableUSBHub = true;
|
||||
|
||||
# Network configuration
|
||||
# useDHCP is set in configuration.nix (base config)
|
||||
networking.interfaces.eth0.useDHCP = true;
|
||||
}
|
||||
32
deploy/nixos/upboard-serial.nix
Normal file
32
deploy/nixos/upboard-serial.nix
Normal file
|
|
@ -0,0 +1,32 @@
|
|||
# Shared serial peripheral configuration for UP Board hardware
|
||||
# (Sintra, tejo, and any other systems with similar UART layout)
|
||||
#
|
||||
# Serial ports used by bitSpire ATM:
|
||||
# ttyJ4 = Printer (Nippon NP-2511D-2) - optional on some configs
|
||||
# ttyJ5 = Validator (iVizion, ID003 protocol)
|
||||
# ttyJ7 = Dispenser (Fujitsu F53/F56)
|
||||
#
|
||||
# These symlinks + udev rules are shared between live.nix (for testing)
|
||||
# and hardware-specific modules (upboard.nix, douro.nix).
|
||||
|
||||
{ config, lib, pkgs, ... }:
|
||||
|
||||
{
|
||||
# Serial peripheral symlinks
|
||||
services.udev.extraRules = ''
|
||||
# ── Validator (iVizion ID003) ─────────────────────────────────────
|
||||
# ttyJ5 on UP Board (FTDI USB bridge) → /dev/ttyJ5
|
||||
KERNEL=="ttyJ5", SYMLINK+="validator-device"
|
||||
SUBSYSTEM=="tty", GROUP="uucp", MODE="0666"
|
||||
|
||||
# ── Dispenser (Fujitsu F56) ───────────────────────────────────────
|
||||
# ttyJ7 on UP Board (SoC MMIO UART) → /dev/ttyJ7
|
||||
KERNEL=="ttyJ7", SYMLINK+="dispenser-device"
|
||||
SUBSYSTEM=="tty", GROUP="uucp", MODE="0666"
|
||||
|
||||
# ── Printer (Nippon NP-2511D-2) ───────────────────────────────────
|
||||
# ttyJ4 on UP Board (optional - not all configs use it)
|
||||
KERNEL=="ttyJ4", SYMLINK+="printer-device", OPTIONS+="static_node=ttyJ4"
|
||||
SUBSYSTEM=="tty", GROUP="uucp", MODE="0666"
|
||||
'';
|
||||
}
|
||||
Loading…
Add table
Add a link
Reference in a new issue