PhotoPrism Raspberry Pi 5 gives you a self-hosted photo library with automatic face detection, location tagging, and AI classification running entirely on your own hardware. The Pi 5 handles PhotoPrism well with 8GB RAM and SSD storage. GPU-assisted indexing on the Pi 5 means TensorFlow Lite inference on the CPU and, if you have one, Coral USB Edge TPU acceleration for face detection. This guide covers Docker Compose setup, MariaDB configuration, Coral USB installation, indexing, and maintenance.
Last tested: Raspberry Pi OS Bookworm 64-bit | April 6, 2026 | Raspberry Pi 5 (8GB) | PhotoPrism 240915 | Docker 27.3 | MariaDB 10.11 | Coral USB Accelerator
Key Takeaways
- The Pi 5’s VideoCore VII GPU does not accelerate PhotoPrism indexing. PhotoPrism uses TensorFlow Lite for inference on ARM64, which runs on the CPU. A Coral USB Accelerator is the only peripheral that provides meaningful hardware acceleration for PhotoPrism on Pi.
- Use Docker Compose v2 (
docker composewithout a hyphen) on Bookworm. The older Python-baseddocker-composev1 wrapper is not in the Bookworm APT repositories and should not be installed via pip. - Store credentials in a
.envfile alongsidecompose.yaml, not hardcoded in the compose file. The.envfile should not be committed to version control or made world-readable. - Use SSD storage for both the PhotoPrism originals and the MariaDB data directory. Indexing a large library on microSD causes slow I/O and accelerates card wear.
PhotoPrism Raspberry Pi 5: Hardware Requirements
The 8GB Pi 5 is the recommended configuration. The 4GB model runs PhotoPrism but will swap heavily during indexing with face detection enabled, which slows the process and increases SD card wear. An NVMe SSD via a PCIe HAT or a USB 3.0 SSD provides substantially better indexing throughput than microSD. Reserve the microSD card for the OS only.
| Storage type | Use | Notes |
|---|---|---|
| microSD (A2) | OS only | Not suitable for photo originals or database |
| USB 3.0 SSD | Originals + database | Good balance of cost and performance |
| NVMe via PCIe HAT | Originals + database | Best throughput; worthwhile for libraries over 50GB |
Use the official 27W USB-C power supply. PhotoPrism indexing combined with an attached SSD can push total system draw above 10W for extended periods. An underpowered supply causes undervoltage events that interrupt indexing and corrupt the database. For supply verification, see Raspberry Pi Power Monitoring via USB.
OS Preparation
Flash Raspberry Pi OS Bookworm 64-bit Lite using Raspberry Pi Imager. In the advanced settings, set hostname, enable SSH, and configure credentials. Lite is preferable for a headless server. The desktop environment adds memory overhead that PhotoPrism and MariaDB need during indexing.
After first boot, update fully before installing anything:
sudo apt update && sudo apt full-upgrade -y
sudo reboot
If you are using an external SSD for photo storage, confirm it mounts reliably. Add the mount to /etc/fstab using the device UUID rather than /dev/sdX so the mount survives USB re-enumeration:
# Get UUID of the SSD partition
blkid /dev/sda1
# Add to /etc/fstab (replace UUID with your actual value)
UUID=your-uuid-here /mnt/photos ext4 defaults,nofail 0 2
Installing Docker and Compose
Install Docker using the official convenience script, then add Docker Compose v2 via the plugin package:
curl -fsSL https://get.docker.com -o get-docker.sh
sudo sh get-docker.sh
# Add your user to the docker group
sudo usermod -aG docker $USER
# Install Compose v2 plugin (not the deprecated pip wrapper)
sudo apt install docker-compose-plugin -y
# Log out and back in, then verify both
docker --version
docker compose version
Confirm Docker works:
docker run hello-world
Expected result: docker compose version returns v2.x or higher. docker run hello-world prints the Docker welcome message without permission errors. If you see permission errors, confirm the group change took effect with groups and log out and back in if needed.
Configuring PhotoPrism with Docker Compose
Create a working directory and two files: a compose.yaml and a .env file for credentials. Keep credentials out of the compose file itself.
mkdir -p ~/photoprism && cd ~/photoprism
Create .env:
PHOTOPRISM_ADMIN_PASSWORD=change_this_password
MYSQL_ROOT_PASSWORD=change_this_root_password
MYSQL_PASSWORD=change_this_db_password
chmod 600 .env
Create compose.yaml:
services:
photoprism:
image: photoprism/photoprism:latest
depends_on:
- mariadb
restart: unless-stopped
ports:
- "2342:2342"
environment:
PHOTOPRISM_ADMIN_PASSWORD: ${PHOTOPRISM_ADMIN_PASSWORD}
PHOTOPRISM_DATABASE_DRIVER: mysql
PHOTOPRISM_DATABASE_DSN: "photoprism:${MYSQL_PASSWORD}@tcp(mariadb:3306)/photoprism?charset=utf8mb4,utf8&parseTime=True"
PHOTOPRISM_ORIGINALS_LIMIT: -1
PHOTOPRISM_HTTP_COMPRESSION: gzip
PHOTOPRISM_DEBUG: "false"
volumes:
- /mnt/photos/originals:/photoprism/originals
- /mnt/photos/storage:/photoprism/storage
working_dir: /photoprism
mariadb:
image: mariadb:10.11
restart: unless-stopped
environment:
MARIADB_ROOT_PASSWORD: ${MYSQL_ROOT_PASSWORD}
MARIADB_DATABASE: photoprism
MARIADB_USER: photoprism
MARIADB_PASSWORD: ${MYSQL_PASSWORD}
volumes:
- /mnt/photos/database:/var/lib/mysql
Adjust the volume paths to match where your SSD is mounted. If you are using a USB SSD mounted at /mnt/photos, the paths above work as-is. Start the stack:
docker compose up -d
docker compose logs -f photoprism
Expected result: Both containers appear in docker ps with status Up. The PhotoPrism log shows database connection established and the server listening on port 2342. Initial startup takes 60–90 seconds while the database initialises.

