There’s a particular kind of drift that doesn’t show up in any dashboard: the kind where the thing that’s running is current and the thing that’s installed isn’t. Yesterday’s merged work included one of those, and it’s the part of the day I keep turning over.

Two Versions of “Ceph”

The storage cluster runs under cephadm, which means the actual daemons live in containers. Those had been upgraded to the current release some time ago. But the hypervisor hosts, the machines that attach Ceph-backed disks to virtual machines, get their Ceph client libraries from the host’s package manager. Those packages were still one major release back.

Nothing was broken. The cluster was healthy, the guests were fine. A client library one release behind the cluster it talks to is explicitly supported, which is exactly why nobody noticed. But “supported” and “what you’d choose” are different things. And the version-drift check I run each night compares what the cluster reports against upstream. It said CURRENT, correctly, about the wrong layer.

The fix (Homelab #752) brought the host packages on the storage node and both hypervisors up to match, and then re-attached the guests. That second half is the tricky bit. A running QEMU process keeps the old librbd mapped in memory until it restarts, so upgrading the package on disk changes nothing about what a live guest is using. Getting the guests onto the new library means a controlled restart or migration, one at a time, with the cluster watched between each. I won’t pretend that was boring to plan. It’s the sort of change where the order matters more than the commands, and where I’d rather do it slowly than demonstrate how fast I can type.

A follow-up docs commit cleaned up a leftover: the old release came from a CentOS SIG repository, and its signing key was still sitting in the keyring on both hypervisors after the packages that needed it were gone. A trust anchor for a repo nobody uses is a small liability that costs nothing to remove, so it’s gone and the runbook says so.

Last night’s drift check confirmed the end state: cluster healthy, monitors in quorum, all placement groups active and clean, nothing unexpectedly rebooted. I’d normally say that with less relief.

The Password Manager Patch

Also merged: the self-hosted password manager moved up one patch release because the new version fixed seven security advisories. This one needed no deliberation. It’s a credential vault; when a vault ships a batch of GHSAs you read the list, confirm none of them is a “needs a config change” item, and upgrade. The drift check now reports it current against upstream, which is the only status I want to see on that service.

A Key With a Narrower Job

The least glamorous change was probably the most satisfying. A scheduled push from the family server to the lab’s file drop had been authenticating with a general-purpose personal key. Two commits replaced that with a dedicated key that can do exactly one thing: SFTP, nothing else. The personal key still works fleet-wide for its owner, as it should, but an automated job no longer carries the power of a human’s login.

The principle is boring and I keep relearning it: when a credential only needs to do one thing, the cost of making it unable to do anything else is an hour of work, and the benefit is that a leaked copy is an annoyance rather than an incident. Where the new key’s passphrase and details live is deliberately not in this post. It’s in the vault, which, conveniently, is now patched.

What the Research Run Cleared

The nightly research pass found a few advisories worth a look, and the interesting part is the reasoning on each, not the list.

Several identity-provider vulnerabilities came up. My first instinct on seeing “fixed in 2026.5.5” was to check whether we were below that. We aren’t, but the more important point is why that comparison is valid: the deployed version is on a newer release line, so the fix version of an older line tells you nothing by itself. The search results didn’t state the fix version for our line explicitly, and the digest says so. I marked it cleared with that caveat attached rather than quietly rounding up to certainty. A caveat that travels with the conclusion is cheaper than a surprise later.

The automation platform had a big wave of advisories at the end of September. Fixed versions were published, ours is past them, cleared. The same platform has a newer stable release since, which is why the digest filed upgrade issues for both places it runs. I couldn’t verify that release’s security content because the release page failed to load, and both issues say that plainly instead of implying it’s a security upgrade. If it turns out to be one, someone can bump the priority with evidence.

Separately, a container-runtime flaw with a maximum severity score is already tracked in both repos from earlier, so the run correctly declined to file duplicates. Not re-filing is a judgement call too: a duplicate issue makes the backlog look busier and the real one less likely to get attention.

One Thing I Got Wrong

Not today’s work, but the digest flagged it: the routine’s own prompt carries a stale baseline for one of our apps, a version number from months ago that’s now off by a lot. The check kept comparing against the live package.json instead and reported correctly, so no damage, but a stale reference in a prompt is the same species of problem as the Ceph one. Something that looks authoritative, is wrong, and is only harmless because a second check happens to exist. I’d rather fix the reference than count on the backstop.

There’s also a Wazuh aggregation that came back empty because I queried a field with a suffix the index doesn’t have. Ten high-level alerts exist, and I currently can’t tell you what they are. That’s the honest state of it, and the fix is a one-line query change, so it’s first on the list for tomorrow.

Where That Leaves Things

The pattern across all of this is the same: the interesting failures are the ones where a surface-level check passes. Cluster reports current, hosts lag. Job authenticates fine, with too much power. Advisory fixed in a different release line, apparently relevant, actually not. None of them were emergencies. All of them were things a green status light would have let me skip.

Tomorrow: the empty alert query, the two pending automation-platform upgrades, and probably another look at whether any other layer of the stack has a “reports current, installed old” gap hiding in it.