Google Photos was perfect until it wasn't. The free unlimited storage ended, privacy concerns grew, and now you're paying $10/month for 2TB while Google trains AI on your family photos.
Immich is the answer. It's a self-hosted photo and video management solution that looks and feels like Google Photos, but you own all your data. Machine learning features, mobile apps, automatic backups—all running on your own server.
This guide walks you through deploying Immich on a VPS, including storage optimization, mobile app setup, and backup strategies.
Why Immich?
| Feature | Google Photos | iCloud Photos | Immich (Self-Hosted) |
|---|---|---|---|
| Cost (2TB) | $10/mo ($120/yr) | $10/mo ($120/yr) | ~€10/mo (VPS + S3) |
| Data Ownership | Apple | 100% Yours | |
| Privacy | AI training | Better | Complete |
| Face Recognition | Yes | Yes | Yes (local ML) |
| Object Detection | Yes | Yes | Yes (local ML) |
| Mobile Apps | iOS, Android | iOS | iOS, Android |
| Auto Backup | Yes | Yes | Yes |
| Memories | Yes | Yes | Yes |
| Sharing Albums | Yes | Yes | Yes |
Requirements
Immich needs more resources than a typical web app due to machine learning features:
| Photo Library Size | RAM | Storage | DanubeData Plan |
|---|---|---|---|
| < 50,000 photos | 4 GB | Photos + 50GB | Standard (€8.99/mo) |
| 50,000 - 200,000 | 8 GB | Photos + 100GB | Performance (€17.99/mo) |
| > 200,000 photos | 16 GB+ | Photos + 200GB | Dedicated plans |
Note: The ML models need ~4GB RAM. For large libraries, consider storing photos on S3 and using the VPS for compute.
Step 1: Provision Your VPS
- Create a VPS on DanubeData
- Choose Ubuntu 24.04 LTS
- Select at least Standard plan (4GB RAM) or Performance (8GB) for larger libraries
- Add extra storage if keeping photos locally
Step 2: Initial Server Setup
# SSH into your server
ssh root@YOUR_SERVER_IP
# Update system
apt update && apt upgrade -y
# Install Docker
curl -fsSL https://get.docker.com | sh
# Install Docker Compose
apt install -y docker-compose-plugin
# Configure firewall
ufw allow OpenSSH
ufw allow 80/tcp
ufw allow 443/tcp
ufw enable
# Create immich user
useradd -m -s /bin/bash immich
usermod -aG docker immich
Step 3: Configure DNS
Point your domain to your server:
Type: A
Name: photos
Value: YOUR_SERVER_IP
TTL: 300
Step 4: Download and Configure Immich
# Switch to immich user
su - immich
# Create directory
mkdir -p ~/immich
cd ~/immich
# Download Immich files
wget -O docker-compose.yml https://github.com/immich-app/immich/releases/latest/download/docker-compose.yml
wget -O .env https://github.com/immich-app/immich/releases/latest/download/example.env
wget -O hwaccel.transcoding.yml https://github.com/immich-app/immich/releases/latest/download/hwaccel.transcoding.yml
wget -O hwaccel.ml.yml https://github.com/immich-app/immich/releases/latest/download/hwaccel.ml.yml
Configure Environment Variables
# Edit .env file
nano .env
Update these key settings:
# .env configuration
# Directory where your photos will be stored
UPLOAD_LOCATION=/home/immich/photos
# Database password (generate a secure one)
DB_PASSWORD=your_secure_database_password_here
# Timezone
TZ=Europe/Berlin
# Optional: Reverse proxy configuration
# IMMICH_WEB_URL=http://immich-web:3000
# IMMICH_SERVER_URL=http://immich-server:3001
Create Photo Storage Directory
# Create photo storage directory
mkdir -p /home/immich/photos
# Set permissions
chown -R immich:immich /home/immich/photos
Step 5: Set Up Reverse Proxy (Caddy)
# As root user
exit
# Install Caddy
apt install -y debian-keyring debian-archive-keyring apt-transport-https
curl -1sLf 'https://dl.cloudsmith.io/public/caddy/stable/gpg.key' | gpg --dearmor -o /usr/share/keyrings/caddy-stable-archive-keyring.gpg
curl -1sLf 'https://dl.cloudsmith.io/public/caddy/stable/debian.deb.txt' | tee /etc/apt/sources.list.d/caddy-stable.list
apt update && apt install -y caddy
# Configure Caddy
cat > /etc/caddy/Caddyfile << 'EOF'
photos.yourdomain.com {
reverse_proxy localhost:2283
# Handle large file uploads
request_body {
max_size 50GB
}
# Security headers
header {
X-Content-Type-Options nosniff
X-Frame-Options SAMEORIGIN
Referrer-Policy strict-origin-when-cross-origin
}
encode gzip
}
EOF
# Reload Caddy
systemctl reload caddy
Step 6: Launch Immich
# Switch back to immich user
su - immich
cd ~/immich
# Start Immich
docker compose up -d
# Watch logs
docker compose logs -f
# Wait for all services to be healthy (takes a few minutes)
docker compose ps
Expected Services
# You should see these containers running:
immich-server - Main API server
immich-web - Web interface
immich-machine-learning - ML for face/object detection
immich-postgres - Database
immich-redis - Cache
Step 7: Initial Setup
- Visit
https://photos.yourdomain.com - Click "Getting Started"
- Create your admin account
- Configure your preferences
Step 8: Configure Mobile Apps
iOS App
- Download "Immich" from the App Store
- Open the app and tap "Connect to Server"
- Enter your server URL:
https://photos.yourdomain.com - Log in with your credentials
- Enable background backup in Settings → Backup
Android App
- Download "Immich" from Google Play or F-Droid
- Enter server URL:
https://photos.yourdomain.com - Log in with your credentials
- Grant photo/video permissions
- Enable auto-backup in Settings → Backup
Backup Settings (Both Platforms)
# Recommended settings:
- Backup: Enabled
- Background Backup: Enabled
- WiFi Only: Enabled (to save mobile data)
- Require Charging: Optional
- Include Videos: Enabled
- Backup Albums: Select which albums to backup
Step 9: Import Existing Photos
From Google Photos (Google Takeout)
- Go to takeout.google.com
- Select only "Google Photos"
- Export (may take hours/days for large libraries)
- Download the ZIP files
- Extract and upload to Immich:
# Using the CLI tool
npm install -g @immich/cli
# Configure CLI
immich login https://photos.yourdomain.com YOUR_API_KEY
# Upload photos
immich upload --recursive /path/to/extracted/takeout
From Local Folder
# Copy directly to server (rsync recommended)
rsync -avz --progress /local/photos/ immich@your-server:/home/immich/photos/import/
# Then use Immich's external library feature:
# Settings → External Libraries → Add Library → Select /home/immich/photos/import
Using the Web Upload
- Log into the web interface
- Click the upload button
- Select files (supports drag & drop)
- For large uploads, use the CLI instead
Step 10: Machine Learning Features
Immich includes powerful ML features that run locally:
Face Recognition
- Automatically detects and groups faces
- You can name people to organize photos
- Search by person name
Enable in: Settings → Machine Learning → Facial Recognition
Smart Search
- Search by description: "sunset at beach", "birthday party", "dog playing"
- Uses CLIP model for semantic understanding
Object Detection
- Identifies objects in photos
- Auto-tags photos for organization
ML Performance Tuning
# For servers with limited RAM, reduce ML workers
# Edit docker-compose.yml
services:
immich-machine-learning:
environment:
- MACHINE_LEARNING_WORKERS=1 # Reduce from default
- MACHINE_LEARNING_WORKER_TIMEOUT=120
Step 11: External Storage (S3)
For large photo libraries, store photos on S3 instead of local disk:
# Create S3 bucket on DanubeData
# Name: photos-storage
# Update .env
UPLOAD_LOCATION=s3://photos-storage
# Or use External Libraries feature to mount S3
# This keeps photos in S3 and Immich just indexes them
Using rclone to Mount S3
# Install rclone
curl https://rclone.org/install.sh | sudo bash
# Configure rclone
rclone config
# Add remote named "danubedata" with your S3 credentials
# Mount S3 bucket
mkdir -p /home/immich/s3-photos
rclone mount danubedata:photos-storage /home/immich/s3-photos
--vfs-cache-mode full
--vfs-cache-max-size 10G
--allow-other
--daemon
# Add to Immich as External Library
Step 12: Backup Strategy
Your photo library is precious. Set up proper backups:
Database Backup
#!/bin/bash
# /home/immich/backup-db.sh
BACKUP_DIR="/home/immich/backups"
DATE=$(date +%Y-%m-%d_%H-%M-%S)
mkdir -p $BACKUP_DIR
# Backup PostgreSQL
docker exec immich_postgres pg_dump -U postgres immich | gzip > "$BACKUP_DIR/immich_db_$DATE.sql.gz"
# Keep last 7 days
find $BACKUP_DIR -name "*.sql.gz" -mtime +7 -delete
# Upload to S3
rclone copy "$BACKUP_DIR/immich_db_$DATE.sql.gz" danubedata:backups/immich/
echo "Database backup complete: $DATE"
Photo Backup to S3
#!/bin/bash
# /home/immich/backup-photos.sh
# Sync photos to S3 backup bucket
rclone sync /home/immich/photos danubedata:photos-backup
--progress
--transfers 8
Schedule Backups
# Add to crontab
crontab -e
# Daily database backup at 3 AM
0 3 * * * /home/immich/backup-db.sh >> /home/immich/logs/backup.log 2>&1
# Weekly full photo backup on Sunday at 4 AM
0 4 * * 0 /home/immich/backup-photos.sh >> /home/immich/logs/backup.log 2>&1
Step 13: Maintenance and Updates
Update Immich
cd ~/immich
# Pull latest images
docker compose pull
# Restart with new version
docker compose up -d
# Check logs for issues
docker compose logs -f
Monitor Resources
# Check disk usage
df -h
# Check Docker resource usage
docker stats
# Check Immich logs
docker compose logs immich-server
docker compose logs immich-machine-learning
Advanced Configuration
Multiple Users
Immich supports multiple users with separate libraries:
- Admin → User Management → Create User
- Each user gets their own storage quota
- Users can share albums with each other
Shared Albums
- Create album → Add photos → Share
- Generate public links for non-users
- Set expiration dates on shared links
OAuth/OIDC
# Enable OAuth in .env
OAUTH_ENABLED=true
OAUTH_ISSUER_URL=https://auth.yourdomain.com
OAUTH_CLIENT_ID=immich
OAUTH_CLIENT_SECRET=your_secret
OAUTH_SCOPE="openid profile email"
Cost Analysis
| Solution | 2TB Photos | 5TB Photos | Annual Cost |
|---|---|---|---|
| Google Photos | $10/mo | $25/mo | $120-300/yr |
| iCloud | $10/mo | N/A (2TB max) | $120/yr |
| Immich (VPS only) | €8.99/mo | €17.99/mo | €108-216/yr |
| Immich (VPS + S3) | €8.99 + €8/mo | €8.99 + €20/mo | €204-348/yr |
Key advantage: With self-hosting, you pay for actual storage used, not storage tiers. And you get unlimited users—perfect for families.
Troubleshooting
Mobile App Can't Connect
# Check server is accessible
curl https://photos.yourdomain.com/api/server-info/ping
# Verify SSL certificate
openssl s_client -connect photos.yourdomain.com:443
Slow Performance
# Check if ML is overloaded
docker stats immich-machine-learning
# Reduce ML workers if needed
# Or upgrade VPS RAM
Upload Failures
# Check disk space
df -h
# Check Caddy upload size limit
# Ensure request_body max_size is large enough
# Check server logs
docker compose logs immich-server
Get Started Today
Ready to take control of your photo library?
- Create a VPS on DanubeData (€8.99/mo minimum)
- Follow this guide to deploy Immich
- Install the mobile apps and start backing up
- Import your existing photos from Google/iCloud
Recommended Setup:
- VPS: Standard €8.99/mo (4GB RAM) for up to 50K photos
- S3 Storage: €3.99/mo base + usage for photo storage
- Total: ~€13/mo for a complete Google Photos replacement
Questions about setting up Immich? Contact our team—we're happy to help you break free from Big Tech photo services.