Affected files: .obsidian/workspace.json 2 Personal/Home Lab/NAS/immich_v1.1_setup.md
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
- acceptable fallback:
- 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+OVMFis 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-appis for the application deployment, not user files./mnt/immich-prodis 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:
dockerdocker composezerotiernfs-commonsudo
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.
Recommended persistent mount in /etc/fstab
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/writehard-> keep retrying if the NAS drops briefly_netdev-> network-dependent mountx-systemd.automount-> avoids ugly boot timing issuesnoatime-> 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:
- verify local Immich admin login works
- configure Authentik OIDC
- test browser login
- test mobile login
- only then consider disabling password login
Pangolin plan
Planned next phase:
- expose Immich publicly through Pangolin
- do not expose port
2283directly to the internet
Reverse proxy requirements for Immich
The reverse proxy must correctly pass:
HostX-Real-IPX-Forwarded-ProtoX-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:
/mntrequires 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
volumelinstead ofvolume1
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:
- Synology NFS service enabled
- Synology export path correct
- Synology NFS permissions allow
192.168.1.52 - VM actually has IP
192.168.1.52 - 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
- Never move Postgres onto the NAS share.
- Keep using the official Immich compose file.
- Do not improvise custom Dockerfiles for V1.
- Do not expose raw Immich directly to the internet. Use Pangolin.
- Do not disable local login until Authentik login is proven working.
- Keep the Synology shared folder dedicated to Immich.
- 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
- verify
/etc/fstabpersistent NFS mount works across reboot - verify Synology snapshots are enabled on
immich-prod - configure Authentik OIDC
- configure Pangolin public access
- test large upload through the reverse proxy
- test Immich mobile login through OIDC
Should do soon
- rotate the DB password because it was shared in chat
- document exact Pangolin config once implemented
- document exact Authentik provider/app config once implemented
- 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.