LOG-032 ·
84,000 Photos Came Home
I moved two decades of photos off a cloud service and onto a machine in my closet. The migration took 11 days, the library shrank by 14%, and the monthly cost went down. Mostly.
- Words
- 722
- Est. read
- 3.1 min
- Confidence
- 0.83
- Topics
- self-hosting, photos, experiment
My photo library was the last large thing I did not hold. 84,317 photos and 2,911 videos, 412 GB, spanning 2006 to now, living on a cloud service that has renamed itself twice and changed its pricing three times since I started paying it.
On 2026-07-06 I began moving all of it to a self-hosted instance running on the closet server. On 2026-07-17 the last byte landed. This entry is the accounting.
The export was the hard part
The takeout archive arrived as 53 zip files totaling 397 GB, which is already interesting because the service claimed my library was 412 GB. Some of the difference is compression. Some of it, I would discover, is that the export does not include everything at original quality, despite my paying for the tier that stores originals.
Verification was not optional. I wrote a script to compare file hashes from the export against my two prior local snapshots (I have synced a read-only mirror monthly since 2023, a habit I recommend before you need it). Results:
| Category | Count |
|---|---|
| Files in export matching a known original | 79,204 |
| Files in export recompressed (hash mismatch, smaller size) | 4,871 |
| Files missing from export entirely | 242 |
| Files recovered from my own mirrors | 5,096 |
| Files unrecoverable at original quality | 17 |
Seventeen files, all videos from 2011 and 2012, exist now only in the recompressed form the export gave me. If I had not kept mirrors, that number would be 5,113. The lesson costs nothing to state and a fair amount to learn: an export feature is a marketing checkbox until you diff it against ground truth.
Deduplication
Two decades of platform migrations left sediment. The same photo imported through three different phone backups, burst shots saved as separates, edited copies alongside originals. Content hashing found 11,904 exact duplicates, deleted without ceremony. Perceptual hashing flagged another 1,286 near-duplicates that I reviewed by hand over four evenings (2 hours 40 minutes total, logged), of which 883 photos and 17 videos did not survive the review.
Post-cleanup: 71,530 photos, 2,894 videos, 341 GB. The library shrank 14% by count and 17% by bytes, and browsing it feels different in a way I did not predict. Less like a landfill, more like an archive.
The stack and the bill
The instance runs in a container on the closet server, indexed with on-device machine learning for faces and search. Indexing 341 GB took 31 hours and pushed the server's power draw from its usual 11 W to 74 W for the duration, call it 2.0 kWh, or about $0.26 at my rate.
The monthly ledger, before and after:
| Item | Cloud (before) | Self-hosted (after) |
|---|---|---|
| Storage subscription | $9.99 | $0 |
| Amortized disk (2x 4 TB, 5-year life) | $0 | $3.10 |
| Incremental power | $0 | $0.41 |
| Offsite encrypted backup (B2) | $0 | $1.87 |
| My time, at 15 min/month maintenance | untracked | untracked |
| Total | $9.99 | $5.38 |
I save $4.61 a month, which will repay the 19 hours the migration consumed in roughly 21 years. If you are doing this for the money, do not do this.
What actually changed
Search by face and object works locally and is, to my surprise, slightly better than the cloud service for my library, because it indexes the RAW files the cloud version silently skipped. Sharing an album with my mother now means she loads it from my house, which added 140 ms of latency she has not mentioned.
The honest downside: I am now the SRE. When the reverse proxy certificate failed to renew on 2026-07-28, photos were unreachable for 6 hours until I noticed. The cloud service's last outage that affected me was shorter. My availability will be worse than theirs. My custody is absolute, and the 3-2-1 rule holds: originals on the server, second copy on the offline drive that gets rotated monthly, third encrypted offsite.
The number that matters
Before: one company could lose, recompress, or lock my entire visual record, and had already quietly done the middle one to 4,871 files. After: three independent copies under two roofs and one legal jurisdiction of my choosing, verified by hash on a schedule.
Confidence 0.83 that the self-hosted instance is still my primary photo store in 24 months. The residual 0.17 is not doubt about the software. It is respect for the base rate of my own abandoned projects, which I also keep in a table.