Skip to main content

Immich - A self-hosted Google Photos alternative

Installation via docker-compose behind traefik proxy

version: '2'

networks:
  traefik:
    external: true
  immich_default:
    external: true

volumes:
  immich_server_upload:
    external: true
  immich_postgres_data:
    external: true
  immich_ml_cache:
    external: true
  immich_redis_data:
    external: true

services:
  server:
    image: ghcr.io/immich-app/immich-server:${IMMICH_VERSION}
    command: [ "start.sh", "immich" ]
    volumes:
      - immich_server_upload:/usr/src/app/upload
      - /etc/localtime:/etc/localtime:ro
    environment:
      - DB_HOSTNAME=postgres
      - DB_USERNAME=postgres
      - DB_DATABASE_NAME=immich
      - REDIS_HOSTNAME=redis
      - DB_PASSWORD=${DB_PASSWORD}
    depends_on:
      - redis
      - postgres
    networks:
      - immich_default
      - traefik
    restart: unless-stopped
    labels:
      - "traefik.enable=true"
      - "traefik.http.routers.immich.rule=Host(`immich.domain.com`)"      
      - "traefik.http.routers.immich.entrypoints=websecure"
      - "traefik.http.routers.immich.tls=true"
      - "traefik.http.services.immich.loadBalancer.server.port=3001"
      - "traefik.docker.network=traefik"
      # CORS for duplicate finder
      - "traefik.http.routers.immich.middlewares=immich-cors"
      - "traefik.http.middlewares.immich-cors.headers.accessControlAllowOriginList=*"
      - "traefik.http.middlewares.immich-cors.headers.accessControlAllowMethods=GET, PUT, POST, DELETE, OPTIONS"
      - "traefik.http.middlewares.immich-cors.headers.accessControlAllowHeaders=X-Api-Key, User-Agent, Content-Type"
      - "traefik.http.middlewares.immich-cors.headers.accessControlMaxAge=1728000"
  microservices:
    image: ghcr.io/immich-app/immich-server:${IMMICH_VERSION}
    command: [ "start.sh", "microservices" ]
    networks:
      - immich_default
    volumes:
      - immich_server_upload:/usr/src/app/upload
      - /etc/localtime:/etc/localtime:ro
    environment:
      - DB_HOSTNAME=postgres
      - DB_USERNAME=postgres
      - DB_DATABASE_NAME=immich
      - REDIS_HOSTNAME=redis
      - DB_PASSWORD=${DB_PASSWORD}
    depends_on:
      - redis
      - postgres
    restart: unless-stopped
  machine-learning:
    image: ghcr.io/immich-app/immich-machine-learning:${IMMICH_VERSION}
    volumes:
      - immich_ml_cache:/cache
    networks:
      - immich_default
    environment:
      - DB_HOSTNAME=postgres
      - DB_USERNAME=postgres
      - DB_DATABASE_NAME=immich
      - REDIS_HOSTNAME=redis
      - DB_PASSWORD=${DB_PASSWORD}
    restart: unless-stopped
  redis:
    image: redis:6.2-alpine@sha256:c5a607fb6e1bb15d32bbcf14db22787d19e428d59e31a5da67511b49bb0f1ccc
    restart: unless-stopped
    networks:
      - immich_default
    volumes:
      - immich_redis_data:/data
  postgres:
    image: tensorchord/pgvecto-rs:pg14-v0.1.11@sha256:0335a1a22f8c5dd1b697f14f079934f5152eaaa216c09b61e293be285491f8ee
    environment:
      POSTGRES_PASSWORD: ${DB_PASSWORD}
      POSTGRES_USER: postgres
      POSTGRES_DB: immich
    volumes:
      - immich_postgres_data:/var/lib/postgresql/data
    networks:
      - immich_default
    restart: unless-stopped

Delete duplicates

  • Create duplicates database
docker container run --rm --volume immich_server_upload:/upload:ro --volume "$PWD:/output/" \
                   ghcr.io/agross/immich-duplicates-findimagedupes --prune \
                   --fingerprints /output/dupes.db --recurse --no-compare \
                   --exclude '\.webp$' /upload/thumbs/<USERID>
  • Group duplicates
docker container run --rm --volume "$PWD:/app/data/" ghcr.io/agross/immich-duplicates-grouper 5
  • Launch duplicate browser
docker container run --env IMMICH_URL=https://immich.domain.com--rm --publish 2222:80 ghcr.io/agross/immich-duplicates-browser