How to Set Up Immich: The Best Self-Hosted Google Photos Alternative in 2026


How to Set Up Immich: The Best Self-Hosted Google Photos Alternative in 2026

Your photos are some of the most personal data you own. Every family gathering, every vacation, every milestone — they all live in the cloud on someone else’s servers. If you have ever felt uneasy about Google scanning your photos for ad targeting, or worried about a service shutting down and taking your memories with it, you are not alone. Immich gives you a way out: a fast, polished, self-hosted Google Photos alternative that you control completely.

In this guide, we will walk through a complete Immich setup from scratch using Docker Compose. By the end, you will have a fully functional photo management server with mobile backup, facial recognition, smart search, and a timeline view that rivals anything Google offers — except your data never leaves your hardware.

What Is Immich?

Immich is a high-performance, self-hosted photo and video management solution built to feel like Google Photos. It was created by Alex Tran and has grown into one of the most popular self-hosted applications on GitHub, surpassing 90,000 stars with the release of v2.5.0 in January 2026.

Unlike older self-hosted photo tools that feel clunky or limited, Immich was designed from day one with a modern mobile-first experience. The feature set is impressive:

  • Mobile auto-backup for iOS and Android with background upload support
  • Facial recognition that automatically groups photos by person
  • Smart search powered by CLIP machine learning models, so you can search for “dog on beach” and actually get results
  • Timeline view that mirrors the Google Photos experience
  • Shared albums and partner sharing for families
  • Non-destructive photo editing introduced in v2.5.0
  • Free Up Space — delete local copies on your phone once they are backed up
  • Hardware-accelerated machine learning with support for NVIDIA CUDA, Intel OpenVINO, and ARM NN
  • Map view showing where your photos were taken
  • Automatic database backups with web-based restore

Immich runs as a set of Docker containers: a main server, a machine learning worker, a PostgreSQL database with vector search extensions, and a Valkey (Redis-compatible) cache.

Why Self-Host Your Photos?

Before we dive into the Immich setup, it is worth understanding why self-hosting your photos matters.

Privacy. Google Photos scans every image you upload to train its models and build advertising profiles. With Immich, your photos stay on your hardware. No third party ever sees them.

Ownership. Cloud services change their terms, raise prices, or shut down entirely. Google already cut free unlimited storage in 2021. When you self-host, you own your data outright.

No storage limits. Google gives you 15 GB free, shared across Gmail, Drive, and Photos. A self-hosted Immich instance can use as much storage as you can attach to your server — a 4 TB drive costs under $80 and holds roughly 800,000 photos.

Speed on your local network. Browsing a local Immich instance over your home network is fast. Thumbnails load instantly, and downloads do not depend on your ISP upload speed.

Full control over backups. You decide where backups go, how many copies exist, and which off-site strategy to use.

Immich vs Google Photos vs PhotoPrism vs LibrePhotos

Before committing to Immich, you may want to compare it against the alternatives. Here is how the major options stack up:

FeatureImmichGoogle PhotosPhotoPrismLibrePhotos
Self-hostedYesNoYesYes
Mobile appiOS + AndroidiOS + AndroidWeb onlyWeb only
Auto-backup from phoneYesYesNoNo
Facial recognitionExcellentExcellentLimited detectionVery good
Smart search (NLP)Yes (CLIP)YesYesYes
Map viewYesYesYesYes
Shared albumsYesYesYesLimited
Partner sharingYesYesNoNo
Non-destructive editingYes (v2.5.0+)YesNoNo
Video supportFullFullFullFull
RAW format supportYesLimitedYesYes
Hardware ML accelerationCUDA, OpenVINO, ARM NNN/A (cloud)LimitedLimited
Free Up Space on deviceYesYesN/AN/A
External library supportYesNoYesYes
LanguageTypeScript/DartProprietaryGoPython/Django
Active developmentVery activeActiveActiveModerate
PrivacyFull controlGoogle scans photosFull controlFull control
CostFree + your hardwareFree (15 GB) / PaidFree / Paid tiersFree

