Google Photos is great until you realize they've trained their face-recognition AI on your kids, can scan every image for ad signals, and quietly downgrade 'free' photos to 1080p compressed previews. Immich is the open-source answer that's matured fast in 2024–25: iOS and Android apps with reliable background uploads, AI face recognition and object search that runs entirely on your hardware, original-quality storage, and a UI that genuinely feels as good as Google Photos.

This guide installs Immich via Docker Compose, sets up Nginx + Let's Encrypt for HTTPS, configures the iOS/Android apps for auto-upload, runs the initial AI scan over your library, and handles backups. The hard parts most tutorials skip — storage planning, CPU-only AI performance, mobile background-upload reliability — get explicit attention.

🐾 What you'll need:
  • A Linux VPS — Ubuntu 22.04 or Debian 12, 4 GB RAM minimum
  • Plenty of storage — see step 2 for sizing
  • A domain pointed at your VPS
  • Roughly 30 minutes

Want Immich pre-installed with the right storage allocation? Our Immich VPS plans ship with 200 GB to 4 TB of storage tuned for photo libraries.

1. Storage planning — read this first

The single biggest mistake people make with self-hosted photo galleries is underestimating storage. Real numbers:

SourceAvg per file10,000 photos =10,000 + 200 short videos =
iPhone HEIC photos2–4 MB~30 GB~50 GB
Android JPEG photos3–6 MB~45 GB~75 GB
Mirrorless / DSLR JPEG8–15 MB~100 GB~150 GB
Mirrorless / DSLR RAW20–50 MB~300 GB~400 GB
Phone 1080p video~120 MB/min+24 GB per hour of video
Phone 4K video~350 MB/min+70 GB per hour of video

For a 5-year iPhone library: expect 150–300 GB. For a family of 4 with shared library: easily 500 GB+. Storage runs out faster than you think — pick a VPS plan with room to grow.

2. Prepare the VPS

apt update && apt upgrade -y
apt install -y curl ca-certificates gnupg ufw

ufw allow 22/tcp
ufw allow 80/tcp
ufw allow 443/tcp
ufw --force enable

# Non-root user for Immich
adduser immich
usermod -aG sudo immich
rsync --archive --chown=immich:immich ~/.ssh /home/immich

3. Install Docker

install -m 0755 -d /etc/apt/keyrings
curl -fsSL https://download.docker.com/linux/ubuntu/gpg | \
  gpg --dearmor -o /etc/apt/keyrings/docker.gpg

echo "deb [arch=$(dpkg --print-architecture) signed-by=/etc/apt/keyrings/docker.gpg] \
  https://download.docker.com/linux/ubuntu $(. /etc/os-release && echo "$VERSION_CODENAME") stable" | \
  tee /etc/apt/sources.list.d/docker.list > /dev/null

apt update
apt install -y docker-ce docker-ce-cli containerd.io docker-compose-plugin
usermod -aG docker immich

If you've never set up Docker before, our Docker on Ubuntu tutorial covers daemon hardening and rootless mode in depth.

4. Deploy Immich

Immich ships a docker-compose.yaml directly from their docs. Switch to the immich user and download it:

su - immich
mkdir -p ~/immich
cd ~/immich

curl -L -o compose.yaml \
  https://github.com/immich-app/immich/releases/latest/download/docker-compose.yml
curl -L -o .env \
  https://github.com/immich-app/immich/releases/latest/download/example.env

Edit .env:

nano .env

Two key variables:

Create the library directory and start everything:

mkdir -p ~/immich-library
docker compose up -d
docker compose logs -f

First start pulls ~3 GB of Docker images (Postgres, Redis, the Immich server, the ML server). Total time: 3–6 minutes. When you see Immich Server is listening on port 2283, the API is up.

5. Nginx reverse proxy + HTTPS

sudo apt install -y nginx certbot python3-certbot-nginx

sudo tee /etc/nginx/sites-available/immich <<'EOF'
server {
    listen 80;
    server_name photos.example.com;

    # Photos and videos can be huge — bump the body size
    client_max_body_size 5G;
    proxy_read_timeout 600s;
    proxy_send_timeout 600s;

    location / {
        proxy_pass http://127.0.0.1:2283;
        proxy_set_header Host $host;
        proxy_set_header X-Real-IP $remote_addr;
        proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;
        proxy_set_header X-Forwarded-Proto $scheme;
        proxy_http_version 1.1;
        proxy_set_header Upgrade $http_upgrade;
        proxy_set_header Connection "upgrade";
    }
}
EOF

sudo ln -s /etc/nginx/sites-available/immich /etc/nginx/sites-enabled/
sudo nginx -t && sudo systemctl reload nginx
sudo certbot --nginx -d photos.example.com

Visit https://photos.example.com — you should see the Immich setup wizard.

6. First account and library config

The first user you create becomes the admin. Use a strong password — Immich serves your entire photo library through this login. Optionally enable 2FA under Account SettingsSecurity.

Under AdministrationExternal Libraries, you can also point Immich at existing photo folders on disk (read-only or read-write). Useful if you already have years of photos in a folder structure you want to keep.

🐾 Already sized for photos

Our Photo Gallery VPS plans ship with 200 GB to 4 TB of storage and Immich pre-installed. We pick the right plan for your library size in 60 seconds.

See Immich VPS Plans →

7. Configure mobile apps

Install Immich from the App Store (iOS) or Play Store / F-Droid (Android). Open the app, tap Login, enter https://photos.example.com as the server URL, then your email/password.

