Skip to content

Immich Server Immich Server

Description / nameInput element
Container Registry
Container Configuration Root Path
Timezone
User ID
Group ID
Immich Server Host Port
Immich Server /config Path
Immich Server /data Path

Build Status Last Commit

Self-hosted photo and video backup and management server with web UI, mobile sync, and shared albums.

Port 2283
Registry ghcr.io/daemonless/immich-server
Daemonless daemonless/immich-server
Source immich-app/immich
Website immich.app

Version Tags

Tag Description Best For
latest Upstream Binary. Built from official release. Most users — recommended.

Before deploying, ensure your host environment is ready. See the Quick Start Guide for host setup instructions, including the security model for host vs. container privileges.

Deployment

services:
  immich-server:
    image: "ghcr.io/daemonless/immich-server:latest"
    container_name: immich-server
    environment:
      - DB_HOSTNAME=immich-postgres  # Postgres database hostname
      - DB_USERNAME=postgres  # Postgres database user
      - DB_PASSWORD=postgres  # Postgres database password
      - DB_DATABASE_NAME=immich  # Postgres database name
      - REDIS_HOSTNAME=immich-redis  # Redis hostname
      - PUID=1000  # User ID for the application process
      - PGID=1000  # Group ID for the application process
      - TZ=UTC  # Timezone for the container
      - SKIP_CHOWN=true  # Skip the startup recursive chown of /config and /data once ownership is recorded in /config/.chown_done (default true). Set false to force a chown on every start. The marker lives in /config, so /config must be a persistent volume for the skip to take effect across restarts.
    volumes:
      - "/path/to/containers/immich-server:/config"
      - "/path/to/containers/immich-server/data:/data"
    ports:
      - "2283:2283"
    # always (not unless-stopped) so FreeBSD's podman rc.d auto-starts it at boot
    restart: always
podman run -d --name immich-server \
  -p 2283:2283 \
  -e DB_HOSTNAME=immich-postgres \
  -e DB_USERNAME=postgres \
  -e DB_PASSWORD=postgres \
  -e DB_DATABASE_NAME=immich \
  -e REDIS_HOSTNAME=immich-redis \
  -e PUID=1000 \
  -e PGID=1000 \
  -e TZ=UTC \
  -e SKIP_CHOWN=true \
  -v /path/to/containers/immich-server:/config \
  -v /path/to/containers/immich-server/data:/data \
  ghcr.io/daemonless/immich-server:latest
- name: Deploy immich-server
  containers.podman.podman_container:
    name: immich-server
    image: "ghcr.io/daemonless/immich-server:latest"
    state: started
    restart_policy: always
    env:
      DB_HOSTNAME: "immich-postgres"
      DB_USERNAME: "postgres"
      DB_PASSWORD: "postgres"
      DB_DATABASE_NAME: "immich"
      REDIS_HOSTNAME: "immich-redis"
      PUID: "1000"
      PGID: "1000"
      TZ: "UTC"
      SKIP_CHOWN: "true"
    ports:
      - "2283:2283"
    volumes:
      - "/path/to/containers/immich-server:/config"
      - "/path/to/containers/immich-server/data:/data"
# .env

DIRECTOR_PROJECT=immich-server
DB_HOSTNAME=immich-postgres
DB_USERNAME=postgres
DB_PASSWORD=postgres
DB_DATABASE_NAME=immich
REDIS_HOSTNAME=immich-redis
PUID=1000
PGID=1000
TZ=UTC
SKIP_CHOWN=true
# appjail-director.yml

options:
  - virtualnet: ':<random> default'
  - nat:
services:
  immich-server:
    name: immich_server
    options:
      - container: 'boot args:--pull'
      - expose: '2283:2283 proto:tcp'
    oci:
      user: root
      environment:
        - DB_HOSTNAME: !ENV '${DB_HOSTNAME}'
        - DB_USERNAME: !ENV '${DB_USERNAME}'
        - DB_PASSWORD: !ENV '${DB_PASSWORD}'
        - DB_DATABASE_NAME: !ENV '${DB_DATABASE_NAME}'
        - REDIS_HOSTNAME: !ENV '${REDIS_HOSTNAME}'
        - PUID: !ENV '${PUID}'
        - PGID: !ENV '${PGID}'
        - TZ: !ENV '${TZ}'
        - SKIP_CHOWN: !ENV '${SKIP_CHOWN}'
    volumes:
      - IMMICH_SERVER_CONFIG_PATH: /config
      - IMMICH_SERVER_DATA_PATH: /data
volumes:
  IMMICH_SERVER_CONFIG_PATH:
    device: '/path/to/containers/immich-server'
  IMMICH_SERVER_DATA_PATH:
    device: '/path/to/containers/immich-server/data'
1
2
3
4
5
6
# Makejail

ARG tag=latest

OPTION overwrite=force
OPTION from=ghcr.io/daemonless/immich-server:${tag}
appjail oci run -Pd \
  -o overwrite=force \
  -o container="args:--pull" \
  -o virtualnet=":<random> default" \
  -o nat \
  -o expose="2283:2283 proto:tcp" \
  -e DB_HOSTNAME=immich-postgres \
  -e DB_USERNAME=postgres \
  -e DB_PASSWORD=postgres \
  -e DB_DATABASE_NAME=immich \
  -e REDIS_HOSTNAME=immich-redis \
  -e PUID=1000 \
  -e PGID=1000 \
  -e TZ=UTC \
  -e SKIP_CHOWN=true \
  -o fstab="/path/to/containers/immich-server /config <pseudofs>" \
  -o fstab="/path/to/containers/immich-server/data /data <pseudofs>" \
  ghcr.io/daemonless/immich-server:latest immich-server

Interactive Configuration

Parameters

Environment Variables

Variable Default Description
DB_HOSTNAME immich-postgres Postgres database hostname
DB_USERNAME postgres Postgres database user
DB_PASSWORD postgres Postgres database password
DB_DATABASE_NAME immich Postgres database name
REDIS_HOSTNAME immich-redis Redis hostname
PUID 1000 User ID for the application process
PGID 1000 Group ID for the application process
TZ UTC Timezone for the container
SKIP_CHOWN true Skip the startup recursive chown of /config and /data once ownership is recorded in /config/.chown_done (default true). Set false to force a chown on every start. The marker lives in /config, so /config must be a persistent volume for the skip to take effect across restarts.

Volumes

Path Description
/config Holds the startup ownership marker (.chown_done). Mount as a persistent volume so the chown is skipped on later starts.
/data Media storage (photos, videos, thumbnails)

Ports

Port Protocol Description
2283 TCP Web UI/API

This image is part of the Immich Stack.

Implementation Details

  • Architectures: amd64
  • User: bsd (UID/GID set via PUID/PGID). Defaults to 1000:1000.
  • Base: Built on ghcr.io/daemonless/base (FreeBSD 15.1).

Need help? Join our Discord community.