Lumio / self-hosted
Guide

Install Lumio on a Raspberry Pi.

The Pi is a charming, low-power self-host target for a solo studio. The stack is the same as everywhere (arm64) — with a few Pi quirks around storage, speed and reachability.

Will your Pi run it?

  • Raspberry Pi 5 with 8 GB (better 16 GB) recommended; Pi 4 with 8 GB works but is slower
  • 64-bit OS — Raspberry Pi OS (64-bit) or Ubuntu for arm64; 32-bit is not supported
  • Boot from SSD (USB SSD or NVMe HAT), not from the SD card
  • Docker ≥ 24 with Compose v2
  • Photos only from 4 GB RAM is tight — 8 GB+ is the comfortable starting point; leave AI tagging off on the Pi

Performance & limits — honestly

  • The first build takes a while — images are built on the Pi itself; budget time and enough free RAM.
  • Video transcoding is sluggish (CPU x264). Fine for a photo studio, an x86 server for lots of video.
  • No GPU tagging on ARM — AI tagging runs on CPU only, best left off on the Pi.
  • SD cards are the enemy — slow and wear-prone. An SSD is a must for a serious setup.

Step 1 — Prepare the Pi

Flash a 64-bit OS onto an SSD and boot from it. Then set up the system and Docker:

# Check 64-bit (should print aarch64)
uname -m

# Update the system
sudo apt update && sudo apt upgrade -y

# Docker engine + Compose plugin
curl -fsSL https://get.docker.com | sh
sudo usermod -aG docker $USER
# log back in, then test:
docker run --rm hello-world

Step 2 — Get Lumio & configure

sudo mkdir -p /opt/lumio && sudo chown $USER:$USER /opt/lumio
cd /opt/lumio
git clone https://github.com/markusthiel/lumio.git .
cp .env.example .env

# Generate secrets
sed -i "s|^POSTGRES_PASSWORD=.*|POSTGRES_PASSWORD=$(openssl rand -base64 24 | tr -d '/+=')|" .env
sed -i "s|^JWT_SECRET=.*|JWT_SECRET=$(openssl rand -base64 32 | tr -d '/+=')|" .env
sed -i "s|^SESSION_SECRET=.*|SESSION_SECRET=$(openssl rand -base64 32 | tr -d '/+=')|" .env
sed -i "s|^S3_ACCESS_KEY=.*|S3_ACCESS_KEY=$(openssl rand -hex 12)|" .env
sed -i "s|^S3_SECRET_KEY=.*|S3_SECRET_KEY=$(openssl rand -base64 32 | tr -d '/+=')|" .env

DEPLOYMENT_MODE=single is the default. Domain/TLS as in the next step.

Step 3 — Reachability & TLS

At home the Pi usually sits behind CGNAT — then the route is a tunnel (Cloudflare Tunnel, Tailscale Funnel). The tunnel handles TLS, Caddy runs on an HTTP port only. This is exactly case B from the on-premise guide:

LUMIO_HOST=photos.yourstudio.com
LUMIO_S3_HOST=s3.yourstudio.com
PUBLIC_URL=https://photos.yourstudio.com
S3_PUBLIC_URL=https://s3.yourstudio.com
CADDY_HTTP_PORT=8080     # the tunnel points here

If you have a public IP at home and can forward 80/443, Caddy obtains the certificate itself — then LUMIO_HOST + PUBLIC_URL + S3_PUBLIC_URL are enough (case A).

Step 4 — Start & create an admin

docker compose -f docker-compose.yml -f docker-compose.prod.yml up -d
docker compose logs -f    # the first build needs patience on the Pi

docker compose exec api npm run create-admin \
  -- --email=you@yourstudio.com --password=atleast12chars

Log in at https://photos.yourstudio.com. You're live once creating a gallery, uploading an image, sharing it and opening it from another device works.

Common questions about the Raspberry Pi

Which Raspberry Pi is suitable? +

The recommendation is a Raspberry Pi 5 with 8 GB (better 16 GB) of RAM. The Pi 4 (up to 8 GB) works too but is noticeably slower, especially at transcoding. Important: a 64-bit operating system (Raspberry Pi OS 64-bit or Ubuntu for arm64) — the 32-bit variant is not supported. 4 GB models are borderline for a photo-only studio and too small for video.

Can I boot from the SD card? +

Technically yes, in practice no. SD cards are slow and wear out quickly under database and image load. Boot from a USB SSD (the Pi 5 can also do NVMe via a HAT) — that's the single biggest performance and reliability win. The image data should also live on SSD or a NAS mount, not on the SD card.

How fast is video transcoding on the Pi? +

Slow. Transcoding runs on the CPU (x264), and GPU acceleration for auto-tagging doesn't exist on ARM. A photo studio runs well; if you want to proof a lot of video, an x86 server serves you much better. Leave the ML auto-tagging off on the Pi.

Does the Pi have to be reachable from the internet? +

For sending gallery links to clients: yes. At home the Pi usually sits behind CGNAT or a router without port forwarding — then a tunnel (Cloudflare Tunnel, Tailscale Funnel) is the easiest route. The approach is identical to the on-premise guide, case B: the tunnel terminates TLS, Lumio's Caddy runs on an HTTP port only.

Is a Pi enough for a real studio? +

For a solo photo studio with moderate volume: yes, a Pi 5 with an SSD and 8–16 GB handles it nicely. For video-heavy workflows, many concurrent client downloads or AI tagging, a small x86 server (or a cheap VPS) is the better choice. The Pi is ideal for trying things out and for small, quiet setups.

Ready for your own gallery?

Source code on GitHub, questions and discussions there too. If anything in the guide trips you up, reach out — we're happy to improve the docs.