Why Run Two Photo Managers at Once
Most self-hosted photo setups ask you to pick a side: Immich for its fast mobile backup and clean interface, or PhotoPrism for its deep AI tagging and browser-based organization. Running both together sounds redundant until you realize they solve different problems. Immich is built around continuous mobile sync – open the app, walk in the door, your photos are already backed up. PhotoPrism works best as a retrospective library tool, crawling through years of existing photos and tagging them by subject, location, and scene type. Neither does the other’s job particularly well.
The setup described here keeps both running on the same machine, pointing at overlapping or complementary storage paths, so your photos get the speed of Immich’s mobile client and the AI depth of PhotoPrism’s indexing engine. No cloud subscriptions, no vendor lock-in, and full control over where your files live. Before starting, make sure Docker and Docker Compose are installed, and that you have enough storage headroom for both databases. PhotoPrism’s index alone can grow significantly depending on library size.

Setting Up Immich First
Immich should go in first because it handles the live ingestion side of the pipeline. Create a dedicated directory for the project – something like /opt/immich – and inside it create a docker-compose.yml file. The official Immich compose file pulls in four containers: the main server, a microservices worker, a machine learning container for face recognition and CLIP embeddings, and a PostgreSQL database with the pgvecto-rs extension. Redis handles job queuing between them. Pull the example compose file from the Immich GitHub repository directly rather than copying fragmented snippets from older tutorials, since the project updates its stack fairly often and field names change between versions.
Set your upload library path by editing the UPLOAD_LOCATION environment variable in the .env file that ships alongside the compose file. This is the directory where Immich writes incoming photos from the mobile app. Point it somewhere with room to grow – an external drive mount or a dedicated data partition works well here. Once the stack is up with docker compose up -d, navigate to http://your-server-ip:2283 and complete the first-run wizard. Create your admin account, then download the Immich app on your phone and point it at the same address. Auto-backup will start working as soon as you grant the app storage permissions. Give the machine learning container five to ten minutes to initialize on first run – it downloads model weights during startup, and the logs will show progress if you watch with docker compose logs -f immich-machine-learning.
Configuring PhotoPrism to Watch the Same Library
PhotoPrism gets its own compose file in a separate directory, such as /opt/photoprism. The key variable to set here is PHOTOPRISM_ORIGINALS_PATH, which you should map to the same upload directory Immich writes to – or to a parent directory that contains it. When PhotoPrism scans its originals folder, it reads photos without moving or modifying them, which means Immich and PhotoPrism can share the same file tree without stepping on each other. The only file PhotoPrism writes back are sidecar XMP or YAML metadata files in a configurable sidecar directory, so keep that pointed somewhere outside the originals path to avoid cluttering Immich’s file view.
PhotoPrism’s compose file needs at minimum three services: the main app container, and a MariaDB instance for its database. Unlike Immich, PhotoPrism does not use Redis or a separate worker – the indexing runs inside the main container as a background process. Set a strong PHOTOPRISM_ADMIN_PASSWORD in the environment block and bind port 2342 to the host. Bring the stack up with the same docker compose up -d command from the /opt/photoprism directory.
After the containers start, navigate to http://your-server-ip:2342 and log in with the admin credentials. Go to Library, then Index, and run a full index of the originals path. Depending on how many photos are already in that directory, the first index can take anywhere from a few minutes to several hours. PhotoPrism processes TensorFlow-based image recognition locally, so expect CPU usage to spike during this period. If you’re running this on a machine without a GPU, set PHOTOPRISM_WORKERS to match your available core count to get the most out of the CPU-only indexing path.
One practical issue: Immich stores photos in a nested date-based folder structure – year, month, day subdirectories under the upload root. PhotoPrism handles nested directories without any additional configuration, so pointing it at the Immich upload root rather than individual year folders is the cleaner approach. If you also have a pre-existing photo archive outside the Immich path, you can mount that as a second read-only volume under a different path inside the PhotoPrism container and include it in the same index job.

Handling Metadata and Avoiding Conflicts
Both tools read EXIF data from the original files, but they maintain separate internal databases. This means if you add a face tag or album in Immich, PhotoPrism won’t see it, and vice versa. That’s not necessarily a problem if you use each tool for what it does best: Immich for album organization, sharing, and mobile review; PhotoPrism for deep search queries, label browsing, and bulk filtering by scene type or color. Treat them as complementary views of the same file system rather than synced databases.
Where conflicts can occur is with sidecar files. If PhotoPrism is configured to write XMP sidecars and Immich later scans those same directories for metadata, you may see unexpected behavior in Immich’s file listings. The safest configuration keeps PHOTOPRISM_SIDECAR_PATH pointed to a path completely outside the Immich upload directory – for example, /opt/photoprism/sidecars on the host, mapped into the container. This keeps both tools operating on clean shared originals without either one’s metadata artifacts interfering with the other.
Automating Rescans and Keeping Both Libraries Fresh
Immich indexes new uploads automatically as they arrive through the mobile app. PhotoPrism does not watch for file changes in real time by default – it relies on scheduled or manual index runs. The cleanest solution is a cron job on the host that triggers PhotoPrism’s index API on a schedule. PhotoPrism exposes a simple API endpoint for this: a POST request to /api/v1/index with the appropriate authorization header will kick off an incremental index that only processes new or changed files. Run this every hour or every few hours depending on how frequently you shoot.
A minimal cron entry to trigger an incremental PhotoPrism index looks like this: add a line to your crontab with curl -s -X POST http://localhost:2342/api/v1/index -H “X-Session-ID: your-session-token”. You can retrieve a session token by logging in through the API’s /api/v1/session endpoint with your admin credentials and pulling the token from the response. Store it in an environment variable or a small shell script rather than hardcoding it in the crontab directly.

If you want to go further, Immich also exposes an API that lets you query recently added assets, which means you could build a lightweight script that checks Immich for new uploads and triggers a targeted PhotoPrism scan only when new files are detected. This keeps PhotoPrism’s indexing focused rather than walking the entire library on every run – a meaningful difference once your archive grows past a few hundred gigabytes. For anyone already running PhotoPrism as a standalone photo manager, integrating Immich alongside it mostly comes down to aligning the storage paths and setting up that cron job. The two stacks are independent enough that neither affects the other’s stability, which means you can update one without touching the other – a real advantage when Immich ships breaking changes, which it does fairly regularly.





