a home server that runs without me
in september 2026 i had seventeen days before leaving home for college, two thousand kilometres away. the plan was simple to say and annoying to do: build a server at home that runs on its own, survives power cuts, and lets me leave google behind. this is how it went, mistakes included.
the brief
the constraints shaped everything. there's no ups, so every power cut is a hard power-off. the home fibre line has a public ip that changes whenever it feels like it, and the isp blocks inbound web ports. and once i left, the only help near the box would be my mum, guided over a camera, pressing a power button.
so every decision had one test: is this safe to make from two thousand kilometres away? that question ended up mattering more than any spec.
the parts, and the parts that changed
i picked an intel core i9-14900k for the core count and the built-in graphics, 32 gb of ram, a 1 tb nvme for the system, and a 2 tb nas hard drive for data.
then the orders fell apart. the motherboard and ram were delayed, so i cancelled them and bought replacements at a local shop the same day. a spare board i had turned out to be the wrong socket. the ssd order was cancelled too. a day before the build, half the parts list had changed. lesson one, before a single screw: when the deadline is close, buy locally and stop waiting on couriers.
build day
build day was the second of october. i checked the socket pins with a torch, set the cpu straight down, and put the ram in the two slots the board marks as first. i made one wiring mistake: the front audio plug went onto the front-panel header, which it physically fits. a photo caught it before power-on. i photograph every small header now.
it posted first try. then i noticed the cpu sitting at ninety degrees doing nothing. the aio's lights were on, so it looked fine, but the pump was on a header that never powered it. i moved it to the cpu fan header at full speed and idle dropped to thirty-four. a full memory test came back with zero errors. lights prove nothing; rpm does.
the real bottleneck wasn't the cpu
stress testing showed the limit was the motherboard's power stage, the vrm, not the chip. at 180 watts it hit 105 degrees in fifty-five seconds while the cpu itself was perfectly happy. a budget board under a flagship cpu will do that.
so i capped the chip at 90 watts sustained and zip-tied a spare case fan right over the power stage. thirty minutes at full load, side panels on: flat at sixty-seven degrees. it's not elegant. it works, and it's measured. this box spends its life at light load anyway, so the cap costs me almost nothing i'd notice.
proxmox, and always two ways in
proxmox ve went on the nvme. password logins went off. tailscale gives me private admin access from any network. since the isp blocks inbound web ports, public apps leave through a cloudflare tunnel, with cloudflare access in front of anything sensitive.
the rule i care about most: there are always two independent ways in. tailscale first, a cloudflare-protected ssh path second, and later a hardened direct ssh path as a third. i never change two of them in the same session. and any risky network change runs behind a ten-minute dead-man switch that undoes itself unless i log back in and cancel it. if i lock myself out, the box lets me back in by itself.
built for power cuts
with no ups, a power cut has to be a normal event, not an incident. the bios powers the box on when mains comes back. the kernel reboots itself on a panic or a hang, because this board's hardware watchdog turned out not to work. i only learned that by crashing the kernel on purpose while i was still home to press reset. every disk is ext4 with safe caching, every database has fsync on, and a small guard restarts tailscale if it gets stuck during boot.
cold boots still took up to thirteen minutes, and nothing was technically wrong. the kernel log explained it: every container disk had multi-mount protection on, which waits about forty-two seconds after an unclean stop, one container at a time. i turned it off, reordered the boot, and pulled the plug twice in a row, the second time in the middle of booting. twenty-two guests came back in fifty-three seconds.
leaving google
this was the part i'd been waiting for. my photos went into immich: 3,471 photos and videos, albums included. drive, notes and an old hard drive went into nextcloud: 166,685 files, 147.6 gb. i checksum-verified every file. zero mismatches.
but data only counts once a restore works. every night the guests are backed up to the hard drive, and photos and files get a second, deduplicated copy with restic. at eight every morning a check pushes an alert to my phone if any backup is older than a day. i've tested restores, not just assumed them. "configured", "test-restored" and "actually backed up last night" turned out to be three different states, and i had to learn that the hard way.
what runs on it
today the box runs about thirty guests: photos, files, a password manager, a document archive with tamil and hindi ocr, media with live tv, a private git server, automations, speed tests, and a code editor in the browser. none of them is special. each one goes through the same crash-safe checklist before it counts as done.
it watches itself
i can't walk over and look at it, so it has to tell me. prometheus and grafana track temperatures and power, loki collects logs from every guest, and uptime kuma checks each app.
but a dead server can't report its own death. so a small aws lambda checks it from the outside every minute and runs a public status page. a power cut now sends exactly two pushes to my phone: down, and back. that's the whole alerting philosophy: if a push doesn't need me to do something, it shouldn't exist.
building for other people
once it was stable, i started building on it for others. api.dharun.dev serves free, open apis for indian developers: pincodes, ifsc codes, panchang and more. every push to main runs ci and ships a release. the server pulls it, health-checks it, and rolls back on its own if it fails.
i also built a honeynet: a virtual machine on its own sealed network running eleven honeypots, an ai-generated fake shell, and a real operating system behind a proxy that resets every six hours. attack logs flow into grafana, and repeat attackers get banned at the edge. it's the most fun thing on the box and the one i trust least, which is why it lives behind its own wall.
what broke
plenty. my ai assistant once deleted the server's /dev/null with a stray filler command, and ssh died with it. only the physical console could fix it. from punjab, that would have meant asking my mum to cut the power. now a guard blocks destructive commands, and a timer recreates the file within thirty seconds if it ever disappears again.
turning on the firewall silently broke tailscale access to the guests, and my rollout test missed it because i never tested from a tailnet device to a guest. a power cut seconds after a config write left a dns file empty. and the isp router quietly dropped its port-forwarding rules until it was restarted. every one of them got a fix, and a test that would have caught it.
how i ran it
i ran the whole project with claude code as a pair sysadmin, in a private repo that is the source of truth for the box. every change gets a changelog entry with a rollback. anything that could wipe data, cut remote access, or expose something to the internet needs my explicit yes. and every mistake becomes one line in a lessons file. there are about a hundred and fifty of them now. that file is the most useful thing in the repo, more than any config.
leaving home
on the twenty-first of october i was in my hostel in punjab, two thousand kilometres from the box. the drill passed: every app and every admin path, from hostel wi-fi. in the week around the move it took several real power cuts, and came back on its own every time.
one box, built in a month, that runs without me. what i actually learned isn't any one tool. it's that "works" is the easy part. the hard part is "keeps working when nobody is there", and you only get that by breaking it on purpose while someone still is.
written by dharun ashokkumar · more reflections