Every photo you upload to Google Photos trains Google's AI models, gets scanned for advertising insights, and lives on infrastructure you don't control. When Google decides to reduce free storage, change pricing, or discontinue a feature, you comply or lose access. Immich changes that equation entirely — it's a self-hosted photo and video management platform that delivers the Google Photos experience on your own Ubuntu VPS, with full privacy and zero subscription fees.

Immich has matured rapidly since its initial release, now offering mobile auto-backup, facial recognition, smart search, map view, shared albums, and timeline browsing. Running it on a VPS rather than a NAS at home means your photos are accessible from anywhere with enterprise-grade uptime, and you're not dependent on your home internet connection or a single hard drive that could fail.

MassiveGRID Ubuntu VPS includes: Ubuntu 24.04 LTS pre-installed · Proxmox HA cluster with automatic failover · Ceph 3x replicated NVMe storage · Independent CPU/RAM/storage scaling · 12 Tbps DDoS protection · 4 global datacenter locations · 100% uptime SLA · 24/7 human support rated 9.5/10

Deploy a self-managed VPS — from $1.99/mo
Need dedicated resources? — from $19.80/mo
Want fully managed hosting? — we handle everything

Why Self-Host Your Photo Library

The case for self-hosting photos goes beyond privacy ideology — it's a practical decision with measurable benefits:

Immich vs Google Photos vs Synology Photos

Choosing a photo management platform means weighing features against control. Here's how the three main options compare:

Immich is the clear winner for anyone who wants Google Photos functionality without Google Photos compromises. Running it on a VPS eliminates the single-point-of-failure problem that plagues home NAS setups.

Prerequisites

Immich requires Docker and Docker Compose for deployment. If you haven't installed Docker yet, follow our Docker installation guide for Ubuntu VPS first.

Immich's resource profile is storage-heavy but compute-light during normal use. A Cloud VPS with 4 vCPU / 4GB RAM and 100GB+ storage handles a library of 50K+ photos. The machine learning container uses more CPU during initial indexing but settles to minimal usage once your library is processed.

Sizing guidelines by library size:

These estimates assume a mix of smartphone photos (3–8MB each) and some videos. RAW photos or 4K video will shift storage requirements significantly upward.

Docker Compose Setup

Create a directory for Immich and download the official configuration files:

mkdir -p /opt/immich && cd /opt/immich

Create the environment file with your configuration:

cat > /opt/immich/.env << 'EOF'
# Database
DB_PASSWORD=CHANGE_ME_strong_random_password_here
DB_USERNAME=postgres
DB_DATABASE_NAME=immich

# Redis
REDIS_HOSTNAME=immich_redis

# Upload location
UPLOAD_LOCATION=/opt/immich/library

# Immich version — pin to a specific release
IMMICH_VERSION=release

# Machine learning
MACHINE_LEARNING_ENABLED=true
EOF

Create the Docker Compose file:

cat > /opt/immich/docker-compose.yml << 'EOF'
version: "3.8"

services:
  immich-server:
    container_name: immich_server
    image: ghcr.io/immich-app/immich-server:${IMMICH_VERSION:-release}
    volumes:
      - ${UPLOAD_LOCATION}:/usr/src/app/upload
      - /etc/localtime:/etc/localtime:ro
    env_file:
      - .env
    ports:
      - "127.0.0.1:2283:2283"
    depends_on:
      - redis
      - database
    restart: always
    healthcheck:
      test: ["CMD-SHELL", "curl -f http://localhost:2283/api/server/ping || exit 1"]
      interval: 30s
      timeout: 10s
      retries: 3

  immich-machine-learning:
    container_name: immich_machine_learning
    image: ghcr.io/immich-app/immich-machine-learning:${IMMICH_VERSION:-release}
    volumes:
      - model-cache:/cache
    env_file:
      - .env
    restart: always

  redis:
    container_name: immich_redis
    image: docker.io/redis:7-alpine
    restart: always
    healthcheck:
      test: ["CMD", "redis-cli", "ping"]
      interval: 10s
      timeout: 5s
      retries: 5

  database:
    container_name: immich_postgres
    image: docker.io/tensorchord/pgvecto-rs:pg16-v0.2.0
    environment:
      POSTGRES_PASSWORD: ${DB_PASSWORD}
      POSTGRES_USER: ${DB_USERNAME}
      POSTGRES_DB: ${DB_DATABASE_NAME}
      POSTGRES_INITDB_ARGS: "--data-checksums"
    volumes:
      - pgdata:/var/lib/postgresql/data
    restart: always
    healthcheck:
      test: ["CMD-SHELL", "pg_isready -d ${DB_DATABASE_NAME} -U ${DB_USERNAME}"]
      interval: 10s
      timeout: 5s
      retries: 5

