From 7e59951fcc45c91167123dd7f9cef2717781b50c Mon Sep 17 00:00:00 2001 From: Padreug Date: Sun, 20 Sep 2026 11:17:41 +0200 Subject: [PATCH] =?UTF-8?q?wip(rpi4):=20park=20the=20Pi=204=20sketch=20?= =?UTF-8?q?=E2=80=94=20superseded=20by=20the=20Pi=205=20machinery=20in=20#?= =?UTF-8?q?87?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit 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 Claude-Session: https://claude.ai/code/session_013A6683cCHnQxFUosx1krY4 --- .envrc | 1 + deploy/nixos/README.md | 107 ++++++++++- deploy/nixos/hardware/raspberry-pi4.nix | 124 +++++++++++++ deploy/nixos/upboard-serial.nix | 32 ++++ docs/raspberry-pi4-setup.md | 225 ++++++++++++++++++++++++ flake.lock | 17 ++ flake.nix | 31 +++- 7 files changed, 533 insertions(+), 4 deletions(-) create mode 100644 .envrc create mode 100644 deploy/nixos/hardware/raspberry-pi4.nix create mode 100644 deploy/nixos/upboard-serial.nix create mode 100644 docs/raspberry-pi4-setup.md diff --git a/.envrc b/.envrc new file mode 100644 index 0000000..3550a30 --- /dev/null +++ b/.envrc @@ -0,0 +1 @@ +use flake diff --git a/deploy/nixos/README.md b/deploy/nixos/README.md index 2bfc333..2bce12f 100644 --- a/deploy/nixos/README.md +++ b/deploy/nixos/README.md @@ -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-` | ISO | ISO image of the live variant | | `packages.x86_64-linux.disk-image-` | 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 2>&1 | \ + grep -oP 'Public key \(share this\):\s*\K[a-f0-9]{64}' | tail -1) + +RELAY_URL=ws://:5001/nostrrelay/test \ +LNBITS_SERVER_PUBKEY="$LNBITS_SERVER_PUBKEY" \ +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 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-backup-*/.env ~/rpi4-backup-*/ +scp bitspire@:~/rpi4-backup-*/state.db ~/rpi4-backup-*/ +``` + +On re-flash, source the backup values: + +```bash +set -a; source ~/rpi4-backup-/.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 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@ '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 diff --git a/deploy/nixos/hardware/raspberry-pi4.nix b/deploy/nixos/hardware/raspberry-pi4.nix new file mode 100644 index 0000000..2a381d9 --- /dev/null +++ b/deploy/nixos/hardware/raspberry-pi4.nix @@ -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; +} diff --git a/deploy/nixos/upboard-serial.nix b/deploy/nixos/upboard-serial.nix new file mode 100644 index 0000000..46b2274 --- /dev/null +++ b/deploy/nixos/upboard-serial.nix @@ -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" + ''; +} diff --git a/docs/raspberry-pi4-setup.md b/docs/raspberry-pi4-setup.md new file mode 100644 index 0000000..cb909f5 --- /dev/null +++ b/docs/raspberry-pi4-setup.md @@ -0,0 +1,225 @@ +# Raspberry Pi 4 bitSpire Setup Guide + +This document describes how to build and deploy bitSpire to a Raspberry Pi 4. + +## Hardware Requirements + +- **Board**: Raspberry Pi 4 (4GB or 8GB RAM recommended for Electron) +- **Storage**: 32GB+ SD card (or external SSD via USB for better reliability) +- **Power**: 5V 3A+ power supply (Pi 4 can draw up to 3A at 5V) +- **Cooling**: Passive heatsinks or active fan for 24/7 operation +- **Network**: Ethernet connection recommended for stability + +## Building the Disk Image + +```bash +cd /home/padreug/dev/bitspire/bitspire/dev + +# Build the Raspberry Pi 4 disk image (aarch64) +nix build .#disk-image-rpi4 + +# The image will be at: result/nixos.img +``` + +## Flashing to SD Card + +```bash +# Replace /dev/sdX with your SD card device (NOT your main disk!) +# Verify first: lsblk -f /dev/sdX + +sudo dd if=result/nixos.img of=/dev/sdX bs=4M status=progress conv=fsync && sync + +# Sync to ensure all writes are flushed +sync +``` + +**Important**: Always verify the target device before flashing! + +## First-Time Deployment + +### 1. Boot the Raspberry Pi 4 + +1. Insert the SD card into the Raspberry Pi 4. +2. Connect Ethernet cable. +3. Power on the device. +4. You should see Raspberry Pi firmware boot messages. +5. The kiosk screen shows "ATM unavailable — needs provisioning". + +### 2. Provision LNbits Credentials + +From your development machine: + +```bash +LNBITS_SERVER_PUBKEY=$(docker logs 2>&1 | \ + grep -oP 'Public key \(share this\):\s*\K[a-f0-9]{64}' | tail -1) + +RELAY_URL=ws://:5001/nostrrelay/test \ +LNBITS_SERVER_PUBKEY="$LNBITS_SERVER_PUBKEY" \ +ATM_PRIVATE_KEY=$(openssl rand -hex 32) \ +bash deploy/nixos/provision-atm.sh 22 +``` + +**Important**: Save the generated `ATM_PRIVATE_KEY` — it's required to preserve the ATM's identity and wallet balance. + +### 3. Verify Connection + +After provisioning completes: + +```bash +ssh bitspire@ 'cat /var/lib/bitspire/.env' +``` + +You should see the environment variables are set correctly. The kiosk should connect to LNbits over nostr-transport and show the live UI after a few seconds. + +## Re-Flashing (Preserving Identity) + +To preserve the ATM's identity and transaction history when reflashing: + +1. **Backup from the running Raspberry Pi**: + +```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)/ +``` + +2. **Copy backups to dev box**: + +```bash +scp bitspire@:~/rpi4-backup-*/.env ~/rpi4-backup-*/ +scp bitspire@:~/rpi4-backup-*/state.db ~/rpi4-backup-*/ +``` + +3. **Re-flash the SD card**: + +```bash +nix build .#disk-image-rpi4 +sudo dd if=result/nixos.img of=/dev/sdX bs=4M status=progress conv=fsync && sync +``` + +4. **Re-provision from backups**: + +```bash +set -a; source ~/rpi4-backup-/.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 22 +``` + +## Hardware-Specific Notes + +### Storage +- **SD cards** are slower and have limited write cycles. For production, consider an external SSD via USB 3.0 for better reliability. +- Use high-quality SD cards with good endurance ratings. +- Avoid frequent rewrites to the same sectors. + +### Power +- The Raspberry Pi 4 can draw up to 3A at 5V during heavy load (Electron startup). +- Use a reliable power supply rated for at least 5V 3A. +- Avoid using USB hubs that don't provide sufficient power. + +### Thermal +- The Pi 4 runs warm, especially under load with Electron. +- Ensure adequate cooling for 24/7 operation: + - Passive heatsinks on the SoC and RAM + - Or a small active fan blowing air over the board +- Consider removing the metal case for better airflow in hot environments. + +### Console +- The serial console is available at `/dev/ttyAMA0` (PL011 UART) at 115200 baud. +- Useful for debugging boot issues. +- Not required for normal operation. + +### Swap +- A 2GB swapfile is enabled by default to prevent hard-freeze under memory pressure. +- Consider increasing this on 4GB models if you expect heavy load. + +## Troubleshooting + +### Boot fails + +**Symptoms**: Pi doesn't boot or shows errors. + +**Solutions**: +1. Verify SD card is properly flashed: + ```bash + lsblk -f /dev/sdX + # Should show GPT partition table with ESP and nixos partitions + ``` +2. Try rebuilding the image: + ```bash + nix build .#disk-image-rpi4 + ``` +3. Check power supply and connections. + +### No network connectivity + +**Symptoms**: Cannot SSH to the Pi or connect to LAN. + +**Solutions**: +1. Verify Ethernet cable is connected and the Pi's lights show activity. +2. Check `/etc/resolv.conf` after boot: + ```bash + ssh bitspire@ 'cat /etc/resolv.conf' + ``` +3. Check network interface status: + ```bash + ssh bitspire@ 'ip a' + ``` + +### ATM doesn't connect to LNbits + +**Symptoms**: Kiosk shows "ATM unavailable" or no connection. + +**Solutions**: +1. Verify environment variables are set: + ```bash + ssh bitspire@ 'cat /var/lib/bitspire/.env' + ``` +2. Check for typos in `VITE_RELAY_URL` and `VITE_LNBITS_SERVER_PUBKEY`. +3. Verify LNbits is running and accessible: + ```bash + curl /api/v1/settings + ``` +4. Check ATM service logs: + ```bash + ssh bitspire@ 'sudo journalctl -u bitspire -n 50' + ``` + +### Electron fails to start + +**Symptoms**: Service logs show Electron crash or OOM (out of memory). + +**Solutions**: +1. Check memory usage: + ```bash + ssh bitspire@ 'free -h' + ``` +2. On 4GB models, close other processes to free up RAM. +3. Consider increasing the swapfile size in `/var/lib/bitspire/.env`. + +## Building Live ISO for Testing + +To build a live USB bootable ISO for testing (without installing): + +```bash +nix build .#iso-rpi4 + +# The ISO will be at: result/*.iso +``` + +## Configuration Files + +- **Hardware config**: `deploy/nixos/hardware/raspberry-pi4.nix` +- **Base config**: `deploy/nixos/configuration.nix` +- **Service module**: `deploy/nixos/bitspire-atm.nix` +- **Provisioning script**: `deploy/nixos/provision-atm.sh` + +## References + +- [NixOS on Raspberry Pi](https://nixos.org/manual/nixos/stable/index.html#sec-architecture-raspberry-pi) +- [bitSpire README](../README.md) +- [NixOS Hardware Configuration](https://nixos.org/manual/nixos/stable/index.html#ch-configuring-hardware) diff --git a/flake.lock b/flake.lock index 7ea214a..9bd3e3d 100644 --- a/flake.lock +++ b/flake.lock @@ -435,6 +435,22 @@ "type": "github" } }, + "nixpkgs-aarch64": { + "locked": { + "lastModified": 1782847189, + "narHash": "sha256-twXPFqFsrrY5r28Zh7Homgcp2gUMBgQ6WDS98Q/3xFI=", + "owner": "NixOS", + "repo": "nixpkgs", + "rev": "b6018f87da91d19d0ab4cf979885689b469cdd41", + "type": "github" + }, + "original": { + "owner": "NixOS", + "ref": "nixos-25.11", + "repo": "nixpkgs", + "type": "github" + } + }, "nixpkgs-regression": { "locked": { "lastModified": 1643052045, @@ -504,6 +520,7 @@ "devenv": "devenv", "flake-utils": "flake-utils", "nixpkgs": "nixpkgs_3", + "nixpkgs-aarch64": "nixpkgs-aarch64", "nixpkgs-unstable": "nixpkgs-unstable", "rust-overlay": "rust-overlay" } diff --git a/flake.nix b/flake.nix index 194ca55..b012a0b 100644 --- a/flake.nix +++ b/flake.nix @@ -5,6 +5,9 @@ # Stable NixOS for the ATM OS base nixpkgs.url = "github:NixOS/nixpkgs/nixos-25.11"; + # Stable NixOS for the ATM OS base (aarch64) — Raspberry Pi 4 + nixpkgs-aarch64.url = "github:NixOS/nixpkgs/nixos-25.11"; + # Unstable for Electron, Node.js, pnpm (latest versions) nixpkgs-unstable.url = "github:NixOS/nixpkgs/nixpkgs-unstable"; @@ -38,15 +41,22 @@ }; }; - outputs = { self, nixpkgs, nixpkgs-unstable, flake-utils, rust-overlay, devenv, determinate, atm-tui }: + outputs = { self, nixpkgs, nixpkgs-unstable, nixpkgs-aarch64, flake-utils, rust-overlay, devenv, determinate, atm-tui }: let system = "x86_64-linux"; + aarch64 = "aarch64-linux"; + pkgs = import nixpkgs { inherit system; config.allowUnfree = true; }; + pkgs-aarch64 = import nixpkgs-aarch64 { + inherit aarch64; + config.allowUnfree = true; + }; + pkgs-unstable = import nixpkgs-unstable { inherit system; config.allowUnfree = true; @@ -504,6 +514,25 @@ ''; # Backwards compat + + # aarch64-linux packages (Raspberry Pi 4) + packages.${aarch64} = { + # ATM app derivation for Raspberry Pi 4 + atm-app-rpi4 = mkAtmApp { model = "rpi4"; fiatCode = "USD"; }; + + # Raspberry Pi 4 disk image (aarch64) + # Note: Raspberry Pi 4 uses the Raspberry Pi firmware bootloader, + # not systemd-boot. The image is built for aarch64 and booted via + # the rpi-bootloader (rpi-firmware). Requires an SD card with GPT + # partition table (ESP + ext4 root). + disk-image-rpi4 = import (nixpkgs-aarch64 + "/nixos/lib/make-disk-image.nix") { + pkgs = pkgs-aarch64; inherit lib; + config = self.nixosConfigurations.rpi4-installed.config; + format = "raw"; + partitionTableType = "efi"; + diskSize = "auto"; + }; + }; iso = self.nixosConfigurations.douro.config.system.build.isoImage; }; }