Immich stands out as the only self-hosted option with native mobile apps and automatic phone backup. PhotoPrism is solid if you do not need mobile backup, while LibrePhotos excels at face detection but has a smaller community. For a true Google Photos replacement, Immich is the clear winner.

Hardware Requirements

Immich is not especially demanding, but the machine learning components do need some resources. Here are the official requirements and practical recommendations:

Minimum Requirements

  • CPU: 2 cores (x86_64 or ARM64)
  • RAM: 6 GB (4 GB possible if you disable machine learning)
  • Storage: SSD for the database, HDD/SSD for photo storage
  • OS: Linux (Ubuntu, Debian, or any Docker-compatible distribution)
  • Docker: Docker Engine v25 or later with docker compose (v2)
  • CPU: 4+ cores (Intel N100 or better for a dedicated NAS/server)
  • RAM: 8-16 GB for smooth ML processing of large libraries
  • Storage: 256 GB+ SSD for OS and database, separate large drive for photos
  • GPU (optional): NVIDIA GPU with CUDA support dramatically speeds up facial recognition and smart search indexing

Important Storage Notes

  • The PostgreSQL database (DB_DATA_LOCATION) must be on local SSD storage. Network shares are not supported for the database and will cause corruption or performance issues.
  • Photo storage (UPLOAD_LOCATION) can be on a larger HDD, NAS mount, or any Unix-compatible filesystem (EXT4, ZFS, XFS, Btrfs).
  • Plan for roughly 5 MB per photo on average. A 50,000-photo library will need approximately 250 GB, plus additional space for generated thumbnails and transcoded videos.

Step-by-Step Immich Setup with Docker Compose

Let us get into the actual Immich Docker Compose deployment. This guide assumes you have a Linux server with Docker Engine v25+ and the docker compose plugin installed.

Step 1: Create the Project Directory

mkdir -p /opt/immich-app
cd /opt/immich-app

Step 2: Create the Docker Compose File

Create a docker-compose.yml file. The following is based on the official Immich v2.5.0 compose file:

name: immich

services:
  immich-server:
    container_name: immich_server
    image: ghcr.io/immich-app/immich-server:${IMMICH_VERSION:-release}
    volumes:
      - ${UPLOAD_LOCATION}:/data
      - /etc/localtime:/etc/localtime:ro
    env_file:
      - .env
    ports:
      - '2283:2283'
    depends_on:
      - redis
      - database
    restart: always
    healthcheck:
      disable: false

  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
    healthcheck:
      disable: false

  redis:
    container_name: immich_redis
    image: docker.io/valkey/valkey:9-alpine
    healthcheck:
      test: redis-cli ping || exit 1
    restart: always

  database:
    container_name: immich_postgres
    image: ghcr.io/immich-app/postgres:14-vectorchord0.4.3-pgvectors0.2.0
    environment:
      POSTGRES_PASSWORD: ${DB_PASSWORD}
      POSTGRES_USER: ${DB_USERNAME}
      POSTGRES_DB: ${DB_DATABASE_NAME}
      POSTGRES_INITDB_ARGS: '--data-checksums'
    volumes:
      - ${DB_DATA_LOCATION}:/var/lib/postgresql/data
    shm_size: 128mb
    restart: always
    healthcheck:
      disable: false

volumes:
  model-cache:

A few things to note about this compose file:

  • Immich uses a custom PostgreSQL image that includes VectorChord and pgvectors extensions. These power the smart search and facial recognition features. Do not substitute a vanilla PostgreSQL image.
  • The redis service uses Valkey, a community fork of Redis that is fully compatible.
  • The model-cache volume persists downloaded ML models so they do not need to be re-downloaded on container restart.

Step 3: Create the Environment File

Create a .env file in the same directory:

# The location where your uploaded files are stored
UPLOAD_LOCATION=/mnt/photos/immich-library

# The location where your database files are stored (must be local SSD)
DB_DATA_LOCATION=/opt/immich-app/postgres

# Timezone (adjust to your location)
TZ=America/New_York

# Pin to a specific Immich version for stability
IMMICH_VERSION=v2.5.0

