Skip to content

SD-card image guide

Set up a Pantry Raider appliance on a Raspberry Pi in four steps: flash a stock Raspberry Pi OS Lite card, boot, SSH in, and run one install command. The installer asks what you want (full stack, or a thin remote) and provisions only that. No files to edit on your PC, nothing to clone on your PC.

New to the hardware side? See supported-hardware.md for boards, RAM guidance, and peripherals. For how a Pi install protects the SD card from power-loss corruption and which stack to run per board, see Pi reliability and memory tiers.

How it works

Pantry Raider runs on the official Raspberry Pi OS Lite (64-bit) image plus an on-device installer. You flash the stock OS, boot it, then run the installer over SSH. It detects the board, any attached display, and any attached Stream Deck, asks for the deployment mode and add-ons, then installs Docker and the containers (for a full host) or just the kiosk/Stream Deck (for a thin remote).

Tradeoff: the install needs internet and takes a few minutes the first time while it pulls Docker and the container images. After that the device is self-contained and boots fast. Staying on the official base image means you keep Raspberry Pi's security updates. (Maintainer/build details: scripts/image-build/README.md.)

What you need

  • A supported board: Raspberry Pi 4 or Pi 5 (ARM64) for a full host; a Pi 3 is fine for a thin remote (see "Hardware coverage" below).
  • A 16 GB+ SD card, 32 GB+ recommended. Use a high-endurance card (Samsung PRO Endurance, SanDisk High Endurance, or an industrial card), especially for a full host: Grocy and Mealie write to the card constantly, and a high-endurance card is rated for that where an ordinary card is not. It costs only a little more and is the single best-value way to keep a Pi appliance healthy. See Pi reliability for why.
  • Ethernet or Wi-Fi with internet.
  • Raspberry Pi Imager on your PC to flash the card.

Step 1: Flash Raspberry Pi OS Lite (64-bit)

  1. Install Raspberry Pi Imager.
  2. Choose Device: your Pi model. Choose OS: Raspberry Pi OS (other) → Raspberry Pi OS Lite (64-bit). Choose Storage: your card.
  3. Click the gear / Edit Settings and set:
  4. Hostname: pr (this becomes pr.local).
  5. Enable SSH (use a password or your public key); it is required for Step 3.
  6. Wi-Fi credentials (skip if using Ethernet).
  7. Locale / timezone.
  8. Write the image, then eject the card.

That is the only thing you do on your PC. Everything else happens on the Pi.

Step 2: Boot the Pi

Insert the card, connect the network (Ethernet or the Wi-Fi you configured), and power on. Give it a minute to come up on the network.

Step 3: SSH in and run the installer

From your PC, SSH to the Pi using the user and hostname you set in Imager:

ssh <user>@pr.local

If pr.local doesn't resolve, use the Pi's IP address (find it in your router, or it may print on an attached screen).

Then run the installer:

curl -fsSL https://raw.githubusercontent.com/Syracuse3DPrintingOrg/PantryRaider/main/install.sh | bash

The installer shows what it detected (board, display, Stream Deck) and asks one question:

  • Deployment mode
  • Pi Hosted: run the full Pantry Raider stack on this Pi (Pantry Raider + Grocy). Pick this for a normal appliance.
  • Pi Remote: thin client. Installs no Docker, Grocy, or Mealie; this device only drives a kiosk and/or Stream Deck pointed at a Pantry Raider server already running elsewhere on your LAN. Viable on a Pi 3. It asks for that server's URL.

The kiosk browser and Stream Deck controller are auto-enabled when the hardware is detected at install time, and Mealie (recipes, meal plans, shopping lists) installs by default on a hosted device (set ENABLE_MEALIE=false to skip it). Everything else (Ollama, display rotation, AI provider, password, Grocy key) is configured in the browser after the install completes.

When it finishes, the terminal prints the URL to open in your browser.

Non-interactive / scripted installs

The installer can run unattended by passing the choices as environment variables and setting NONINTERACTIVE=1:

curl -fsSL https://raw.githubusercontent.com/Syracuse3DPrintingOrg/PantryRaider/main/install.sh \
  | NONINTERACTIVE=1 DEPLOYMENT_MODE=pi_hosted ENABLE_MEALIE=true bash

Recognized variables: DEPLOYMENT_MODE (pi_hosted | pi_remote | server), REMOTE_SERVER_URL, ENABLE_MEALIE, ENABLE_OLLAMA, ENABLE_KIOSK, ENABLE_STREAMDECK, DISPLAY_ROTATION, PR_HOSTNAME, ENABLE_FB_SPLASH, ENABLE_BOOT_SPLASH. Anything left unset is auto-detected (kiosk/Stream Deck default to whether the hardware is attached).

