Immich Photo Library
Immich is the photo and video management server running on the home NAS. The primary goal was consolidating years of family photos that had been sitting on old Buffalo NAS drives, along with a complete iPhone backup. Part of the TrueNAS SCALE Setup.
Buffalo NAS Photo Import
After the TrueNAS setup cloned the Buffalo NAS data to /tank/buffalo, the photos and videos needed to be imported into Immich. Rather than pointing Immich at a folder and letting it scan, I used the Immich REST API to upload programmatically — this preserves original file timestamps and handles duplicates more cleanly than a bulk folder import.
The Buffalo drives contained several layers of photo libraries:
- Thousands of family photos and videos dating back 26 years
- Backups of old computers, most of which had their own photo libraries mixed in
The API upload ran for a long time given the volume. Once complete, Immich’s ML started grouping faces and categorizing scenes automatically.
Filtering Unwanted Content
The raw import included a lot of noise: screenshots, memes, stock photos, app icons, and random internet downloads that had accumulated in photo folders over the years. Immich’s ML-powered search makes this surprisingly manageable — searching for terms like “screenshot,” “meme,” or “wallpaper” surfaces most of the clutter. I went through each search result and removed anything that didn’t belong.
After filtering: over half a terabyte of photos and videos spanning 26 years.
Face Identification
Immich’s ML automatically clusters faces across the library but needs manual labels to attach names. I started working through the suggested clusters, naming everyone I recognized and merging groups where the model split one person across multiple clusters.
There are faces I can’t identify — older relatives or family friends I don’t recognize from photos taken before I was born or when I was very young. The plan is to eventually give family members access so they can name the people I can’t.
iPhone Backup
After the Buffalo import, I backed up roughly 12,000 photos and 500 videos from my iPhone. Same process: API upload, then a filtering pass to remove screenshots, memes, and other unwanted content from the phone library.
Cloudflare Tunnel Timeout Issue
Uploading overnight while away from home ran into a real limitation: Cloudflare tunnels have a connection timeout that’s short enough to kill transfers of medium-to-large video files. The photos were fine — it was specifically the larger video files (anything over a few hundred MB) that would fail mid-upload.
The fix was Tailscale. With a direct Tailscale connection to the NAS, the upload bypasses Cloudflare entirely and there’s no timeout to worry about. I split the upload: photos through the Cloudflare tunnel, videos over Tailscale. Everything completed overnight.
Remote Access
Immich is accessible publicly at immich.harrisonsmith.me via Cloudflare tunnel. Immich handles its own user authentication — accounts can be created per person and library sharing is configurable at the album or person level.
Tailscale remains the fallback for large uploads or anything where the Cloudflare tunnel is too limiting.
Tasks
- Complete face identification (share remaining with family) medium
- Give family members access to shared albums medium
- Deploy Immich from TrueNAS app catalog high
- Configure storage path to /tank/photos high
- Write Python script to upload Buffalo NAS photos via Immich API high
- Filter unwanted content (screenshots, memes, stock photos) high
- Begin face identification and tagging from ML suggestions medium
- Back up iPhone photos and videos high
- Resolve Cloudflare timeout issue for large video uploads high
- Configure Cloudflare tunnel (immich.harrisonsmith.me) high
Milestones
- Immich deployed and accessible
- Buffalo NAS photos imported
- iPhone backup complete
- Accessible publicly via Cloudflare tunnel
- Family given access
Dev Log
iPhone backup — Cloudflare timeout on large videos, fixed with Tailscale
Started backing up ~12,000 iPhone photos and 500 videos. Photos uploaded fine through the Cloudflare tunnel. Large video files timed out mid-transfer — switched to Tailscale for those and everything completed overnight.
With the Buffalo import and filtering done, the next chunk of work was backing up my iPhone library. I was away from home when I started this, so everything was going through the Cloudflare tunnel.
iPhone backup volume
- ~12,000 photos
- ~500 videos
Started the API upload script pointing at the Immich tunnel URL. Photos were uploading without issues.
Cloudflare timeout problem
The video uploads started failing partway through. Specifically, any video file over a certain size would time out mid-transfer — the connection would just drop. Smaller files (short clips, a few hundred MB) went through fine. Longer videos (anything approaching or exceeding a gigabyte) consistently failed.
This is a known Cloudflare tunnel limitation. The tunnel enforces a connection timeout that’s short enough to interrupt large uploads. There’s no obvious way around it on the Cloudflare side without paying for higher-tier features.
Tailscale fix
The solution was to split the upload:
- Photos → upload via Cloudflare tunnel (no timeout issues at typical photo sizes)
- Videos → connect via Tailscale and upload directly, bypassing Cloudflare entirely
With Tailscale, the upload goes directly to the NAS without any intermediary timeout. Set it to run overnight on Tailscale and by morning all 500 videos had uploaded successfully.
Post-upload filtering
Same process as the Buffalo import — ran through Immich’s ML searches to remove screenshots and unwanted content from the phone library. Phone screenshots are plentiful and easy to catch with a single search. Also removed duplicate photos from burst shots where I’d kept five nearly-identical frames.
The combined library (Buffalo + iPhone) is now the working state: over half a terabyte, 26 years of family media on one side, and my complete phone backup on the other.
Import done — filtering and face naming in progress
Buffalo NAS upload completed. Going through ML search results to remove screenshots and noise. Started naming faces from the ML clusters — 26 years of family photos means a lot of people I don't recognize.
Upload finished overnight. The library is large and Immich’s ML worker has been running since it completed, processing faces and scenes in the background.
Filtering pass
The raw import included a lot of content that doesn’t belong in a photo library. Years of accumulated screenshots, memes, stock photos, app icons, and random downloads mixed in with the actual family photos. Immich’s search makes this manageable:
- Searching “screenshot” returned hundreds of hits — phone screenshots, Windows screenshots, software UIs
- “Meme” and “wallpaper” caught most of the other noise
- A few manual searches for specific categories (charts, graphs, logos) caught additional clutter
Went through each search result and deleted anything that didn’t belong. The process took a few hours but was much faster than trying to do it folder by folder.
After filtering: just over half a terabyte of photos and videos, spanning 26 years (roughly 2000 through today).
Face identification
Immich’s ML grouped faces into clusters automatically. Some of the clustering is excellent — it consistently identifies the same person across hundreds of photos taken years apart. Other times it splits one person into several clusters, or merges two different people who apparently look similar.
Started going through the clusters:
- Named everyone I recognized confidently
- Merged clusters where the same person was split into multiple groups
- Left question marks on anyone I couldn’t identify — a lot of these are relatives from photos taken before I was born or when I was very young
There are a significant number of faces I simply don’t know. Some of them appear frequently, which suggests they’re family friends or relatives who were around a lot. Getting family access to Immich so they can help with naming is the next step here.
Immich deployed — Buffalo NAS photo upload running
Immich up and running on the NAS. Started uploading family photos and videos from the Buffalo NAS clones via the Immich API. Large volume — running overnight.
With the Jellyfin library sorted, next up was getting the family photos into Immich.
Deployment
Deployed from the TrueNAS app catalog. Pointed the storage path at /tank/photos. The Immich stack (server, microservices, ML worker, Redis, Postgres) all come up together from the catalog configuration.
Why API instead of folder import
Immich has a watched folder / external library feature, but I opted to upload via the REST API instead. The main advantages:
- Preserves original file timestamps (the creation date in Immich matches when the photo was actually taken, not when the file was copied)
- Handles duplicates — the API returns a
409if a file with the same hash already exists, so running the script multiple times is safe - Gives progress feedback per file rather than waiting for a bulk scan to finish
The data
The Buffalo drives had photos scattered across multiple places:
- A main
Photosshare with organized subfolders by year - Computer backup archives that contained additional photo libraries, some of which overlapped with the main share
- A mix of actual family photos, screenshots, stock images, and random internet downloads that had accumulated over the years
Started the API upload script. Given the total volume it’s going to run overnight, probably into tomorrow. Will deal with filtering once the import is done.