Be honest about the money first
Most self-hosting guides open by telling you how much you'll save. That's usually a lie of omission, so here's the real arithmetic.
A cloud photo plan big enough for a family runs somewhere around [FILL: check today's Google One 2TB price] per month. This build costs roughly $540 up front plus about $6/month for encrypted offsite backup — because a server in your basement is not a backup, and I'll die on that hill.
Straight payback against a 2TB plan lands somewhere in the three-to-five year range. That's real but it's not thrilling, and if someone tells you it pays for itself in six months, they're selling something.
What you're building
Immich is an open-source, self-hosted photo library that is — genuinely, not as a consolation prize — a close match for Google Photos. Phone apps for iOS and Android with background auto-upload, face recognition and grouping, search by content ("beach", "dog", "receipts"), albums, shared albums, timeline, memories. It runs in Docker on hardware you own.
When this build is finished you have:
- Your entire Google Photos export imported with dates, albums, and location data intact
- Automatic phone backup for everyone in the house — it just works in the background like Google's did
- Hardware-accelerated thumbnail and video transcoding, so browsing is instant instead of a slideshow of spinners
- Face and content search running locally — the machine learning happens in your house, on your photos, and nothing leaves
- Remote access from anywhere with zero ports forwarded to the internet
- Encrypted offsite backup on a schedule, with a restore you've actually tested
The parts list
This is the cheap, boring, reliable build. There's no reason to buy anything new here — refurbished enterprise gear is the entire trick, and it's why the number is $540 instead of $1,500.
| Part | What to get | ~Price | Why this one |
|---|---|---|---|
| Compute | Refurb small-form-factor desktop, Intel 8th-gen or newer i5, 16GB RAM Dell OptiPlex 5060 / Lenovo M720q class |
$170 | Intel QuickSync gives you free hardware transcoding with no graphics card at all. This is the single biggest money-saver in the build. |
| Bulk storage | 2 × 8TB refurbished enterprise HDDs | $220 | Mirrored, so one drive can die without taking your library. Refurb enterprise drives are the best $/TB on the market and come with real warranties. |
| Fast storage | 1TB NVMe SSD | $60 | OS, the Immich database, and the thumbnail cache. Putting the database on spinning rust is why some people's Immich feels slow. |
| Power protection | Small UPS, ~600VA | $70 | Not optional. A dirty shutdown mid-write corrupts the database, and then you're restoring from backup on a Tuesday. |
| Cables | SATA data + power splitters | $20 | SFF cases never ship with enough. Buy them now, not after the drives arrive. |
| One-time total | ~$540 | Leaves headroom under $600 for tax and shipping | |
| Offsite backup | Object storage (Backblaze B2 or equivalent) | ~$6/mo | The only recurring cost. Encrypted before it leaves the house, so the provider is storing noise. |
The build, end to end
1. Get your data out of Google first
Do this before you buy anything, because the export takes days and it's the step most likely to surprise you. Google Takeout, select Photos only, choose 50GB archive chunks. Google emails you download links that expire in a week, so start it on a Friday when you'll be around.
.json files instead. Import the folder naively and every photo you own gets
dated the day you imported it — your entire timeline, destroyed. Immich's import tooling
handles this correctly if you point it at the JSON. Verify the dates on a handful of
old photos before you delete anything from Google.
2. Install the OS and set up the mirror
Ubuntu Server LTS, minimal install, on the NVMe. Then mirror the two spinning drives so either one can fail without taking your library with it:
# two 8TB drives, mirrored — either can die and you keep everything
sudo apt install -y mdadm
sudo mdadm --create /dev/md0 --level=1 --raid-devices=2 /dev/sda /dev/sdb
sudo mkfs.ext4 /dev/md0
sudo mkdir -p /srv/photos && sudo mount /dev/md0 /srv/photos
Add it to /etc/fstab so it survives a reboot. Then pull a drive out while
it's running and confirm everything still works. A mirror you haven't tested is a
rumour.
3. Immich
Docker Compose, straight from the official docs. Two things in the config actually matter and both are easy to get wrong:
- Point the upload volume at your mirror (
/srv/photos), not at the boot SSD. People fill their 1TB NVMe and wonder why everything stopped. - Enable the hardware transcoding profile. It's a separate override file, it is not on by default, and skipping it is the number one reason people say Immich is slow.
4. Prove hardware transcoding is actually on
This is where most builds silently fail. Immich will happily fall back to CPU transcoding without telling you — it works, it's just ten times slower and pins every core. Start a library scan and watch the chip:
# Intel QuickSync — should show non-zero engine usage during a scan
sudo apt install -y intel-gpu-tools
sudo intel_gpu_top
# NVIDIA — look for the container in the process list
nvidia-smi dmon
If those stay flat while your CPU sits at 100%, it's not working. Fix it now — before you import 40,000 photos and spend two days waiting.
5. Remote access, without exposing anything
Do not port-forward this to the internet. You'd be putting a database full of pictures of your children on the public internet behind software you're not going to patch every week.
Install Tailscale on the server and on every phone in the house. It builds a private encrypted network between your own devices. Your firewall stays completely closed, and the Immich app on your phone reaches the server from anywhere in the world as if you were on the couch. Setup is about five minutes and it's free at family scale.
6. Backup — the step everyone skips
A mirror protects you from a dead drive. It does nothing about fire, theft, flood, a bad power supply cooking both drives at once, or you deleting the wrong album at 1am.
# encrypted, versioned, offsite — runs nightly
restic -r s3:s3.us-west-000.backblazeb2.com/your-bucket backup /srv/photos
# and the part that actually matters:
restic -r s3:... restore latest --target /tmp/restore-test --include /srv/photos/2019
Four things that broke when I did this
None of these are in the official docs. All four cost me hours, and every one of them will happen to you in some form.
1. Everything was slow, and the network was innocent
Connections to the server hung for seconds before doing anything. I blamed the drives, then Docker, then my router. The real cause: Tailscale gives every machine an IPv6 address, my ISP provides no working IPv6, and Linux was dutifully preferring the IPv6 route — waiting for a timeout on every single connection before falling back.
Fix: /etc/gai.conf, set IPv4 precedence higher. Instant.
2. Everything died because a different machine moved
Weeks later, the whole setup broke at once. The cause was my Pi-hole — it had been on DHCP, the router handed it a different address after a reboot, and every device on the network lost DNS. The photo server was fine. It just couldn't be found by name.
Fix: static IPs on anything other machines depend on. All of them.
3. Hardware transcoding was off and nothing said so
Immich ran. Photos imported. It was just crawling, with every CPU core pinned. The hardware acceleration override file was never applied, so it had been silently falling back to software the entire time — no error, no warning, just quiet slowness.
Fix: watch the GPU during a scan. Verify, don't assume.
4. I nearly deleted the originals too early
The strong temptation once Immich is running is to free up the Google account immediately. Don't. Keep both for at least a month, and spot-check old photos, videos, live photos, and anything from a phone you no longer own — those are where import gaps hide.
Fix: 30-day overlap, minimum. Verify before you burn the boat.
Should you actually do this?
Yes, if
- You have more than ~1TB of photos and the bill keeps climbing
- The idea of your family archive living in an account that can be suspended bothers you
- You're comfortable pasting terminal commands and reading an error message
- You can give it a weekend and an hour a month afterward
No, if
- You're under the free tier and it's fine — genuinely, keep your weekend
- Nobody in the house can troubleshoot it when you're travelling
- You want it to be zero-maintenance forever. It's low, not zero.
- You'd skip the offsite backup to save $6/month. Then don't do this at all.
Or I'll set it up for you — $199
Same build, done over a screen share, working when you hang up. You buy the hardware and own it outright. I do the migration, the transcoding config, the remote access, and the backup — and I test the restore in front of you so you've seen it work with your own eyes.
- Library migrated with dates and albums intact — verified, not assumed
- Hardware transcoding confirmed on, not silently falling back
- Tailscale remote access for every phone in the house, zero ports open
- Encrypted offsite backup scheduled, with a live restore test
- Plain-English runbook and two weeks of email support