Immich is probably the best self hosted and local way to manage, store and view your photos. I've been using it for quite a while now to backup photos from my phone, but in the past I had the NUC doing all the heavy-lifting. In this guide I'm going to pass that off to a better equipped machine and also pass through Quicksync for transcoding videos. I'm also going to set up a dataset in TrueNAS to store all the photos. And of course I'll be doing all of this in Proxmox.
Update 2025/05/02
Welp, here we are again, re-installing Immich because of breaking changes. I pretty much only use Immich a few times a year which means I don't regularly update my Docker image. Today I logged in and saw that I was on 1.111.0
and 1.132.3
is the latest version. Naturally I'm like, "Cool, just a few minor releases, may as well update." So I run a sudo docker compose pull
, update and start the containers. Surprise ...broken.
To be fair, it has been almost a year since I last updated, but still, this is a bit ridiculous. But whatever.
I'm going to attempt to back up/restore my data, but I'm not 100% it's going to work out, but we'll see...
I was able to get my original/outdated version running by removing the existing images and setting the version variable in the .env
.
The rest of the guide has been updated with instructions for installing the latest release of Immich as of May 02, 2025.
Ubuntu Server Setup
Normally I would prefer to use an LXC instead of a full VM, but Immich suggests using Docker and I don't feel like setting up each service one by one, so that means I'll be doing this in a VM. I really don't like running Docker in an LXC.
Create a new VM in Proxmox (ref)
I'm using Ubuntu 24.04, 4 cores, 4GB of ram and 100GB HDD. Yes, 100GB is overkill, but I've been screwed too many times by this damn app/docker/logs/etc. Not messing around on this one.
Once that's up and running go through the install process. When it asks if you want any packages pre installed, don't select any, just skip through.
Now you should be logged in and in the terminal.
Update the system
sudo apt update && sudo apt upgrade
The next two steps are optional, but I'll be using Vim as my text editor and Zsh as my bash. Install some quality-of-life packages
sudo apt install neovim zsh
Install oh-my-zsh
sh -c "$(curl -fsSL https://raw.githubusercontent.com/ohmyzsh/ohmyzsh/master/tools/install.sh)"
Docker
Install Docker Stuff
sudo apt install apt-transport-https ca-certificates curl software-properties-common
Add GPG key
curl -fsSL https://download.docker.com/linux/ubuntu/gpg | sudo gpg --dearmor -o /usr/share/keyrings/docker-archive-keyring.gpg
Add Docker repo to apt
echo "deb [arch=$(dpkg --print-architecture) signed-by=/usr/share/keyrings/docker-archive-keyring.gpg] https://download.docker.com/linux/ubuntu $(lsb_release -cs) stable" | sudo tee /etc/apt/sources.list.d/docker.list > /dev/null
Update
sudo apt update
Check to see that it's ready to go. If you see something like (Installed), you're good to go.
apt-cache policy docker-ce
Install
sudo apt install docker-ce
Check
sudo systemctl status docker
You should see the docker version.
Docker Compose
Docker is cool, but Docker Compose is a better way of using it. Let's get that going now.
Create a directory for Docker Stuff
mkdir -p ~/.docker/cli-plugins/
Install Docker Compose
curl -SL https://github.com/docker/compose/releases/download/v2.3.3/docker-compose-linux-x86_64 -o ~/.docker/cli-plugins/docker-compose
Set permissions
chmod +x ~/.docker/cli-plugins/docker-compose
Check version
sudo docker compose version
You should now see the Docker Compose version. If you've used Docker Compose before and you're used to the command being docker-compose
, just know that they've updated it and the new command is now docker compose
. Everything else should be the same, but there's just no hyphen (-) anymore.
This is where we start to deviate on our own path. My Immich server is going to be storing all the photos on my TrueNAS server, so we need to set up a dataset to hold everything and then link it up with our VM.
TrueNAS
Create a dataset in TrueNAS and set up the permissions as you wish. When developing I tend to set read/write for everyone and only allow specific IP addresses in the NFS rules, but it's up to you.
Set up an NFS share for the dataset you just created and put in the IP address of your Immich VM in the allow list. Or you can just put you local subnet and allow all devices on your network, whatever works for you.
Back on the Immich VM.
NFS
Install nfs-common
sudo apt install nfs-common
Make shared directory for images. I like to keep all my external/network shares in the /mnt
folder.
sudo mkdir /mnt/immich-nas
Obviously replace the next line with the IP address/path of you TrueNAS dataset.
sudo mount 192.168.X.X:/mnt/<pool>/<dataset> /mnt/immich-nas
Check that it mounted
df -h
In the Filesystem column you should see the IP address of the NAS and the path of the dataset. The Mounted On column should have /mnt/immich-nas
Set the Immich server to mount this folder when it boots up
sudo nvim /etc/fstab
Add to the bottom of the file
192.168.X.X:/mnt/<pool>/<dataset> /mnt/immich-v2 nfs auto,nofail,noatime,nolock,intr,tcp,actimeo=1800 0 0
Immich
Now that we're all set up it's finally time to install Immich.
Create a directory for the Docker files
mkdir ~/immich-app
Navigate to the new directory
cd ~/immich-app
Download the Docker Compose file
wget https://github.com/immich-app/immich/releases/latest/download/docker-compose.yml
Download the .env file
wget -O .env https://github.com/immich-app/immich/releases/latest/download/example.env
Download the hardware acceleration file (optional)
wget https://github.com/immich-app/immich/releases/latest/download/hwaccel.yml
Edit the .env file
- Change
UPLOAD_LOCATION
value to/mnt/immich-nas
- Update
DB_PASSWORD
to a random string
Quicksync
Since my Proxmox server is an Intel NUC with Quicksync, I'm going to pass that through to the VM so Immich can use it to transcode. If you aren't going to use Quicksync or don't have it available you can skip this part.
Install some hardware packages
sudo apt install --install-recommends linux-generic-hwe-22.04
Update: change 22.04
to the version of your Ubuntu server if you're not on 22.04
Download/install the Intel Compute-Runtime stuff Follow the steps on this page.
https://github.com/intel/compute-runtime/releases
Log in to the Proxmox web ui and add the Intel driver to the VM
- Select the VM
- Go to the Hardware tab
- Click Add > PCI
- Select the Intel graphics driver option
- Stop and restart VM
- SSH back in
Once you're back in the VM, type
ls -l /dev/dri
You should see something like renderD128
listed now.
Download the hwaccel.transcoding
file to the directory with the docker-compose.yml
wget https://github.com/immich-app/immich/releases/latest/download/hwaccel.transcoding.yml
Enable the hardware acceleration in the docker-compose file
services:
immich-server:
container_name: immich_server
image: ghcr.io/immich-app/immich-server:${IMMICH_VERSION:-release}
extends:
file: hwaccel.transcoding.yml
service: quicksync # set to one of [nvenc, quicksync, rkmpp, vaapi, vaapi-wsl] for accelerated transcoding
Start Immich with Docker compose
sudo docker compose up
Once everything is up and running and there are no errors, you can stop the container and run it with
sudo docker compose up -d
At this point the Immich server should be up and running and you should be able to log in/create the admin account by going to
http://192.168.X.X:2283
Remote Machine Learning
The Intel NUC is a pretty great server, but I'm planning on throwing a bunch of photos in here and I want to use Immich's facial recognition features. This can really bog down the NUC so I'm going to offload this work to another machine I have in the house that I mainly use for AI/ML/LLM stuff. The Following steps will be done on that computer, which is running Ubuntu 22.04, but the full desktop version with an RTX 3060 graphics card.
Note: Since I'm using an NVIDIA card I'm going to use the
cuda
tag for the image, you may need to replace that with the one that matches your setup.
Make sure you have the NVIDIA Container Toolkit installed. Just follow the guide here: https://docs.nvidia.com/datacenter/cloud-native/container-toolkit/latest/install-guide.html
This computer didn't already have Docker installed so I followed the steps above for installing Docker/Docker Compose.
Create a folder for the Docker Compose file
mkdir -p ~/immich-ml && cd ~/immich-ml
Download the hwaccel.ml.yml
file from the repo
wget https://github.com/immich-app/immich/releases/latest/download/hwaccel.ml.yml
Create the compose file
touch docker-compose.yml
Edit the file
nvim docker-compose.yml
Add the Following
name: immich_remote_ml
services:
immich-machine-learning:
container_name: immich_machine_learning
# For hardware acceleration, add one of -[armnn, cuda, rocm, openvino, rknn] to the image tag.
# Example tag: ${IMMICH_VERSION:-release}-cuda
image: ghcr.io/immich-app/immich-machine-learning:${IMMICH_VERSION:-release-cuda}
extends:
file: hwaccel.ml.yml
service: cuda # set to one of [armnn, cuda, rocm, openvino, openvino-wsl, rknn] for accelerated inference - use the `-wsl` version for WSL2 where applicable
volumes:
- model-cache:/cache
restart: always
ports:
- 3003:3003
volumes:
model-cache:
Save, exit and run the container
sudo docker compose up
You can also add the -d
flag here, but since it's my first time running this I'm going to omit that so I can see the logs.
Open up the Immich web ui and log in as the administrator if you've already set that up. If not just go to http://192.168.X.X:2283
and set up the admin account now.
Once logged in as the administrator, click the Administration
button at the top right and go to Settings > Machine Learning Settings
In the URL textfield, put in the IP address of the machine running the immich-machine-learning
container with the port 3003
.
http://192.168.X.X:3003
Save the settings.
I'll be testing that the GPU is working by running the Face Detection job, so I uploaded a handful of photos with people in them.
Navigate to the Jobs section of the Administrator Settings and run the Face Detection.
If you didn't start the container with the -d
flag, you should see some logs in your immich_machine_learning
container.
Before setting up GPU:
[05/02/25 21:20:43] INFO Application startup complete.
[05/02/25 21:20:50] INFO Loading detection model 'buffalo_l' to memory
[05/02/25 21:20:50] INFO Setting execution providers to
['CPUExecutionProvider'], in descending order of
preference
[05/02/25 21:20:50] INFO Loading recognition model 'buffalo_l' to memory
[05/02/25 21:20:50] INFO Setting execution providers to
['CPUExecutionProvider'], in descending order of
preference
Note the CPUExecutionProvider
, that's not what we want.
After setting up the GPU you should see something like this:
[05/02/25 21:23:54] INFO Application startup complete.
[05/02/25 21:24:39] INFO Loading detection model 'buffalo_l' to memory
[05/02/25 21:24:39] INFO Setting execution providers to
['CUDAExecutionProvider', 'CPUExecutionProvider'],
in descending order of preference
[05/02/25 21:24:40] INFO Loading recognition model 'buffalo_l' to memory
[05/02/25 21:24:40] INFO Setting execution providers to
['CUDAExecutionProvider', 'CPUExecutionProvider'],
in descending order of preference
Now we can see that the CUDAExecutionProvider
is first and it will fallback to the CPU if needed.
A+++++
In the past I've run in to issues where the Immich logs take up so much space it fills up the VM storage. So I like to set the Log Level to either Error or Fatal once I'm confident everything is working as it should.
And that's that. We've got Immich up and running with all the machine learning stuff offloaded to a computer that can handle it and Quicksync ready to transcode all those stupid hevc (or whatever) files from people with iPhones. Even if you're the only one using it, I still suggest making yourself a new account that isn't the admin account. Keep the admin account just for admin stuff.
I was originally planning on trying to restore my previous albums, but at this point I feel like I'll just re-upload everything and deal with it. Sucks, but hey, that's Immich for ya'. Maybe one day they'll get on a regular versioning system so you don't have to read release notes for every release. Seriously, I was something like, 20 releases behind, that's a lot, but they're putting out around 3-4 releases a month. Am I supposed to go through and read the changelogs for every single one? Today I just saw that the latest was still on the same major version I was running so I updated. Really shouldn't have to go through all this every single time...