I read 128,000 lines of access logs. Turns out we’re very popular.
People say homelabs don’t need real security. It’s just a media server. A photo gallery. A chatbot that teaches English to a six-year-old. Who’s going to attack that?
I read 128,530 lines of access logs to find out.
144 unique attackers. Over 20,000 requests from a single subnet. Someone had probed us for database credentials, medical imaging data, cryptocurrency nodes, and enterprise admin panels — on a network whose most sensitive asset is a bear named Benny who helps a first-grader practice the past tense.
I’d say we’re flattered, but Benny doesn’t know what a port scan is, and I’d like to keep it that way.
The top performer was a seven-machine cluster working from one address block. Twenty thousand requests across two weeks, rotating through every hostname we have. They tried .env, .env.bak, .env.backup, .env.production, .env.local, .env.development, .env.staging, and — for the truly optimistic — .env.save.
Our .env.save contains the media server’s API key. The one printed in the setup guide. On the project’s public GitHub page.
What did they actually get back? The same HTML page. Every single time. Our services use single-page apps that serve their homepage for any URL they don’t recognise. So this seven-machine operation spent two weeks downloading the same login screen six thousand times, each response catalogued as a freshly discovered secret.
Six thousand identical secrets. Not one of them opened anything.
A vulnerability intelligence platform saw the 200 OK on a path called /swagger-ui.html and indexed us as hosting exposed API documentation. We’re in a database now, somewhere. Filed under “exposed services.” A photo gallery and a children’s English tutor — exposed.
Then there was the nine-minute burst where two coordinated subnets probed our default host for — deep breath — remote desktop, internet telephony, Windows file sharing, a database wire protocol, networked storage, a message broker, directory services, medical imaging, industrial automation, chat servers, cryptocurrency peering, another database, a memory cache, and a key-value store.
On port 80. Of a homelab that streams cartoons to the living room TV.
I don’t even know what half of those are. But apparently we might be running a hospital imaging system and a Bitcoin mine on the same port, so it was worth checking.
The real punchline wasn’t the attackers. It was us.
I already had a security monitor. A workflow running every five minutes, checking the logs, auto-banning anyone crossing the line. Thirteen days on the job. Zero log lines processed.
The command used a wildcard. The tool that runs it doesn’t expand wildcards. So every five minutes, it asked for a file literally named proxy-host-star-access.log, received nothing, reported success, and went back to sleep. For thirteen days.
The attackers had seven machines. We had a guard dog that barked at a wall. Reliably. On schedule.
It’s fixed. A proper daemon now watches every log line in real time. Five attack patterns in ten minutes — thirty-day ban. Three knocks on the default host without a valid name — thirty-day ban. A hundred and twenty IPs from the audit got a permanent entry on the guest list. The one that says don’t come back.
“Just because you’re paranoid doesn’t mean they aren’t after you.” We proved both halves in one evening. The attackers were real. Our security monitor was imaginary.
Next time someone says a homelab doesn’t need real security, I have 128,530 lines that disagree.