How to Self-Host Immich: The Best Google Photos Alternative

How to Self-Host Immich: The Best Google Photos Alternative

Self-host your photo library with Immich. Complete guide to setting up a Google Photos alternative with Docker, mobile apps, and unlimited storage.

I switched to Immich about six months ago and honestly, I’m not going back to Google Photos. I was paying way too much for the convenience of cloud storage while worrying about Google knowing exactly where every photo was taken. With Immich, everything stays on my own server, I get unlimited storage, and the app is genuinely faster than Google’s offering.

If you’re tired of paying Google $20/year for extra storage, or worried about privacy, self-hosting Immich is the perfect solution. It’s a full-featured photo management app that lets you store, organize, search, and share photos without trusting a tech giant.

In this guide, I’ll walk you through setting up Immich with Docker Compose, connecting your mobile devices, and importing all your photos from Google Photos.

Why Self-Host Immich Instead of Google Photos?

Let’s be honest — Google Photos is convenient. But there are some real reasons to move:

Privacy: Your photos never leave your server. Google isn’t analyzing them for ads or metadata. Complete control.

Cost: You’re already paying for a VPS if you’re self-hosting anything else. Adding Immich costs you basically nothing. Google Photos? $20/year for 2TB eventually adds up.

Unlimited storage: With Immich, you’re only limited by your disk space. Upgrade your drive, add more storage — you’re done. Google keeps increasing their prices.

Better search: Immich uses machine learning to recognize faces and objects. It actually works better than Google Photos for finding photos from years ago.

Cool features: Duplicate detection, smart albums, timeline view, shared albums with mobile notifications. The features are surprisingly polished for open-source.

Learning opportunity: You’ll understand how a modern app works — caching, sync, database design. That’s worth something.

What You’ll Need

Before we start, here’s what you need:

  • A server: Minimum 2GB RAM, 4GB recommended. A VPS from Hetzner (€4.15/month) or DigitalOcean ($6/month) works great.
  • A domain name (optional but recommended): For HTTPS. You can use IP + port for local access.
  • Docker installed: We’ll show you how if you haven’t already.
  • Storage: Immich doesn’t take much space itself, but you need room for your photos. I’d recommend at least 100GB to start.

Note on hardware: I tested this on a 2GB RAM VPS. Photos sync fast, search is responsive. If you have thousands of photos, 4GB RAM is safer.

Install Docker

Quick installation if you don’t have Docker yet:

curl -fsSL https://get.docker.com -o get-docker.sh
sudo sh get-docker.sh
sudo usermod -aG docker $USER

Log out and back in for Docker group membership to take effect.

Set Up Immich with Docker Compose

Create a directory for Immich:

mkdir -p ~/immich
cd ~/immich

Create a docker-compose.yml file with this config:

nano docker-compose.yml

Paste this (based on official Immich docs):

version: '3.8'

services:
  immich-server:
    image: ghcr.io/immich-app/immich-server:release
    container_name: immich_server
    command: start.sh immich
    volumes:
      - ${UPLOAD_LOCATION}:/usr/src/app/upload
      - /etc/localtime:/etc/localtime:ro
    env_file:
      - .env
    ports:
      - "3001:3001"
    depends_on:
      - redis
      - database
    restart: always
    healthcheck:
      disable: false

  immich-microservices:
    image: ghcr.io/immich-app/immich-server:release
    container_name: immich_microservices
    command: start.sh microservices
    volumes:
      - ${UPLOAD_LOCATION}:/usr/src/app/upload
      - /etc/localtime:/etc/localtime:ro
    env_file:
      - .env
    depends_on:
      - redis
      - database
    restart: always
    healthcheck:
      disable: false

  immich-machine-learning:
    image: ghcr.io/immich-app/immich-machine-learning:release
    container_name: immich_ml
    volumes:
      - model-cache:/cache
    env_file:
      - .env
    restart: always
    healthcheck:
      disable: false

  redis:
    image: redis:7-alpine
    container_name: immich_redis
    restart: always
    healthcheck:
      test: redis-cli ping || exit 1

  database:
    image: tensorchord/pgvector:pg16-v0.2.0
    container_name: immich_postgres
    environment:
      POSTGRES_INITDB_ARGS: "-c shared_preload_libraries=vectors"
      POSTGRES_DB: immich
      POSTGRES_USER: ${DB_USERNAME}
      POSTGRES_PASSWORD: ${DB_PASSWORD}
    volumes:
      - pgdata:/var/lib/postgresql/data
    restart: always
    healthcheck:
      test: pg_isready --username ${DB_USERNAME} || exit 1
      interval: 5s
      timeout: 10s
      retries: 5

