Self-host Immich on a VPS

Run Immich, the self-hosted photo and video backup, from its Docker Compose file, keep it private until it has HTTPS, and back up your phone to it.

To self-host Immich, download the docker-compose.yml and example.env from its latest release, set a database password and a storage location, and start it with docker compose up -d. On VPSNine the Immich one-click app does that on the first boot, keeps Immich on the server's loopback, creates the admin account for you, and puts it on your domain with HTTPS in one command.

Immich backs up photos and videos from your phone and organises them with faces, places and search, much like Google Photos.

What you need

  • The Extreme plan (4 vCPU, 8 GB). It's the only plan we offer Immich on: Immich asks for at least 6 GB of memory and recommends 8 GB, and 4 GB only works with its machine learning turned off.
  • Room for your library. Extreme has 160 GB, shared between your originals, Immich's thumbnails and converted videos (10 to 20% on top), the database (1 to 3 GB) and the system. That's roughly 120 GB of photos and videos. Check your phone's library size before you start.
  • A domain or subdomain for it, like photos.example.com. The phone app connects to it over HTTPS.

Install it with the one-click app

Order a server with the Immich app. On the first boot we install Docker and use the docker-compose.yml and example.env from Immich's latest release in /opt/immich: the server, machine learning, PostgreSQL and Valkey. Immich's own Compose file publishes port 2283 to everyone; the installer changes it to 127.0.0.1:2283, and stops rather than start Immich publicly if it can't. Immich normally makes the first person to sign up its admin, so the installer creates the admin before anyone can reach the port. One-click apps shows how to follow the install.

Immich is ready when this answers pong on the server:

bash
curl http://127.0.0.1:2283/api/server/ping

Then:

  1. Point photos.example.com at the server (an A record with its IPv4 address, for example 203.0.113.10), allow ports 80 and 443 in the panel firewall, and run:

    bash
    vps9-https photos.example.com
  2. Show your login, open https://photos.example.com and log in. In Account Settings, change the admin's email (it starts as admin@example.com) and password.

    bash
    cat /root/immich-admin.txt
  3. Install the Immich app on your phone, connect it to https://photos.example.com, and turn on backup.

To look around before you have a domain, open an SSH tunnel from your computer with ssh -L 2283:127.0.0.1:2283 root@203.0.113.10 and browse to http://localhost:2283.

Put it on your domain with HTTPS

For Immich, vps9-https installs Caddy from Caddy's own packages, writes a site for your domain that passes everything to 127.0.0.1:2283, and reloads Caddy, which gets and renews a Let's Encrypt certificate. Port 2283 stays on loopback; only 80 and 443 face the internet.

If the domain doesn't point at the server yet, it says so, and Caddy gets the certificate once DNS catches up. To move to another domain, run it again with the new one.

Doing it by hand on another server

Immich's Docker Compose guide is the official method. You need Docker Engine with the Compose plugin; Install Docker covers it. The outline:

bash
mkdir /opt/immich && cd /opt/immich
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

In .env, set UPLOAD_LOCATION to a folder with enough space, DB_DATA_LOCATION to local storage (not a network share), DB_PASSWORD to letters and digits only, and TZ to your time zone. Before you start it, change the server's 2283:2283 port line in docker-compose.yml to 127.0.0.1:2283:2283, so the first visitor can't claim the admin account. Then:

bash
docker compose up -d

Open it through an SSH tunnel, create the admin account, and put a reverse proxy with a certificate in front, as in Serve a site with nginx and HTTPS.

Updates and backups

Updates are yours, and Immich changes often. Read the release notes first, especially for breaking changes, then:

bash
cd /opt/immich
docker compose pull
docker compose up -d

We turn on the operating system's automatic security updates; they don't touch Immich's containers.

Immich dumps its database every night into the backups folder under /opt/immich/library. Copy that, and the library, upload and profile folders that hold your photos, off the server. Backups you should run shows how to do it nightly.

Immich isn't a backup on its own, and its own documentation says not to rely on it as your only copy. Keep a second copy of your library somewhere else, such as an external drive or another provider's storage, and test that you can restore it.

When it goes wrong

  • The phone app can't connect: give it the full https://photos.example.com address. Port 2283 isn't public, so http://203.0.113.10:2283 won't work from your phone. If the HTTPS address doesn't load in a browser either, check the domain points at the server and that ports 80 and 443 are open; journalctl -u caddy -n 30 shows whether Caddy got its certificate.
  • The disk fills up: check with df -h and du -sh /opt/immich/library. Converted videos and thumbnails add 10 to 20% to your originals. Empty Immich's trash, or add disk with the Extra NVMe add-on before you hit the limit, since a full disk can stop the database.
  • The server runs out of memory: machine learning is the biggest user. You can turn it off in Administration, Settings, Machine Learning, and remove the immich-machine-learning service from /opt/immich/docker-compose.yml. Face recognition and smart search then stop working.

Be first when orders open

Join the waitlist and we'll send you one email when VPSNine launches. Pick a plan if you already know which one you want, and we'll size the first servers around it.

  • One email, on launch day
  • Monthly or yearly, no lock-in
  • 14-day money-back guarantee