Immich — a high-performance, self-hosted photo and video backup solution (a Google Photos alternative) with mobile apps, AI-powered search, face recognition and albums. Batteries-included: bundles PostgreSQL (with vector extensions), Redis and the machine-learning service.
Needs nomad-pack on PATH. The script only adds the nomploy registry and runs this pack.
Source ↗ Project ↗ ★ 115k ⚑ Report an issue
Save as values.hcl, edit, then run:
# The name of the Nomad job.
job_name = "immich"
# The Nomad namespace to deploy into.
namespace = "default"
# The datacenters to deploy to.
datacenters = ["*"]
# The Immich server image. Pin a tag in production (keep it in sync with machine_learning_image).
image = "ghcr.io/immich-app/immich-server:release"
# The Immich machine-learning image. Keep its tag in sync with the server image.
machine_learning_image = "ghcr.io/immich-app/immich-machine-learning:release"
# The Immich PostgreSQL image. This is a special build with the required vector extensions — do not swap it for stock postgres.
postgres_image = "ghcr.io/immich-app/postgres:14-vectorchord0.4.3-pgvectors0.2.0"
# The Redis/Valkey image used as the job queue.
redis_image = "valkey/valkey:8-bookworm"
# Host port for the Immich web UI / API.
port = 2283
# Host port for the bundled PostgreSQL (loopback only).
db_port = 5432
# Host port for the bundled Redis/Valkey (loopback only).
redis_port = 6379
# Host port for the machine-learning service (loopback only). Fixed at 3003 inside the image.
ml_port = 3003
# PostgreSQL username.
db_user = "postgres"
# PostgreSQL password. CHANGE THIS. Use alphanumeric characters only (no special characters).
db_password = "change-me-immich-postgres"
# PostgreSQL database name.
db_name = "immich"
# Named volume mounted at /data — your photo and video library. This grows large; back it up.
upload_volume = "immich_upload"
# Named volume for the PostgreSQL data directory.
db_data_volume = "immich_db"
# Named volume for the machine-learning model cache (/cache).
model_cache_volume = "immich_model_cache"
# Named volume for Redis/Valkey persistence (/data).
redis_data_volume = "immich_redis"
# Placement constraints. Pin to the node holding the volumes. On a nomploy cluster: attribute = "$${meta.nomploy_control_plane}", operator = "=", value = "true".
constraints = []
# Resources for the Immich server task.
resources = {
cpu = 1000
memory = 1024
}
# Resources for the machine-learning task. Model inference is CPU/RAM heavy.
machine_learning_resources = {
cpu = 1000
memory = 1536
}
# Resources for the PostgreSQL task.
postgres_resources = {
cpu = 500
memory = 512
}
# Resources for the Redis/Valkey task.
redis_resources = {
cpu = 200
memory = 128
}
| Name | Type | Default | Description |
|---|---|---|---|
| job_name | string | "immich" | The name of the Nomad job. |
| namespace | string | "default" | The Nomad namespace to deploy into. |
| datacenters | list | ["*"] | The datacenters to deploy to. |
| image | string | "ghcr.io/immich-app/immich-server:release" | The Immich server image. Pin a tag in production (keep it in sync with machine_learning_image). |
| machine_learning_image | string | "ghcr.io/immich-app/immich-machine-learning:release" | The Immich machine-learning image. Keep its tag in sync with the server image. |
| postgres_image | string | "ghcr.io/immich-app/postgres:14-vectorchord0.4.3-pgvectors0.2.0" | The Immich PostgreSQL image. This is a special build with the required vector extensions — do not swap it for stock postgres. |
| redis_image | string | "valkey/valkey:8-bookworm" | The Redis/Valkey image used as the job queue. |
| port | number | 2283 | Host port for the Immich web UI / API. |
| db_port | number | 5432 | Host port for the bundled PostgreSQL (loopback only). |
| redis_port | number | 6379 | Host port for the bundled Redis/Valkey (loopback only). |
| ml_port | number | 3003 | Host port for the machine-learning service (loopback only). Fixed at 3003 inside the image. |
| db_user | string | "postgres" | PostgreSQL username. |
| db_password set me | string | "change-me-immich-postgres" | PostgreSQL password. CHANGE THIS. Use alphanumeric characters only (no special characters). |
| db_name | string | "immich" | PostgreSQL database name. |
| upload_volume | string | "immich_upload" | Named volume mounted at /data — your photo and video library. This grows large; back it up. |
| db_data_volume | string | "immich_db" | Named volume for the PostgreSQL data directory. |
| model_cache_volume | string | "immich_model_cache" | Named volume for the machine-learning model cache (/cache). |
| redis_data_volume | string | "immich_redis" | Named volume for Redis/Valkey persistence (/data). |
| constraints | list | [] | Placement constraints. Pin to the node holding the volumes. On a nomploy cluster: attribute = "$${meta.nomploy_control_plane}", operator = "=", value = "true". |
| resources | object | {
cpu = 1000
memory = 1024
} | Resources for the Immich server task. |
| machine_learning_resources | object | {
cpu = 1000
memory = 1536
} | Resources for the machine-learning task. Model inference is CPU/RAM heavy. |
| postgres_resources | object | {
cpu = 500
memory = 512
} | Resources for the PostgreSQL task. |
| redis_resources | object | {
cpu = 200
memory = 128
} | Resources for the Redis/Valkey task. |
No variables match.
This pack stores data in 4 Docker named volumes:
immich_dbimmich_redisimmich_model_cacheimmich_upload
⚠ This pack bundles a database. A cold copy of the volume can be inconsistent — for a reliable backup, dump the DB (pg_dump / mysqldump) or stop the job while backing up.
restic
# Run on the node hosting this pack. Point restic at your repo first: # export RESTIC_REPOSITORY="s3:https://<account>.r2.cloudflarestorage.com/<bucket>" # export RESTIC_PASSWORD="<repo-password>" # export AWS_ACCESS_KEY_ID=<key> AWS_SECRET_ACCESS_KEY=<secret> restic backup \ /var/lib/docker/volumes/immich_db/_data \ /var/lib/docker/volumes/immich_redis/_data \ /var/lib/docker/volumes/immich_model_cache/_data \ /var/lib/docker/volumes/immich_upload/_data
rclone (sync to S3/R2)
rclone sync /var/lib/docker/volumes/immich_db/_data backup:<bucket>/immich_db rclone sync /var/lib/docker/volumes/immich_redis/_data backup:<bucket>/immich_redis rclone sync /var/lib/docker/volumes/immich_model_cache/_data backup:<bucket>/immich_model_cache rclone sync /var/lib/docker/volumes/immich_upload/_data backup:<bucket>/immich_upload
Paths assume the default Docker volume location (/var/lib/docker/volumes). Restore by stopping the job, restoring files into the same volume, and re-running the pack.
Immich — a high-performance, self-hosted photo and video backup solution and a genuine Google Photos alternative. Automatic mobile backup, timeline and map views, albums and sharing, plus AI-powered search, face recognition and object detection — all running on your own hardware.
This pack is batteries-included: a single host-networked group running four tasks —
nomad-pack registry add nomploy https://github.com/Nomploy/nomad-packs
nomad-pack run immich --registry=nomploy
| Variable | Default | Description |
|---|---|---|
port |
2283 |
Web UI / API port. |
db_password |
change-me-… |
Change this. PostgreSQL password — alphanumeric only. |
upload_volume |
immich_upload |
/data — your photo/video library. Grows large; back it up. |
image |
ghcr.io/immich-app/immich-server:release |
Server image. Pin a tag — keep it in sync with the ML image. |
machine_learning_image |
…/immich-machine-learning:release |
ML image. Match its tag to the server. |
postgres_image |
ghcr.io/immich-app/postgres:14-vectorchord… |
Do not swap for stock postgres — Immich needs the vector extensions. |
redis_image |
valkey/valkey:8-bookworm |
Job-queue image. |
db_data_volume / model_cache_volume / redis_data_volume |
… | Postgres data, ML model cache, Redis persistence. |
db_port / redis_port / ml_port |
5432 / 6379 / 3003 |
Loopback ports for the bundled services. |
resources |
{ cpu = 1000, memory = 1024 } |
Server task resources. |
machine_learning_resources |
{ cpu = 1000, memory = 1536 } |
ML resources — inference is heavy. |
postgres_resources / redis_resources |
… | Bundled DB / queue resources. |
Version pinning: pin
imageandmachine_learning_imageto the same Immich version in production, and read the release notes before upgrading (Immich makes breaking changes). All four tasks share the host network, so they run together on one node — pin the job to the node holding the volumes withconstraints. The first account you create becomes the admin. Put Immich behind an authenticating reverse proxy over TLS before exposing it.