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.
- 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:
| Source | Avg per file | 10,000 photos = | 10,000 + 200 short videos = |
|---|---|---|---|
| iPhone HEIC photos | 2–4 MB | ~30 GB | ~50 GB |
| Android JPEG photos | 3–6 MB | ~45 GB | ~75 GB |
| Mirrorless / DSLR JPEG | 8–15 MB | ~100 GB | ~150 GB |
| Mirrorless / DSLR RAW | 20–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:
UPLOAD_LOCATION=/home/immich/immich-library— where photos actually live on disk. Plan storage accordingly (step 1).DB_PASSWORD=...— change from the default. Postgres password for the internal DB.
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 Settings → Security.
Under Administration → External 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):
- Backup → Backup Settings → toggle Foreground Backup and Background Backup
- Use Cellular Data: off by default — only uploads on Wi-Fi. Toggle on if you want full mobile coverage.
- Battery Optimization: on Android, exclude Immich from battery optimization in system settings, otherwise the OS kills background uploads
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 Administration → Jobs: 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
| Plan | Library size | Realistic use |
|---|---|---|
| Starter ($7.99, 4 GB RAM, 200 GB) | Up to 50k photos | 1 person, phone library only |
| Pro ($15.99, 8 GB, 1 TB NVMe) | Up to 250k photos | Family of 2–4, full phone + camera |
| Premium ($35.99, 8 GB, 4 TB HDD) | 500k+ photos | Family 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.