A kiosk device shows the Pantry Raider mark on screen moments after power-on instead of scrolling boot text, then hands the display to the app when it is ready. This is on by default and completely fail-safe: if the screen cannot be painted for any reason, the device simply keeps its plain quiet boot. Set ENABLE_FB_SPLASH=false to turn it off.

ENABLE_BOOT_SPLASH=true additionally installs a Plymouth boot theme (an animated splash that starts even earlier in boot). It stays off by default while the on-screen handoff is tuned per display; if installing it does not suit a given board, the device keeps its normal boot rather than risk a blank screen.

Step 4: Complete setup in the browser

The installer prints the URL when it finishes. Open it:

http://pr.local:9284/setup

The web wizard takes you through: deployment mode confirmation, security (set a password), hardware (display scale and rotation, Stream Deck), Grocy connection, AI provider, and optional integrations. When you click Start using Pantry Raider everything is saved and you're done.

A Pi Remote install has no local app; it drives the server URL you gave the installer.

If pr.local doesn't resolve, use the device's IP: http://<device-ip>:9284/. (Some Android devices and older Windows lack mDNS; see Troubleshooting.)

Pre-built appliance image (advanced, no SSH step)

If you want a flash-and-go card with no SSH install step, a pre-built foodassistant-appliance-*-arm64.img.xz is published to the Releases page. It installs the full Pi Hosted stack on its own the first time it starts. Flash it with balenaEtcher or dd.

Raspberry Pi Imager 2.x turns off its OS customization settings (Wi-Fi, user, SSH) for third-party images like this one, so you make those settings in two files on the card before its first start. After flashing, remove the card and put it back in: it shows up on your computer as a drive named bootfs. If Windows offers to format another drive from the card, choose Cancel: formatting it would erase the card's system. Edit the files with a plain text editor, indent with spaces (never tabs), and keep the quotes shown. The card reads these files once, the first time it starts, so make your changes before you boot it. Leave meta-data as it is.

A wpa_supplicant.conf file on the card does nothing on this image. Set up Wi-Fi in network-config as shown below.

Wi-Fi: network-config

On Ethernet you can leave this file as it is. For Wi-Fi, add these lines to the end of network-config, with your own network name, password, and two-letter country code:

network:
  version: 2
  wifis:
    renderer: NetworkManager
    wlan0:
      dhcp4: true
      regulatory-domain: "US"
      access-points:
        "Your Wi-Fi name":
          password: "your Wi-Fi password"
      optional: true

The country code decides which Wi-Fi channels the Pi may use, so set it to the country the Pi is in.

Login account and SSH: user-data

The image comes with no login account. The kiosk display and the Stream Deck run as that account, so create one here if you use either of them, or if you want to sign in over SSH. Keep #cloud-config as the first line of user-data (the file is ignored without it) and add these lines below it:

users:
  - name: pi
    groups: users,adm,dialout,audio,netdev,video,plugdev,cdrom,games,input,gpio,spi,i2c,render,sudo
    shell: /bin/bash
    sudo: ALL=(ALL) NOPASSWD:ALL
    lock_passwd: false
    passwd: "your password hash"
    ssh_authorized_keys:
      - ssh-ed25519 AAAA... you@your-computer
enable_ssh: true
ssh_pwauth: true
  • name is the account name. Change pi to any lowercase name you like.
  • To sign in with a password, put a password hash in passwd, never the password itself. On a Linux computer, run openssl passwd -6, type the password twice, and paste the line it prints (it starts with $6$).
  • To sign in with an SSH key, replace the ssh-ed25519 ... line with the contents of your public key file, for example ~/.ssh/id_ed25519.pub (ssh-keygen makes one). This works from any computer, so use a key if you have no Linux computer to make a password hash.
  • Use a password, a key, or both. For a key only, delete the lock_passwd and passwd lines and change ssh_pwauth to false. For a password only, delete the ssh_authorized_keys line and the key line below it.
  • enable_ssh: true turns on SSH, and ssh_pwauth: true allows signing in over SSH with the password. The sudo line lets the account run admin commands, like the ones in Troubleshooting below, without typing a password.

Timezone and first start

The appliance uses the timezone set in foodassistant.config.env, on the same drive: remove the # in front of the TZ= line and set your zone, for example TZ=America/Chicago. Without it, the appliance runs on UK time (Europe/London). That file also holds the other optional appliance settings.