volumes:
  pgdata:
  model-cache:
EOF

Start the stack:

cd /opt/immich && docker compose up -d

Verify all containers are running:

docker compose ps

You should see four containers running: immich_server, immich_machine_learning, immich_redis, and immich_postgres. The server takes 30–60 seconds to initialize on first launch.

Nginx Reverse Proxy with SSL

Immich listens on port 2283 internally. To access it securely over the internet, configure Nginx as a reverse proxy with SSL. If you haven't set up Nginx yet, follow our Nginx reverse proxy guide and SSL certificate installation guide.

cat > /etc/nginx/sites-available/immich << 'EOF'
server {
    listen 80;
    server_name photos.yourdomain.com;
    return 301 https://$server_name$request_uri;
}

server {
    listen 443 ssl http2;
    server_name photos.yourdomain.com;

    ssl_certificate /etc/letsencrypt/live/photos.yourdomain.com/fullchain.pem;
    ssl_certificate_key /etc/letsencrypt/live/photos.yourdomain.com/privkey.pem;

    # Required for large photo/video uploads
    client_max_body_size 50000M;

    # Proxy timeouts for large uploads
    proxy_read_timeout 600s;
    proxy_send_timeout 600s;
    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;

        # WebSocket support (required for real-time updates)
        proxy_http_version 1.1;
        proxy_set_header Upgrade $http_upgrade;
        proxy_set_header Connection "upgrade";
    }
}
EOF

ln -sf /etc/nginx/sites-available/immich /etc/nginx/sites-enabled/
nginx -t && systemctl reload nginx

The client_max_body_size 50000M setting is critical — without it, Nginx will reject large video uploads. Adjust this value based on your largest expected upload.

Initial Setup and First Library

Open https://photos.yourdomain.com in your browser. The first account you create becomes the admin account. Choose a strong password — this account controls server settings, user management, and all administrative functions.

After creating the admin account, configure these essential settings in Administration:

Mobile App Configuration

Immich provides native mobile apps for both iOS and Android that offer automatic background photo backup — the core feature that makes Google Photos so convenient.

Install the Immich app from the App Store (iOS) or Google Play (Android). On first launch:

  1. Enter your server URL: https://photos.yourdomain.com
  2. Log in with your account credentials
  3. Enable Background Backup in app settings
  4. Select which albums to back up (Camera Roll, Screenshots, Downloads, etc.)
  5. Choose whether to backup over Wi-Fi only or include cellular data

The app will begin uploading existing photos and automatically back up new photos as you take them. Initial upload of a large camera roll can take hours — let it run overnight on Wi-Fi. Progress is visible in the app's backup screen.

For families, each person installs the app and logs in with their own account. Their photos remain private unless explicitly shared through albums.

Library Import Strategies

If you have an existing photo library on a computer or external drive, there are several ways to get it into Immich:

Web upload — drag and drop folders in the Immich web interface. Best for libraries under 10GB. The browser handles the upload, so large libraries may time out.

Immich CLI tool — the official command-line tool is designed for bulk imports:

# Install the Immich CLI
npm install -g @immich/cli

# Authenticate
immich login https://photos.yourdomain.com YOUR_API_KEY

# Upload a directory recursively
immich upload --recursive /path/to/photos/

Rsync + External Library — for very large libraries, rsync the files directly to the server, then configure Immich to scan them as an external library:

# From your local machine, transfer photos to the server
rsync -avP --progress /local/photos/ user@your-vps:/opt/immich/external-library/

# Then in Immich Administration → External Libraries:
# Add a new library pointing to /usr/src/app/upload/external-library/

The external library approach is the fastest for large migrations because it skips the upload process entirely. Immich scans the files in place and generates thumbnails without moving or copying anything.

