OpenScan3 Pi Image
April 15, 2026 · View on GitHub
This guide explains how to use the Raspberry Pi image produced by this repository. The image is based on Raspberry Pi OS Lite and ships with OpenScan3-Firmware (FastAPI backend) plus the Vue.js/Quasar-based OpenScan3-Client SPA, alongside camera-specific tweaks depending on the chosen build variant.
TL;DR
- Flash the image using Raspberry Pi Imager and, in Advanced options, set the hostname, create a user (do NOT name it
openscan), and configure Wi‑Fi. - Optionally enable SSH in Raspberry Pi Imager for headless access.
- Boot the Pi, connect it to your network (Ethernet recommended for first boot).
- Open a browser to
http://openscan/or the Pi’s IP. - You’ll land on the OpenScan3-Client dashboard (served at
/). - API is available on the device at
http://<pi>/api/(proxied by nginx) and directly athttp://<pi>:8000/latest. - API documentation is available at
http://<pi>:api/latest/docs.
What’s in the image
-
OpenScan3 service
- Installed to
/opt/openscan3and run in a Python venv. - Systemd unit:
openscan3.service(seestage3-openscan/00-base/files/etc/systemd/system/openscan3.service).
- Installed to
-
OpenScan3-Client web UI
- Vue.js/Quasar SPA prebuilt into
/opt/openscan3-client. - Served statically by nginx (no separate systemd service).
- Default routes:
/(dashboard) with history fallback handled by nginx.
- Vue.js/Quasar SPA prebuilt into
-
nginx reverse proxy
- Installed in stage3 (
stage3-openscan/02-nginx). - Base site
openscan3-api.confproxies/apito the OpenScan3 FastAPI backend (127.0.0.1:8000) and serves the SPA from/opt/openscan3-client. - Admin site
openscan3-admin.confexposes the updater at/admin/. - Additional locations (e.g., camera helpers) are included via
/etc/nginx/openscan3/locations-enabled/*.conf.
- Installed in stage3 (
-
Persistent settings
- OpenScan settings are stored in
/etc/openscan3(created and made group-writable bystage3-openscan/00-base/01-run.sh).
- OpenScan settings are stored in
-
Updater
- A simple updater for OpenScan3 and the OpenScan3-Client SPA is reachable at
/admin. - Also reachable from within the OpenScan3-Client SPA.
- A simple updater for OpenScan3 and the OpenScan3-Client SPA is reachable at
Supported variants (camera-specific)
Select the right image for your camera. Differences are applied in stage 5.
-
Generic (experimental) (
stage5-generic)- Installs stock
libcamerapackages. - Adds a comment to
/boot/firmware/config.txt; no camera overlay is forced (seestage5-generic/01-camera-generic/00-packages,01-run.sh).
- Installs stock
-
IMX519 (
stage5-imx519)- Installs Arducam PiVariety
libcamerapackages. - Appends
dtoverlay=imx519to/boot/firmware/config.txt(seestage5-imx519/01-camera-imx519/01-run.sh).
- Installs Arducam PiVariety
-
**Arducam 64MP (HawkEye) ** (
stage5-arducam-64mp)- Installs Arducam PiVariety
libcamerapackages. - Appends to
/boot/firmware/config.txt:dtoverlay=arducam-64mpdtoverlay=vc4-kms-v3d,cma-512(increases CMA for high-res camera)
- See
stage5-arducam-64mp/01-camera-arducam-64mp/01-run.sh.
- Installs Arducam PiVariety
Your build variant is chosen via the .env config used at build time (see camera-configs/*.env).
First boot and network access
- User account (important): Use the user you created in Raspberry Pi Imager. Do not create a user named
openscan— this name is reserved for the internal service account created by the image. If you haven't created a user, you won't be able to SSH into the Pi. - Network:
- If Wi‑Fi was configured in Raspberry Pi Imager, the Pi will join that network on first boot. If no network is configured, the device will automatically try to connect to a Wi-Fi from a qr code you can generate with your smartphone.
- Hostname: Use the hostname you set in Raspberry Pi Imager. If not set, it defaults to
openscan3-alpha. - Discovery:
- Default hostname is
http://openscan/and via mDNS it resolves ashttp://openscan.local/. - Avahi publishes
_http._tcpand_smb._tcpDNS‑SD records automatically, so Windows/macOS/Linux network browsers show an “OpenScan3” web endpoint and Samba share without extra setup. Changing the hostname (e.g., in Raspberry Pi Imager) propagates to these announcements on next boot.
- Default hostname is
Accessing the web UI
- Open
http://<pi>/→ serves the OpenScan3-Client SPA directly.- History mode fallback keeps URLs such as
/projectsworking without manual nginx tweaks.
- History mode fallback keeps URLs such as
- FastAPI generated OpenAPI docs:
http://<pi>/api/latest/docs - OpenAPI JSON:
http://<pi>/api/latest/openapi.json - Typical endpoints consumed by the SPA:
/latest/device/info,/latest/projects, and other REST/WS routes exposed by the firmware.
Updater
- Admin page:
http://<pi>/admin/- Minimal PHP page to:
- Download OpenScan3 device settings as tar.gz (
/etc/openscan3). - Download the packaged OpenScan3-Client bundle (
/opt/openscan3-client). - Trigger a quick update (see below). Default branch is
main.
- Download OpenScan3 device settings as tar.gz (
- Security: No authentication by default. Use only on trusted networks.
- Minimal PHP page to:
Services and logs
Run these on the Pi (SSH or local):
-
Status
systemctl status openscan3systemctl status nginx
-
Start/Stop/Restart
sudo systemctl restart openscan3sudo systemctl restart nginx
-
Logs
journalctl -u openscan3 -e -fjournalctl -u nginx -e -f
File and directory layout (key locations)
- OpenScan app (runtime, editable install):
/opt/openscan3 - OpenScan git source copy:
/opt/openscan3-src(used for future updates/sync) - Python venv for the service:
/opt/openscan3/venv - OpenScan3-Client static files:
/opt/openscan3-client - Nginx config roots:
/etc/nginx/sites-available/openscan3-api.conf,/etc/nginx/sites-available/openscan3-admin.conf, and snippet dir/etc/nginx/openscan3/locations-enabled/ - OpenScan settings:
/etc/openscan3(group-writable foropenscan) - Boot config:
/boot/firmware/config.txt(camera overlays added per variant)
Updating OpenScan3 (application code)
The service is installed in editable mode from /opt/openscan3, so changes there take effect after a restart.
Example (on the Pi):
# Optional: update the source mirror
sudo -u openscan bash -lc 'cd /opt/openscan3-src && git remote -v && git fetch --all && git checkout <desired-branch> && git pull'
# Sync updated source into the runtime tree (without .git)
sudo rsync -av --delete --exclude '.git' /opt/openscan3-src/ /opt/openscan3/
# Restart the service
sudo systemctl restart openscan3
Updater
-
CLI:
# Default branch is main; add --keep-settings to preserve local overrides sudo /usr/local/sbin/openscan3-update --branch main [--keep-settings]- Stops services, force-resets
/opt/openscan3-srctoorigin/<branch>, syncs to/opt/openscan3, rebuilds the venv, refreshes/etc/openscan3unless retained, downloads the latest OpenScan3-Client bundle, then restarts services.
- Stops services, force-resets
-
Web:
- Open
http://<pi>/admin/(or the updater entry inside the SPA) and use the form to trigger the same updater. - You can choose branch and optionally keep settings; the client bundle is always refreshed to the latest release.
- Open
Flashing the image
- Locate the image: Find the generated image in
pi-gen/deploy/(.img,.img.xz, or.zip).
Optional: generate a Raspberry Pi Imager manifest (online + local)
We ship scripts/generate-imager-json.py to emit both the hosted repository metadata (imager/repo.json) and a manifest that points at your locally downloaded artifacts so the customization wizard stays enabled even when you select "Use custom".
-
Build or download your OpenScan images so they exist in
pi-gen/deploy/. -
Generate the manifests:
./scripts/generate-imager-json.py \ --deploy-dir pi-gen/deploy \ --local-manifestimager/repo.json: reference file for publishing/hosting (HTTP URLs).imager/os_list_local.rpi-imager-manifest: usesfile://paths that Raspberry Pi Imager can open directly.
-
Launch Raspberry Pi Imager and either double-click the
.rpi-imager-manifestfile or go to App Options → Content Repository → Use custom file and select it. The OS list now shows your OpenScan builds with all customization sliders, including USB Gadget mode.
Recommended: Raspberry Pi Imager with custom repository
Note: Advanced customization (hostname, user, Wi‑Fi, etc.) is confirmed to work with Raspberry Pi Imager > 2.0. Older versions may not apply the customizations properly.
- Open Raspberry Pi Imager (>=2.0.6).
- Click ADD OPTIONS -> Click EDIT Content Repository -> Use custom URL and paste
https://openscan.eu/rpi-repo.json-> Click Apply and restart - Choose your raspberry pi device
- Select the image according to your camera variant. IMPORTANT: Ensure the image matches your camera model. Choosing the wrong image may result in permanent hardware damage.
- Select the storage device to write the image to.
- Modify configuration options if needed (hostname, user, Wi‑Fi, etc.) via the Raspberry Pi Imager interface.
- Write the image. Eject the card and insert it into the Pi.
Troubleshooting
-
No dashboard on port 80
- Check services:
systemctl status nginx. - Confirm
/opt/openscan3-clientcontains the built SPA (index.html, assets) and that/etc/nginx/openscan3/locations-enabled/60-client.confexists.
- Check services:
-
UI shows setup screen / device not initialized
- Check OpenScan3:
systemctl status openscan3andjournalctl -u openscan3 -e -f.
- Check OpenScan3:
-
Camera not detected / errors with libcamera
- Verify
/boot/firmware/config.txtcontains the correctdtoverlayfor your variant. - For 64MP builds ensure the CMA overlay line exists:
dtoverlay=vc4-kms-v3d,cma-512. - Power-cycle after changing overlays.
- Verify
-
SPA caching issues after update
- Force-refresh the browser (Ctrl+Shift+R) or clear cache; nginx sets
no-storeheaders but some proxies may still cache aggressively.
- Force-refresh the browser (Ctrl+Shift+R) or clear cache; nginx sets
Notes for advanced users
- The upstream pi-gen defaults include cloud-init support (see
pi-gen/README.md). If your build usedENABLE_CLOUD_INIT=1, cloud-init will apply any config placed on the boot partition at first boot. - Stage order per image is controlled by the
.envyou chose (seecamera-configs/*.env, variableSTAGE_LIST).