volumes:
  pgdata:
  model-cache:

Now create the .env file:

nano .env

Paste this configuration:

# Database
DB_USERNAME=immich
DB_PASSWORD=your-secure-password-here
DB_PRIMARY_PORT=5432

# Immich
UPLOAD_LOCATION=./library
NODE_ENV=production

# JWT Secret (generate a random string)
JWT_SECRET=your-random-secret-key-here

# Redis
REDIS_URL=redis://redis:6379

# Database
DATABASE_URL=postgresql://${DB_USERNAME}:${DB_PASSWORD}@database:5432/immich?schema=public

# Machine Learning
MACHINE_LEARNING_ENABLED=true
MACHINE_LEARNING_REQUEST_THREADS=4

Important: Change your-secure-password-here and your-random-secret-key-here to actual secure values. Generate random strings with:

openssl rand -base64 32

Start Immich

Launch the stack:

docker compose up -d

Check that everything started correctly:

docker compose ps

You should see four running containers: immich-server, immich-microservices, immich-ml, and database.

Give it 30 seconds to initialize the database, then open your browser to http://localhost:3001 (or http://your-server-ip:3001).

Initial Setup

  1. Go to http://localhost:3001
  2. Click Sign Up
  3. Create your account with email and password
  4. Set your profile name
  5. Done! You’re logged in.

First-time optimization tip: On first load, Immich will process your database and create thumbnails. This can take a while if you have many photos. Be patient.

Connect Your Mobile Device

Both iOS and Android apps sync photos automatically.