# Database credentials - CHANGE THE PASSWORD
DB_PASSWORD=Y0ur_Str0ng_P4ssw0rd_H3re
DB_USERNAME=postgres
DB_DATABASE_NAME=immich

Critical: Change DB_PASSWORD from the default. Use only alphanumeric characters (A-Z, a-z, 0-9) — special characters can cause issues with the PostgreSQL connection string. Adjust UPLOAD_LOCATION to point to where you want your photos stored, and make sure DB_DATA_LOCATION points to a local SSD path.

Step 4: Create the Storage Directories

sudo mkdir -p /mnt/photos/immich-library
sudo mkdir -p /opt/immich-app/postgres
sudo chown -R $USER:$USER /mnt/photos/immich-library
sudo chown -R $USER:$USER /opt/immich-app/postgres

Step 5: Start the Stack

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

Watch the logs to make sure everything starts cleanly:

docker compose logs -f

You should see the database initialize, the server start on port 2283, and the machine learning service begin downloading its models (this may take a few minutes on first launch). Press Ctrl+C to exit the log stream once you see the server is ready.

Step 6: Initial Web Setup

Open your browser and navigate to http://<your-server-ip>:2283. You will see the Immich welcome screen.

  1. Click Getting Started.
  2. Create your admin account. The first user to register automatically becomes the administrator.
  3. You will be taken to the main timeline view — your Immich instance is live.

From the admin panel (accessible via your profile icon), you can configure:

  • Storage template settings for how files are organized on disk
  • Machine learning model preferences
  • Job concurrency settings
  • User management to create accounts for family members
  • Server-wide settings for maps, notifications, and more

Setting Up the Mobile App

The mobile app is where Immich really shines as a self-hosted Google Photos replacement. Here is how to set it up:

Install the App

  • Android: Download Immich from the Google Play Store or F-Droid.
  • iOS: Download Immich from the Apple App Store.

Connect to Your Server

  1. Open the app and enter your server URL: http://<your-server-ip>:2283/api
  2. Log in with the credentials you created during web setup.
  3. If you are accessing Immich outside your local network, you will need to set up a reverse proxy with HTTPS (covered in the performance tips section below).

Configure Auto-Backup

  1. Tap the cloud icon in the top-right corner of the app.
  2. Select which albums to back up. Choosing Recents will capture all new photos and videos.
  3. Tap Enable Backup to start the initial upload.
  4. Configure backup preferences:
    • Foreground backup: Uploads happen whenever the app is open. Enabled by default.
    • Background backup: The app periodically checks for new photos and uploads them even when closed. Enable this for a truly automatic experience.
    • Wi-Fi only: Enabled by default. Disable if you want uploads over cellular data.

Free Up Space

Once your photos are fully backed up, you can use the Free Up Space feature (introduced in v2.5.0) to delete local copies from your phone. Access it from the user profile panel or Settings. Immich will verify that each file exists on the server and is not in the trash before allowing deletion.

Importing Existing Photos

If you have years of photos on a hard drive, you will want to get them into Immich. There are three approaches:

External libraries let Immich index photos in-place without moving or copying them. This is ideal for existing organized photo directories.

  1. Edit your docker-compose.yml to mount the external directory:
  immich-server:
    volumes:
      - ${UPLOAD_LOCATION}:/data
      - /etc/localtime:/etc/localtime:ro
      - /mnt/photos/old-library:/mnt/old-library:ro
  1. Restart the stack: docker compose up -d

  2. In the Immich web UI, go to Administration > External Libraries.

  3. Click Create Library, select a user to own it, and add the import path /mnt/old-library.

  4. Click the three-dot menu on the library and select Scan New Library Files.

Immich will recursively scan the directory, read EXIF data, generate thumbnails, and make everything searchable. Note that externally mounted files are read-only — Immich will not modify or move them.

Method 2: Immich CLI Upload

The official Immich CLI is useful for one-time bulk uploads directly into a user’s main library:

# Install the CLI
npm i -g @immich/cli

