Skip to content

Self-host PhotoPrism

updated Sep 2026prices checked · Jul 2026
We earn commissions when you shop through the links below. Full disclosure →

Self-hosted AI-powered photo gallery in Go. Lighter on RAM than Immich, strong tagging and search.

Key facts

LicenseAGPL-3.0
StackGo, JavaScript
Min RAM2048 MB
Official imageyes
Measured idle RAM102 MB
Difficulty
Our recommendation

Pick PhotoPrism when you want a photo library with face and object tagging that runs as one Go binary and idles low: the Community Edition is AGPL-3.0, ships as `photoprism/photoprism:ce`, and defaults to SQLite, so a single container is a complete install — we measured 102 MB of idle RAM and 3.2 GB on disk on a GCP e2-standard-2 on 2026-08-28. Indexing is the other story: upstream asks for 3 GB of RAM plus 4 GB of swap, and the `latest` tag is not the AGPL image. Immich is the catalog's other photo library; PhotoPrism is the one built around a folder of originals you already have.

What you need

  • Any VPS with at least 2048 MB of RAM
  • A domain you control — most self-hosted setups need HTTPS in front of them
  • Under an hour if you've used Docker before
Where to host itaffiliate disclosure
Hetzner Cloudrun it on
From $23.59/mo · 2 vCPU / 4 GB / 80 GB · EU + US
Get Hetzner Cloud (opens in new tab)
Kamaterafree trial
From $4/mo · 1 vCPU / 1 GB / 20 GB · US + EU + Asia
Start free on Kamatera → (opens in new tab)
DigitalOceanalso works on
From $6/mo · 1 vCPU / 1 GB / 25 GB · US + EU + Asia
Deploy on DigitalOcean → (opens in new tab)

Paid link — we earn a commission if you shop through it.

Install

Run these commands on your server:

# PhotoPrism — official docker run (docs → Getting Started → Docker), on the :ce tag
# :ce is the AGPL Community Edition image; :latest bundles the Plus extensions under PhotoPrism's Plus License
PP_PASS=$(openssl rand -base64 18) && echo "admin password: $PP_PASS"   # 8–72 chars; never a default like 'insecure' on a public server
docker run -d \
  --name photoprism \
  --security-opt seccomp=unconfined \
  --security-opt apparmor=unconfined \
  -p 2342:2342 \
  -e PHOTOPRISM_UPLOAD_NSFW="true" \
  -e PHOTOPRISM_ADMIN_PASSWORD="$PP_PASS" \
  -v ~/PhotoPrism/storage:/photoprism/storage \
  -v ~/Pictures:/photoprism/originals \
  photoprism/photoprism:ce
# /photoprism/storage holds the SQLite index, config, cache, thumbnails — it must always be mounted or you lose them on recreate
# open http://SERVER_IP:2342 — user admin, password printed above

What you take on

PhotoPrism's getting-started pages are explicit about memory, the storage volume and the two image tags:

non-negotiableOur snippet mounts only originals. Upstream says the storage folder "is used to save config, cache, backup, thumbnail, and sidecar files" and "must always be mounted so that you do not lose these files after a restart or upgrade" — with the default SQLite driver the index database lives there too. Add ./storage:/photoprism/storage, and "Never configure the storage folder to be inside the originals folder unless the name starts with a .".
non-negotiableUpstream wants "at least 2 cores, 3 GB of physical memory, and a 64-bit operating system" plus "at least 4 GB of swap", and says not to set a hard memory limit "as this can cause unexpected restarts when the indexer temporarily needs more memory to process large files". Idle is cheap (102 MB measured); indexing RAW files and panoramas is what spikes, and the FAQ's answer for low-resource hosts is fewer indexing workers and smaller file limits, not a cgroup cap.
non-negotiablePHOTOPRISM_ADMIN_PASSWORD is the initial superadmin password (8–72 characters) and upstream says "Never use easy-to-guess passwords or default values like insecure on publicly accessible servers" — our snippet's changeme is the same class of value. Set PHOTOPRISM_SITE_URL to the real scheme://host[:port]: it is the canonical URL "used in generated links and to determine HTTPS/TLS" and defaults to http://localhost:2342/.
non-negotiablephotoprism/photoprism:latest is not the pure-AGPL build: the FAQ says use "the ce tag instead of latest to get a slightly smaller Docker image distributed under the AGPL", while latest bundles Plus-licensed extensions, and several config options (HTTPS security headers, rate limiting, SVG support) are marked plus-only. :preview is the development build. Both ce and latest are multi-arch for 64-bit amd64 and arm64 only.
non-negotiableSQLite is the default, but the FAQ says "If you are looking for scalability and high performance, it is not a good choice" and upstream's compose example ships MariaDB (mariadb:12.3; 10.5.12+ required). A backup must include originals and "a copy of the index database" — docker compose exec photoprism photoprism backup -i -f writes it under storage/backup/ — and ideally the whole storage folder. Upstream asks for 3 GB of RAM + 4 GB swap; our 2 GB figure is below that, and the 102 MB we measured is idle only — size for indexing, not idle.

An alternative to

Head-to-head

More in Photo backup & gallery

We use analytics cookies (Google Analytics, PostHog) to see which guides are useful. No ad networks, no cross-site tracking. See our privacy policy.