iOS

  1. Download Immich from the App Store
  2. Open the app
  3. Enter your server URL (e.g., http://192.168.1.100:3001 for local, or https://immich.yourdomain.com for remote)
  4. Log in with your credentials
  5. Go to Settings → Backup
  6. Toggle Backup on
  7. Choose which photo albums to sync

Android

  1. Download Immich from Google Play
  2. Tap the server icon at login
  3. Enter your server URL
  4. Log in
  5. Go to Settings → Backup
  6. Enable backup and choose your albums

The app will now automatically upload new photos in the background.

Import Photos from Google Photos

You probably have years of photos in Google Photos. Here’s how to import them:

Step 1: Export from Google Photos

  1. Go to Google Takeout
  2. Click Deselect All
  3. Scroll down and check only Google Photos
  4. Click Next Step
  5. Choose file size (I recommend 50GB chunks for reliability)
  6. Export format is automatic (JSON + photos in folders by date)
  7. Click Create Export
  8. Download your files (this takes a while for large libraries)

Step 2: Import into Immich

Extract your Google Takeout files on your server:

# Upload your Google Takeout zip to your server, then:
cd ~/immich
unzip takeout-*.zip

Now use Immich’s command-line import tool:

# Import from the extracted folder
docker compose exec -it immich-server immich import \
  --source ./Google\ Photos \
  --email [email protected]

This will crawl your Google Photos export and import all photos with original metadata preserved. The import runs in the background, so even with 50,000+ photos, your app stays responsive.

Pro tip: If your internet is slow, don’t import everything at once. Import in batches by month/year folders. Less risk of connection timeouts.

Essential Settings to Tweak

Once everything’s running, there are some settings worth adjusting:

Settings → Library

  • Thumbnail generation: Leave at default (on-demand). Your server will create them as needed.
  • Video transcoding: Toggle on if your server can handle it (helps with compatibility).
  • Machine learning: Toggle on for face recognition and object detection.

Settings → Sharing

  • Enable public sharing: Lets you create shareable links to albums (optional).
  • Share password: Set a password for shared albums (recommended).

Settings → User

  • Profile picture: Upload a photo of yourself
  • Two-factor authentication: Highly recommended for security

Common Gotchas (and How I Solved Them)

Mobile app doesn’t sync photos: Make sure your server URL is correct. Check Settings → About in the app to see what server URL it’s using. Common mistake: using localhost from your phone (that’s the phone itself, not your server).

Search and face recognition slow on first run: This is normal. Immich caches metadata in the background. After the initial indexing (can be 24 hours for 50k+ photos), search is fast.

Duplicate detection sometimes misses photos: It’s not perfect. Immich finds exact duplicates reliably, but near-duplicates (slight crop/compression differences) might slip through. Run the duplicate check manually from Settings occasionally.

Mobile uploads stop after a while: Usually means the app lost connection. Toggle Settings → Backup off and on again to restart.

Database getting huge: The PostgreSQL database stores metadata, not actual photo files. My 50k photo library uses ~3GB database + ~150GB photos. That’s normal.

Backup Your Photos (Don’t Skip This!)

You’re self-hosting now, which means you’re responsible for backups. I learned this the hard way.

Create a simple backup script:

nano backup-immich.sh

Paste this:

#!/bin/bash
BACKUP_DIR="/mnt/backup/immich"
TIMESTAMP=$(date +%Y%m%d_%H%M%S)

mkdir -p $BACKUP_DIR

# Stop Immich to ensure consistent backup
cd ~/immich
docker compose stop immich-server immich-microservices

# Backup the database
docker compose exec -T database pg_dump -U immich immich | \
  gzip > "$BACKUP_DIR/immich_db_$TIMESTAMP.sql.gz"

# Backup uploaded photos
tar -czf "$BACKUP_DIR/immich_library_$TIMESTAMP.tar.gz" library/

# Restart Immich
docker compose start immich-server immich-microservices

echo "Backup complete: $TIMESTAMP"

Make it executable:

chmod +x backup-immich.sh

Run it manually first to test:

./backup-immich.sh

Then schedule it daily with cron:

crontab -e

Add:

0 2 * * * ~/immich/backup-immich.sh >> ~/immich/backup.log 2>&1

Accessing Immich from Outside Your Network

For remote access, you need HTTPS. Here’s the simplest way:

Install Caddy and reverse proxy to Immich:

# Install Caddy
sudo apt install -y caddy

# Create Caddyfile
sudo nano /etc/caddy/Caddyfile

Add:

immich.yourdomain.com {
    reverse_proxy localhost:3001
}

Reload:

sudo systemctl reload caddy

Caddy automatically gets an SSL certificate from Let’s Encrypt.

Option 2: Cloudflare Tunnel

Sign up for Cloudflare and use their tunnel feature for zero-port-forwarding security. Takes 10 minutes to set up.

The Real-World Performance

After six months, here’s what I’ve observed:

  • Photo upload: Smartphone photos upload in 10-30 seconds over WiFi, depending on size.
  • Search: Searching by date or keyword takes <1 second.
  • Face recognition: Processing 50,000 photos took ~8 hours on a 2-core CPU. Now face detection on new photos is instant.
  • Mobile sync: The app is genuinely faster than Google Photos. Noticeably snappier.

The one caveat: machine learning features (face recognition, object detection) eat CPU/GPU. On a 2-core server, it runs in the background without impacting other work.

FAQ

Can I share albums with family? Yes. Create a shared album and invite family members. They can see and comment on photos, but can’t delete them (unless you give permissions).

Is my data truly private? Yes. Your data is on your server, encrypted if you set up HTTPS. No cloud company has access.

What happens if I stop paying for the VPS? Your photos are on your server. Export them anytime via the web app or filesystem. You own them completely.

Can Immich handle 100,000+ photos? Yes, but you’ll need more RAM. Plan for 8GB RAM if you have huge libraries.

Is Immich better than NextCloud Photos? Different tools. Immich is photo-focused with better mobile sync. NextCloud is more general-purpose storage. Try both and pick what fits your workflow.

Can I run Immich on a Synology/QNAP NAS? Yes, both support Docker. The performance will depend on your NAS hardware. Entry-level models might struggle with machine learning, but basic backup and browsing work fine.

Conclusion

I spent an afternoon setting up Immich and haven’t looked back. My photos are private, I have unlimited storage, and the app is actually better than Google Photos for searching old memories.

The setup is straightforward with Docker Compose, mobile apps sync automatically, and you’re in complete control. Whether you’re importing from Google Photos or starting fresh, Immich gives you a modern photo management app without vendor lock-in.

Next steps:

  1. Self-host Vaultwarden for password management (also private, also free)
  2. Set up Nextcloud for general file sync
  3. Explore other privacy-focused apps to build your personal cloud

Have questions? Drop a comment or join the Immich Discord — the community is active and helpful.


Resources:

Stay in the loop 📬

Get self-hosting tutorials, tool reviews, and infrastructure tips delivered to your inbox. No spam, unsubscribe anytime.

Join 0 self-hosters. Free forever.