How to Self-Host PiGallery2 with Docker Compose
What Is PiGallery2?
PiGallery2 is a fast, directory-first photo gallery designed to run on low-resource servers — including Raspberry Pi. Point it at a folder of photos on disk and it serves a browsable web gallery without importing, copying, or modifying your files. It supports face detection, GPS-based maps, video thumbnails, and full-text search. Unlike Immich or PhotoPrism, PiGallery2 treats your existing folder structure as the source of truth. Official site.
Prerequisites
- A Linux server (Ubuntu 22.04+ recommended)
- Docker and Docker Compose installed (guide)
- 512 MB of free RAM (minimum — 1 GB recommended for large libraries)
- A directory of photos accessible to Docker
- A domain name (optional, for remote access)
Docker Compose Configuration
Create a directory for PiGallery2:
mkdir -p /opt/pigallery2/{config,db,tmp}
Create a docker-compose.yml file:
services:
pigallery2:
image: bpatrik/pigallery2:3.5.2
container_name: pigallery2
restart: unless-stopped
environment:
- NODE_ENV=production
# Uncomment to set a different port inside the container
# - PORT=80
volumes:
# Application config (JSON settings file)
- ./config:/app/data/config
# SQLite database for caching metadata
- ./db:/app/data/db
# Temporary files (thumbnails, transcoded videos)
- ./tmp:/app/data/tmp
# Your photo directory — mounted READ-ONLY
# CHANGE THIS to your actual photo directory
- /path/to/your/photos:/app/data/images:ro
ports:
- "8085:80"
mem_limit: 3g
Important configuration notes:
/path/to/your/photos— change this to wherever your photos live on the host. PiGallery2 reads from this directory without modifying it.- The
:roflag mounts photos as read-only. PiGallery2 never modifies your originals. mem_limit: 3gprevents runaway memory usage during face detection or thumbnail generation on large libraries.
Start the stack:
docker compose up -d
Initial Setup
Open http://your-server-ip:8085 in a browser. PiGallery2 starts with no authentication — the first thing to do is set a password.
- Click the Settings gear icon in the top-right corner
- Navigate to User Management
- Create an admin user with a strong password
- Enable authentication under Basic Settings → Authentication
PiGallery2 immediately begins scanning the mounted photo directory. For large collections (10,000+ photos), the initial indexing takes a few minutes.
Configuration
PiGallery2 stores all settings in /app/data/config/config.json. You can edit settings through the web UI or by modifying this file directly.
| Setting | Location | Notes |
|---|---|---|
| Authentication | Basic Settings → Authentication | Enable and set password immediately |
| Thumbnail quality | Photo → Thumbnail | Adjust size and quality. Smaller = faster on low-end hardware |
| Face detection | Faces | Enable face recognition. CPU-intensive on first run |
| Map | Map | Enable GPS-based photo map. Requires OpenStreetMap tiles |
| Search | Search | Full-text search across filenames, directories, EXIF data |
| Video support | Video → Enable | Transcodes video thumbnails. Requires ffmpeg (included in image) |
| Indexing | Indexing | Set scan interval. Default: checks for changes on access |
Environment Variable Overrides
PiGallery2 supports environment variable configuration using a specific naming pattern:
environment:
# Override any config.json setting via env vars
# Pattern: Server-[section]-[key]=value
- Server-Threading-enabled=true
- Server-Threading-thumbnailThreads=2
- Client-Map-enabled=true
- Client-Map-mapProvider=OpenStreetMap
This is useful for container orchestration where editing JSON files is impractical.
Advanced Configuration (Optional)
Nginx Reverse Proxy
For production deployments with SSL, place Nginx in front of PiGallery2:
services:
pigallery2:
image: bpatrik/pigallery2:3.5.2
container_name: pigallery2
restart: unless-stopped
environment:
- NODE_ENV=production
volumes:
- ./config:/app/data/config
- ./db:/app/data/db
- ./tmp:/app/data/tmp
- /path/to/your/photos:/app/data/images:ro
expose:
- "80"
mem_limit: 3g
networks:
- pigallery-net
nginx:
image: nginx:1.27-alpine
container_name: pigallery2-nginx
restart: unless-stopped
ports:
- "80:80"
- "443:443"
volumes:
- ./nginx.conf:/etc/nginx/nginx.conf:ro
- ./ssl:/etc/nginx/ssl:ro
depends_on:
- pigallery2
networks:
- pigallery-net
networks:
pigallery-net:
For a simpler approach, use Nginx Proxy Manager or Caddy as your reverse proxy.
Extensions
PiGallery2 3.x supports extensions for custom functionality. Extensions live in the config directory:
mkdir -p /opt/pigallery2/config/extensions
Enable extensions in Settings → Extensions. The extension API allows custom metadata processing, additional authentication providers, and webhook integrations.
Reverse Proxy
PiGallery2 works behind any reverse proxy. Point the proxy to port 80 on the PiGallery2 container. No special headers or WebSocket configuration required.
See: Reverse Proxy Setup | Nginx Proxy Manager | Caddy Setup
Backup
Back up these directories:
| Directory | Contents | Critical? |
|---|---|---|
./config/ | Settings, user accounts, extensions | Yes — recreating config is tedious |
./db/ | SQLite metadata cache | No — regenerated on next scan |
./tmp/ | Thumbnail cache | No — regenerated automatically |
| Photos directory | Your actual photos | Yes — this is your data |
The database and thumbnail cache can be regenerated from the photo directory, so the photos themselves and config/ are the only critical backup targets.
See: Backup Strategy
Troubleshooting
Thumbnails not generating
Symptom: Photos appear but thumbnails are missing or broken.
Fix: Check container logs with docker logs pigallery2. Ensure the temp directory has write permissions:
chmod 777 /opt/pigallery2/tmp
If using a Raspberry Pi, increase the memory limit or reduce thumbnail quality in settings.
Photos not appearing
Symptom: Gallery is empty despite photos in the mounted directory. Fix: Verify the volume mount is correct:
docker exec pigallery2 ls /app/data/images
If empty, the mount path is wrong. Check that the host path exists and contains images. PiGallery2 supports JPEG, PNG, GIF, WebP, and HEIC formats.
Face detection causing high CPU
Symptom: Server becomes unresponsive after enabling face detection.
Fix: Face detection is CPU-intensive on first run. On low-end hardware, process in batches by setting Server-Threading-thumbnailThreads=1 and letting it run overnight. Alternatively, disable face detection if not needed.
Permission denied errors
Symptom: Logs show EACCES: permission denied for config or database files.
Fix: PiGallery2 runs as UID 1000 inside the container. Ensure mounted directories are writable:
chown -R 1000:1000 /opt/pigallery2/{config,db,tmp}
Memory issues on Raspberry Pi
Symptom: Container killed by OOM on Raspberry Pi with large photo libraries.
Fix: Set mem_limit: 1g in Docker Compose and reduce concurrent thumbnail generation threads:
environment:
- Server-Threading-thumbnailThreads=1
Resource Requirements
| Resource | Minimum | Recommended |
|---|---|---|
| RAM | 256 MB idle | 1-3 GB during indexing |
| CPU | 1 core (ARM or x86) | 2+ cores for face detection |
| Disk | 100 MB for application | Plus ~10% of photo library size for thumbnails |
| Architecture | AMD64, ARM64, ARMv7 | Raspberry Pi 3+ supported |
PiGallery2 is one of the lightest photo gallery options available — it runs comfortably on a Raspberry Pi 3 with a few thousand photos.
Verdict
PiGallery2 is the best choice if you already have an organized photo directory and want a web gallery without importing or duplicating files. It respects your existing folder structure, runs on minimal hardware, and never touches your originals. The trade-off is no mobile app and no automatic upload — it’s a gallery viewer, not a photo management platform. If you need Google Photos-style features (mobile backup, AI tagging, sharing), use Immich instead. If you want a lightweight gallery that stays out of your way, PiGallery2 is excellent.
Frequently Asked Questions
How does PiGallery2 compare to PhotoPrism?
PiGallery2 is a lightweight gallery viewer that reads your existing folder structure as-is — no import process, no database migration. PhotoPrism is a full photo management platform with AI-powered classification, labels, and advanced search. PhotoPrism requires significantly more RAM (2–4 GB vs 256 MB). Choose PiGallery2 for a simple, fast gallery on low-power hardware. Choose PhotoPrism for smart indexing and search capabilities on a more powerful server.
Does PiGallery2 support video files?
Yes. PiGallery2 displays video thumbnails and plays videos directly in the browser. Supported formats include MP4, WebM, and other browser-compatible codecs. It does not transcode videos — if a format isn’t natively supported by the browser, it won’t play. For a media server with transcoding, use Jellyfin.
Can PiGallery2 run on a Raspberry Pi?
Yes — it’s designed for it. PiGallery2 runs on Raspberry Pi 3 and newer with ARM support built into the Docker image. Set thumbnail thread count to 1 (Server-Threading-thumbnailThreads=1) and limit container memory to avoid OOM kills on boards with 1 GB RAM. Initial indexing is slow on Pi hardware but browsing is fast once complete.
Does PiGallery2 have user authentication?
Yes. PiGallery2 includes built-in authentication with configurable user roles and access controls. You can create multiple users with different permission levels and restrict access to specific directories per user. No external authentication system is required.
Can I share albums or photos publicly?
PiGallery2 supports sharing through the web UI. You can generate shareable links for specific directories. The sharing functionality is basic compared to Immich or Lychee — there’s no built-in guest album or public gallery feature without authentication.
How does PiGallery2 handle face detection?
PiGallery2 includes face detection that groups detected faces for browsing. The detection runs during the initial scan and identifies faces in photos automatically. It’s less sophisticated than Immich’s face recognition (which identifies and names individuals), but it works on much lower-powered hardware. Face detection increases RAM usage during scanning — allocate at least 1 GB during initial indexing.
Related
Get self-hosting tips in your inbox
Get the Docker Compose configs, hardware picks, and setup shortcuts we don't put in articles. Weekly. No spam.
Comments