Blog

How to Install and Optimize Immich on Unraid for Faster Timeline Loading

How to Install and Optimize Immich on Unraid for Faster Timeline Loading

Move Your Immich Thumbnails to Cache for Speed, a how-to guide
Building a Tech Support Business; My Journey and Lessons Learned

Building a Tech Support Business; My Journey and Lessons Learned

My journey of creating a personalized tech support business, from brainstorming the initial concept to building a website using AI tools like Bolt.new. I also share my experiences and lessons learned while working with technologies like React, Supabase, and edge functions.
A Custom LaunchAgent for Nudge

A Custom LaunchAgent for Nudge

Why we needed to deploy a custom LaunchAgent for our school
On Hugo, the static site generator

On Hugo, the static site generator

So, I published a little blog post about browser extensions to write down how we’re currently doing it, and I thought it went well, since I didn’t look at the site on mobile at all.
How to Enforce Browser Extensions Across your Org

How to Enforce Browser Extensions Across your Org

If you’re a sysadmin or sysengineer at an organization that supports multiple browsers and platforms, this is for you.
Dash Cameras

Dash Cameras

I’ve been using the Viofo A119 Plus Duo for about 3 years now, until…
Working with Jamf School

Working with Jamf School

I’ve been using Jamf School at work for 3 years now. This is the first year (2024) in which I believe ALL of our faculty and staff Macs are enrolled in JS. Previously to the 21-22 school year, the school paid for Jamf Pro to manage the iPads for the K-5th graders and used imaging to deploy the Macs. I arrived in 2021, and that summer we began to move our devices and configurations to Jamf School.
Pfsense Https V2

Pfsense Https V2

Yesterday, I learned how to get Let’s Encrypt working on our PfSense router.
Unifi Controller HTTPS

Unifi Controller HTTPS

Here’s another HTTPS certificate story. This time, a self-hosted Unifi Controller was the invalid certificate annoyance.
A Real pfsense HTTPS Certificate

A Real pfsense HTTPS Certificate

Yesterday, I learned how to get Let’s Encrypt working on our PfSense router.

Hello World

First post!

How to Install and Optimize Immich on Unraid for Faster Timeline Loading

Planted July 8, 2025

How to Install and Optimize Immich on Unraid for Faster Timeline Loading

Move Your Immich Thumbnails to Cache for Speed

tl;dr at bottom

Hello! What’s Immich?

If you’re new to the self-hosted world and you’re searching for alternatives for Google Photos (Hi PewDiePie!), look no further than Immich - the most polished piece of open-source in-progress beta software I’ve seen.

What does self-hosted mean? I would say the central point of self-hosting is keeping your data in your control. You can self-host a very large number of apps, many of which are alternatives to popular proprietary apps that might not let you own your own data.

Immich is a self-hosted alternative to Google Photos, Synology Photos or iCloud Photos. That means you own all of your photos and data and you’re not sharing any of it with “big data” corporations. If you want to share specific albums or photos with individuals, you can! People are using Immich to share and hold onto their photos and using it to migrate from Google Photos to de-Google their lives.

Why am I using Immich? I read a story of a parent who had a concern about their child’s skin, and took a photo to send to their doctor’s office. That photo was stored on Google Photos, but since it was considered sensitive in nature, Google shut down the parent’s entire Google account without warning including all of their backed up photos and memories. I absolutely did not want that to happen to me, so I took it upon myself to get Immich up and running about a year ago.

Why Unraid?

Immich will run on anything you have laying around from an old laptop, your current PC, a Steam Deck, an Apple Mac or even in the cloud. I’ve got my old computer set up with hard drives in it running Unraid, a custom Linux operating system. If you need a suggestion to get your “home lab” started, I would suggest a refurbished Dell ultra small form factor (uSFF) PC on eBay. They’re typically around $150 and often a lot faster than a new Raspberry Pi, and not much more expensive in the end.