# Upload a directory
immich upload --key <your-api-key> --server http://<server-ip>:2283/api /path/to/photos

You can generate an API key from the Immich web UI under Account Settings > API Keys.

Method 3: Immich-Go for Google Takeout

If you are migrating from Google Photos, the community tool immich-go handles Google Takeout archives natively. It correctly maps the metadata JSON files that Google exports alongside each photo:

# Download immich-go from GitHub releases
# Then upload a Google Takeout archive:
immich-go upload from-google-photos --server http://<server-ip>:2283/api --key <api-key> /path/to/takeout-*.zip

This preserves dates, descriptions, and album structures from your Google Photos export.

Backup Strategy

Self-hosting means you are responsible for backups. A solid 3-2-1 strategy (three copies, two different media, one off-site) is essential for your photo library.

What to Back Up

You need to back up two things:

  1. The photo files in your UPLOAD_LOCATION directory
  2. The PostgreSQL database which stores all metadata, user accounts, facial recognition data, album structures, and search indexes

Automatic Database Backups

Immich automatically creates database backups and stores them in UPLOAD_LOCATION/backups. You can manage these from the web UI under Administration > Server Settings > Backup. These backups contain only metadata, not the actual photo files.

Manual Database Backup

For more control, you can dump the database manually:

docker exec -t immich_postgres pg_dumpall \
  --clean --username=postgres \
  | gzip > "/path/to/backup/immich_db_$(date +%Y%m%d).sql.gz"

Schedule this as a daily cron job:

# Add to crontab (crontab -e)
0 3 * * * docker exec -t immich_postgres pg_dumpall --clean --username=postgres | gzip > /mnt/backups/immich_db_$(date +\%Y\%m\%d).sql.gz

Restoring from Backup

Immich v2.5.0 supports restoring database backups directly from the web UI, which is the recommended method. For command-line restores:

# Stop Immich but keep the database running
docker compose stop immich-server immich-machine-learning

# Restore the backup
gunzip < "/path/to/backup/immich_db_20260210.sql.gz" \
  | docker exec -i immich_postgres psql --username=postgres --dbname=immich

# Restart everything
docker compose up -d

Photo File Backup

For the actual photo files, use rsync to an external drive or remote server:

rsync -avz --progress /mnt/photos/immich-library/ /mnt/backup-drive/immich-library/

For versioned off-site backups, consider Borg Backup or Restic, both of which support deduplication and encryption. Immich even provides a template Borg backup script in their documentation.

Monitoring Your Backups

Once you have automated backups running, you need to know if they stop working. A missed backup is as dangerous as no backup at all. This is where a monitoring service like CronPing becomes valuable. CronPing can monitor scheduled backup jobs by expecting a ping at regular intervals — if your 3 AM database dump cron job fails to report in, you get an alert before the gap in your backup chain grows. You can also use CronPing to monitor the Immich server itself by pinging its health endpoint, so you know immediately if your photo server goes down.

Performance Tips

Put a Reverse Proxy in Front of Immich

For HTTPS access (required for mobile backup outside your LAN), use Caddy or nginx as a reverse proxy:

# Caddyfile example
photos.yourdomain.com {
    reverse_proxy localhost:2283
}

Caddy automatically provisions and renews Let’s Encrypt TLS certificates. This gives you a secure https://photos.yourdomain.com URL to use in the mobile app.

Enable Hardware-Accelerated Machine Learning

If you have an NVIDIA GPU, modify the machine learning service in your docker-compose.yml:

  immich-machine-learning:
    container_name: immich_machine_learning
    image: ghcr.io/immich-app/immich-machine-learning:${IMMICH_VERSION:-release}-cuda
    volumes:
      - model-cache:/cache
    env_file:
      - .env
    restart: always
    deploy:
      resources:
        reservations:
          devices:
            - driver: nvidia
              count: 1
              capabilities:
                - gpu

Note the -cuda tag on the image. For Intel iGPUs (common on mini PCs like the N100), use the -openvino tag instead.

CUDA acceleration can reduce smart search indexing time by 10x or more on a library of tens of thousands of photos.

