Immich on Proxmox: VM, Docker & Storage Guide
Install Immich in a Proxmox Linux VM with Docker Compose. Choose CPU features, database and NAS storage, then verify uploads, updates and backup coverage.
On this page
Direct Answer
For a new Proxmox deployment, create a full Linux VM and run Immich's official Docker Compose stack inside it. Immich documents full virtual machines as a suitable environment and does not recommend Docker inside LXC. A native Immich helper-script container is a community distribution with its own update and recovery responsibilities. Immich requirements ↗
Keep PostgreSQL on local guest storage backed by suitable disks, preferably SSD. Treat NAS photos as a separate mount and backup responsibility. Proxmox's successful guest-backup message does not by itself prove that externally mounted photos were included. In particular, LXC bind-mount contents are excluded from vzdump. Proxmox container documentation ↗
This page was reviewed against stable Immich v3.2.2 ↗ on September 16, 2026. v3 machine learning on amd64 requires x86-64-v2 or later as seen inside the guest. The host's physical CPU capability alone is not enough if the VM exposes an older model. GPU passthrough is optional and hardware-specific; get the CPU-based installation working first.
Who this setup is for
Choose this route if you already operate Proxmox and want Immich isolated from the hypervisor with a recognizable Linux and Docker recovery path. It is especially useful when the application lives on local SSD-backed virtual storage while photos live on a separate NAS. It assumes you can install and maintain a Linux guest; it does not require a GPU or a community installer.
Before creating the VM, identify the guest's resource allocation, LAN address, database disk, photo destination and independent backup destination. The next steps turn those choices into a working stack. An existing native LXC with valuable data needs a separate migration plan; do not point a new Compose database at its old directory.
Choose VM, Docker-in-LXC or native LXC
| Layout | Support and isolation boundary | Main operational consequence |
|---|---|---|
| Linux VM + official Compose | Recommended Immich method inside a full VM | Guest has its own kernel/runtime; follow normal Compose release updates |
| Docker inside LXC | Advanced/community approach; not recommended by Immich | Container nesting, device access and UID mapping add failure layers |
| Native/helper-script Immich LXC | Community packaging, separate from official Compose | Helper's service names, dependencies and upgrade path may differ |
| Privileged LXC | Broader host privilege exposure | Do not switch merely to hide an unexplained permission error |
| Unprivileged LXC | Host and guest user IDs are mapped | A host-readable directory may still be unreadable by the app user |
A maintainer reiterated the Docker support boundary in Discussion #29317 ↗. That thread asks about moving a working Docker-in-LXC library to a helper container; it does not provide a verified migration recipe. If you already have data, establish backups and a restore test before changing deployment type.
Step 1: Create the Linux VM
Use Proxmox's Create VM workflow with a supported 64-bit Linux installer ISO. Allocate at least 2 cores and 6 GB RAM; 4 cores and 8 GB match Immich's recommendations. Plan virtual disk capacity for the guest, Docker images, PostgreSQL and any local media. There is no single documented disk size that fits every photo collection. Proxmox VM guide ↗, Immich sizing ↗
Choose a guest CPU model that exposes at least x86-64-v2 for v3 amd64 machine learning. Proxmox identifies kvm64 with the older x86-64-v1 level, whereas x86-64-v2-AES meets the newer level. host can expose host capabilities but changes portability across dissimilar hosts; choose it with your migration requirements in mind. Install Linux and establish a reachable guest IP before adding Immich. CPU models ↗
Verification: log into the guest console, confirm the configured resources and IP, and confirm the chosen CPU model rather than assuming Proxmox's current default matches an old VM. v2.7.5 is the last documented x86-64-v1 option but is unsupported; retaining it is not a recommended long-term v3 solution.
Step 2: Plan the storage layers
| Layer | Example planning choice | What to verify |
|---|---|---|
| Proxmox storage | SSD-backed virtual disk | The VM disk and backup policy include the intended data |
| Guest PostgreSQL directory | Local Linux filesystem | Suitable ownership/permissions; not a guest NFS/SMB mount |
| Guest managed-media directory | Local disk or deliberately mounted media storage | Available before Immich starts and large enough for originals/derivatives |
| Existing NAS collection | Dedicated guest mount, then additional Docker mount | Same container-visible path after restart or recovery |
| External backup destination | Independent copy of DB and media | Files can be recovered without the current guest |
This is an operational map derived from the two products' storage models, not a universal mount configuration. Preserve the normal upload mount while adding a separate read-only external library. A mount visible in Proxmox is not automatically visible in Linux, and a Linux mount is not automatically visible inside Docker. External-library mount instructions ↗
For a NAS-backed media directory, make the share available inside the Linux guest before starting Docker. Confirm the intended remote files are present, not just an empty local mount-point directory. Check availability again after a guest restart. The required mount persistence and credentials depend on your distribution and NAS; no universal SMB/NFS command is safe for every setup.
Set DB_DATA_LOCATION to the guest-local PostgreSQL directory and UPLOAD_LOCATION to the chosen managed-media directory. Existing photos get a separate mount into the server container, then a library import path inside Immich. Record all three path layers so a restored VM can reconstruct them. Immich storage requirements ↗
Step 3: Install Docker and Immich inside the guest
Install Docker Engine and its Compose plugin using the distribution's official Docker instructions. Then follow the complete Compose tutorial: create the application directory, download both release files, set a new upload directory and local database directory, choose a password and version, and validate the configuration. Do not run those application commands on the Proxmox hypervisor. Official Immich install ↗
From the guest's Immich Compose directory, start the stack:
docker compose up -dExpected: application services are created and start in the guest. If the command fails, identify the Compose/runtime or storage error before changing Proxmox privileges. The command is the official installation command, with the execution location explicitly scoped to the VM.
Step 4: Verify the complete path
From that same guest directory:
docker compose ps -a
docker compose logs --tail=100The first command lists service state, including stopped containers; the second shows recent logs. Look for the server, ML, cache and database remaining running, and investigate repeated exits, mount-check errors or CPU failures. Docker ps ↗, Docker logs ↗
Open http://VM-IP:2283, create the first admin, upload a few test files and verify original download and video playback. If external storage is used, scan a small test folder and check its original from the web. These are acceptance checks built from the documented install/upload flow; this guide has not tested your physical host. Post-installation ↗
Advanced branch: LXC storage and permissions
Proxmox bind mounts connect host directories to LXC paths. Unprivileged containers map user IDs into a different host range; the common root mapping begins at host 100000, but actual application IDs and custom maps must be checked. A number copied from a forum may refer to a different service user. Unprivileged LXC documentation ↗
Trace a failing path in order: the host directory exists; the LXC mount points to it; the guest's actual application identity can traverse/read it; and, for Docker-in-LXC, the additional Docker mount exposes it at the expected destination. A native helper installation will not necessarily have an immich_server Docker container, so Docker diagnostics do not apply there.
Advanced branch: GPU and hardware acceleration
Hardware acceleration has two separate layers: Proxmox must expose a usable device to the guest, and Immich must be configured for the correct backend. VM PCI passthrough needs suitable IOMMU support and device grouping; a passed-through physical device is not simultaneously available for ordinary use by the host or another VM. Proxmox documents PCIe passthrough and machine-type constraints. Proxmox VM passthrough ↗
After the guest can use the device, follow Immich's backend-specific video transcoding ↗ instructions. NVIDIA additionally requires the appropriate driver and container toolkit inside the Linux environment running Docker. Machine-learning acceleration has its own configuration and verification ↗; enabling video acceleration alone does not enable ML acceleration.
Verify an actual transcode or ML job using the chosen backend's documented checks. If the guest cannot access the device, fix passthrough first. If the guest can but Docker cannot, check the runtime/device mapping. If Docker can but the job fails, inspect Immich's backend logs. Hardware-specific driver/VFIO commands are outside what one generic page can safely establish.
For the application-side steps after guest device access works, follow the hardware-acceleration guide, which separates video and machine-learning configuration.
Backup and upgrade
Keep both a database dump and media backup, plus the Compose configuration and guest/storage mapping. For LXC, Proxmox explicitly excludes bind-mount contents from vzdump; the backup flag for storage-backed volumes does not turn arbitrary host bind mounts into backed-up data. Independently protect NAS originals. Rehearse recovery with the mounts included. Proxmox container backup scope ↗, Immich backup
Use the Immich update guide inside a Compose VM. For v2→v3, check VectorChord and CPU exposure before updating. A helper-native LXC must follow its maintainer's supported path instead of borrowing Compose database commands.
Update the application inside the VM
- Record the current version and save the Compose file,
.envand mount configuration with the backup set. - Read every applicable release note through the target version. Compare its official Compose file with your customized copy, especially database-image changes.
- In the guest's application directory, follow the version-aware update procedure. Pull and recreate only after satisfying any migration instructions.
- Check service logs and repeat login, upload, original download and an external-library scan. Do not treat a running VM as proof the application update succeeded.
What a Proxmox snapshot does not establish
A VM snapshot is useful for managing guest state, but is not an independent database-and-photo recovery set. A snapshot-mode vzdump backup is also distinct from a local VM snapshot: it copies selected guest disks, while a NAS share mounted inside Linux remains a separate backup job. The QEMU guest agent's filesystem freeze can improve disk consistency; it does not replace an Immich database dump or coordinate photos outside those disks. Proxmox backup documentation ↗
Write down which virtual disks are included in the backup, which media paths are remote, and where the database dump is saved. Recover a small test set before relying on this arrangement for the only copy of your library.
If this does not work
| Failure | Next diagnostic layer | Verification after correction |
|---|---|---|
| Cannot reach 2283 | Guest IP/network, then Docker services and firewall | Browser opens the VM endpoint |
| ML stops after v3 | Guest CPU model and ML/backend logs | ML service stays up and a real job completes |
| NAS visible on host only | Host→guest→Docker path and identity chain | Same known original is readable through Immich |
| Upload permission denied in LXC | Actual mapped user and dedicated-directory ACL | Small upload succeeds without broad privilege changes |
| Restart during upgrade | Logs, allocated memory and database migration progress | No repeated exit; test originals and search |
| Guest restore has missing images | External mounts and media backup coverage | Original download and integrity checks pass |
For broken originals or previews after a mount or restore change, use Immich image-loading troubleshooting. First identify whether the original is missing or only a derived thumbnail has failed.
FAQ
Should a working Docker-in-LXC installation move to a helper script?
The maintainer's answer in #29317 ↗ does not endorse that migration. Decide based on a tested recovery path and the support boundary, not the availability of a one-click installer.
Can I make the LXC backup flag include an arbitrary bind mount?
The flag applies to storage-backed mount-point volumes. Bind mounts remain a separate backup responsibility. Proxmox container documentation ↗
Is GPU passthrough required?
No. Establish a working CPU-based deployment first. Transcoding and machine learning use separate acceleration settings, and both depend on the device being usable inside the guest. Choose acceleration only after identifying a real workload need.
Can the database live beside photos on an SMB or NFS share?
Keep the PostgreSQL data directory on a supported local guest filesystem. A network share suitable for originals is not automatically suitable for live PostgreSQL state. The database and remote photos can still be backed up to an independent destination using the documented backup procedure.
Sources
- Immich requirements ↗ — Official Immich support and resource baseline.
- Compose install ↗ — Official Immich procedure.
- Post-installation ↗ — Official Immich first-login workflow.
- External Libraries ↗ — Official Immich mount model.
- Virtual Machines ↗ — Official Proxmox CPU, VM and passthrough documentation.
- Containers ↗ — Official Proxmox mount and backup scope.
- Unprivileged LXC ↗ — Official Proxmox UID mapping documentation.
- Hardware Transcoding ↗ — Official Immich video acceleration.
- ML Hardware Acceleration ↗ — Official Immich ML backend guide.
- Docker ps ↗ — Official Docker reference.
- Docker logs ↗ — Official Docker reference.
- LXC migration question, #29317 ↗ — GitHub discussion with maintainer support clarification.
- Backup and Restore ↗ — Official Proxmox guest-backup consistency and scope.