Why am I using Unraid? I wanted to turn my old PC into a NAS (network accessible storage, letting you store and access files anywhere on your network) server for things like backups and Nextcloud and I was torn between running TrueNAS Scale and Unraid. The benefit of using TrueNAS Scale would have been the native Docker container support and a true hardware RAID array. The downside of TrueNAS would have been that I needed all new hard disks since I did not then have enough for a full RAID array.

The benefit of Unraid for me was that I could have a parity disk (protecting against data loss) without having a true hardware RAID solution, and I could mix-and-match my current hard disks to get started (an old 2TB, a 4TB, and a 8TB disk). Funny enough, I ended up purchasing 4x 14TB refurb enterprise hard drives anyways, so I could have definitely gone the TrueNAS Scale route, and I probably will next time I build a NAS.

Immich Unraid installation methods

There are a few ways to install Immich on Unraid depending on how you like to run apps on Unraid. I prefer to use docker-compose.yml files to manage the majority of my stacks, but let’s start with another method first.

Community Applications Template

If you search the Community Apps section in your Unraid server for Immich, you’ll find a lot of apps. A few of them are directly related to Immich and some have integrations with Immich. The one that says “Immich” and “Monthly Spotlight” is the one you’re searching for, but once you click on it, you’ll find there are few extra requirements. You’ll need a PostgreSQL with Tensorchord container and a redis container up and running.

In order to install Immich from the Unraid CA, you will need an existing Redis and PostgreSQL 14 container, If you do not already have Redis or PostgreSQL you can install them from the Unraid CA, just make sure you choose PostgreSQL 14.

Once you have Redis and PostgreSQL running, search for Immich on the Unraid CA, choose either of the templates listed and fill out the example variables.

For more information about setting up the community image see here

It does appear that there are some ready to go PostgreSQL and redis containers for you, in the CA.

PostgreSQL_Immich   SpaceInvaderOne’s Repository

Although I have installed and played with many Community Applications apps, I do not run Immich using that method because I prefer the benefits of using the Docker-Compose method.

Docker-Compose Method (Official)

The method I prefer is the “official” method, per the Immich team. To get started, install the Compose Manager plugin from the CA. Then, go to the Docker tab, and scroll to the bottom where you’ll find the new “Add New Stack” button. Instead of typing everything out again, go visit the official Immich docs (deeplinked here to the correct header) and then come back before you click “Compose Up” in step 8. We’re going to make some changes to the docker-compose.yml and the .env files.

The default docker-compose.yml and .env explained

First up, let’s download the files. These two links are to the current release version of Immich on GitHub.

  1. docker-compose.yml
  2. sample.env

If you drop those into the Immich project in your compose manager, you’ll end up with a perfectly default working Immich app. Let’s look at what is happening when you do that. Docker Compose will use the .yml file to start several containers.

  1. immich-server
    1. This container is the main brain and controller behind the entire app. It does the port forwarding for the website and pushes and reads to the database.
  2. immich-machine-learning
    1. This container does specialized tasks like face analyzing locally on your device so when you search for pictures of your dog, you get pictures of your dog.
  3. redis
    1. This container does task management for Immich - redis is a very common way to schedule tasks that need to be completed in services.
  4. database
    1. Finally, this container stores all of the data for your library. As you upload pictures, the relative path in the filesystem is stored in the database. So, when you want to view image ID number 10101, you’ll actually see the correct image.

Next up, the example.env file has a few variables in it for you to edit or keep as is, depending on your setup. 1. UPLOAD_LOCATION is where your library of photos will exist. In a default case, you would create a new share in Unraid and place the library there, like /mnt/user/immich 2. DB_DATA_LOCATION is where your database will be stored on your file system. This should be a cache only location so that it’s super fast. I put mine in /mnt/cache/appdata/immich. Or if you’re confident that your cache is set up properly, you can also swap cache for user. 3. Next up we have the time zone, the version of Immich you want to run and some database password settings you’ll need to change to protect your data, or as a good practice.

Now, let’s look at my changes to tune Immich to be a bit faster on Unraid.

Tuning the docker-compose.yml and .env for my setup, and yours too

The main changes I want to make are separating Immich’s generated content from your original photo library. The official docs also talk about this, but I’ll give you an Unraid specific example.

