Build a Raspberry/Pi QR vault

draft

This guide takes you from “I have a Pi Zero kit” to “the device returned a signed fixture event the companion verified”. It tracks the prototype build — the device is not ready for production secrets yet.

Prerequisites

  • A Linux/macOS workstation with git, python3, make.
  • A microSD card writer.
  • About 30 minutes for first-time setup.

Bill of materials

Follows the Raspberry/Pi kit requirements in nSealr/hardware. For one device:

PartNotes
Pi Zero-class boardPi Zero W is fine — wireless is disabled by the OS profile.
Pi/ZeroCam OV5647 camera + ribbonThe camera that fits the Pi Zero connector.
Waveshare-compatible ST7789 240×240 LCD HATThe trusted display.
GPIO joystick / buttonsFive-way joystick + side buttons, per the validated GPIO map.
Removable microSDClass 10, ≥ 8 GB. Removability matters — see the OS profile.
USB power sourceAny 5V/2A. Battery pack works for air-gapped use.

Other Pi variants (3/4/5) can be development or accessibility targets later if they preserve the same offline-QR, local-review, physical-approval, RAM-only-custody boundary.

OS profile

Follow the Raspberry/Pi OS profile in nSealr/hardware:

  • Removable boot media (microSD).
  • Wireless disabled or absent at the firmware level.
  • RAM-only session custody — no persistent signing-secret storage.
  • No swap during signing.
  • No remote access during signing.

The profile ships as a minimal SeedSigner-OS-inspired image. Flash it to the microSD with dd or the imager of your choice.

Build the software

The Raspberry/Pi-side software lives in nSealr/raspberry.

git clone https://github.com/nSealr/raspberry
cd raspberry
make setup
make ci          # repo verification, tests, content lint

make ci is the sanity check after a clone — it runs the verifier, the unit tests, and the spec fixtures. If something fails here, fix it locally before touching hardware.

First boot

  1. Insert the flashed microSD into the Pi Zero.
  2. Connect the camera (camera-connector facing the board).
  3. Connect the ST7789 HAT.
  4. Connect the joystick / buttons per the GPIO map in nSealr/hardware.
  5. Power on. The display should show the boot splash and land on the idle screen within a few seconds.

If the display stays black, see Troubleshooting.

Sign a fixture event

With the device idle, run on your host workstation:

nsealr-rasp sign-fixture --request specs/vectors/requests/request-v0.json

Expected output (abridged):

↗ nsealr1:<base32-payload>
  (the device should scan this QR — point the camera at the screen,
   confirm on the display, press OK)
↘ nsealr1r:<base32-response>
✓ event id matches BIP-340 signature
✓ approval_digest matches reviewed material

The CLI computes the canonical NIP-01 event id, signs BIP-340 / secp256k1, and emits a nsealr1: QR response that the host verifies through the same signed-response-verification-v0 contract used by the companion.

Verify with the companion

nsealr verify-response --request request-v0.json --response response.json

If you see the same two lines, the device + companion handshake is intact.

Troubleshooting

SymptomLikely causeFix
Display stays blackWrong HAT pinout, or HAT not seatedReseat the HAT; verify it’s the ST7789 240×240 variant
Camera not detectedRibbon flipped, or camera not enabled in firmware configReseat ribbon (blue side facing the board); enable camera in config.txt
make ci failsToolchain mismatchmake setup re-pins versions; on macOS also xcode-select --install
Joystick presses ignoredGPIO map mismatchDouble-check the 40-pin map in nSealr/hardware; some kits use a different button arrangement
QR not decodedGlare on the host screenLower brightness on the host screen, or move the device 10–15cm away

Where to go next

Last updated 2026-05-20