Put the card in the Pi, connect the network, and power on. The Pi restarts by itself early on, which is expected, then installs Docker and the containers. That takes several minutes the first time. When it is done, open http://pr.local:9284/setup and finish in the browser (Step 4 above).

The pre-built image always installs the full host stack and detects a display and a Stream Deck on its own. To choose Pi Remote or pick add-ons, use the stock-OS and installer path above.

If a card keeps restarting

A card flashed from an earlier release image can restart over and over on its first start and never finish setting up. To fix it without reflashing, put the card in another computer and open cmdline.txt on the bootfs drive. It holds a single line: delete everything from systemd.run= to the end of that line, keep the rest of the line as it is, save the file, and boot the Pi again.

That card has not read network-config or user-data yet, so set them up as described above before you boot it. If the kiosk display or the Stream Deck still does not come up, sign in over SSH and re-run the installer (see Troubleshooting).

Add-ons and settings

The installer auto-enables the kiosk and Stream Deck when the hardware is present. Use Settings in the web UI to adjust display settings, Stream Deck configuration, Wi-Fi, and hostname at any time.

To add optional backends to a running device:

Enable Mealie / Ollama later

cd /opt/foodassistant
docker compose --profile with-mealie up -d     # add Mealie
docker compose --profile with-ollama up -d      # add Ollama

Display rotation

Choose a rotation in the installer, or change it later without reflashing:

sudo /usr/local/bin/foodassistant-set-rotation 90 --reboot

This rotates the KMS framebuffer (boot console, splash, and kiosk). The app's Settings page also offers a CSS-only rotation for the kiosk browser (no reboot, but it does not affect the boot console).

Kiosk mode (touchscreen)

If a display is present at install time the installer offers to set up the kiosk: it installs cage + Chromium and starts foodassistant-kiosk.service, which opens the app full-screen on tty1. Manage it with:

systemctl status foodassistant-kiosk
systemctl restart foodassistant-kiosk

A display added later lights the kiosk up on its own: the device notices the screen within about a minute of it being plugged in and provisions (or starts) the kiosk with no reflash or SSH needed. The Settings Hardware pane shows the same detection with a one-click Enable button. On a kiosk device the boot console is also quieted, so the screen stays clean from power-on until the app appears.

Hardware coverage

Board / class Status
Raspberry Pi 5 (ARM64) ✅ Recommended
Raspberry Pi 4B 4/8 GB (ARM64) ✅ Supported
Raspberry Pi 4B 2 GB 🟡 Grocy-only; Mealie tight
Raspberry Pi 3B+ / equivalent ✅ Pi Remote (thin client) only
Generic x86-64 Debian/Ubuntu ✅ Server mode (the installer runs the same way)
Other ARM64 Debian/Ubuntu boards 🟡 Best-effort; Docker via get.docker.com
Pi Zero 2 W ❌ Insufficient RAM

The installer runs on any Debian/Ubuntu host, not just a Pi. On a non-Pi host it selects Server mode automatically.

See supported-hardware.md for the full matrix.

Troubleshooting

pr.local won't resolve. mDNS isn't universal. Use the device IP, or install Bonjour (Windows) / ensure avahi-daemon is running on the device (systemctl status avahi-daemon). Find the IP from your router.

The install seems stuck. It's pulling Docker images: give it 5 to 10 minutes on a slow connection. The provisioner logs to /var/log/foodassistant-firstboot.log (tail -f it in another SSH session).

A pre-built card keeps restarting and never finishes. See "If a card keeps restarting" under Pre-built appliance image, above.

The Stream Deck isn't detected (No Stream Deck found in the log). Check the USB cable first: many USB-C and micro-USB cables are charge-only, so the deck lights up but carries no data. A deck that disconnects at random usually means an undersized power supply instead. Both are covered in Power and cabling.

Re-run the installer / change choices. Just run the curl ... | bash line again. To force the provisioner to redo a completed step set FORCE=1:

sudo rm -f /var/lib/foodassistant/firstboot.done
curl -fsSL https://raw.githubusercontent.com/Syracuse3DPrintingOrg/PantryRaider/main/install.sh | bash

Verify the stack.

cd /opt/foodassistant && docker compose ps

Containers didn't start. Confirm Docker installed: docker --version && docker compose version, then re-run the installer.

No internet during install. Docker install and image pulls require it. Connect the network and re-run.

docker compose up fails with "unauthorized" or "pull access denied". The GHCR package may be private. The installer handles this automatically: when the pull fails it builds the image from the on-device checkout at /opt/foodassistant-src. That first build adds a few minutes.