When you upload an original photo to Immich from your phone, the image is probably around 2-3MB. Immich will accept that photo and place it in the library directory. Next, Immich will generate a tiny (less than 10KB) thumbnail of that image so you can see it in the timeline view as well as a compressed version (100-500KB) of the full size image so that it loads very quickly when you click on it. Since the original image is not accessed very often, we can save it on the hard disks and allow those disks to spin down after a period of inactivity, and rely on the generated content which will be stored on our SSD cache drive.

docker-compose.yml modification

  1. remove the original UPLOAD_LOCATION variable from the volumes list.
  2. Add the HDD_LOCATION and SSD_LOCATION variables

Before:

services:
  immich-server:
    container_name: immich_server
    image: ghcr.io/immich-app/immich-server:${IMMICH_VERSION:-release}
    # extends:
    #   file: hwaccel.transcoding.yml
    #   service: cpu # set to one of [nvenc, quicksync, rkmpp, vaapi, vaapi-wsl] for accelerated transcoding
    volumes:
     # Do not edit the next line. If you want to change the media storage location on your system, edit the value of UPLOAD_LOCATION in the .env file
      - ${UPLOAD_LOCATION}:/usr/src/app/upload
      - /etc/localtime:/etc/localtime:ro
... (etc)

After:

services:
  immich-server:
    container_name: immich_server
    image: ghcr.io/immich-app/immich-server:${IMMICH_VERSION:-release}
    # extends:
    #   file: hwaccel.transcoding.yml
    #   service: cpu # set to one of [nvenc, quicksync, rkmpp, vaapi, vaapi-wsl] for accelerated transcoding
    volumes:
      - ${HDD_LOCATION}/upload:/usr/src/app/upload/upload
      - ${HDD_LOCATION}/backups:/usr/src/app/upload/backups
      - ${HDD_LOCATION}/library:/usr/src/app/upload/library
      - ${SSD_LOCATION}/thumbs:/usr/src/app/upload/thumbs
      - ${SSD_LOCATION}/encoded-video:/usr/src/app/upload/encoded-video
      - ${SSD_LOCATION}/profile:/usr/src/app/upload/profile
      - /etc/localtime:/etc/localtime:ro
... (etc)
  • Are you sure /upload/upload is correct?
    • Yes. Docker has limitations when it comes to nested volume mounts. Specifically, mounting a volume inside another volume can lead to issues where the inner volume’s content is not properly accessible within the container.
    • Therefore, you cannot specify /usr/src/app/upload and then /usr/src/app/upload/upload, etc., you must list out every subdirectory to be mounted.

.env modification

Be prepared with a new Unraid share for these two locations

  1. remove the original UPLOAD_LOCATION variable
  2. Add the HDD_LOCATION and SSD_LOCATION variables
HDD_LOCATION=/mnt/user/immich
SSD_LOCATION=/mnt/user/immich-gen

I have my full .env and docker-compose.yml examples available as a gist. I also have the GPU hardware acceleration enabled and I’ve added a docker network section for my reverse proxy docker network.

One important risk

By placing the thumbnails and generated content on your SSD cache, there is a potential risk of data loss in the event of a hardware failure of your SSD. Unraid does not have any parity in the SSD cache, but there is a way to use ZFS (software RAID) to add a layer of protection your SSD cache and get better performance from it. To mitigate the risk, ensure that your original images in your library are properly backed up. If you for some reason lose your SSD cache, reinstall Immich and have to run the Generate Thumbs task in Immich, as long as your library is protected you’ll be OK.

Steps to modify your current Unraid setup

If you’re reading this and you already have Immich set up on Unraid using the Docker Compose method, then you’re very close to getting way faster thumbnail loading times.

1. Stop Immich docker containers

2. create immich-gen on the cache only

Feel free to add the Array as secondary storage, as I have, shown below. And I’m assuming that you already have an Immich share or directory for your library, not an external library.

3. edit .env and docker-compose.yml to add the SSD_LOCATION and modify for the HDD_LOCATION

see above for those specific details

4. move data from your existing immich share to the immich-gen share

