A thin client, an 8TB drive and far too much curiosity. It runs my photos, music, passwords, smart home and this website, and these days it's built to survive its own failure.
Internet
Full-fibre
Router
VPN in · forwards no ports
Dell Wyse 5070
A thin client: 4-core Celeron, 16GB RAM, Intel UHD 600. Silent, and sips power
512GB SSD
Ubuntu Server, and every container's own state
8TB USB drive
The media library, the photo library, and this site's files
Four websites, and nothing else
A visitor
Anyone, anywhere
Cloudflare
Public DNS, TLS, the edge the internet actually talks to
Tunnel connector
Runs on the server and dials out. It never listens for anything
Server time (UTC). Marked ones run on Sundays.
SMART readings from both drives, compared against each drive's own baseline
Every compose file, crontab and setting, secrets stripped, checked against git for drift
Encrypted, deduplicated, to Backblaze B2, at the lowest disk priority so nothing stutters
This personal site.
Armarium marketing site.
Dægwork marketing site.
Mesh Wi-Fi
2 nodes
Ubuntu Server
Dell Wyse 5070 · Docker · 8TB · BLE
Trusted network
Gaming · media · workstation (wired)
Smart home Wi-Fi
Cameras & IoT, isolated
What it hosts
Docker stacks · tunnel dials out
Scroll to see the full diagram →
Every one of these is a Docker Compose stack in its own folder. The host itself runs very little else.
The public site
wanating.uk and three product domains. Read-only, holding no secrets
Everything else, private by default
My phone or laptop
On the sofa, or on the other side of the country
The router
The only way in. It forwards no ports at all
Pi-hole
Private names that only exist inside the house, ad blocking, encrypted DNS upstream
Reverse proxy
One wildcard certificate, so even private pages are proper HTTPS
Everything else
The admin console, smart home, media, photos, passwords, audiobooks, monitoring
The router forwards no ports, so the public side only exists because the server opened a connection outward itself, and that connection only leads to the public site. The one thing that crosses over is my phone’s location report: the public site hands it straight to the admin console, which does all the checking. The admin console itself isn’t in the same container, let alone on the same route.
Every container except DNS, with the old image IDs written down first
Only if an update asked for one, and never mid-backup
A short test weekly, a full surface scan monthly
Restores every config backup to a scratch folder and checks it's really there
The rebuild, in the order the runbook insists on.
Fresh disk, fresh Ubuntu
From a USB stick
Pull the config back
With a read-only key that can't damage the backup
DNS first
Everything else resolves through it
Proxy and tunnel
The front doors, public and private
Apps and data
Each stack restored from its own backup
Check it's all back
A checklist, not a feeling
Target: back within a day or two, losing no more than a day. Films and TV aren’t in the offsite backup on purpose. The discs are on the shelf.
Wanating CMS Core marketing site.
A full-fibre line comes in through the router, which also does the firewalling. It's closed by default, and as it turns out I haven't opened anything (more on that below).
A two-node mesh covers the house for Wi-Fi. Anything that can be wired, is. The server, my gaming PC, the media streamers and the workstation where most of my real work happens all sit on a wired backbone instead of competing for radio. Smart-home devices, cameras included, get their own Wi-Fi, away from everything else. A camera doesn't need to phone home to a vendor's cloud to be useful to me.
Most people have a workshop. Mine is a small, silent box running Ubuntu, with a big external drive plugged into the back.
It started the way most of my projects start: as a place to find out how things work. Game servers on a spare PC in my bedroom. Then websites for the communities I played in. Then whatever I was curious about that month. It's still that. I build things here, break them, and rebuild them properly once I understand why they broke.
But somewhere in the last year it stopped being a toy. It now holds every photo I've taken, my whole ripped CD collection, my passwords, the smart home and the website you're reading. Every DNS lookup in the house goes through it.
So the question has changed from "can I get this working?" to "what happens when this breaks, and would I even know?" This page is my best answer so far.
The server is a Dell Wyse 5070. It's a thin client: the small, fanless box that sits on an office desk and shows someone else's computer on a screen. It was never meant to be a server, which is exactly why I like it. A four-core Celeron, 16GB of RAM, no fan, and very little power drawn for something that never switches off.
It isn't powerful, but it doesn't need to be, because almost everything it does is waiting: for a request, for a sensor to change, for 2am. The one heavy job, transcoding video for Plex, goes to the small Intel GPU built into the chip, which does it far better than the CPU could.
Two drives. A 512GB SSD holds Ubuntu and every container's own state. An 8TB USB drive holds the media, the photo library and this site's files. Everything runs in Docker, one Compose stack per folder, so each service can be understood, updated, backed up and rebuilt on its own.
This is the decision everything else rests on. The router forwards no ports at all. The one way in from outside is the router's own VPN, and it wants credentials before it says anything useful.
So how is this website public? The server runs a Cloudflare Tunnel connector, which dials out to Cloudflare and holds that connection open. Cloudflare handles the public DNS and the certificates, and sends requests for wanating.uk (and the three product domains that share its app) back down the tunnel. The tunnel leads to exactly one thing: the public site.
Everything else, I reach over the router's VPN. Once I'm on it, Pi-hole answers for private names that only exist inside the house, with no public DNS records at all. A reverse proxy puts every service behind proper HTTPS with one wildcard certificate. Plex's own remote access is switched off, so even films on the train come through the VPN.
Home Assistant used to be the exception. It had a public hostname so the phone app could report my location from anywhere. Once my own companion app took over that job, the public route went, and Home Assistant went private like everything else. It's one less thing I have to think about.
Nothing clever here, just a few dull rules I try to stick to everywhere:
In September I sat down and audited the whole thing as if it belonged to someone I didn't trust. It was humbling. The most embarrassing find: the internet-facing container had been handed every secret on the server (the session key, the backup keys, the database password), because it loaded the same settings file as everything else. It never read any of them, but it had them all the same. Now each container gets a file with only its own keys, and the public one gets an explicit allowlist of four.
Backups help after something's gone wrong. I'd rather know before.
Both drives are checked every hour. The media drive is healthy, but it parks its heads nearly 30 times an hour, a very keen power-saving habit of this particular WD drive, and it's done that over 335,000 times. It's rated for at least 600,000. I tried to calm it down and found the USB enclosure won't pass the right commands through to the drive. My first thresholds were twitchy: a warning at 450,000 and "buy a new drive now" at 550,000, before it had even reached its minimum rating. Head parking is wear, not a sign of failure, so now it's a note at 600,000, a nudge to plan a replacement at a million, and never a reason to panic-buy.
The SSD taught me something about alerting, too. The first version warned whenever that error count was above zero. That meant a permanent warning, one I'd soon have learned to ignore, and it would have hidden the one change that mattered. Now each drive has a baseline, and the alarm is for new damage. Each kind of drive has a written list of replacement triggers, in two strengths: "buy now" for a drive that's actually failing, "plan one" for one that's just wearing. That way the decision gets made calmly, rather than at midnight.
Beyond the drives, an outside service expects a ping from the server every five minutes and tells me if it stops. If the house goes quiet, something outside the house notices. A watchdog restarts any container that fails its own health check. Updates run weekly rather than nightly, so a bad release gets a week to show itself, and the old image IDs are written down first so rolling back is quick. The exception is DNS. Pi-hole is updated by hand, because when it goes down, the whole house notices.
All of it rolls up into the admin console behind this site, and into a widget on my phone's home screen. I tend to hear about a problem before I'd have gone looking for it.
For years my disaster recovery plan was "I could rebuild it." Then I looked at the SMART data for the SSD that holds every container's state. At some point in its past, it had logged 21 uncorrectable errors and 40 unreadable sectors. It isn't failing now, and nothing has changed since I started watching. But an SSD with that history can go without warning, and I realised "I could rebuild it" wasn't really a plan.
So now there is one:
Some things are left out on purpose. Films and TV aren't in the offsite backup: the discs are on the shelf, and re-ripping is cheaper than storing terabytes in the cloud. Home Assistant's sensor history isn't either. I'd miss it, but not enough to pay to store it.
It's easy to write about the plumbing and forget why it exists.
Every photo I've taken now lives in Immich on my own disk instead of someone else's cloud. Moving over a decade of them out of iCloud was a project in itself, and the part I'm proudest of is the boring bit at the end, restoring them from the offsite backup to prove it all worked.
My CD collection is fully ripped, with the discs kept alongside (the same physical-plus-digital thinking behind Armarium), and Plex serves it. Audiobookshelf does the same for audiobooks and keeps my place across devices. Home Assistant runs the lights, climate and sensors, and drives the cameras' privacy mode, which switches them off when someone's home.
And then there's this website and the private console behind it, which has grown into its own story: how this site works.
It's still a workshop really, not an enterprise environment and definitely not a hardware showcase.
What has changed is that I now build as if it's going to fail, because one day it will. Next on the list is a bigger drive for the media, with the current one becoming a second local backup, so the important things exist in three places.
The hardware will change again, and so will the software, and I'll probably still be poking at it.