# Immich - Self-hosted Photo & Video Management # Domain: ${SUBDOMAIN}.${DOMAIN} # Database: PostgreSQL (with VectorChord) + Redis # RAM: ~4GB minimum (mem_limit: 4096M total — server 2048M + ML 1536M + postgres 256M + redis 128M) | Pi-compatible: No (ML too heavy) # # Environment variables: # DOMAIN - Your domain (e.g., demo-felhom.eu) # HDD_PATH - Drive namespace root (managed upload lives under appdata) # USERDATA_PATH - Ügyfél-tartalom gyökér (/userdata) # DB_PASSWORD - PostgreSQL password (auto-generated) # # Storage layout (felhom userdata convention): # Managed upload (Immich-owned) → ${HDD_PATH}/appdata/immich (HDD, host path — app-managed) # External photo library (RO) → ${USERDATA_PATH}/media/photos → /external/photos # PostgreSQL data → immich_postgres_data (named volume, NVMe) # ML model cache → immich_ml_cache (named volume, NVMe) # Redis data → immich_redis_data (named volume, NVMe) # # ⚠ EXTERNAL LIBRARY IS NOT WIRED BY COMPOSE: mounting /external/photos only makes the files # visible to the container. To actually surface them in Immich you MUST register an External # Library pointing at /external/photos in the Immich admin UI (Administration → External # Libraries) or via the API — a POST-DEPLOY step. Until then photos sharing is "mount ready, # registration pending". See .felhom.yml first_steps + REPORT. # # First-time setup: # Create admin account on first visit, then register the External Library (see above). services: immich-server: image: ghcr.io/immich-app/immich-server:v2.5.5 container_name: immich-server restart: unless-stopped depends_on: immich-postgres: condition: service_healthy immich-redis: condition: service_healthy environment: - DB_PASSWORD=${DB_PASSWORD} - DB_HOSTNAME=immich-postgres - DB_USERNAME=immich - DB_DATABASE_NAME=immich - REDIS_HOSTNAME=immich-redis - IMMICH_MACHINE_LEARNING_URL=http://immich-machine-learning:3003 - TZ=Europe/Budapest volumes: - ${HDD_PATH}/appdata/immich:/usr/src/app/upload - ${USERDATA_PATH}/media/photos:/external/photos:ro networks: - traefik-public - immich-internal deploy: resources: limits: memory: 2048M healthcheck: test: ["CMD", "curl", "-sf", "http://127.0.0.1:2283/api/server/ping"] interval: 30s timeout: 10s retries: 3 start_period: 60s labels: - "traefik.enable=true" - "traefik.http.routers.immich.rule=Host(`${SUBDOMAIN}.${DOMAIN}`)" - "traefik.http.routers.immich.entrypoints=websecure" - "traefik.http.routers.immich.tls=true" - "traefik.http.routers.immich.tls.certresolver=letsencrypt" - "traefik.http.services.immich.loadbalancer.server.port=2283" immich-machine-learning: image: ghcr.io/immich-app/immich-machine-learning:v2.5.5 container_name: immich-machine-learning restart: unless-stopped environment: - TZ=Europe/Budapest - TRANSFORMERS_CACHE=/cache volumes: - immich_ml_cache:/cache networks: - immich-internal deploy: resources: limits: memory: 1536M healthcheck: test: ["CMD", "python3", "-c", "import urllib.request; urllib.request.urlopen('http://127.0.0.1:3003/ping')"] interval: 30s timeout: 10s retries: 3 start_period: 120s immich-postgres: image: ghcr.io/immich-app/postgres:16-vectorchord0.3.0 container_name: immich-postgres restart: unless-stopped environment: - POSTGRES_USER=immich - POSTGRES_PASSWORD=${DB_PASSWORD} - POSTGRES_DB=immich - POSTGRES_INITDB_ARGS=--data-checksums - TZ=Europe/Budapest volumes: - immich_postgres_data:/var/lib/postgresql/data networks: - immich-internal deploy: resources: limits: memory: 512M healthcheck: test: ["CMD-SHELL", "pg_isready -U immich -d immich"] interval: 10s timeout: 5s retries: 5 start_period: 30s immich-redis: image: redis:7-alpine container_name: immich-redis restart: unless-stopped command: redis-server --appendonly yes environment: - TZ=Europe/Budapest volumes: - immich_redis_data:/data networks: - immich-internal deploy: resources: limits: memory: 128M healthcheck: test: ["CMD", "redis-cli", "ping"] interval: 10s timeout: 5s retries: 3 volumes: immich_ml_cache: immich_postgres_data: immich_redis_data: networks: traefik-public: external: true immich-internal: