← The Journey

The File That Was Actually Being Read Was Three Layers Down

Homelab 2026-08-24 · Monday · 12:00 AM 5 min read 90% AI Eric Li

The day's stated job was moving secrets out of plaintext files and into a vault, one consumer at a time. Two of six cutovers finished clean, one was blocked because the service behind it turned out to already be retired, and one is staged but unprovable until a placeholder key gets replaced. None of that is the interesting part. The interesting part is what happened when a straightforward integration fix refused to take three times in a row, and what turned up on the side while thinking about locking down a storage target that had never needed a password before.

Both stories have the same shape. Something looked broken in an obvious way, the obvious fix didn't work, and the reason turned out to be one level away from where I was looking. In the first case that level was a file. In the second it was the difference between a cause and a symptom that happens to arrive at the same time.

Three files, and only one of them mattered

The network-controller integration was returning 403 and its tools were unreachable. First fix: edit the config file, restart, still 403. Second fix: same file, double-check the syntax, still 403. Third attempt at actually diagnosing it found that the wrapper responsible for loading that config was never being invoked at startup at all — the file I'd been editing for two rounds was not in the path that mattered. Editing the right content in the wrong file fails identically to editing the wrong content. There is no error for it. The process starts, the tool is unreachable, and nothing points back at the file you should have touched.

The actual authoritative source was a third location: an inline configuration block cached inside a plugin file, sitting ahead of both the marketplace copy and the config I'd been staring at. It had never been patched, because nobody had reason to believe it existed as a separate thing to patch. Once I patched that block directly, the 403 went away.

Then login still failed, with an empty password. Not a wrong password — empty. A cache-warming step that ran earlier in the same startup sequence was reading from stdin to prime itself, and it consumed the session handshake before the credential read got a turn at the same stream. The password was correct and was never delivered. Fixed by reordering so the cache-warming step stops reaching for stdin before the handshake happens, then verified end to end with the credential fetch showing up in the audit log.

The lesson is not "check your config." It's narrower than that: when a fix doesn't take, the question isn't whether the fix is right, it's whether the file you just edited is the one the running process actually reads. Three passes at the same file will look exactly like three failed fixes even when the fix was correct the whole time.

The outage that had been running for a month

Planning authentication for the backup storage target meant looking closely at its recent logs, which is how a bigger problem turned up sideways: the NAS drops its network link for 60 to 90 seconds at almost exactly 07:02 and 11:49, every day. Seven days of logs showed it at both times on every single day. A month-old log sample showed the same pattern already established then. This has been happening the whole time and nothing was watching for it in a way that would have surfaced it.

My first read was that the DHCP renewal was failing and that was the cause — the timestamps line up with lease-renewal attempts. That's backwards. The interface was already unreachable when the renewal fired; the renewal failure is a symptom logged a beat after the real event, not the trigger for it. I checked the other four machines on the same network for any link-state event at either time and found none, which rules out the switch or the upstream side and puts the fault on the NAS itself. It rebooted three times in one day during this, independently confirmed each time, against a box that normally stays up for days to weeks without being touched.

Cause unknown. The kernel logs that would show what's actually happening to the interface are root-gated, and there's no root access on this appliance, so the honest status is that the mechanism stays unknown rather than filled in with a plausible-sounding guess. What I did instead was make the daily glitch stop being able to hurt anything downstream: added nofail to the mount so a dead network share can never hang a boot, and changed the fsck pass from 2 to 0, since a network-backed filesystem shouldn't be checked at boot in the first place. Verified with findmnt --verify against a hashed backup of the original.

The decision that came out of this matters more than the mitigation. I was in the middle of planning to add authentication to that storage target, and the temptation after finding an instability bug is to add a security layer anyway, since you're already in there. I didn't. The sessions are dropping because the appliance loses its network link, not because anything is unauthenticated. Adding a password layer on top of an interface that vanishes twice a day would add a new failure mode without touching the one that's actually firing.

What else turned out to be wrong on paper

Separately, five read-only agents checked seventeen documented claims about the lab against the running systems. A backup timer documented as present did not exist. A service documented as running had already been retired. Monitors documented as healthy were flapping. None of these were dramatic on their own, but seventeen claims producing several outright false ones is a reminder that a plan's premise is not a fact just because it's written down — it's a claim from whenever it was last checked, and every day since then it's had a chance to go stale without telling anyone.

A near-miss from the same day is worth one line: an agent was dispatched to make a config change at 01:04, straight into a documented no-touch window that runs until 05:30 for the nightly backup jobs. It read the plan, declined to touch anything, and reported back instead. Nothing broke, and the reason nothing broke is that the check happened before the action rather than after.