For background auto-upload (the killer feature):

On iOS, background uploads are limited by Apple's restrictions — they happen but unpredictably. Open the app once a day to flush queued uploads. Android background uploads are more reliable.

8. Run the AI scan

Immich's killer feature: local AI for face recognition and content-based search. No third-party services, all runs on CPU.

The first scan over a 100 GB library takes 4–8 hours on a Pro plan VPS — it processes every photo through CLIP (for content search) and a face detection model. Subsequent uploads scan in seconds.

Under AdministrationJobs: see the queue. The Smart Search job is the CLIP indexer. Face Detection finds faces. Facial Recognition groups them into clusters you can name.

Tune the ML container's CPU limit in compose.yaml if it's eating too much CPU during initial scan:

  immich-machine-learning:
    # ... existing config ...
    deploy:
      resources:
        limits:
          cpus: '2.0'   # cap at 2 cores

9. Backups

Two things to back up:

The library itself — your photos. Use rclone to mirror to S3 / Backblaze B2:

sudo apt install -y rclone
rclone config  # set up your remote

# Daily mirror at 4 AM
crontab -e
# Add:
0 4 * * * rclone sync /home/immich/immich-library remote:immich-backup --transfers=4 --bwlimit 50M

The database — user accounts, face clusters, album definitions:

cat > /home/immich/backup-db.sh <<'EOF'
#!/bin/bash
cd /home/immich/immich
docker compose exec -T database pg_dumpall --clean --if-exists --username=postgres \
  | gzip > /home/immich/db-backups/immich-$(date +%F).sql.gz
find /home/immich/db-backups -name '*.sql.gz' -mtime +30 -delete
EOF
chmod +x /home/immich/backup-db.sh

# Add to cron — runs at 3 AM (before the library sync)
echo "0 3 * * * /home/immich/backup-db.sh" | crontab -

Test recovery! Untested backups aren't backups.

10. Reference: scaling and performance

Per-plan recommendations

PlanLibrary sizeRealistic use
Starter ($7.99, 4 GB RAM, 200 GB)Up to 50k photos1 person, phone library only
Pro ($15.99, 8 GB, 1 TB NVMe)Up to 250k photosFamily of 2–4, full phone + camera
Premium ($35.99, 8 GB, 4 TB HDD)500k+ photosFamily of 4+, decade of full RAW + 4K video

NVMe vs HDD for photo storage

NVMe is faster but expensive per GB. HDD is slow on first thumbnail generation but fine for cached browsing afterward. For libraries under 500 GB, NVMe gives a snappier first experience. For larger libraries, HDD with NVMe cache (via bcache or LVMcache) is the practical sweet spot — most VPS providers offer this hybrid model. Our NVMe vs SSD explainer covers the trade-offs in depth.

Hardware-accelerated transcoding

Immich can transcode videos to web-friendly formats. Without GPU acceleration this is slow — set the transcode quality to "Web optimized" and let it run overnight. With GPU passthrough (rare on shared VPS but available on our dedicated nodes), full HEVC → H.264 transcoding runs at 5× real-time.

External libraries vs upload

External libraries point Immich at an existing folder. Useful if you have a NAS or external drive mounted via NFS. The library is indexed but files stay in place — moving or renaming files outside Immich requires a re-scan.

Mobile app reliability

Android background upload is reliable if you whitelist Immich in battery optimization. iOS background upload is best-effort — Apple kills background processes after a few minutes, so foreground uploads (open the app daily) cover the rest. There's no fix for this; it's an iOS platform limitation.

FAQ

How does Immich compare to PhotoPrism / Nextcloud Photos?

Immich wins on mobile apps — both iOS and Android are first-class with reliable auto-upload. PhotoPrism is more mature for desktop browsing and metadata editing. Nextcloud Photos is bundled with Nextcloud and great if you already self-host that. Immich is the best choice if 'replace Google Photos' is your specific goal.

Will my photos be readable on the VPS file system?

Yes — Immich stores originals in the file system under your UPLOAD_LOCATION. Folder structure mirrors your timeline. If you ever stop using Immich, all your originals are still in ~/immich-library/ as plain JPEG / HEIC / MP4 files. No proprietary format.

Can I import from Google Takeout?

Yes — Immich has a CLI tool (immich-go) specifically for Google Takeout. Download your takeout zip, run immich-go upload, and it ingests photos with their original metadata (timestamps, locations, album structure). Plan ~1 hour per 50 GB of source.

How much CPU does the AI use?

Initial scan is CPU-heavy — a 100 GB library can saturate 4 cores for several hours. After the initial scan, incremental work is light (face detection on new uploads only). The CLIP model used for content search is small enough to run on CPU at ~5 photos/second.

Does this work for multiple family members?

Yes — Immich supports multiple users, each with their own library and quota. Optional shared albums let you pool family vacation photos without merging libraries. Each person installs the mobile app, logs into their own account, and their phone uploads to their library.

What if my VPS storage fills up?

Immich keeps working but new uploads fail. The mobile app shows the error. Upgrade your plan or move the library to attached block storage. Adding storage is straightforward: mount a new disk, rsync the library, update UPLOAD_LOCATION in .env, restart. Plan ahead — bigger libraries also mean bigger backup bandwidth.

🐱
OliveVPS Team

We migrated 180 GB of family photos from Google Photos to Immich and never looked back. The face-recognition AI found people we'd forgotten about — including a cat that consistently shows up in 300+ photos.