Immich is currently the most powerful open-source alternative to Google Photos. It offers high-performance backup, AI-driven face recognition, and a polished mobile app. This guide focuses on a robust deployment using Docker Compose, integrating it into our existing Traefik v3 reverse proxy and securing it with the CrowdSec IPS.

By placing Immich behind Traefik, we benefit from automatic TLS certificates and a central entry point for our mobile devices, while CrowdSec protects our personal memories from brute-force and bot attacks.

Changelog

DateChange
2026-01-15Initial Version: Immich v1.12x+, Traefik v3 integration, pgvector, and specific CrowdSec bypass notes for mobile sync.

1. Prerequisites

This deployment assumes you have followed our foundational security stack guide. Immich is resource-intensive, especially during the initial scan of your library.

โš ๏ธ HARD REQUIREMENT

The following steps will not work correctly without the Traefik stack running as described in the prerequisite guide:

System Recommendations:

  • RAM: Minimum 4GB (8GB+ recommended for AI/Machine Learning).
  • Storage: A large dedicated disk or mount point for your photo library.
  • Domain: A subdomain like photos.your-domain.com.

2. Directory Structure

Immich requires several volumes for its database, machine learning cache, and the actual photo library.

# Create the main directory
sudo mkdir -p /opt/containers/immich
cd /opt/containers/immich

# Create directories for data persistence
sudo mkdir -p volumes/db      # Postgres data
sudo mkdir -p volumes/library # Your actual photos/videos
sudo mkdir -p volumes/model-cache # AI models

3. Configuration

Immich uses a .env file for core settings and a docker-compose.yml for service orchestration.

3.1. Generate Database Password

DB_PASSWORD=$(openssl rand -hex 32)
echo "Your Immich DB password: $DB_PASSWORD"

3.2. Environment Variables (.env)

Create the .env file. Replace placeholders with your values.

sudo tee .env > /dev/null << EOF
# --- Database ---
DB_PASSWORD=$DB_PASSWORD
DB_USERNAME=immich
DB_DATABASE_NAME=immich

# --- System ---
TZ=Europe/Vienna
IMMICH_VERSION=release

# --- Library Location ---
# Ensure this path has sufficient space (ideally a dedicated disk)
UPLOAD_LOCATION=./volumes/library

# --- Domain ---
DOMAIN_NAME=photos.your-domain.com
EOF

3.3. Docker Compose (docker-compose.yml)

sudo tee docker-compose.yml > /dev/null << 'EOF'
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
    depends_on:
      - redis
      - database
    restart: unless-stopped
    networks:
      - proxy
      - immich-net
    labels:
      - "traefik.enable=true"
      - "traefik.http.routers.immich.rule=Host(`${DOMAIN_NAME}`)"
      - "traefik.http.routers.immich.entrypoints=websecure"
      - "traefik.http.routers.immich.tls.certresolver=tls_resolver"
      # See Section 4.3 for opting out of CrowdSec if needed
      - "traefik.http.routers.immich.middlewares=security-headers@file,crowdsec-bouncer@docker"
      - "traefik.http.services.immich.loadbalancer.server.port=2283"

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

  redis:
    container_name: immich_redis
    image: redis:6.2-alpine
    restart: unless-stopped
    networks:
      - immich-net

  database:
    container_name: immich_postgres
    image: tensorchord/pgvecto-rs:pg16-v0.2.0
    environment:
      POSTGRES_PASSWORD: ${DB_PASSWORD}
      POSTGRES_USER: ${DB_USERNAME}
      POSTGRES_DB: ${DB_DATABASE_NAME}
    volumes:
      - ./volumes/db:/var/lib/postgresql/data
    restart: unless-stopped
    networks:
      - immich-net

networks:
  proxy:
    external: true
  immich-net:
    driver: bridge
EOF

4. Hardware & Security Tuning

4.1. Hardware Acceleration (Optional)

Using an iGPU or GPU speeds up video transcoding and AI processing significantly.

๐Ÿ’ก TRANSCODING & ML

To enable Intel QuickSync, add the following to both immich-server (for video) and immich-machine-learning (for AI) in your docker-compose.yml:

devices:
  - /dev/dri:/dev/dri

4.2. Mobile Apps & CrowdSec

Immich mobile apps (especially on iOS) perform many rapid requests during background synchronization.

โš ๏ธ MOBILE SYNC & FALSE POSITIVES

If you experience โ€œConnection Lostโ€ or sync issues in the mobile app, check your CrowdSec decisions (cscli decisions list). Frequent background requests can sometimes trigger rate-limiting or bot-detection scenarios.

4.3. Running Immich without CrowdSec (Optional)

If you find that the CrowdSec middleware frequently interferes with your mobile backups, you can choose to bypass it for Immich specifically while keeping your other services protected.

To disable CrowdSec for Immich, update the labels in your docker-compose.yml by removing crowdsec-bouncer@docker:

# In the immich-server labels section:
- "traefik.http.routers.immich.middlewares=security-headers@file"

For more details on why you might want to do this, see:

5. Maintenance & Backup

Updating Immich

cd /opt/containers/immich
sudo docker compose pull
sudo docker compose up -d

Backup Strategy

Gezieltes Database Backup:

# Export only the 'immich' database for a cleaner dump
sudo docker compose exec -t database pg_dump -U immich immich > immich_db_backup_$(date +%F).sql

Conclusion

You now have a secure, high-performance photo management system. By integrating Immich with Traefik and CrowdSec (or selectively bypassing it for sync reliability), you achieve a โ€œGoogle Photosโ€ experience while maintaining full control over your private data.

๐Ÿ“šOFFICIAL IMMICH DOCS ๐Ÿ“ฆIMMICH GITHUB