High performance self-hosted photo and video management solution.
| Registry | ghcr.io/daemonless/immich |
| Source | https://github.com/immich-app/immich |
| Website | https://immich.app/ |
These tags apply to the immich-server image (set via IMMICH_TAG):
| Tag | Description | Best For |
|---|---|---|
latest |
Current stable release, built from the latest upstream Immich release. | Most users. |
beta |
Beta release built from upstream v3.0.0-rc.0. | Testing upcoming releases early. |
Machine learning (immich-ml, set via IMMICH_ML_TAG) follows the same latest and beta tags.
immich-postgres:latest and :14 are both PostgreSQL 14, matching upstream Immich. New installs can use :18; upgrading an existing database needs a full dump and restore.
Before deploying, ensure your host environment is ready. See the Quick Start Guide for host setup instructions.
1. Save as .env and fill in what is empty:
# Immich for FreeBSD (Daemonless)
# Compatible with official Immich environment variables
# Docs: https://docs.immich.app/install/environment-variables
# Image tag for the Immich server and machine-learning containers.
# Defaults to 'latest' (stable). Set to 'beta' to run the Immich 3.0 pre-release.
# IMMICH_TAG=latest
# Image tag for machine learning (defaults to 'latest').
# The location where your uploaded files are stored
UPLOAD_LOCATION=/containers/immich/library
# The location where your database files are stored
DB_DATA_LOCATION=/containers/immich/postgres
# To set a timezone, uncomment the next line and change Etc/UTC to a TZ identifier
# https://en.wikipedia.org/wiki/List_of_tz_database_time_zones#List
# TZ=Etc/UTC
# Connection secret for postgres. Change this to a random password!
# Use only characters A-Za-z0-9 (no special characters or spaces)
DB_PASSWORD=postgres
# Where the server looks for the other three services. The defaults are right
# when they all share one network stack, which is what this file sets up. Set
# them when postgres, redis and the ML service are somewhere else -- on their
# own private segment, or a redis you already run.
# DB_HOSTNAME=localhost
# REDIS_HOSTNAME=localhost
# IMMICH_ML_HOST=localhost
# Machine learning: false turns it off (the Machine learning choice does this).
# IMMICH_ML_ENABLED=true
# Public sharing (the Public sharing choice): the address the proxy is reached at.
# PUBLIC_BASE_URL=
# The address the server binds. Immich binds loopback unless told otherwise,
# which answers nothing if the container has an address of its own.
# IMMICH_HOST=0.0.0.0
# The values below this line do not need to be changed
###################################################################################
DB_USERNAME=postgres
DB_DATABASE_NAME=immich2. Save as compose.yaml:
#
# Immich for FreeBSD (Daemonless)
#
# Drop-in compatible with official Immich docker-compose.yml
#
# Prerequisites:
# pkg install podman-suite py311-podman-compose
#
# Usage:
# 1. Copy example.env to .env and edit
# 2. Run: podman-compose up -d
#
name: immich
services:
immich-server:
container_name: immich_server
image: ghcr.io/daemonless/immich-server:${IMMICH_TAG:-latest}
network_mode: host
volumes:
- ${UPLOAD_LOCATION}:/data
- /etc/localtime:/etc/localtime:ro
environment:
DB_HOSTNAME: ${DB_HOSTNAME:-localhost}
REDIS_HOSTNAME: ${REDIS_HOSTNAME:-localhost}
IMMICH_MACHINE_LEARNING_URL: http://${IMMICH_ML_HOST:-localhost}:3003
IMMICH_MACHINE_LEARNING_ENABLED: ${IMMICH_ML_ENABLED:-true}
# Immich binds loopback unless told otherwise, so it answers nothing on
# the host's address -- or on a published port, which forwards to the
# container's own and not to its loopback.
IMMICH_HOST: ${IMMICH_HOST:-0.0.0.0}
env_file:
- .env
depends_on:
- redis
- database
- immich-machine-learning
restart: always
immich-machine-learning:
container_name: immich_machine_learning
image: ghcr.io/daemonless/immich-ml:${IMMICH_ML_TAG:-latest}
network_mode: host
environment:
HF_HOME: /cache/huggingface
MPLCONFIGDIR: /tmp
volumes:
- model-cache:/cache
env_file:
- .env
restart: always
# Public links to albums for people with no account. Only with the Public
# sharing choice; it reaches the server over localhost and answers on 3000.
immich-public-proxy:
container_name: immich_public_proxy
image: ghcr.io/daemonless/immich-public-proxy:latest
network_mode: host
profiles: [proxy]
environment:
IMMICH_URL: http://localhost:2283
PUBLIC_BASE_URL: ${PUBLIC_BASE_URL:-}
IPP_PORT: "3000"
env_file:
- .env
depends_on:
- immich-server
restart: always
redis:
container_name: immich_redis
image: ghcr.io/daemonless/redis:latest
network_mode: host
volumes:
- /etc/localtime:/etc/localtime:ro
- redis-data:/config
restart: always
database:
container_name: immich_postgres
image: ghcr.io/daemonless/immich-postgres:latest
network_mode: host
# FreeBSD requires sysvipc for PostgreSQL shared memory
annotations:
org.freebsd.jail.allow.sysvipc: "true"
environment:
POSTGRES_PASSWORD: ${DB_PASSWORD}
POSTGRES_USER: ${DB_USERNAME}
POSTGRES_DB: ${DB_DATABASE_NAME}
volumes:
- /etc/localtime:/etc/localtime:ro
- ${DB_DATA_LOCATION}:/var/lib/postgresql/data
restart: always
volumes:
model-cache:
redis-data:Then run podman-compose up -d.
.env:
# .env
DIRECTOR_PROJECT=immich
DB_HOSTNAME=localhost
REDIS_HOSTNAME=localhost
IMMICH_MACHINE_LEARNING_URL=http://${IMMICH_ML_HOST:-localhost}:3003
IMMICH_MACHINE_LEARNING_ENABLED=true
IMMICH_HOST=0.0.0.0
UPLOAD_LOCATION=/containers/immich/library
DB_DATA_LOCATION=/containers/immich/postgres
DB_PASSWORD=postgres
DB_USERNAME=postgres
DB_DATABASE_NAME=immich
IMMICH_ML_TAG=
IMMICH_ML_ENABLED=
PUBLIC_BASE_URL=
TZ=
appjail-director.yml:
# appjail-director.yml
options:
- alias:
- ip4_inherit:
services:
immich:
name: immich
options:
- container: 'args:--pull'
oci:
user: root
environment:
- DB_HOSTNAME: !ENV '${DB_HOSTNAME}'
- REDIS_HOSTNAME: !ENV '${REDIS_HOSTNAME}'
- IMMICH_MACHINE_LEARNING_URL: !ENV '${IMMICH_MACHINE_LEARNING_URL}'
- IMMICH_MACHINE_LEARNING_ENABLED: !ENV '${IMMICH_MACHINE_LEARNING_ENABLED}'
- IMMICH_HOST: !ENV '${IMMICH_HOST}'
- UPLOAD_LOCATION: !ENV '${UPLOAD_LOCATION}'
- DB_DATA_LOCATION: !ENV '${DB_DATA_LOCATION}'
- DB_PASSWORD: !ENV '${DB_PASSWORD}'
- DB_USERNAME: !ENV '${DB_USERNAME}'
- DB_DATABASE_NAME: !ENV '${DB_DATABASE_NAME}'
- IMMICH_ML_TAG: !ENV '${IMMICH_ML_TAG}'
- IMMICH_ML_ENABLED: !ENV '${IMMICH_ML_ENABLED}'
- PUBLIC_BASE_URL: !ENV '${PUBLIC_BASE_URL}'
- TZ: !ENV '${TZ}'
volumes:
- immich_data: /data
- etc_localtime: /etc/localtime
database:
name: database
options:
- from:
- template: !ENV '${PWD}/immich-postgres-template.conf'
volumes:
immich_data:
device: '/containers/immich/data'
etc_localtime:
device: '/etc/localtime'Makejail:
# Makejail
ARG tag=latest
OPTION container=boot
OPTION overwrite=force
OPTION from=ghcr.io/daemonless/immich:${tag}
Save the files above, then run appjail-director up.
PostgreSQL shared memory. PostgreSQL wants System V IPC, which a jail does not get by default. The compose carries the annotation (org.freebsd.jail.allow.sysvipc: "true", read by ocijail) and the director bundle ships immich-postgres-template.conf for the same reason.
Machine learning. immich-ml runs a FreeBSD-native onnxruntime on the CPU; there is no GPU acceleration on FreeBSD. Models (about 1 GB) download on first use into /cache, so the first start is slow and the rest are not.
Network. The stack shares the host's network stack, so the services find each other over localhost and only 2283 needs to reach the outside. Put the parts on networks of their own and the *_HOSTNAME variables name where each one went; fjord does that for you.
Managing it. podman-compose logs -f for every service, podman logs -f immich_server for one; podman-compose restart, podman-compose down, and podman-compose pull && podman-compose up -d to update.
??? question "ML service keeps restarting"
Check memory - the ML service needs at least 2GB RAM:
bash podman logs immich_machine_learning
If you see OOM errors, give it more memory or turn the Machine learning choice off.
??? question "Database connection errors"
Ensure PostgreSQL has started and the sysvipc annotation is working:
bash podman logs immich_postgres
The database needs a few seconds to initialize on first run.
??? question "Photos not uploading from mobile"
Ensure port 2283 is accessible from your network. Check firewall rules:
bash # PF firewall pass in on egress proto tcp to port 2283
??? question "Facial recognition not working"
The ML service downloads models on first use. Check if models are cached:
bash podman exec immich_machine_learning ls -la /cache/huggingface
| Variable | Default | Description |
|---|---|---|
DB_HOSTNAME |
localhost |
|
REDIS_HOSTNAME |
localhost |
|
IMMICH_MACHINE_LEARNING_URL |
http://${IMMICH_ML_HOST:-localhost}:3003 |
|
IMMICH_MACHINE_LEARNING_ENABLED |
true |
|
IMMICH_HOST |
0.0.0.0 |
|
UPLOAD_LOCATION |
/containers/immich/library |
Path to store uploaded media |
DB_DATA_LOCATION |
/containers/immich/postgres |
Path to store database files |
DB_PASSWORD |
postgres |
PostgreSQL database password |
DB_USERNAME |
postgres |
PostgreSQL username |
DB_DATABASE_NAME |
immich |
PostgreSQL database name |
IMMICH_ML_TAG |
`` | Machine learning image tag (defaults to 'latest') |
IMMICH_ML_ENABLED |
`` | false turns machine learning off (set by the choice) |
PUBLIC_BASE_URL |
`` | Address the public proxy is reached at, no trailing slash (optional; it uses the request's host otherwise) |
TZ |
`` | Timezone |
| Path | Description |
|---|---|
/data |
Media storage (mapped to UPLOAD_LOCATION) |
/etc/localtime |
Architectures: amd64
User: bsd (UID/GID via PUID/PGID, defaults to 1000:1000)
Base: FreeBSD 15.1
Need help? Join our Discord community.