PhotoPrism vs Immich: which photo server?
Two self-hosted photo servers compared: the real RAM floors, the phone apps, the maps, and the exact backup commands each one needs on a VPS.
PhotoPrism vs Immich: the short answer
PhotoPrism vs Immich is a choice between two different jobs, not two versions of the same product. Immich replaces Google Photos: a phone app backs up your camera roll automatically, and the timeline you get looks familiar to anyone leaving a phone gallery behind. PhotoPrism organises a photo library you already have: it indexes folders of files on disk, reads their metadata, puts them on a map, and leaves the files exactly where they were.
Pick Immich if the problem is "my phone is full and I want off Google Photos". Pick PhotoPrism if the problem is "I have 400 GB of photos on a drive and I cannot find anything in them". Both are open source, both run as Docker containers on a normal VPS, and both index and search your library without sending anything to a third party.
The philosophy split, and why it decides everything
Immich owns the files. You point it at an upload location, the phone app or the web uploader sends originals in, and Immich stores them under its own path with its own naming. The database holds the truth about albums, faces and search. That design is what makes the phone experience good, because the server always knows the full state of every asset.
PhotoPrism reads the files. You mount an originals folder that you already control, and PhotoPrism builds an index over it. Your directory tree stays yours. If you remove PhotoPrism tomorrow, the photos sit there in the same folders with the same names, and the sidecar YAML files PhotoPrism wrote describing what it learned sit in its own storage folder, which is where it keeps them by default.
That single difference explains most of the rest. Immich has strong mobile support because it controls ingestion. PhotoPrism has strong library curation because it never fights your existing structure. Immich is the better answer for a family whose photos live on phones. PhotoPrism is the better answer for an archive that lives on a disk.
Hardware appetite: Immich asks for more
The documented memory floors are far apart, and on a small VPS this is usually the deciding factor.
The data behind this chart
[
{
"label": "Immich",
"min_ram_gb": 6
},
{
"label": "PhotoPrism",
"min_ram_gb": 3
}
]Immich documents 6 GB of RAM as the minimum and 8 GB as recommended, with a note that a 4 GB machine can run it only with machine learning turned off. PhotoPrism documents 3 GB of physical memory and two CPU cores, and says that beyond that minimum the amount of RAM should match the core count.
The gap is real, and it comes from the machine learning container. Immich runs its models in a separate immich-machine-learning service that loads CLIP (contrastive language image pretraining) and face detection models into memory. On a 2 GB box the kernel kills that container, and you see it exit with code 137, the status for a process killed with signal 9, which is how an out of memory kill shows up in Docker. PhotoPrism's built-in models run on ONNX, which its docs say generally perform well on all types of hardware, and it has a documented fallback for tight memory: on machines with 1 GB or less it disables RAW conversion and face recognition. That is not a promise of stability, though. Below its 3 GB minimum the project warns of instability and performance problems, so treat the floor as a floor.
PhotoPrism's docs are explicit about wanting at least 4 GB of swap on the server. Immich's requirements page does not mention swap, but swap gives its machine learning container headroom on a small box. Add it before you install either one.
sudo fallocate -l 4G /swapfile
sudo chmod 600 /swapfile
sudo mkswap /swapfile
sudo swapon /swapfile
echo '/swapfile none swap sw 0 0' | sudo tee -a /etc/fstab
free -hfree -h should now print a Swap: line showing 4.0Gi. If it prints 0B, then swapon failed, usually because the filesystem does not support fallocate, and sudo dd if=/dev/zero of=/swapfile bs=1M count=4096 is the fallback. Container memory ceilings matter here too, and setting memory limits in Docker Compose is how you stop one hungry service taking the whole box down. The exception is PhotoPrism itself: its docs advise against a hard memory limit on its container, because indexing large files briefly needs extra memory and a limit can cause unexpected restarts.
One more requirement catches people. Immich's Postgres database must sit on a normal Unix filesystem with real ownership and permissions, on local storage, never on a network share. PhotoPrism warns never to store its database files on a shared network folder and calls local SSD storage the best place for them. Neither app is safe to run with its database on a mounted object store.
How to install each one
Both installs are a vendor compose file plus one command. Set up Docker Engine and the Compose plugin first, as covered in our guide to Docker Compose on a VPS.
Immich publishes its compose file and an example environment file with every release.
sudo mkdir -p /opt/immich && cd /opt/immich
wget -O docker-compose.yml https://github.com/immich-app/immich/releases/latest/download/docker-compose.yml
wget -O .env https://github.com/immich-app/immich/releases/latest/download/example.envEdit .env before starting anything. UPLOAD_LOCATION is where your originals will live. DB_PASSWORD comes with a working default, and Immich recommends changing it to a random password, though it does not require it. Postgres is not exposed publicly, so the password is only used for local authentication, but a random one costs nothing to set. Use only the characters A-Za-z0-9, because Immich's docs say other characters can cause problems when Docker parses the value. Then start it.
docker compose up -d
docker compose psThe web interface answers on port 2283. The first account registered through that page becomes the administrator, so reach it and register immediately rather than leaving an open instance sitting on the internet.
PhotoPrism ships one compose file that already includes MariaDB.
sudo mkdir -p /opt/photoprism && cd /opt/photoprism
wget https://dl.photoprism.app/docker/compose.yamlOpen compose.yaml and change PHOTOPRISM_ADMIN_PASSWORD before the first start. The docs are blunt about this: the app starts with whatever initial password is in that file, the minimum length is 8 characters, and the default value must never be used on a public server. Set the originals volume to the folder holding your photos at the same time.
docker compose up -d
docker compose logs -f photoprismPhotoPrism answers on port 2342 with the user admin. Neither app should be exposed directly. Put a reverse proxy with TLS (transport layer security) in front, the same shape of setup used for a self-hosted Nextcloud with Docker, TLS and backups, or keep the server private and reach it over a VPN. If that VPS ends up carrying more than photos, apply the same restraint to every service you add to it, because a self-hosted RustDesk relay needs only its own two ports reachable and nothing else.
Which one has the better phone app
This is where the two projects are furthest apart, and it is the reason most people end up on Immich.
Immich ships official apps for Android and iOS. They do background camera roll backup, which means new photos leave the phone without anyone opening anything. To use it away from home, Immich documents three routes: a VPN such as WireGuard or OpenVPN, Tailscale, or a reverse proxy serving HTTPS. The reverse proxy is the one that lets the phone apps connect without a VPN app on each phone, and Immich warns never to forward port 2283 straight to the internet without additional configuration.
PhotoPrism has no official native app. It ships a progressive web app, which you add to the home screen from the browser, and it documents WebDAV (web distributed authoring and versioning) as the way to sync from a phone. The project recommends a third party app called PhotoSync for this, pointed at the /import/ or /originals/ directory over WebDAV. It works, and it is a paid third party app doing a job Immich does inside its own client.
If automatic phone backup for several family members is the requirement, that settles it. Immich.
What the machine learning actually gives you
Immich does semantic search over your library using CLIP, so a query like "red bicycle in snow" finds photos nobody ever tagged. It also does face detection and clustering, and duplicate detection. Indexing a large import on CPU runs for hours in the background, which is normal and does not need a GPU (graphics processing unit).
PhotoPrism classifies images into labels with a built-in ONNX model, detects faces and groups them into people with ONNX face models, and reads location metadata to build a places map. A vision.yml file in its config folder can swap in Ollama or OpenAI for labels and captions if you want them. The map is the feature people stay for: a library indexed by where it happened is a genuinely different way to browse twenty years of photos. The same idea works on other media collections, and Halcyon's 90s video store front end for Jellyfin is the film version of it, browsing by shelf instead of by list. Face recognition is included in the free Community edition. The paid Essentials and Plus memberships add extras such as richer map layers, more user roles and a user management interface, starting at a few euros per month, billed annually, as of October 2026.
Immich has no paywalled features, and the project says it never will. It does sell optional lifetime product keys, $25 for one user or $100 for a whole server at the prices Immich announced in July 2024, but buying one unlocks nothing and Immich works without restriction if you never pay. PhotoPrism's core is free, with optional paid extras.
Backups decide whether you keep it
A photo server with no backup is one disk failure away from losing everything a family has. Both apps need two backups: the database, and the files.
For Immich, dump the database from the Postgres container and copy the upload location.
docker exec -t immich_postgres pg_dump --clean --if-exists --dbname=immich --username=postgres | gzip > /backup/immich-db.sql.gzThen back up UPLOAD_LOCATION. The folders holding irreplaceable data are upload, library and profile. The thumbs and encoded-video folders can be regenerated, at the cost of hours of CPU time. A database dump on its own restores nothing, because it holds only metadata.
For PhotoPrism, the index has its own command.
docker compose exec photoprism photoprism backup -i -fThat writes an SQL dump under storage/backup/. Then copy the originals folder and the storage folder. Because PhotoPrism also writes sidecar YAML files describing each photo, a lost index can be rebuilt from the files alone, which is a real advantage for an archive you plan to keep for decades.
Whichever you pick, send those backups off the server on a schedule with encrypted, deduplicated restic backups to remote storage. A backup living on the same disk as the library is not a backup. Have the job shout when it fails, because a backup that quietly stopped running in March looks exactly like one that ran last night until the day you need it, and a self-hosted ntfy server will push that failure to your phone the same evening.
Which one should you run
Run Immich if your photos are on phones, if more than one person needs to back up a camera roll, and if you can give the server 6 GB of RAM or more. It is the closest thing to Google Photos you can host yourself, and the mobile experience is the point. Our step by step Immich install guide covers the memory kills and the upgrade traps in detail.
Run PhotoPrism if you already have a photo archive on disk, if you care about maps and metadata and keeping your own folder structure, or if your VPS has 4 GB of RAM and you would rather have a working library than a swapping one. It is the better curation tool and it is gentler on small hardware.
Running both is also reasonable. Immich handles daily phone ingestion, and once a year you sort the keepers into your archive and let PhotoPrism index that. They do not conflict, because PhotoPrism reads folders while Immich owns its own.
FAQ
Can PhotoPrism and Immich share the same photo folder?
Not safely in both directions. PhotoPrism indexes an originals folder and has features that write to it unless it runs in read-only mode, while Immich expects to own the contents of its upload location. You can point PhotoPrism at a read-only copy of Immich's library folder to browse it, but do not let both apps manage the same files, because Immich's storage template can move or rename assets under PhotoPrism while it is indexing.
Is Immich stable enough to hold the only copy of my photos?
No self-hosted app should ever hold the only copy of anything. Immich now follows semantic versioning and says breaking changes are limited to major releases, so pin IMMICH_VERSION to a major version tag such as v3, read the release notes, and then upgrade with docker compose pull && docker compose up -d. Downgrading is not supported, even within the same minor version, so take a database dump before every upgrade. Keep the original files backed up off the server and the risk stays small.
Why does the Immich machine learning container keep restarting?
Usually it is being killed for using too much memory. Run docker compose ps --all, because a stopped container is hidden without that flag, and look for the machine learning service exiting with code 137. That code means the process was killed with signal 9; the kernel out of memory killer is the usual cause but not the only one, so confirm it with sudo dmesg | grep -i 'out of memory'. Add swap, or disable machine learning entirely on a 4 GB machine. A memory limit on the container does not throttle it: at the limit it is still killed, but it stops starving the rest of the server. Smart search and face recognition stop working without machine learning, and the rest of Immich runs fine.
Does PhotoPrism need MariaDB, or will SQLite do?
SQLite works and is fine for a personal library, but PhotoPrism caps itself at four workers when using it, and the docs recommend switching to MariaDB because it handles high concurrency better. The compose file the project ships already includes MariaDB, so the recommended path is also the default one.
How much disk space should I budget above my library size?
Add 10 to 20 percent on top of the size of your originals, for either app. That covers generated thumbnails and transcoded video previews. A 200 GB collection needs roughly 220 to 240 GB for the library alone, plus room for the database and growth. If you also keep a complete local backup copy on the same volume, the originals and that copy need at least 400 GB before anything else is counted, so budget around 450 GB or put the copy on a separate volume.