Skip to content
daemonlessPublic

Repository files navigation

Immich

Build Status Last Commit OCI Pulls

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/

Version Tags

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.

Prerequisites

Before deploying, ensure your host environment is ready. See the Quick Start Guide for host setup instructions.

Deployment

Podman Compose

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=immich

2. 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.

AppJail Director

.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.

Setup Instructions

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.

Troubleshooting

??? 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

Parameters

Environment Variables

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

Volumes

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.

Releases

Packages

Contributors