399 lines
12 KiB
Markdown
399 lines
12 KiB
Markdown
# Immich V1 setup on Proxmox + Synology NAS + Authentik + Pangolin
|
|
|
|
## Goal
|
|
|
|
Set up **Immich first**, on a **full Linux VM in Proxmox** (not Docker inside LXC), with:
|
|
|
|
- **media storage on a Synology NAS share**
|
|
- **database on local VM storage**
|
|
- **OIDC login via Authentik**
|
|
- **public access through Pangolin**
|
|
- **Synology snapshots enabled** for the media share
|
|
|
|
This is the right V1 shape because Immich recommends Linux, Docker Compose, and a **full VM** when virtualized. It also explicitly says the **Postgres database should ideally use local SSD storage and never a network share**. The reverse proxy must forward the right headers, allow large uploads, and Immich must be served at the root of a domain/subdomain rather than a sub-path.
|
|
Sources: Immich Requirements, Reverse Proxy, OAuth Authentication.
|
|
|
|
---
|
|
|
|
## Recommended architecture
|
|
|
|
```mermaid
|
|
flowchart LR
|
|
subgraph Internet
|
|
U[Users / Immich mobile app / browser]
|
|
end
|
|
|
|
subgraph Edge
|
|
P[Pangolin\nTLS + public entrypoint]
|
|
end
|
|
|
|
subgraph Prod[Proxmox production]
|
|
VM[Debian/Ubuntu VM\nDocker Compose\nImmich server + ML + Redis + Postgres]
|
|
DB[(Postgres data\nlocal VM disk)]
|
|
CFG[(Compose files/.env\nlocal VM disk)]
|
|
end
|
|
|
|
subgraph NAS[Synology NAS]
|
|
NFS[NFS share for Immich upload library]
|
|
SNAP[Synology snapshots]
|
|
HB[Hyper Backup / offsite replication later]
|
|
end
|
|
|
|
subgraph IdP[Identity]
|
|
AK[Authentik\nOIDC provider]
|
|
end
|
|
|
|
U --> P --> VM
|
|
VM --> AK
|
|
VM --> DB
|
|
VM --> CFG
|
|
VM --> NFS
|
|
NFS --> SNAP
|
|
SNAP --> HB
|
|
```
|
|
|
|
---
|
|
|
|
## Hard recommendations
|
|
|
|
### Do this
|
|
|
|
1. **Run Immich in a VM, not an LXC.**
|
|
2. Put **Postgres on local VM storage**.
|
|
3. Put **Immich upload/media storage on the NAS** using a **Unix-compatible mounted path**.
|
|
4. Use **OIDC with Authentik**, but **keep local password login enabled until OIDC works**.
|
|
5. Publish Immich on its own subdomain, for example `immich.example.com`.
|
|
6. Use a **dedicated Synology shared folder** for Immich media.
|
|
7. Turn on **Btrfs snapshots** on that shared folder.
|
|
|
|
### Do not do this
|
|
|
|
1. **Do not put `DB_DATA_LOCATION` on the NAS.**
|
|
2. **Do not serve Immich on a sub-path** like `https://example.com/immich`.
|
|
3. **Do not expose port 2283 directly to the internet**.
|
|
4. **Do not use the NAS share for everything**. Only media belongs there; DB does not.
|
|
|
|
---
|
|
|
|
## Best-practice V1 decision: primary upload storage vs external library
|
|
|
|
For a fresh setup, use the NAS-mounted path as **Immich's main `UPLOAD_LOCATION`**.
|
|
|
|
Use **External Libraries** only if you already have existing folders on the NAS that Immich should **index without owning**. External libraries need the directory mounted into the container too, and tcby adding additional volume mounts.
|
|
Source: Immich External Library guide.
|
|
|
|
So for V1:
|
|
|
|
- `UPLOAD_LOCATION` -> NAS share mounted in the VM
|
|
- Postgres data -> local VM disk
|
|
- Optional later: extra read-only external libraries from other NAS folders
|
|
|
|
---
|
|
|
|
## V1 implementation plan
|
|
|
|
### 1. Create a dedicated Proxmox VM
|
|
|
|
Use a **Debian 12** or **Ubuntu 24.04 LTS** VM.
|
|
|
|
Suggested starting size:
|
|
|
|
- 4 vCPU
|
|
- 8 GB RAM
|
|
- 40-80 GB local SSD/NVMe disk for OS + Docker + Postgres + cache
|
|
|
|
Immich's current requirements say:
|
|
|
|
- Linux or Unix-like 64-bit OS recommended
|
|
- minimum **6 GB RAM**, recommended **8 GB**
|
|
- minimum **2 cores**, recommended **4**
|
|
- in a virtualized environment, a **full VM** is recommended
|
|
- storage should support Unix ownership/permissions
|
|
- the **Postgres database should ideally use local SSD storage and never a network share**
|
|
Source: Immich Requirements.
|
|
|
|
### 2. Create a dedicated Synology shared folder for Immich
|
|
|
|
Create something like:
|
|
|
|
- Shared folder: `immich-prod`
|
|
|
|
Inside it, keep it simple. Let Immich create its own structure under `UPLOAD_LOCATION`.
|
|
|
|
Do **not** manually invent a lot of subdirectories unless you have a reason.
|
|
|
|
### 3. Export that Synology folder to the VM
|
|
|
|
Prefer **NFS** from Synology to the Linux VM.
|
|
|
|
Reason:
|
|
|
|
- cleaner Linux permissions model than SMB for this use case
|
|
- easier predictable mount behavior inside a Linux VM
|
|
|
|
Mount it in the VM, for example:
|
|
|
|
- NAS export -> VM mountpoint: `/srv/immich-upload`
|
|
|
|
Then point Immich `UPLOAD_LOCATION` there.
|
|
|
|
### 4. Keep local storage for DB and configs
|
|
|
|
Example local paths in the VM:
|
|
|
|
- `/opt/immich` -> compose files
|
|
- `/var/lib/immich-postgres` -> database data
|
|
- `/var/lib/immich-model-cache` -> model cache
|
|
|
|
The important part is that the Postgres path stays **local**, not on the NAS.
|
|
Source: Immich Requirements.
|
|
|
|
### 5. Install Docker Engine + Compose plugin in the VM
|
|
|
|
Immich requires Docker with the Compose plugin and explicitly requires the command `docker compose`; `docker-compose` is deprecated and no longer supported by Immich.
|
|
Source: Immich Requirements.
|
|
|
|
### 6. Deploy Immich with Docker Compose
|
|
|
|
Use the official compose example from Immich and modify only what matters:
|
|
|
|
- `UPLOAD_LOCATION=/srv/immich-upload`
|
|
- `DB_DATA_LOCATION=/var/lib/immich-postgres`
|
|
- model cache on local disk
|
|
- bind only to the VM internally; Pangolin handles public entry
|
|
|
|
### 7. Configure Pangolin
|
|
|
|
Publish Immich via Pangolin on its own subdomain.
|
|
|
|
Important reverse-proxy requirements from Immich:
|
|
|
|
- forward `Host`
|
|
- forward `X-Real-IP`
|
|
- forward `X-Forwarded-Proto`
|
|
- forward `X-Forwarded-For`
|
|
- allow **large uploads**
|
|
- Immich must be on the **root path of a domain/subdomain**
|
|
Source: Immich Reverse Proxy docs.
|
|
|
|
### 8. Configure Authentik OIDC for Immich
|
|
|
|
Immich supports OIDC and explicitly lists Authentik among supported identity providers.
|
|
Source: Immich OAuth Authentication.
|
|
|
|
Create an application/provider pair in Authentik using **OAuth2/OIDC**. Authentik recommends creating the application and provider together via **Applications -> Applications -> Create with provider**.
|
|
Source: Authentik Create an OAuth2 provider.
|
|
|
|
Use these redirect URIs in Authentik:
|
|
|
|
- `app.immich:///oauth-callback`
|
|
- `https://immich.example.com/auth/login`
|
|
- `https://immich.example.com/user-settings`
|
|
|
|
Immich requires the mobile redirect URI `app.immich:///oauth-callback` for iOS/Android app login to work properly.
|
|
Source: Immich OAuth Authentication.
|
|
|
|
Then in Immich Admin -> Settings -> OAuth:
|
|
|
|
- enable OAuth
|
|
- set issuer URL to the Authentik OIDC discovery URL
|
|
- set client ID / secret
|
|
- scope: `openid email profile`
|
|
- auto-register: on
|
|
- auto-launch: optional, keep off in V1
|
|
|
|
### 9. Keep password login enabled initially
|
|
|
|
Do not lock yourself out.
|
|
|
|
First:
|
|
|
|
- create the initial local Immich admin
|
|
- verify normal web login
|
|
- configure OIDC
|
|
- verify browser login
|
|
- verify mobile login
|
|
- only then decide whether to disable password login
|
|
|
|
Immich allows disabling password authentication instance-wide, but that can lock everyone out if OAuth is also broken.
|
|
Source: Immich System Settings.
|
|
|
|
### 10. Enable Synology snapshots
|
|
|
|
Because your Synology is Btrfs, this is a good fit.
|
|
|
|
Enable snapshots on the `immich-prod` shared folder.
|
|
|
|
Good V1 retention example:
|
|
|
|
- every hour for 24 hours
|
|
- every day for 14 days
|
|
- every week for 8 weeks
|
|
|
|
That gives you fast rollback for accidental deletion or a bad import.
|
|
|
|
Important caveat: snapshots help with rollback, but the full backup still also needs the Immich database and a true backup destination later.
|
|
|
|
---
|
|
|
|
## Concrete directory layout
|
|
|
|
### In the VM
|
|
|
|
```text
|
|
/opt/immich/ # compose + .env
|
|
/var/lib/immich-postgres/ # local postgres data
|
|
/var/lib/immich-model-cache/ # local ML cache
|
|
/srv/immich-upload/ # NFS mount from Synology
|
|
```
|
|
|
|
### On Synology
|
|
|
|
```text
|
|
Shared folder: immich-prod
|
|
\- mounted into VM as /srv/immich-upload
|
|
```
|
|
|
|
Immich will create and use directories under `UPLOAD_LOCATION`, including backups for automatic DB dumps. Immich stores automatic database backups in `UPLOAD_LOCATION/backups`, and those backups only contain metadata, not the photos/videos.
|
|
Source: Immich Backup and Restore.
|
|
|
|
---
|
|
|
|
## Example Compose shape
|
|
|
|
This is **not** a full copy of the official file. It is the shape that matters.
|
|
|
|
```yaml
|
|
services:
|
|
immich-server:
|
|
image: ghcr.io/immich-app/immich-server:release
|
|
env_file:
|
|
- .env
|
|
volumes:
|
|
- ${UPLOAD_LOCATION}:/data
|
|
ports:
|
|
- "2283:2283"
|
|
depends_on:
|
|
- redis
|
|
- database
|
|
|
|
immich-machine-learning:
|
|
image: ghcr.io/immich-app/immich-machine-learning:release
|
|
env_file:
|
|
- .env
|
|
volumes:
|
|
- /var/lib/immich-model-cache:/cache
|
|
|
|
redis:
|
|
image: redis:6.2-alpine
|
|
|
|
database:
|
|
image: ghcr.io/immich-app/postgres:14-vectorchord0.4.0-pgvectors0.8.1
|
|
env_file:
|
|
- .env
|
|
volumes:
|
|
- ${DB_DATA_LOCATION}:/var/lib/postgresql/data
|
|
```
|
|
|
|
And the key bits in `.env`:
|
|
|
|
```env
|
|
UPLOAD_LOCATION=/srv/immich-upload
|
|
DB_DATA_LOCATION=/var/lib/immich-postgres
|
|
```
|
|
|
|
Use the exact current compose file and image tags from the Immich docs/release example when you deploy, not a random blog post. Immich has changed its Postgres/vector extension story over time and currently documents VectorChord-based setups and upgrade cautions.
|
|
Sources: Immich Requirements, Upgrading, Pre-existing Postgres.
|
|
|
|
---
|
|
|
|
## Pangolin-specific guidance
|
|
|
|
Pangolin is an identity-aware remote access platform combining reverse proxy and VPN-style connectivity. For this use case, the key point is: use Pangolin only as the **public entrypoint**, and keep Immich itself private behind it.
|
|
Source: Pangolin GitHub README.
|
|
|
|
For Immich specifically, make sure Pangolin is configured so that:
|
|
|
|
- the service is published on a **dedicated host/subdomain**
|
|
- uploads are allowed to be large enough
|
|
- timeouts are not too short for big videos
|
|
- forwarded headers match what Immich expects
|
|
|
|
Because Immich documents strict reverse-proxy expectations, do not rely on defaults you have not checked.
|
|
Source: Immich Reverse Proxy docs.
|
|
|
|
---
|
|
|
|
## Authentik-specific guidance
|
|
|
|
In Authentik:
|
|
|
|
1. Create an application/provider pair with **OAuth2/OIDC**.
|
|
2. Use **Authorization Code** flow.
|
|
3. Use a **confidential** web client.
|
|
4. Add all redirect URIs you will actually use.
|
|
|
|
Immich's OAuth docs say the redirect URIs should include:
|
|
|
|
- mobile callback
|
|
- web login callback
|
|
- user settings callback
|
|
|
|
and they should contain all domains used to access Immich.
|
|
Source: Immich OAuth Authentication.
|
|
|
|
---
|
|
|
|
## What to back up for Immich in this design
|
|
|
|
You need both:
|
|
|
|
1. **`UPLOAD_LOCATION`** on the NAS
|
|
2. **the database**
|
|
|
|
Immich says a comprehensive backup includes both uploaded photos/videos and the Immich database. It also says the automatic database backups are stored in `UPLOAD_LOCATION/backups`, but these backups contain only metadata, not photos/videos.
|
|
Source: Immich Backup and Restore.
|
|
|
|
In your design that means:
|
|
|
|
- NAS snapshots protect the media path and DB backup files stored under `UPLOAD_LOCATION/backups`
|
|
- local-VM backup later must also protect `/var/lib/immich-postgres` or you rely on Immich DB dumps inside `UPLOAD_LOCATION/backups`
|
|
|
|
For V1, I would still enable Immich automatic DB backups in the UI.
|
|
|
|
---
|
|
|
|
## Minimum test plan for today
|
|
|
|
1. VM boots and NFS mount is present at `/srv/immich-upload`
|
|
2. `docker compose up -d` starts all Immich services
|
|
3. local browser login works on `http://VM-IP:2283`
|
|
4. upload one test image and one test video
|
|
5. verify files appear on Synology share
|
|
6. configure Pangolin and verify public HTTPS access
|
|
7. configure Authentik OIDC and verify browser login
|
|
8. verify mobile app login using OIDC
|
|
9. create a manual DB backup in Immich and confirm it appears under `UPLOAD_LOCATION/backups`
|
|
10. create a Synology snapshot and verify the snapshot schedule is active
|
|
|
|
---
|
|
|
|
## Final recommendation
|
|
|
|
For your **V1 today**, the clean setup is:
|
|
|
|
- **Proxmox VM** for Immich
|
|
- **Docker Compose** inside the VM
|
|
- **local VM disk** for Postgres and local runtime state
|
|
- **Synology NFS share** for `UPLOAD_LOCATION`
|
|
- **Synology Btrfs snapshots** on that shared folder
|
|
- **Pangolin** for public HTTPS exposure
|
|
- **Authentik OIDC** for login
|
|
|
|
That is the right compromise between best practice and what you want to achieve right now.
|
|
|
|
## The one thing not to compromise on
|
|
|
|
Do **not** place the Immich Postgres data on the NAS share. That is the main thing Immich explicitly warns against.
|
|
Source: Immich Requirements.
|