This blog post isn't a detailed step by step guide, as there are countless ways of achieving sovereignty over your photos.
My goal is to outline the most important steps and my personal learnings, in order to provide you with the knowledge & the motivation you will need to do the same.
Table of contents
Motivation
Your Photos Stay Yours
Photos contain personal information: faces, locations, relationships, travel history, you name it. Uploading them to cloud services such as Google Photos means you are trusting a third party with some of your most sensitive files..
However, with a self-hosted approach:
- Your photos stay on hardware you control and own
- No corporation has broad access to your files
- You decide how data is stored, shared, and secured
Protection Against AI and Generative Model Usage
Cloud platforms increasingly use AI for face recognition, object detection, search, and automated organization. Even if providers claim not to directly train public AI models on your photos, policies and data practices can change over time.
Your image library is valuable AI training data, self-hosting solves this issue as Immich (more on this later) runs image recognition locally, on your own hardware.
Avoiding Vendor Lock-In
Cloud photo platforms are designed to keep users inside their ecosystem. Over time, exporting large libraries along with albums, edits, and metadata becomes difficult and time-consuming.
With self-hosting:
- Your files remain portable
- You can switch software or storage providers anytime
- Access to your memories does not depend on a company account or subscription
- No one can suddnely increase the price of your service
Requirements
Note: I won't recommend any specific software, vendor or product. I am solely sharing my decision process as I highly suggest everyone to do research based on their own specific needs and abilities.
Time
I have spent
a lot of time until everything was running how I envisioned it. Please don't think you can simply order the parts and be done after 2-3 hours.
In retrospect, it was worth every single minute as I learned a lot and got a big piece of mind by finally
owning my own photos.
Protip: Use the money that you save by not paying Google to pay yourself for the time setting this up and maintaining it ;)
Space
When looking for the right place in your home, please consider the following things:
- Noise - Assuming you use mechanical drives you will want to get drives that are made for 24x7 usage and these tend to be quite loud
- Ambient Temperature - The hotter the room, the less performant and the noisier the NAS will be
- Physical Safety - Ensure that no one (toddlers, animals, clumsy friends) can accidentally bump into || spill water on || unplug the cable of the NAS.
The optimal solution for me was the cellar, there isn't anyone being bothered by the noise and the ambient temp is pretty cool. Just make sure the humidity of your cellar is within operating specs of your equipment.
NAS
Lets start with the NAS (network attached storage), the hardware where our Immich service will be hosted.
I chose the
UGREEN DXP4800 Plus as it fulfills all of my requirements:
- Somewhat powerful CPU with a decent iGPU (for video transcoding, facial recognition)
- Ability to upgrade the RAM
- 10 Gbp/s network interface (even though all of my other devices "solely" support 2.5 Gbp/s, this is nice to have in relation to future proofing)
- Four harddisk bays (the more, the better)
- M.2 slots (so I can add some fast SSDs in the near future)
I added another 8 GB of RAM (16 GB in total) to ensure I had enough left for some other use cases running on the NAS.
Harddrives
I chose two WD Red Plus 12TB drives as they have a pretty low defect rate as well as a competitive price.
Note: Be aware that using
RAID has an influence on your total available capacity.
Networking Equipment
Switch
I opted for the
UniFi Flex Mini 2.5G as it is the cheapest 2.5G switch from a reputable brand that I could find. Since solely the NAS and a RasperryPi are using the switching fabric, it should be plenty powerful for now.
Cables
I wired up everything using CAT
6A cables, which means I will be ready for when I want to upgrade my other equipment to 10G.
Having to crimp your own cables is nostalgic at best, but it is a good way to save some money as well as allowing you to route cables through tight spaces / other rooms.
UPS
Even though the power grid here is very stable, having a UPS for an always on system is an absolute no-brainer.
It serves the following functions:
- bridging short power outages
- ensuring the OS shuts down properly in case of longer outages
- giving additional protection against overcurrents (such as caused by lightning strikes)
I opted for a cheap UPS from a reputable brand, connected it through USB and setup the UPS configuration in TrueNAS.
Now I receive an email notifications (thanks HexOS) should the UPS kick in and when power is restored.
Software
OS
I opted for
HexOS which is a "UI wrapper" around
TrueNAS, making it way easier to setup, configure and maintain.
You might say that this isn't quite the spirit of full control, but I have enough trust in that company and this made things a lot less complicated.
Photos
Immich is open source and does everything I need (image recognition, mobile apps, nice UI).
Remote Access
Since I didn't want my Immich instance reachable to the whole internet, I opted to use
Tailscale.
Offsite Backup Location
In the case that the both harddrives (RAID 1) should die at the same time (stroke of fate, fire, water, etc.), I needed an offsite location for the photos.
I ended up going for a
Hetzner Storage Box, the reasons are straightforward: SSH access, European company, servers in Europe and fairly priced.
You will find the backup approach I used in detail under "Maintenance".
Now you might say, "hey, now your photos are back in the cloud || under someone elses control".
The backups are fully encrypted and with the big difference that I can actually validate this on my own, which isn't possible for any service being sold to you as being "end-to-end encrypted".
Installation
NAS
The first part was the easy, tangible part: unpack the NAS, add the extra RAM, and insert the disks.
After that, I inserted a USB drive loaded with the HexOS installer preloaded and followed their
user guide.
Protip: Go to the UGREEN bios and disable their watchdog first, as otherwise your NAS will reboot every 3 minutes.
One reason I chose HexOS instead of building a pure TrueNAS setup from scratch is that HexOS is designed to validate hardware, partition the system, and get you into a usable dashboard quickly while still sitting on top of TrueNAS underneath.
Immich was the main reason I built this in the first place. HexOS now supports curated app installs, and Immich is on that curated list, which meant I did not have to manually compose every container, port, mount, and permission from scratch. HexOS’s install-script system is explicitly built to preconfigure networking, folders, storage paths, and resources using opinionated best-practice templates, and the Immich script creates dedicated locations for photo data and database storage while exposing the web interface on port 2283.
One click and waiting a few seconds is all you need to do until you are greeted by Immichs setup-guide.
The same goes for Tailscale, simply go to the app "store" and install it.
Network
Solely two things were required, configuring a fixed IP for the NAS and opening & forward UDP port 41641 for tailscale.
Smartphone(s)
Once the server side was working, the phone setup was pleasantly simple.
First, I installed Tailscale on the phone and signed it into the same tailnet. Tailscale supports iOS and Android directly from the App Store and Google Play, and once a device joins the tailnet it gets the same private-network treatment as everything else: its own address, its own identity, and the ability to reach other approved devices securely.
Then I installed the Immich mobile app. Immich’s own mobile docs say the app signs into a server endpoint URL, and that is exactly what I used: the NAS over Tailscale instead of a public domain. In practice, that meant I could point the mobile app at the NAS’s Tailscale address and keep the whole thing private. That is not a separate Immich feature so much as a nice consequence of combining Immich’s endpoint-based mobile login with Tailscale’s private networking.
The last thing is to check if the connection to your NAS is direct or going through peer relay nodes (see "Network" chapter):
Migration
The basic flow is straightforward. Google’s supported way to get your photo library out is Google Takeout: select the Google Photos data you want, create an export archive, and download it. That process does not delete anything from Google by itself, it simply gives you a copy of your data so you can keep it, archive it, or move it somewhere else.
From there, the goal was to get the archive into Immich. Immich’s own
CLI can upload photos and videos to an Immich server, the photos will be sorted based on their EXIF data, simple as can be.
Backups
A self-hosted photo library is only as good as its backup story, and this is the part I tried to keep as simple as possible.
Immich itself is very clear about the separation between metadata and files. Its quick-start documentation warns that the built-in database backup only covers metadata and user information, while the actual images and videos in `UPLOAD_LOCATION` still need manual backup.
My offsite target is a Hetzner Storage Box. As the Storage Box supports connecting through SSH and my last bash script I wrote by hand is from
2024, I vibecoded the following
restic script to do my nightly backup to the offsite location:
#!/bin/bash
SCRIPT_DIR="$(cd -- "$(dirname -- "${BASH_SOURCE[0]}")" &> /dev/null && pwd)"
# -------------------------
# CONFIGURATION
# -------------------------
SOURCE_DIR="/mnt/immich"
TARGET_REPO="/mnt/storagebox/immich"
RESTIC_PASSWORD="$(< "$SCRIPT_DIR/restic_pass")"
# -------------------------
# EXPORT ENVIRONMENT
# -------------------------
export RESTIC_REPOSITORY="$TARGET_REPO"
export RESTIC_PASSWORD="$RESTIC_PASSWORD"
# -------------------------
# FUNCTION TO CHECK LAST COMMAND STATUS
# -------------------------
check_status() {
if [ $? -eq 0 ]; then
echo "✅ $1"
else
echo "❗ $1"
exit 1
fi
}
# -------------------------
# CHECK IF RESTIC INSTALLED
# -------------------------
if ! command -v restic &> /dev/null; then
echo "❗ Restic is not installed. Please install it first."
exit 1
else
echo "✅ Restic is installed"
fi
# -------------------------
# PRE-RUN CHECK: IS SOURCE MOUNTED?
# -------------------------
if mountpoint -q "$SOURCE_DIR"; then
echo "✅ $SOURCE_DIR is already mounted"
else
echo "$SOURCE_DIR is not mounted. Attempting to mount..."
"$SCRIPT_DIR/mnt" immich
check_status "Mounting $SOURCE_DIR"
fi
if mountpoint -q "$TARGET_REPO"; then
echo "✅ $TARGET_REPO is already mounted"
else
echo "$TARGET_REPO is not mounted. Attempting to mount..."
"$SCRIPT_DIR/mnt" storagebox
check_status "Mounting $TARGET_REPO"
fi
# -------------------------
# INITIALIZE REPOSITORY (if not already)
# -------------------------
if [ ! -f "$TARGET_REPO/config" ]; then
echo "Initializing restic repository at $TARGET_REPO..."
restic init
check_status "Restic repository initialized"
else
echo "✅ Restic repository already exists"
fi
# -------------------------
# PERFORM BACKUP
# -------------------------
echo "Backing up $SOURCE_DIR to $TARGET_REPO..."
restic backup "$SOURCE_DIR"
check_status "Backup completed"
# -------------------------
# KEEP MAX 10 SNAPSHOTS
# -------------------------
echo "Pruning old snapshots, keeping only the last 10..."
restic forget --keep-last 10 --prune
check_status "Old snapshots pruned"
# -------------------------
# VERIFY BACKUP
# -------------------------
echo "Verifying backup snapshots..."
restic snapshots
check_status "Snapshots verification done"
echo "✅ Backup complete and encrypted!"
Conclusion
That combination of local storage that I own, private remote access through Tailscale and an offsite backup is what finally made the setup feel complete.
My photos are not magically safer just because they live on a NAS now. They are safer because I know where they are, how they are accessed, and how they are backed up.
Would I recommend you to do the same? Absolutely, even if you lack the skills for any of the specific steps required, there are plenty of great resources online, as ultimately your freedom is priceless.