Here’s what my immich-gen share looks like on my SSD cache:

root@Tower:/mnt/user/immich-gen# ls -lha
total 0
drwxrwxrwx 1 nobody users  56 Jul 12 15:26 ./
drwxrwxrwx 1 nobody users 185 Jan  8 10:31 ../
drwxr-xr-x 1 root   root  153 Sep 13 08:14 encoded-video/
drwxr-xr-x 1 root   root   65 Sep 13 08:14 profile/
drwxr-xr-x 1 root   root  153 Sep 13 08:14 thumbs/

and my immich share on my HDD pool:

root@Tower:/mnt/user/immich# ls -lha
total 0
drwxrwxrwx 1 nobody users  66 Jul 12 15:26 ./
drwxrwxrwx 1 nobody users 185 Jan  8 10:31 ../
drwxr-xr-x 1 root   root   59 Jan  8 20:02 backups/
drwxr-xr-x 1 root   root  123 Jul 15 08:04 library/
drwxr-xr-x 1 root   root  154 Jul 12 15:28 upload/

5. do a compose up and it should just run

If there is an error, read the logs first. Maybe, they’ll already be on-screen for you, or from the Compose plugin on the Docker tab, click the gear, and then choose logs. Otherwise, run docker-compose logs in the Immich project directory and you’ll get the issues read out for you.

The project directory can be found on the Docker tab in Unraid. Mine looks like:

/boot/config/plugins/compose.manager/projects/immich/

Updating Immich Moving Forward

Step 1, subscribe to Immich updates on GitHub! Select “Watch” then “Custom” then check “Releases” - that way you’ll get notified when a new update comes out.

There have been a few cases of breaking changes, and the release notes in your inbox should help you move forward. Breaking changes, so far, have included updating the docker-compose.yml to a different version of postgres with vectors - anyways, just read the release notes and if you still need help if there is a breaking change listed, check out the discord channels or /r/immich.

Step 2, push update in Unraid at the bottom of the Docker tab in the Compose section. You’ll see a terminal style modal pop up (which in the background runs docker-compose pull then docker-compose up -d or some variant of that) and it will notify you when it has been completed. Now, visit your FQDN for Immich and make sure it’s working! Otherwise, back to check the logs.

Wrap Up & Conclusion

I’ve been able to help at least 2 people out on /r/immich with moving the generated content to the SSD cache, so I wanted to gather my thoughts here for future reference.

My hope is that by reading something here you’ve successfully increased the speed that your Immich timeline loads.

tl;dr: update your stock Immich docker-compose.yml to include more volume mount location variables from your .env so that your Immich timeline loads way faster than if the thumbnails were on a spinning platter of rust.

FAQ

  • What is the benefit of moving the [generated content] to the cache drive? what are you trying to achieve?
    • Immich generates thumbnails and other sizes of images to load faster in the app and on the website timelines. If you have to wait for a hard disk to spin up before those files are loaded, you might have a poor experience using Immich. Especially if you have tens of thousands of photos and videos in your timeline. The goal of this project is to make a small modification to the Immich install so that the thumbnails are on a SSD cache drive and load instantaneously (versus a HDD) and the experience using Immich is stellar.
  • Have you had to do anything special during update time? Or does it keep your custom settings?
    • Most of the time, I just run the Update Stack button a little bit after I get the email that there’s a new update from GitHub. Occasionally, I’ll wait a full day for the Android app to update and then update the server to match it. But, watch for breaking changes in the Immich release notes! They happen from time to time. This is beta software, after all.
  • What if I don’t have an SSD cache?
    • Well, I would recommend making a plan to add one to your server. Adding a SSD cache will significantly improve your experience as your Immich library grows, and as your Unraid server expands.
  • How do I know if my changes worked?
    • This depends on how many assets you have in Immich. For example, if you have a significant number, then scroll back to a random date in the app or on the webapp and see how long it takes to load all of the thumbnails. After this change, the time will be less than a second.

AI Disclosure - I did not use any AI generated outputs in the text above. I did, definitely, use AI to generate the thumbnail image for this blog post.