PhotoPrism is a self-hosted photo management app that indexes your existing photo and video folders, recognises faces and objects, reads EXIF and location data, and gives you a fast, searchable web interface, all on your own server. It’s especially good at organising existing archives (including RAW files) without moving or modifying them.
Comparing options? See Immich vs PhotoPrism.
Requirements
- 2 vCPU and 3–4 GB RAM minimum, with 4 vCPU and 6–8 GB recommended for large libraries. Indexing is CPU-heavy, and TensorFlow (AI labels and faces) needs memory. Add swap on smaller servers. See swap.
- Storage for your originals, plus roughly 10–20% for thumbnails and sidecar files. A storage VPS suits large libraries. See storage VPS.
- Docker and Docker Compose. See install Docker.
1. Docker Compose
PhotoPrism provides an official compose.yaml. Download it from their docs, or use this outline:
# /opt/photoprism/compose.yaml (outline)
services:
photoprism:
image: photoprism/photoprism:latest
restart: unless-stopped
depends_on: [mariadb]
security_opt:
- seccomp:unconfined
- apparmor:unconfined
ports:
- "127.0.0.1:2342:2342"
environment:
PHOTOPRISM_ADMIN_USER: "admin"
PHOTOPRISM_ADMIN_PASSWORD: "change-me-long-password"
PHOTOPRISM_SITE_URL: "https://photos.example.com/"
PHOTOPRISM_DATABASE_DRIVER: "mysql"
PHOTOPRISM_DATABASE_SERVER: "mariadb:3306"
PHOTOPRISM_DATABASE_NAME: "photoprism"
PHOTOPRISM_DATABASE_USER: "photoprism"
PHOTOPRISM_DATABASE_PASSWORD: "change-me-db"
PHOTOPRISM_ORIGINALS_LIMIT: 5000 # max file size in MB
PHOTOPRISM_WORKERS: 2 # indexing workers (≈ vCPUs/2)
volumes:
- "/srv/photos/originals:/photoprism/originals"
- "/srv/photos/import:/photoprism/import"
- "./storage:/photoprism/storage"
mariadb:
image: mariadb:11
restart: unless-stopped
command: --innodb-buffer-pool-size=512M --transaction-isolation=READ-COMMITTED --character-set-server=utf8mb4 --collation-server=utf8mb4_unicode_ci --max-connections=512
environment:
MARIADB_DATABASE: "photoprism"
MARIADB_USER: "photoprism"
MARIADB_PASSWORD: "change-me-db"
MARIADB_ROOT_PASSWORD: "change-me-root"
volumes:
- "./database:/var/lib/mysql"
Folder roles:
- originals: your photo library. PhotoPrism indexes it in place.
- import: a drop folder. Files are moved into originals, sorted by date.
- storage: cache, thumbnails, sidecar files and settings. Keep it on fast storage.
cd /opt/photoprism && docker compose up -d
docker compose logs -f photoprism
Use strong passwords from a password manager.
2. HTTPS
Put PhotoPrism behind Nginx with Let’s Encrypt (WebSocket headers required):
server {
server_name photos.example.com;
client_max_body_size 500M;
location / {
proxy_pass http://127.0.0.1:2342;
proxy_set_header Host $host;
proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;
proxy_set_header X-Forwarded-Proto $scheme;
proxy_http_version 1.1;
proxy_set_header Upgrade $http_upgrade;
proxy_set_header Connection "upgrade";
}
# listen 443 ssl; certbot --nginx
}
PHOTOPRISM_SITE_URL must match the public URL. See Nginx WebSocket proxy.
3. Get photos in and index them
- Copy existing photos into
originals(rsync from another server or NAS works well), then Library → Index in the web UI. - Or put them in
import, and use Library → Import. - From phones: PhotoPrism has no native backup app. Use PhotoSync, a WebDAV client (PhotoPrism exposes WebDAV), or Syncthing to a folder that you index regularly. See Syncthing.
The first index of a large library can take hours. Later runs are incremental. Schedule indexing (settings or CLI) to pick up new files:
docker compose exec photoprism photoprism index
4. Faces, labels and places
- Faces: People → review detected faces and assign names. PhotoPrism clusters similar faces.
- Labels: automatic object and scene classification (search “beach”, “dog”).
- Places: a map view from GPS EXIF data. Reverse geocoding uses PhotoPrism’s service unless disabled.
Tuning
- Lower
PHOTOPRISM_WORKERSon small VPSes, to keep the server responsive during indexing. - Disable features you don’t need (TensorFlow, faces, video transcoding) via environment options to save CPU and RAM.
- Use
niceand off-peak schedules for big imports. See process priority.
Backups
Back up three things: originals (irreplaceable), the database (albums, labels, faces, edits), and storage (sidecars and settings, regenerable but slow to rebuild).
docker compose exec -T mariadb mariadb-dump -uroot -p"change-me-root" photoprism > /backups/photoprism-db-$(date +%F).sql
Copy everything off-server. See backup strategy.
Security
- HTTPS, a strong admin password, and multi-user accounts (editions differ in user features).
- Consider VPN-only access for private libraries. See Tailscale.
- Keep it updated. See updating self-hosted apps.
Quick reference
| Task | Command / setting |
|---|---|
| Start | docker compose up -d |
| Index | docker compose exec photoprism photoprism index |
| Public URL | PHOTOPRISM_SITE_URL |
| Workers | PHOTOPRISM_WORKERS |
| Port | 2342 (behind Nginx) |
| Backup DB | mariadb-dump … photoprism |
Related: Immich photo backup and Jellyfin vs Plex.