If you’re running a homelab and want your own photo backup system that doesn’t send everything to Google, Immich is worth the time to set up. It’s a self-hosted photo and video server with AI-powered search, facial recognition, and object detection all running locally. This walkthrough covers installing Immich with Docker Compose on a standard Linux box.

Why Install Immich Instead of Cloud Photo Services
The obvious answer is privacy. Your photos stay on your hardware, not synced to someone’s data center. That part is real. But there’s a practical reason too: the AI features actually work offline and they’re genuinely useful. You can search for “my dog in the snow” and it finds those photos. You can see faces grouped across thousands of images. The machine learning models run on your own GPU or CPU, which means no monthly API costs and no rate limits.
There’s a catch though. If you’ve never self-hosted anything with machine learning components, Immich is heavier than a typical Docker container. The inference models take storage space, GPU memory if you use one, and CPU time on first run. I’ll cover what that looks like in the gotchas section.
Prerequisites and Hardware Specifications
You need a Linux box or VM running Docker and Docker Compose. I tested this on Ubuntu 22.04 LTS, but Debian, Fedora, or any Docker-capable Linux should work the same way.
Minimum specs: 4GB RAM, 2-core CPU, 50GB disk space (for OS, Immich, and some photos). This will work, but it’ll be slow during initial face recognition and tagging.
Comfortable specs: 8GB+ RAM, 4-core CPU, 250GB+ disk space, ideally an NVIDIA GPU if you want face recognition to finish in hours instead of days. A used RTX 3060 or 4060 makes a noticeable difference here.
You’ll also need Docker Compose installed. If you don’t have it yet, grab it from the official Docker docs. Make sure you can run docker ps and docker-compose --version without sudo, or you’ll spend the next three hours debugging permission errors.
Installing Immich with Docker Compose
The official Immich docs recommend pulling their example compose file and modifying it. That’s reasonable, but I’ll walk through the parts that matter and where you might need to change things.
First, create a directory for your Immich setup:
mkdir -p ~/immich-homelab
cd ~/immich-homelab
Next, grab the official docker-compose file from the Immich repository. As of early 2026, the current stable version is 1.110.x, but check immich.app for the latest:
curl https://raw.githubusercontent.com/immich-app/immich/main/docker/docker-compose.yml -o docker-compose.yml
This file pulls several services: the Immich server, Immich microservices (which handle the heavy ML work), PostgreSQL for metadata, Redis for caching, and Typesense for search. Before you run it, open the file and check a few things.
The default PostgreSQL password is hardcoded as postgres. Change it to something else. Edit this section:
services:
postgres:
environment:
POSTGRES_PASSWORD: "your-secure-password-here"
POSTGRES_DB: immich
Also add a password for the Immich API in the environment. Find the immich-server section and add:
immich-server:
environment:
DB_PASSWORD: "your-secure-password-here"
REDIS_PASSWORD: "your-redis-password-here"
By default, Immich listens on port 2283. That’s fine, but if you’re running other services, change the port binding in the compose file. Look for ports: - "2283:3001" and adjust the first number to whatever you want externally.
One important thing: the microservices container does the actual ML work. It’s memory-heavy during face recognition. The default docker-compose file doesn’t set memory limits, which is actually fine for most homelabs—you want that headroom for inference. But if you’re on a tight RAM box, you can limit it:
immich-microservices:
deploy:
resources:
limits:
memory: 4G
If you have an NVIDIA GPU and want Immich to use it for faster inference, add this to the microservices section:
immich-microservices:
runtime: nvidia
environment:
CUDA_VISIBLE_DEVICES: "0"
You’ll need the NVIDIA Container Runtime installed for this to work. If you haven’t set it up, do that first before starting the compose file.
Now start the stack:
docker-compose up -d
This pulls all the images, creates the containers, and starts them in the background. The first run takes a few minutes depending on your internet connection and hardware. You can watch the logs with:
docker-compose logs -f immich-server
Wait until you see something like Immich Server is running before moving on. This usually takes 30-60 seconds.
First-Run Configuration and Account Setup
Once the server is up, open your browser to http://localhost:2283 (or whatever port you mapped). You’ll hit the setup wizard. It asks you to create an admin account with an email and password. Use a real password here—this is the key to your photo library.
After that, you’re logged in to the web interface. You’ll see an empty library with an option to upload photos. But before you upload thousands of photos, configure a couple of things.
Go to Settings (bottom left, your profile icon). Under “Library,” turn on “Enabled Face Detection” if you want facial recognition. Also check “Enabled Clip Encoding”—this powers the “describe what you’re looking for” search that’s genuinely surprising when it works. Both of these will use CPU/GPU time, but they run in the background and you can adjust the scheduling.
In Settings under “Jobs,” you’ll see sliders for when Immich runs its ML tasks. By default, face detection runs at 2 AM. If your homelab is off at night, change this to something realistic for your setup. The slider is in 5-minute increments.
The mobile app setup comes next. Download the Immich app for iOS or Android, add your server address (your IP or domain on port 2283), log in with your admin credentials, and you can start backing up photos automatically. The app shows a backup status and you can configure which folders to sync.
A useful step: in the web interface, go to Administration and check the Storage location. By default, Immich stores uploads in the container’s `/usr/src/app/upload` directory, which means they’re lost if the container is deleted. You want to bind this to a directory on your host machine. Stop the compose stack and update your docker-compose file:
immich-server:
volumes:
- /mnt/photos/immich:/usr/src/app/upload
immich-microservices:
volumes:
- /mnt/photos/immich:/usr/src/app/upload
Make sure /mnt/photos/immich exists and has appropriate permissions. Then restart:
docker-compose down
docker-compose up -d
Common Gotchas and Troubleshooting
The biggest surprise I had: face detection is not fast. On a 4-core CPU with no GPU, processing 10,000 photos takes about 12 hours of continuous background work. If you upload that many photos at once, the microservices container will peg your CPU at 100% for a while. It works, but your homelab might be slow for other things. Spread uploads over a few days if you can, or schedule the jobs for off-peak hours.
Another common issue is that the Immich server loses connection to PostgreSQL on startup. This usually means the postgres container didn’t finish initializing before the server tried to connect. The compose file includes a health check, but it can take 30-45 seconds for the database to be ready on slow hardware. If you see connection errors in the logs, just wait and let it retry. It usually resolves itself.
If you’re using an NVIDIA GPU and it’s not being detected, check two things. First, run nvidia-smi on the host to confirm the GPU is visible. Second, confirm the NVIDIA Container Runtime is actually installed and set as the default runtime in your Docker daemon config. If you’ve never done this, the Docker documentation has a clear walkthrough, but it involves editing /etc/docker/daemon.json.
The microservices container sometimes runs out of memory during face recognition on large libraries. If you see the container killed by Docker, increase its memory limit or enable swap on the host. Not ideal, but it works.
One last gotcha: if you’re behind a reverse proxy (nginx, Caddy, etc.) and want the mobile app to work, you need to handle WebSocket connections correctly. Immich uses WebSockets for real-time backup status and notifications. Most reverse proxies need explicit WebSocket support in their config. If the app disconnects frequently, that’s usually why.
What to Do After Installation
Start small. Upload 100 photos through the web interface or the mobile app and let the inference jobs run. You’ll see faces get grouped in the People section and objects start appearing in search. It’s satisfying when it works, and it gives you a feel for how slow or fast the ML part is on your hardware.
Set up a regular backup strategy. Immich is excellent for redundancy, but it’s not a backup service—it’s a primary library. You still want the raw photos backed up somewhere else. Syncthing to another device or B2 backups both work well alongside Immich.
If you end up running this for a few months, consider setting up monitoring. Immich exposes Prometheus metrics on port 8081, so if you already have Grafana in your homelab, you can hook it up and watch CPU/memory usage during inference jobs. It’s not essential, but it helps you understand what’s actually happening during those background ML tasks.
The Immich community is active. If you run into something weird, their GitHub discussions are usually worth checking. The project updates regularly and gains features like better search, mobile improvements, and performance optimizations. It’s worth checking back every few months.
FAQ
Can Immich run on a Raspberry Pi?
Technically yes, but you won’t like it. A Raspberry Pi 5 can run the Immich server and store photos, but face detection and CLIP encoding take hours per thousand photos on ARM processors. It’s viable for small libraries under 1,000 photos, but beyond that, the wait times become frustrating. An x86 mini-PC from a few years ago is a better investment.
How much storage does Immich need?
Immich stores the original photos you upload, so you need at least as much space as your photo library. Add 10-15% for database metadata and cache. If you enable CLIP encoding for smart search, add another 500MB to 1GB for the model files. Face detection model files add another 200MB. The actual storage equation is: (photo size × count) + buffer + models.
Do I need a GPU for Immich?
No, but it helps significantly. Face detection on CPU takes roughly 1 second per photo on a modern 4-core processor. An NVIDIA GPU with at least 4GB VRAM cuts that to 0.2-0.3 seconds per photo. If you have fewer than 5,000 photos, CPU is fine. Over 10,000, a GPU starts to matter.
Can Immich search photos by description?
Yes, if you enable CLIP encoding in Settings. It indexes photos using vision AI and lets you search with natural language like “dog playing in snow” or “sunset over water.” The accuracy is reasonable, though it sometimes pulls in unexpected results. The CLIP model runs on startup and inference happens in the background.
Is Immich secure for remote access?
By default, no. Immich has no built-in HTTPS or authentication beyond the admin password. If you want to access it remotely, put it behind a reverse proxy (nginx, Caddy, Traefik) with TLS certificates and strong authentication. Never expose the raw Immich port directly to the internet.
Explore Immich in our AI Homelab Toolkit.
Recommended Hardware & Hosting
Build your homelab with hardware tested and used by our team.
Affiliate links — we may earn a small commission at no extra cost to you.