Immich
Docker Compose deployment guide for Immich on Ubuntu.
Immich is a self-hosted photo and video management platform that provides automatic backups, facial recognition, machine learning features, timeline browsing, albums, sharing, and mobile app support.
Official project:
Why Use Immich?
Many homelab users use Immich as a private alternative to Google Photos.
Key features include:
- Automatic photo and video uploads
- Facial recognition
- Object and location search
- Shared albums
- Mobile applications for Android and iPhone
- Machine learning features
- External library support
- Self-hosted and privacy focused
Create the Project Folder
mkdir -p ~/docker/immich
cd ~/docker/immich
Create the Environment File
Create:
nano .env
Paste:
UPLOAD_LOCATION=./library
DB_DATA_LOCATION=./postgres
DB_PASSWORD=change_this_password
DB_USERNAME=immich
DB_DATABASE_NAME=immich
IMMICH_VERSION=release
Save and exit.
Create the Docker Compose File
Create:
nano docker-compose.yml
Paste:
services:
immich-server:
image: ghcr.io/immich-app/immich-server:release
container_name: immich_server
restart: unless-stopped
ports:
- "2283:2283"
volumes:
- ./library:/usr/src/app/upload
env_file:
- .env
depends_on:
- redis
- database
immich-machine-learning:
image: ghcr.io/immich-app/immich-machine-learning:release
container_name: immich_machine_learning
restart: unless-stopped
volumes:
- model-cache:/cache
env_file:
- .env
redis:
image: valkey/valkey:7
container_name: immich_redis
restart: unless-stopped
database:
image: tensorchord/pgvecto-rs:pg16-v0.2.0
container_name: immich_postgres
restart: unless-stopped
environment:
POSTGRES_PASSWORD: ${DB_PASSWORD}
POSTGRES_USER: ${DB_USERNAME}
POSTGRES_DB: ${DB_DATABASE_NAME}
volumes:
- ./postgres:/var/lib/postgresql/data
volumes:
model-cache:
Start Immich
Run:
docker compose up -d
Verify the containers are running:
docker ps
Access Immich
Open:
http://YOUR_SERVER_IP:2283
Example:
http://192.168.1.100:2283
First Login
When accessing Immich for the first time:
- Create the administrator account
- Log in using your new credentials
- Install the Immich mobile application
- Configure automatic photo backups
Storage Locations
This guide stores data in:
~/docker/immich
├── docker-compose.yml
├── .env
├── library
└── postgres
The folders contain:
| Folder | Purpose |
|---|---|
| library | Uploaded photos and videos |
| postgres | Database files |
Reverse Proxy Recommendation
For remote access, a reverse proxy is strongly recommended.
Benefits include:
- HTTPS encryption
- Easier access using a domain name
- Automatic certificate management
- Better security
Example:
https://photos.yourdomain.com
If you are new to reverse proxies, see the Topic page:
Notes
- Immich works best with a large storage location for photos and videos
- Mobile apps are available for Android and iPhone
- Machine learning features may take time to process large photo libraries
- Database backups are recommended
- Reverse proxy and HTTPS are recommended for remote access
Advanced Example (Reference Only)
This is my current Immich deployment.
It includes:
- External media library support
- Machine learning health checks
- Additional PostgreSQL tuning
- Separate data locations
- Graceful shutdown timers
name: immich
services:
immich-server:
container_name: immich_server
stop_grace_period: 90s
image: ghcr.io/immich-app/immich-server:${IMMICH_VERSION:-release}
volumes:
- ${UPLOAD_LOCATION}:/usr/src/app/upload
- ${EXTERNAL_PATH}:/mnt/media/photos:ro
- /etc/localtime:/etc/localtime:ro
env_file:
- .env
ports:
- "2283:2283"
depends_on:
- redis
- database
restart: always
immich-machine-learning:
container_name: immich_machine_learning
stop_grace_period: 90s
image: ghcr.io/immich-app/immich-machine-learning:${IMMICH_VERSION:-release}
volumes:
- model-cache:/cache
env_file:
- .env
restart: always
healthcheck:
test: ["CMD-SHELL", "python3 -c 'import urllib.request; urllib.request.urlopen(\"http://localhost:3003/ping\")' || exit 1"]
interval: 30s
timeout: 10s
retries: 3
start_period: 60s
redis:
container_name: immich_redis
stop_grace_period: 90s
image: docker.io/valkey/valkey:7
restart: always
healthcheck:
test: ["CMD-SHELL", "redis-cli ping | grep PONG"]
interval: 10s
timeout: 5s
retries: 5
database:
container_name: immich_postgres
stop_grace_period: 90s
image: 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:
- ${DB_DATA_LOCATION}:/var/lib/postgresql/data
shm_size: 128mb
restart: always
healthcheck:
test: ["CMD-SHELL", "pg_isready -U ${DB_USERNAME} -d ${DB_DATABASE_NAME}"]
interval: 10s
timeout: 5s
retries: 5
volumes:
model-cache: