Files
Main/2 Personal/Home Lab/NAS/immich_v1.1_setup.md
Obsidian-MBPM4 0d1dc5990e vault backup: 2026-03-31 14:56:35
Affected files:
.obsidian/workspace.json
2 Personal/Home Lab/NAS/immich_v1.1_setup.md
2026-03-31 14:56:35 +02:00

14 KiB

Immich V1 setup on Proxmox + Synology NAS + Authentik + Pangolin

Status

This document is the ground truth for the current Immich V1 deployment and the first troubleshooting reference.

Current state:

  • Platform: Proxmox VM
  • Guest OS: Debian 13 server, headless
  • Networking: LAN IP via DHCP reservation, plus ZeroTier installed
  • Container runtime: Docker + Docker Compose
  • Immich deployment: official Immich docker-compose.yml
  • Storage model:
    • media/library on Synology NAS via NFS
    • Postgres on local VM storage
  • Planned next steps: Authentik OIDC login, Pangolin public reverse proxy, Synology snapshots verification

Why this architecture

This is the correct V1 shape because:

  • Immich recommends a full VM in virtualized environments, not Docker in LXC.
  • Immich recommends Docker Compose for normal deployment.
  • Immich explicitly states that the Postgres database should stay on local SSD storage and not on a network share.
  • Synology Btrfs snapshots are a good fit for the media share.
  • NFS is a cleaner Linux-to-Linux storage mount than SMB for this use case.

Current implemented architecture

flowchart LR
    subgraph Users
        U1[Browser users]
        U2[Immich mobile app users]
        U3[Admin via SSH]
    end

    subgraph Edge
        ZT[ZeroTier]
        PG[Pangolin - planned]
    end

    subgraph Proxmox
        VM[Debian 13 VM\nimmich-vm]
        DC[Docker Compose]
        IS[Immich Server]
        IML[Immich ML]
        R[(Redis)]
        DB[(Postgres\nlocal disk)]
        CFG[/opt/immich-app\ncompose + .env/]
        NFSM[/mnt/immich-prod\nNFS mount/]
    end

    subgraph Synology
        SHARE[Shared folder: immich-prod]
        SNAP[Snapshots - to configure/verify]
    end

    subgraph Identity
        AK[Authentik - planned]
    end

    U3 --> ZT --> VM
    U1 --> PG --> IS
    U2 --> PG --> IS
    VM --> DC
    DC --> IS
    DC --> IML
    DC --> R
    DC --> DB
    IS --> NFSM
    IML --> NFSM
    NFSM --> SHARE
    SHARE --> SNAP
    IS --> AK

VM build decisions

Guest type

  • Debian 13 server/headless
  • No desktop environment
  • SSH server installed
  • Standard system utilities installed

Proxmox VM settings used/recommended

  • Machine type: q35
  • BIOS: OVMF (UEFI)
  • Graphics: default / minimal, no desktop needed
  • CPU type: ideally host
    • acceptable fallback: x86-64-v2-AES
  • vCPU: 4
  • RAM: 8 GB recommended
  • Disk: local SSD-backed VM disk, enough for OS + Docker + Postgres
    • good V1 default: 64 GB
  • NIC model: VirtIO

Why

  • q35 + OVMF is the modern sane default.
  • Debian headless keeps the VM simple and low-maintenance.
  • Immich itself does not need a GUI on the host.
  • Local disk is used for DB because the DB must not live on NFS.

Directory layout

On the VM

/opt/immich-app/
├── docker-compose.yml
├── .env
└── postgres/

/mnt/immich-prod/
├── library/
└── model-cache/   # optional, if you keep ML cache here

Why this layout

  • /opt/immich-app is for the application deployment, not user files.
  • /mnt/immich-prod is the mounted NAS share.
  • postgres/ stays on local VM storage.
  • Do not put the project under /home/cef/... for production-style operation.

Installed packages / components

Installed on the VM:

  • docker
  • docker compose
  • zerotier
  • nfs-common
  • sudo

Useful verification commands:

docker --version
docker compose version
zerotier-cli info
showmount -e 192.168.1.34
mount | grep immich

Synology NFS setup

NAS

  • Synology IP: 192.168.1.34
  • Shared folder / export: /volume1/immich-prod
  • Allowed client: 192.168.1.52

Verified export list:

sudo showmount -e 192.168.1.34

Expected output:

Export list for 192.168.1.34:
/volume1/Downloads   192.168.1.35/24
/volume1/immich-prod 192.168.1.52

VM mountpoint

sudo mkdir -p /mnt/immich-prod

Manual mount command

sudo mount -t nfs 192.168.1.34:/volume1/immich-prod /mnt/immich-prod

Important typo that already happened once

Wrong:

sudo mount -t nfs 192.168.1.34:/volumel/immich-prod /mnt/immich-prod

Correct:

sudo mount -t nfs 192.168.1.34:/volume1/immich-prod /mnt/immich-prod

The mistake was volumel with letter l instead of volume1 with number 1.

Use this:

192.168.1.34:/volume1/immich-prod  /mnt/immich-prod  nfs  rw,hard,_netdev,x-systemd.automount,noatime  0  0

Then test it:

sudo mount -a
mount | grep immich-prod
df -h | grep immich-prod

Why these mount options

  • rw -> read/write
  • hard -> keep retrying if the NAS drops briefly
  • _netdev -> network-dependent mount
  • x-systemd.automount -> avoids ugly boot timing issues
  • noatime -> reduces metadata writes

Immich deployment files

Project directory

cd /opt/immich-app

Compose file

Use the official Immich release docker-compose.yml unchanged unless there is a specific reason to change it.

This is important because:

  • the official file stays aligned with the current release
  • random blog versions drift
  • hand-written compose files become future maintenance debt

Current .env

Current deployment values:

# You can find documentation for all the supported env variables at https://docs.immich.app/install/environment-variables

# The location where your uploaded files are stored
UPLOAD_LOCATION=/mnt/immich-prod/library

# The location where your database files are stored
# MUST stay on local VM storage, not on NFS
DB_DATA_LOCATION=/opt/immich-app/postgres

# Set your timezone
TZ=Europe/Zurich

# Immich Settings
IMMICH_ENV=production

# Immich version
IMMICH_VERSION=v2

# Database credentials
# Use only A-Za-z0-9 for this value
DB_PASSWORD=my-secret-pw. # See Lastpass

# Usually leave these as default unless you have a reason to change them
DB_USERNAME=postgres
DB_DATABASE_NAME=immich

Why these values are correct

  • UPLOAD_LOCATION=/mnt/immich-prod/library
    • correct because media belongs on the NAS share
  • DB_DATA_LOCATION=/opt/immich-app/postgres
    • correct because DB must stay local
  • TZ=Europe/Zurich
    • good operational default
  • IMMICH_ENV=production
    • correct for this VM
  • IMMICH_VERSION=v2
    • matches current official release convention

Useful Docker commands

Start / recreate stack

cd /opt/immich-app
docker compose up -d

Stop stack

cd /opt/immich-app
docker compose down

See running containers

docker ps

Follow logs

cd /opt/immich-app
docker compose logs -f

Follow a single service log

docker compose logs -f immich-server
docker compose logs -f database
docker compose logs -f redis
docker compose logs -f immich-machine-learning

Restart stack

docker compose restart

Pull updated images later

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

Current data model

Media

Stored on NAS via:

/mnt/immich-prod/library

This means:

  • media is on Synology storage
  • Synology snapshots can protect it
  • the actual photos/videos do not live on the VM disk

Database

Stored locally via:

/opt/immich-app/postgres

This means:

  • DB is not exposed to NFS consistency problems
  • VM backup strategy must include this path
  • DB and media are separate backup concerns

Automatic Immich DB backups

Immich also stores automatic DB dumps under the upload location, typically in:

UPLOAD_LOCATION/backups

Those backups contain metadata only, not the photo/video files.

So:

  • NAS snapshots help protect media and DB dump files
  • but media + DB are still two separate pieces of the system

Synology snapshots

Goal

The immich-prod shared folder should have Synology snapshots enabled.

Why

This gives:

  • fast rollback after accidental deletion
  • protection against bad imports or user mistakes
  • short-term recovery without touching full backups

Good V1 retention suggestion

  • hourly snapshots for 24 hours
  • daily snapshots for 14 days
  • weekly snapshots for 8 weeks

Important truth

Snapshots are not enough by themselves. They are rollback protection, not the full backup strategy.

The real backup picture later must include:

  • Synology media share backup offsite
  • VM / Postgres backup
  • restore testing

Authentik plan

Planned next phase:

  • configure Immich login through Authentik OIDC
  • keep local Immich login enabled until OIDC is proven working

Important future redirect URIs

When creating the Immich OIDC application/provider in Authentik, include:

app.immich:///oauth-callback
https://immich.<your-domain>/auth/login
https://immich.<your-domain>/user-settings

The mobile callback is required for app login.

Safe rollout rule

Do this in order:

  1. verify local Immich admin login works
  2. configure Authentik OIDC
  3. test browser login
  4. test mobile login
  5. only then consider disabling password login

Pangolin plan

Planned next phase:

  • expose Immich publicly through Pangolin
  • do not expose port 2283 directly to the internet

Reverse proxy requirements for Immich

The reverse proxy must correctly pass:

  • Host
  • X-Real-IP
  • X-Forwarded-Proto
  • X-Forwarded-For

It also must:

  • allow large uploads
  • serve Immich on the root of a subdomain, not a sub-path

Correct:

https://immich.example.com

Wrong:

https://example.com/immich

Networking notes

DHCP reservation issue already seen

The VM originally still held the old IP lease after a router DHCP reservation change.

Fastest fix was simply:

su -
reboot

Reason:

  • DHCP reservation does not always force immediate address change
  • the client often keeps the old lease until renew/reboot/expiry

Current relevant IPs

  • Synology NAS: 192.168.1.34
  • Immich VM: 192.168.1.52

Troubleshooting logbook

Problem: sudo: command not found

Cause:

  • user did not yet have sudo available / configured

Fix:

su -
apt update
apt install sudo
usermod -aG sudo cef
reboot

Problem: apt update permission denied / lock file errors

Cause:

  • command was run as non-root user without sudo

Fix:

su -
apt update

Problem: showmount: command not found

Cause:

  • NFS client tools not installed yet

Fix:

sudo apt update
sudo apt install -y nfs-common

Then:

sudo showmount -e 192.168.1.34

Problem: mkdir: cannot create directory '/mnt/immich-prod': Permission denied

Cause:

  • /mnt requires root privileges

Fix:

sudo mkdir -p /mnt/immich-prod

Problem: mount.nfs: access denied by server while mounting ...

Actual cause in this case:

  • typo in mount source path: used volumel instead of volume1

Correct command:

sudo mount -t nfs 192.168.1.34:/volume1/immich-prod /mnt/immich-prod

If it happens again with the correct path, then check:

  1. Synology NFS service enabled
  2. Synology export path correct
  3. Synology NFS permissions allow 192.168.1.52
  4. VM actually has IP 192.168.1.52
  5. export visible via showmount -e 192.168.1.34

Problem: changed router DHCP reservation but VM kept old IP

Cause:

  • client kept existing lease

Fix:

su -
reboot

Alternative debugging commands:

ip a
networkctl
systemctl status systemd-networkd

Problem: hidden .env file does not show in normal ls

Cause:

  • dotfiles are hidden by default

Fix:

ls -la /opt/immich-app

Operational rules

Rules to keep

  1. Never move Postgres onto the NAS share.
  2. Keep using the official Immich compose file.
  3. Do not improvise custom Dockerfiles for V1.
  4. Do not expose raw Immich directly to the internet. Use Pangolin.
  5. Do not disable local login until Authentik login is proven working.
  6. Keep the Synology shared folder dedicated to Immich.
  7. Treat snapshots as rollback, not as the only backup.

Rules for changes later

If changing .env or updating Immich:

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

If something acts weird after env changes:

docker compose up -d --force-recreate

What still needs to be done

Must do next

  1. verify /etc/fstab persistent NFS mount works across reboot
  2. verify Synology snapshots are enabled on immich-prod
  3. configure Authentik OIDC
  4. configure Pangolin public access
  5. test large upload through the reverse proxy
  6. test Immich mobile login through OIDC

Should do soon

  1. rotate the DB password because it was shared in chat
  2. document exact Pangolin config once implemented
  3. document exact Authentik provider/app config once implemented
  4. create first restore notes for:
    • Immich DB
    • media share
    • full VM restore

Fast command reference

Check mount

mount | grep immich
df -h | grep immich
ls -la /mnt/immich-prod

Check Docker

docker ps
docker compose logs -f

Restart Immich

cd /opt/immich-app
docker compose restart

Full stack recreate

cd /opt/immich-app
docker compose down
docker compose up -d

Reboot VM

sudo reboot

Final blunt summary

The current setup is on the right track.

The important good decisions already made are:

  • full VM instead of LXC
  • Debian server instead of desktop bloat
  • official Immich compose
  • media on NAS via NFS
  • Postgres on local storage
  • clear deployment path under /opt/immich-app

The main things that can still hurt later are:

  • forgetting to persist and verify the NFS mount properly
  • forgetting to enable/test Synology snapshots
  • breaking login while introducing Authentik
  • exposing Immich badly when adding Pangolin
  • leaving the documented DB password unchanged

This document should be updated after every meaningful change.