Machine Learning Features

Immich's machine learning pipeline runs three models that transform your photo library from a chronological dump into a searchable, organized collection:

Initial ML processing is CPU-intensive. When you first import a large library, the ML container will run at high CPU utilization for hours or days depending on library size and available CPU. For libraries exceeding 50K photos, consider a Dedicated VPS where dedicated CPU resources ensure indexing runs at maximum speed without contention from other tenants — reducing processing time from days to hours.

Monitor ML processing progress in the Administration panel under Jobs. You can adjust concurrency settings to balance processing speed against system responsiveness.

Multi-User Setup for Families

Immich supports multiple users with separate libraries — ideal for families and partners:

  1. Create accounts for each family member in Administration → Users
  2. Each user gets their own library, timeline, and face recognition database
  3. Users can create shared albums and invite other users to view or contribute
  4. The admin can set storage quotas per user to manage disk usage

Shared albums are the primary collaboration mechanism. A user creates an album, adds photos, and shares it with specific users. Recipients can view, download, and optionally contribute their own photos to the shared album.

Partner sharing is a deeper integration — two users can grant each other access to their entire timeline. This is ideal for couples who want to browse each other's photos without explicitly sharing every album.

Storage Growth Planning

Photo libraries grow predictably once you enable auto-backup. Estimate your growth rate:

Immich also generates thumbnails and ML embeddings that add roughly 10–15% overhead to your raw storage usage.

MassiveGRID's independent resource scaling means you can increase storage without changing your CPU or RAM allocation. When your library outgrows 100GB, scale storage to 250GB or 500GB without migrating to a new server or reconfiguring anything. This is a significant advantage over traditional VPS providers where storage is bundled with compute tiers.

Backup Strategy for Photo Data

Your photo library is irreplaceable — a server failure without backups means permanent loss. Implement a layered backup strategy using our automated backup guide:

# Backup the Immich upload directory to external storage
# Run nightly via cron
#!/bin/bash
BACKUP_DATE=$(date +%Y-%m-%d)
BACKUP_DIR="/backup/immich"

# Sync the photo library (incremental, only new files transferred)
rsync -a --delete /opt/immich/library/ ${BACKUP_DIR}/library/

# Backup PostgreSQL database (metadata, face data, album structure)
docker exec immich_postgres pg_dumpall -U postgres | gzip > ${BACKUP_DIR}/db-backup-${BACKUP_DATE}.sql.gz

# Retain 7 daily database backups
find ${BACKUP_DIR} -name "db-backup-*.sql.gz" -mtime +7 -delete

echo "Immich backup completed: ${BACKUP_DATE}"

The photo files themselves are the most critical component, but the PostgreSQL database contains all your metadata — face recognition data, album structures, user accounts, and search indices. Losing the database means re-processing your entire library through ML models. Follow our PostgreSQL guide for database-specific backup best practices.

For off-site backup, consider syncing backups to a second VPS in a different datacenter location, or to an S3-compatible object storage bucket.

Your Photos Deserve Enterprise Storage

Family photos, travel memories, and personal videos are the kind of data that can never be recreated. This is exactly where MassiveGRID's Ceph storage architecture provides real value.

Every block of data written to your VPS storage is automatically replicated three times across independent NVMe drives in a Ceph cluster. If a drive fails — which all drives eventually do — your data is immediately served from a replica while the cluster self-heals. This is the same storage technology used by enterprise cloud platforms, and it's included in every MassiveGRID VPS at no additional cost.

Combined with Proxmox HA clustering that provides automatic failover if a compute node fails, your Immich instance achieves a level of data durability and availability that no home NAS can match.

Prefer Managed Photo Infrastructure?

Your irreplaceable family photos deserve infrastructure that's actively maintained by professionals. With MassiveGRID's fully managed hosting, our team handles server security patches, automated backups with verification, SSL certificate renewals, monitoring, and emergency response — so you can focus on capturing moments instead of managing servers.

Whether you start with a self-managed VPS and handle everything yourself, or choose fully managed infrastructure from day one, MassiveGRID provides the enterprise-grade foundation your photo library needs: triple-replicated storage, automatic failover, and 100% uptime SLA backed by 24/7 human support.