> ## Documentation Index
> Fetch the complete documentation index at: https://docs.arct.cloud/llms.txt
> Use this file to discover all available pages before exploring further.

# Self-host Immich

> Deploy Immich on an Ubuntu VPS with the official Docker Compose stack, HTTPS, storage planning, backups, and safe upgrades.

Arct Cloud provides the unmanaged Linux VPS for this deployment. Immich is not preinstalled or managed by Arct Cloud, and you are responsible for application administration, storage capacity, backups, security, and updates.

<Warning>
  Immich should not be the only copy of your photos or videos. Maintain independent, tested backups of both the asset files and the database.
</Warning>

## Choose a Plan

Immich's current official minimum is 2 CPU cores and 6 GB RAM; the recommended size is 4 CPU cores and 8 GB RAM.

| Arct plan     | vCPU |  RAM | NVMe storage | Fit                                           |
| ------------- | ---: | ---: | -----------: | --------------------------------------------- |
| **cvm.tiny**  |    2 | 6 GB |        55 GB | Official minimum; small library or evaluation |
| **cvm.small** |    4 | 8 GB |        75 GB | Official recommended CPU and memory profile   |

Thumbnails and transcoded video can add roughly 10–20% to the original library size. Check current plan resources on the [Arct Cloud pricing page](https://www.arct.cloud/pricing), leave space for the database and Docker images, and plan migration before the disk approaches capacity.

## Before You Begin

Prepare the following:

* A fresh Ubuntu 24.04 server
* A domain or subdomain such as `photos.example.com`
* An `A` record pointing that hostname to the server's public IPv4 address
* Docker Engine 25 or newer with the Docker Compose plugin, installed from the [official Docker repository](https://docs.docker.com/engine/install/ubuntu/)
* A reverse proxy such as Caddy or Nginx

Immich requires a full virtual machine, local SSD-backed PostgreSQL storage, and the `docker compose` command. The legacy `docker-compose` command is not supported.

## Install Immich

<Steps>
  <Step title="Deploy and Connect">
    [Deploy an Ubuntu server](/compute/virtual-machines/deploy), then [connect over SSH](/compute/virtual-machines/connect-ssh).
  </Step>

  <Step title="Allow the Ubuntu User to Run Docker">
    After installing Docker Engine and the Compose plugin from Docker's official Ubuntu repository, add the default Ubuntu user to the Docker group:

    ```bash theme={null}
    sudo usermod -aG docker ubuntu
    exit
    ```

    Reconnect so the group change takes effect, then verify Docker and Compose work without `sudo`:

    ```bash theme={null}
    ssh ubuntu@YOUR_SERVER_IP
    docker version
    docker compose version
    ```

    <Warning>The `docker` group grants effective root access through privileged containers and host mounts. Add only trusted administrator accounts.</Warning>
  </Step>

  <Step title="Download the Official Compose Files">
    ```bash theme={null}
    sudo install -d -m 0750 -o "$USER" -g "$USER" /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
    ```

    These release assets are the installation method recommended by Immich for production Docker Compose deployments.
  </Step>

  <Step title="Configure Storage and Secrets">
    Edit `/opt/immich/.env` and set at least these values:

    ```dotenv theme={null}
    UPLOAD_LOCATION=/opt/immich/library
    DB_DATA_LOCATION=/opt/immich/postgres
    TZ=Etc/UTC
    IMMICH_VERSION=v3
    DB_PASSWORD=REPLACE_WITH_A_LONG_ALPHANUMERIC_SECRET
    ```

    Use only letters and numbers in `DB_PASSWORD`, as recommended by Immich. Keep the PostgreSQL directory on local NVMe storage; a network share is not supported for the database.

    Protect the environment file after editing it:

    ```bash theme={null}
    chmod 0600 /opt/immich/.env
    ```
  </Step>

  <Step title="Keep the Application Port Private">
    In the `immich-server` service, bind the published port to loopback rather than every interface:

    ```yaml theme={null}
    ports:
      - "127.0.0.1:2283:2283"
    ```

    Do not expose port `2283` through UFW or an external firewall.
  </Step>

  <Step title="Start the Stack">
    ```bash theme={null}
    cd /opt/immich
    docker compose pull
    docker compose up -d
    docker compose ps
    ```

    Wait until the containers report healthy before continuing. Initial machine-learning image downloads and startup can take several minutes.
  </Step>

  <Step title="Create the Administrator Privately">
    Keep port `2283` bound to loopback. From a second terminal on your local computer, open an SSH tunnel:

    ```bash theme={null}
    ssh -N -L 2283:127.0.0.1:2283 ubuntu@YOUR_SERVER_IP
    ```

    Open `http://127.0.0.1:2283`, create the first account, and sign in. The first account becomes the administrator. Enable multi-factor authentication, save the recovery codes separately, and review user creation and storage settings before exposing the service publicly.

    Stop the tunnel with <kbd>Ctrl</kbd>+<kbd>C</kbd> only after administrator access and MFA are verified.
  </Step>

  <Step title="Enable Public HTTPS">
    Install Caddy using its [official Debian and Ubuntu instructions](https://caddyserver.com/docs/install#debian-ubuntu-raspbian), then add this block to `/etc/caddy/Caddyfile`:

    ```caddy theme={null}
    photos.example.com {
        reverse_proxy 127.0.0.1:2283
    }
    ```

    Immich must be served from the root of a domain or subdomain, not a path such as `/immich`.

    ```bash theme={null}
    sudo caddy validate --config /etc/caddy/Caddyfile
    sudo systemctl reload caddy
    ```

    Open `https://photos.example.com`, sign in with the existing administrator, and confirm MFA before inviting other users. At no point should the unauthenticated first-account screen be reachable through the public proxy.
  </Step>
</Steps>

## Firewall

Allow SSH before enabling UFW:

```bash theme={null}
sudo ufw allow OpenSSH
sudo ufw allow 80/tcp
sudo ufw allow 443/tcp
sudo ufw enable
sudo ufw status
```

Only `22`, `80`, and `443` should normally be public. Keep PostgreSQL, Redis, and port `2283` private.

## Back Up and Restore

Immich automatically creates database dumps under `UPLOAD_LOCATION/backups`, but those dumps do not include photos or videos. A complete recovery set requires all of the following:

* A current Immich database dump
* An off-server copy of the entire `UPLOAD_LOCATION`, especially `upload`, `library`, and `profile`
* The contents of every external library, or a separately protected authoritative copy of those files
* The protected `.env` file and every Compose or override file, including all external-library mount definitions
* The exact configured image references, running image IDs, and Immich version used when the backup was created

Create a restricted metadata checkpoint alongside each asset and database backup:

```bash theme={null}
(
  set -euo pipefail
  cd /opt/immich
  stamp="$(date -u +%Y%m%dT%H%M%SZ)"
  checkpoint="/var/backups/immich/${stamp}"
  sudo install -d -m 0700 -o "$USER" -g "$USER" "$checkpoint"

  cp -p .env "$checkpoint/"
  find . -maxdepth 1 -type f \
    \( -name 'docker-compose*.yml' -o -name 'docker-compose*.yaml' \
       -o -name 'compose*.yml' -o -name 'compose*.yaml' \) \
    -exec cp -p {} "$checkpoint/" \;

  docker compose config --images >"$checkpoint/configured-images.txt"
  docker compose ps -q | while read -r container_id; do
    docker inspect --format '{{.Name}} {{.Config.Image}} {{.Image}}' \
      "$container_id"
  done >"$checkpoint/running-images.txt"
  grep '^IMMICH_VERSION=' .env >"$checkpoint/immich-version.txt"
  chmod 0600 "$checkpoint"/*
)
```

The Compose files preserve host-to-container mount definitions for external libraries; the database dump preserves Immich's library records. Both are required to reconnect the same paths during recovery. Store this metadata checkpoint encrypted with the matching database and filesystem backup.

For the most consistent filesystem copy, stop the `immich-server` container while the backup tool reads the asset directories. If the service must remain online, back up the database first and the filesystem second. Never edit files inside the Immich library directly.

Follow the [official backup and restore guide](https://docs.immich.app/administration/backup-and-restore/) and perform a test restore before relying on the backup. Restores across different Immich versions can require migrations.

## Update Safely

Immich supports the current stable release and does not support downgrades. Before updating, upgrade mobile clients, read the [release notes](https://github.com/immich-app/immich/releases), account for breaking changes, and create a complete backup.

```bash theme={null}
cd /opt/immich
docker compose pull
docker compose up -d
docker compose ps
docker compose logs --tail=150 immich-server
```

If you pin `IMMICH_VERSION`, update it only after reviewing the target release. Restore a compatible backup instead of attempting an unsupported downgrade.

## Troubleshooting

| Symptom                             | Check                                                                                                                       |
| ----------------------------------- | --------------------------------------------------------------------------------------------------------------------------- |
| A container never becomes healthy   | Run `docker compose ps` and `docker compose logs`; confirm Docker Engine is current and the server meets the RAM minimum.   |
| Uploads fail or time out            | Confirm the reverse proxy forwards WebSocket and forwarded headers, allows large request bodies, and has adequate timeouts. |
| The mobile app cannot connect       | Use the root URL of the HTTPS subdomain and confirm `/.well-known/immich` reaches Immich.                                   |
| PostgreSQL reports storage errors   | Confirm `DB_DATA_LOCATION` is on local NVMe with free space and correct ownership.                                          |
| The disk grows faster than expected | Review original assets, thumbnails, transcoded video, database dumps, and unused Docker images separately.                  |

## Official Resources

<CardGroup cols={2}>
  <Card title="Immich Installation" icon="book-open" href="https://docs.immich.app/install/docker-compose/">
    Current Docker Compose files, environment settings, and post-installation guidance.
  </Card>

  <Card title="Immich on GitHub" icon="github" href="https://github.com/immich-app/immich">
    Source code, releases, issues, and security information.
  </Card>
</CardGroup>

<Note>Immich is developed independently of Arct Cloud. Arct Cloud is an independent infrastructure provider and is not affiliated with, sponsored by, or endorsed by Immich or FUTO.</Note>
