Use case · Photo and video library

A self-hosted Immich server, built around the library

A self-hosted Immich server needs 64-bit Linux with Docker Engine and the Compose plugin, at least 6 GB of RAM (8 GB recommended) and 2 CPU cores (4 recommended), according to Immich's requirements page, with the PostgreSQL database kept on a local SSD rather than any network share. The photo library itself goes wherever the disks are largest, and that is what sizes the machine.

Configure it

Immich's requirements

ResourceImmich documentation
OSLinux or another 64-bit *nix (Ubuntu, Debian); non-Linux OSes strongly discouraged
DockerDocker Engine with the Compose plugin: docker compose, not the old docker-compose
RAM6 GB minimum, 8 GB recommended; 4 GB works with machine learning disabled
CPU2 cores minimum, 4 recommended; since v3 the amd64 machine-learning container needs x86-64-v2
FilesystemUnix-compatible with ownership and permissions (EXT4, ZFS)
DatabaseLocal SSD, never a network share; typically 1-3 GB

Thumbnails and transcoded video grow the library by roughly 10-20% on top of the originals. With Docker resource limits in place, Postgres needs at least 2 GB of RAM of its own.

Two kinds of storage

Immich splits cleanly into a small, latency-sensitive database and a large, sequential library. Put DB_DATA_LOCATION on an SSD and UPLOAD_LOCATION on a RAID array of large drives. Size the array from the existing library plus 10-20% for derived files plus the years of growth you expect, then mirror or add parity so one drive failure is a rebuild, not a restore.

Installing with Docker Compose

  1. Install Docker Engine and the Compose plugin from Docker's repository; Immich's docs note that the docker.io package on Ubuntu 22.04.3 can produce errors.
  2. Create a directory and download docker-compose.yml and example.env (saved as .env) from the latest release.
  3. In .env, point UPLOAD_LOCATION at the array and DB_DATA_LOCATION at the SSD, change DB_PASSWORD, and set TZ. Then edit the compose file so the server publishes 127.0.0.1:2283:2283 instead of 2283:2283: Docker publishes ports on every interface and its rules bypass ufw.
  4. Run docker compose up -d, reach the web app over an SSH tunnel (ssh -L 2283:localhost:2283 user@server), and register at once: the first user to register becomes the administrator.
mkdir ./immich-app && cd ./immich-app
wget -O docker-compose.yml https://github.com/immich-app/immich/releases/latest/download/docker-compose.yml
wget -O .env https://github.com/immich-app/immich/releases/latest/download/example.env
# edit .env: UPLOAD_LOCATION, DB_DATA_LOCATION, DB_PASSWORD, TZ
# edit docker-compose.yml: under immich-server ports, change '2283:2283' to '127.0.0.1:2283:2283'
docker compose up -d

Register the admin account over the tunnel first. Then, for the mobile apps, put a reverse proxy with TLS on the server itself (pointed at 127.0.0.1:2283) and publish only the proxy's 443. Port 2283 stays bound to 127.0.0.1 and is never exposed.

Backups that restore

Immich dumps its database daily at 02:00 by default and keeps the last 14, in UPLOAD_LOCATION/backups. Those dumps hold metadata and paths, not photos. The originals live in library, upload and profile under UPLOAD_LOCATION; back up those, or the whole folder, and the dumps together.

Immich's docs recommend a 3-2-1 strategy and note that stopping the server during the backup keeps database and files consistent. RAID on the server is not one of the three copies.

Building the machine to order

A photo library is the workload fixed plans fit worst: the drive count and capacity matter more than anything else. On a custom dedicated server you choose the platform, processor, memory, controller, drives and how many of them (up to 24 bays), the RAID level, and an optional GPU, with the monthly price updating as you pick. The whole machine is yours: root, every disk, and an unmetered port.

A build is handed over 4 to 24 hours after approval. A racked machine that already fits the specification goes live in about 30 minutes. For a GPU to accelerate machine learning or video transcoding, the configurator lists which cards a board takes, and every card we fit is on the GPU page.

When a dedicated server is too much

A single household with a few hundred gigabytes can run Immich on a home box. A dedicated machine makes sense for a large family archive, several households or a studio, when the library runs to terabytes and should sit on enterprise disks in a data centre rather than at home. For general file sync next to it, see Nextcloud.

Questions

How much RAM does Immich need?

Immich's documentation gives 6 GB minimum and 8 GB recommended. With machine learning disabled, 4 GB can run it.

Can the database live on a NAS?

No. The docs say DB_DATA_LOCATION should ideally use local SSD storage and never a network share of any kind. The photo library can sit on larger, slower storage.

Which port does Immich use?

The web app answers on port 2283. Register first, since that account becomes the admin, then publish it through a reverse proxy with TLS.

Why does docker-compose fail?

Immich needs the Compose plugin, invoked as docker compose. The older docker-compose command is not supported and fails with a compose-file error.

Are Immich's database backups enough?

No. The automatic dumps hold metadata and file paths only. Back up library, upload and profile (or all of UPLOAD_LOCATION) with them.

Does machine learning work on any CPU?

Since v3, the amd64 machine-learning container needs the x86-64-v2 microarchitecture level. Older processors without it are no longer supported for that container.

Build the Immich server

Choose the drives, RAID, memory and GPU part by part, priced as you go, month to month.

Configure it

Related on Server Room

Other use cases