Tune Job Concurrency

In the Immich web UI, navigate to Administration > Jobs. You can increase concurrency for:

  • Thumbnail generation: Safe to set to 4-8 on a 4-core system
  • Metadata extraction: Safe to increase to 4-6
  • Smart search (CLIP encoding): Keep at 1-2 unless you have GPU acceleration
  • Facial recognition: Keep at 1-2, this is memory-intensive

Increasing concurrency speeds up initial library processing but uses more CPU and RAM. Monitor system resources during initial indexing and adjust as needed.

Use SSD for the Database

This bears repeating: the PostgreSQL database must run on SSD storage. Database performance directly affects the speed of the web interface, search queries, and the timeline view. A slow database on a spinning disk will make the entire application feel sluggish.

Configure Storage Templates

By default, Immich stores uploaded files in a date-based directory structure. You can customize this under Administration > Storage Template to organize files by year/month, camera model, or other EXIF metadata. This makes the underlying file structure browsable even without Immich.

A common template:

{{y}}/{{y}}-{{MM}}-{{dd}}/{{filename}}

This creates directories like 2026/2026-02-12/IMG_1234.jpg.

Offload Machine Learning to a Separate Host

If your server is low on resources (for example, a Raspberry Pi or a NAS with only 4 GB of RAM), you can run the machine learning container on a more powerful machine. Set the IMMICH_MACHINE_LEARNING_URL environment variable to point to the remote ML service:

IMMICH_MACHINE_LEARNING_URL=http://192.168.1.50:3003

This lets you keep a low-power, always-on server for storage while offloading heavy ML processing to a desktop or laptop on demand.

Keeping Immich Updated

Immich is under very active development, with new releases roughly every two weeks. To update:

cd /opt/immich-app

# Pull the latest images
docker compose pull

# Recreate containers with new images
docker compose up -d

If you pinned IMMICH_VERSION in your .env file (as recommended), update the version number before pulling, then run the same commands. Always check the release notes before upgrading — major version changes occasionally require migration steps. Take a database backup before any upgrade; it takes 30 seconds and could save you from a painful recovery.

Securing Your Instance

A few security considerations for your Immich deployment:

  • Never expose port 2283 directly to the internet. Always use a reverse proxy with HTTPS.
  • Use strong, unique passwords for both user accounts and the database.
  • Enable two-factor authentication for admin and user accounts from the Immich settings.
  • Keep Docker and your host OS updated to patch security vulnerabilities.
  • Restrict network access using firewall rules. Only the reverse proxy should be able to reach port 2283.

Troubleshooting Common Issues

“Cannot connect to server” in the mobile app: Make sure you are using the correct URL format: http://<ip>:2283/api. If connecting over the internet, ensure your reverse proxy is configured and your DNS records point to your server.

Machine learning is slow or crashing: Check available RAM with free -h. The ML container needs at least 2-3 GB. If you are running low, add more RAM, enable swap, or disable ML features in the admin panel.

Photos not showing in the timeline after upload: Immich processes metadata and generates thumbnails after upload. Check the job queue in Administration > Jobs to see if processing is still running.

Database connection errors after changing the password: If you change DB_PASSWORD in .env after initial setup, you also need to change it inside the running PostgreSQL container. Back up your database, delete the DB_DATA_LOCATION directory, update the password, let the database reinitialize, then restore.

Final Thoughts

Immich has matured into a genuinely excellent self-hosted Google Photos replacement. The mobile app experience is polished, smart search actually works, and the development pace is remarkable. Version 2.5.0 brought non-destructive editing, improved backup and restore through the web UI, and the Free Up Space feature that makes mobile photo management seamless.

Setting up Immich with Docker Compose takes about 15 minutes. From there, you have a private, fast, feature-rich photo management platform that you fully control. Pair it with a solid backup strategy, a monitoring service like CronPing to watch over your cron jobs and server health, and a reverse proxy for secure remote access, and you have a setup that genuinely rivals cloud services — without giving up your privacy.

Your photos are worth owning. Immich makes it practical.