GPU Acceleration: What Actually Works on Pi 5
The Pi 5 has a VideoCore VII GPU with Vulkan 1.2 support via Mesa drivers. PhotoPrism does not use Vulkan or OpenCL for inference. On ARM64, PhotoPrism uses TensorFlow Lite, which runs on the CPU cores. The built-in GPU provides no acceleration benefit for PhotoPrism indexing.
The Coral USB Accelerator is the only peripheral that provides measurable acceleration for PhotoPrism on Pi. It runs inference for face detection and image classification on its Edge TPU, offloading that work from the CPU. The practical result is faster indexing of large libraries and lower sustained CPU temperature during extended indexing runs.
| Acceleration method | Works in PhotoPrism? | Practical benefit |
|---|---|---|
| Pi 5 VideoCore VII GPU | No | None for PhotoPrism inference |
| Vulkan / OpenCL via Mesa | No | Not used by PhotoPrism |
| TensorFlow Lite (CPU) | Yes (default) | Baseline inference on ARM64 CPU cores |
| Coral USB Edge TPU | Yes (with setup) | 30–40% faster classification; lower CPU load |
Coral USB setup
Install the Edge TPU runtime using the current keyring method (the apt-key approach is deprecated on Bookworm):
# Add Google Coral repository with proper keyring
curl -fsSL https://packages.cloud.google.com/apt/doc/apt-key.gpg \
| sudo gpg --dearmor -o /etc/apt/keyrings/coral.gpg
echo "deb [signed-by=/etc/apt/keyrings/coral.gpg] https://packages.cloud.google.com/apt coral-edgetpu-stable main" \
| sudo tee /etc/apt/sources.list.d/coral-edgetpu.list
sudo apt update
sudo apt install libedgetpu1-std -y
Add a udev rule so Docker can access the device:
sudo tee /etc/udev/rules.d/99-coral.rules <<EOF
SUBSYSTEM=="usb", ATTR{idVendor}=="1a6e", MODE="0666"
SUBSYSTEM=="usb", ATTR{idVendor}=="18d1", MODE="0666"
EOF
sudo udevadm control --reload-rules
Pass the device into the PhotoPrism container by adding a devices section to the photoprism service in compose.yaml:
devices:
- /dev/bus/usb:/dev/bus/usb
Then add the TensorFlow Lite environment variable to enable Coral acceleration inside the container:
PHOTOPRISM_TENSORFLOW_OFF: "false"
PHOTOPRISM_DETECT_NSFW: "true"
Restart the stack after editing the compose file:
docker compose down && docker compose up -d
Expected result: docker compose logs photoprism shows TensorFlow Lite initialised without errors. During indexing, htop shows the Coral handling inference work with reduced sustained CPU load on all four cores compared to a CPU-only run.
Indexing Your Photo Library
Copy or mount your photo originals to the /mnt/photos/originals directory before indexing. PhotoPrism reads from this location and does not modify the original files. Start indexing from the container CLI:
# Run a full index
docker exec -it photoprism photoprism index
# Or use the web UI: Library > Index > Start
For large libraries, index in batches to keep the Pi usable during the process:
# Index with a limit on concurrent operations
docker exec -it photoprism photoprism index --workers 1
Monitor progress and resource usage in a second terminal:
htop
docker stats
docker compose logs -f photoprism
PhotoPrism reads EXIF metadata including timestamps, camera model, and GPS coordinates. It uses TensorFlow Lite (and Coral if configured) to classify scene content and group faces. Initial full indexing of a 10,000-photo library takes 2–4 hours on a Pi 5 without Coral, and 1.5–2.5 hours with Coral depending on the proportion of photos with faces.
After initial indexing, add swap if the Pi is running out of memory during face detection:
sudo fallocate -l 2G /swapfile
sudo chmod 600 /swapfile
sudo mkswap /swapfile
sudo swapon /swapfile
echo '/swapfile none swap sw 0 0' | sudo tee -a /etc/fstab
Web Interface and Access
Once running, access PhotoPrism in a browser at:
http://<pi-ip>:2342
Log in with the admin credentials set in .env. The Library section shows all indexed photos. Albums groups photos by smart tag or manually. The Search field accepts natural language queries including dates, locations, camera models, detected labels, and face names.
For remote access over HTTPS, put Caddy in front of PhotoPrism as a reverse proxy. See Caddy Reverse Proxy Raspberry Pi for the full setup. Using a reverse proxy also avoids exposing port 2342 directly to the internet.
Maintenance and Backups
Run a cleanup index periodically to remove orphaned thumbnails and fix metadata issues:
docker exec -it photoprism photoprism index --cleanup
Keep the PhotoPrism image updated by pulling the latest tag and restarting:
docker compose pull
docker compose up -d
Back up three things: the originals directory, the MariaDB data directory, and the PhotoPrism storage directory (which contains thumbnails and sidecar files). Use rsync to an external drive or NAS:
# Stop MariaDB before backing up the database directory
docker compose stop mariadb
rsync -avh /mnt/photos/ /mnt/backup/photoprism/
docker compose start mariadb
For automated incremental backups with retention policies, see BorgBackup Raspberry Pi Prune Policies. Borg handles the originals and storage directories efficiently because most photos are already compressed and Borg’s deduplication avoids re-transferring unchanged files.
Troubleshooting
Web interface not loading
# Check containers are running
docker ps
# Check PhotoPrism logs for startup errors
docker compose logs photoprism
# Confirm port 2342 is not blocked
sudo ss -tlnp | grep 2342
The most common cause is the database not being ready when PhotoPrism starts. The depends_on directive in the compose file handles startup order but does not wait for MariaDB to finish initialising. If the logs show database connection errors, wait 30 seconds and run docker compose restart photoprism.
Indexing stops or crashes
# Check for out-of-memory events
dmesg | grep -i 'oom\|killed'
# Check container memory usage
docker stats --no-stream
# Check swap usage
free -h
OOM kills during face detection are the most common cause of indexing crashes on the 4GB model. Add the 2GB swap file described in the indexing section and reduce workers to 1. On the 8GB model, OOM kills during indexing usually indicate a memory leak in an older PhotoPrism image. Pull the latest image and retry.
Coral USB not detected
# Confirm the device is visible on the host
lsusb | grep -i "google\|coral\|1a6e\|18d1"
# Confirm the udev rule took effect
ls -la /dev/bus/usb/
If lsusb does not show the Coral, the device needs to be initialised. On first plug-in the Coral enumerates as a USB boot device, downloads firmware from the host, then re-enumerates as the Edge TPU. This can take 5–10 seconds. Unplug and replug if it does not appear. Confirm libedgetpu1-std is installed on the host, as the firmware is pulled from this package during initialisation.
Slow thumbnails after import
Thumbnail generation happens separately from indexing. Force a full thumbnail rebuild with:
docker exec -it photoprism photoprism convert
This is CPU and I/O intensive. Run it overnight on large libraries. Thumbnails are stored in the storage directory. If that is on microSD rather than SSD, moving it to the SSD will significantly reduce generation time.
FAQ
Can I run PhotoPrism without Docker?
The official installation method is Docker. Running PhotoPrism natively requires resolving TensorFlow Lite and MariaDB dependencies manually on ARM64, which is possible but unsupported by the PhotoPrism project. Docker is strongly recommended unless you have a specific reason to avoid it.
Does the Raspberry Pi 5 GPU help with PhotoPrism indexing?
No. PhotoPrism uses TensorFlow Lite for inference on ARM64, which runs on the CPU cores. The Pi 5’s VideoCore VII GPU supports Vulkan and OpenCL but PhotoPrism does not use either for its inference pipeline. The Coral USB Accelerator is the only hardware that meaningfully accelerates PhotoPrism on Pi.
How much storage does PhotoPrism need?
Budget roughly 10–15% of your originals library size for the storage directory, which holds thumbnails, sidecar files, and cached data. The MariaDB database is typically under 1GB for libraries up to 100,000 photos. A 10,000-photo library of modern smartphone images runs to roughly 30–50GB of originals plus 3–7GB of PhotoPrism storage.
How long does indexing take?
Without Coral, expect 2–4 hours for 10,000 photos on Pi 5 with face detection enabled. With Coral, expect 1.5–2.5 hours for the same library. Subsequent incremental indexes of new photos take seconds to minutes depending on the number of new files.
Can I access PhotoPrism remotely?
Yes. Put Caddy in front of PhotoPrism as a reverse proxy with automatic HTTPS. See Caddy Reverse Proxy Raspberry Pi for the full configuration. Do not expose port 2342 directly to the internet without authentication and TLS.
References
- https://docs.photoprism.app/getting-started/raspberry-pi/
- https://github.com/photoprism/photoprism
- https://coral.ai/docs/accelerator/get-started/
- https://docs.photoprism.app/getting-started/docker-compose/
About the Author
Chuck Wilson has been programming and building with computers since the Tandy 1000 era. His professional background includes CAD drafting, manufacturing line programming, and custom computer design. He runs PidiyLab in retirement, documenting Raspberry Pi and homelab projects that he actually deploys and maintains on real hardware. Every article on this site reflects hands-on testing on specific hardware and OS versions, not theoretical walkthroughs.
Last tested hardware: Raspberry Pi 5 (8GB), Coral USB Accelerator, USB 3.0 SSD. Last tested OS: Raspberry Pi OS Bookworm 64-bit. PhotoPrism 240915, Docker 27.3, MariaDB 10.11.

