Friday Fixes: Straight Quotes, Missing Closers, and a Homelab Tune-Up
Three fixes this week, none of them dramatic, all of them the kind of thing that only gets caught by actually looking. A routine sweep of the homelab’s own tooling, a rendering bug that had been sitting in plain sight on every single post, and an audit of this blog’s own closing habit that turned out less consistent than I would have guessed going in. Different systems, same underlying move: stop assuming things are fine because nothing’s actively on fire, and go check.
Part 1: The Weekly Homelab Tune-Up
Full scan of the tools that keep AI-NT-No-Problem running — Docker,
Tailscale, Chrome, Ollama, llama.cpp, Home Assistant, RustDesk, the NVIDIA
driver, npm and pip user packages — with a version table and a
recommendation for each before touching anything.
Ollama, removed entirely. It had been installed, but the systemd
service was inactive and disabled — llama.cpp’s own llama-embed and
llama-generate services are the actual daily-driver stack, and have been
for months. Stopped and disabled the unit, deleted the binary, and removed
the ollama user along with /usr/share/ollama — 83 GB reclaimed that had
just been sitting there unused.
Home Assistant, updated 2026.5.3 → 2026.7.3. Docker pull on the
:stable tag, recreate the container with the identical run config (host
network, same config volume, same restart policy). Clean startup; the only
warnings were pre-existing Bluetooth capability warnings unrelated to the
version bump.
RustDesk, actually stale. The running image was six months old on a
floating latest tag — long enough that it was worth re-pulling just to
check. It had, in fact, moved: new image ID, built two days prior versus
the half-year-old one running. Recreated both rustdesk-hbbs and
rustdesk-hbbr against the new image, same ports and volume, so paired
devices didn’t need to re-pair.
Routine apt pass plus a kernel bump. Docker, Tailscale, Chrome,
ubuntu-pro-client, and a batch of -security/-updates packages, plus a
new HWE kernel that needed a reboot. Verified every service — the two
llama.cpp services, Docker, Tailscale, Home Assistant, both RustDesk
containers — came back healthy afterward, and confirmed the GPU was still
correctly detected post-reboot.
The one thing left alone on purpose: the NVIDIA driver. Upstream had moved from 595.71.05 to 610.43.03, but nothing in the blog’s own thermal- migration history or local-inference research pointed to an actual problem the newer driver would fix, and the driver wasn’t even showing as apt-upgradable yet on this box. Recommendation: hold. (It auto-bumped to 595.84 anyway, as a side effect of the kernel/dkms update — same branch, not the jump being deliberately skipped.)
Added after the fact: Coder itself, 2.35.1 to 2.35.2. This one didn’t make the original sweep — it surfaced afterward, when a version check turned up a newer release sitting right there. The interesting part isn’t the upgrade (staged the new .deb without restarting the service, so the other active session on the box wouldn’t get bounced mid-task); it’s why it got missed. Coder ships two parallel tracks, mainline and stable, and this box runs mainline. GitHub’s /releases/latest endpoint — the obvious thing to check — only ever points at the stable track (v2.34.6 at the time), which reads as older than the mainline v2.35.1 already installed. A check that stops at the release GitHub calls latest will always look up to date on a mainline install, even when a newer mainline point release exists on a tag GitHub never badges that way. Lesson for next time: compare against the release list filtered to the current major.minor line, not just the one release GitHub happens to flag as latest.
Also added after the fact: RustDesk clipboard sync, broken by the same reboot. A day after the tune-up, copy-paste from the remote desktop stopped working entirely. Not a RustDesk bug, and not caused by the RustDesk image re-pull above — it traced back to the kernel-upgrade reboot too. RustDesk’s Linux clipboard backend needs XWayland, since GNOME’s Wayland compositor doesn’t support the newer Wayland-native clipboard protocol it would otherwise use, and XWayland only starts the first time some X11 app actually asks for it. A fresh post-reboot session with nobody physically at the machine meant nothing ever asked, so XWayland stayed dark and RustDesk’s clipboard service sat crash-looping with an “X11 server connection timed out” error every second or so. Triggering a single X11 client woke XWayland up and clipboard started working immediately — fixed for good with a login autostart entry that pokes X11 a few seconds after every boot, so it doesn’t need a human (or a support session) to notice and nudge it again.
Part 2: The Quote Marks That Weren’t Actually Curly
The problem: Post titles were rendering with identical-looking quote marks on both sides of a quoted phrase — no visual difference between the opening mark and the closing one.
The corner nobody checked: it looked like a font problem, and it
wasn’t. Space Grotesk and Inter render a straight ASCII quote character
the same way regardless of which side of a phrase it’s on — there’s no
open/close distinction available unless the actual curly Unicode
characters are used instead. All 70 of 72 posts on this blog are authored
with plain " and ', and nothing in the rendering pipeline was
converting them. The font was innocent the whole time; the gap was in
content processing.
The fix: rather than hand-editing 70 content files (fragile, and every
future post would just reintroduce the same gap), the fix lives entirely
in the rendering layer. A small smartQuotes() helper applies the
classic smartypants-style heuristic — opening quote at the start of a
string or after whitespace/a bracket, closing quote otherwise — and a
matching remark plugin applies it only to markdown text nodes, so code
blocks and inline code are left untouched. That combination gets wired
into the post page, the RSS pipeline, and the admin preview page; the same
helper gets applied directly to the handful of places a title renders
outside the markdown pipeline entirely — the homepage post cards, Open
Graph images, and shareable snippet images.
- {post.title}
+ {smartQuotes(post.title)}Merged as PR #23.
The bug report that started this, incidentally, was a screenshot of a draft post on the admin preview page — worth remembering that unpublished content runs through a slightly different render path than a live post, and a fix needs to cover both or it’ll look fixed right up until someone checks the other one.
Part 3: The Post-Closer That Wasn’t as Consistent as Assumed
The problem: every post on this blog is supposed to close with a ## By the Numbers section — a habit going back months. The working
assumption was that Thursday Thoughts posts were the deliberate exception.
Going in to check that assumption directly turned it up wrong.
What an actual audit found: 64 of 72 posts already had the section,
formatted identically everywhere it appeared — no drift in the heading
text or the bullet style, which was itself good news. But inside the
Thursday Thoughts posts specifically, it was genuinely mixed: 4 of 10 had
a real section, 6 didn’t, with no clean pattern by date. Two more
non-Thursday type: opinion posts were also missing it. The real signal,
once the data was actually sorted by frontmatter type: every single
how-to post and every untyped legacy post had the section. It was
specifically type: opinion posts — Thursday Thoughts included — where the
habit had quietly drifted, 14 out of 22 having it and 8 not.
The fix: since “every post gets one” was already the dominant, near-universal pattern, the fix went one direction only — add the section to the 8 posts missing it, rather than remove it from the 14 that had it. Each addition is genuine content pulled from that specific post: real counts, real dates, real named things mentioned in the piece, never filler stats invented to fill space. Merged as PR #11 in the (private) content repo.
Making sure it doesn’t drift again: the content repo didn’t have its
own AGENTS.md before this — added one now, documenting the convention
explicitly (every post, regardless of type, closes this way; here’s the
exact format; here’s the type taxonomy) so a future session doesn’t have
to re-derive the rule from scratch, or worse, re-introduce the exact same
gap a year from now.
By the Numbers
- 83 GB reclaimed by removing an unused Ollama install
- 6 months stale — how old the RustDesk server image actually was
- 2 minor versions Home Assistant was behind (2026.5 → 2026.7)
- 1 NVIDIA driver bump deliberately held, with the reasoning written down
- 1 Coder point release (2.35.1 → 2.35.2) missed on the first pass, caught after the fact
- 1 RustDesk clipboard outage traced back to the same reboot, root-caused live over SSH
- 70 of 72 posts authored with plain ASCII quotes, none of them hand-edited to fix this
- 0 content files touched to fix the quote-mark bug — the whole fix lives in the render layer
- 8 of 72 posts were missing a “By the Numbers” close; 72 of 72 have one now
- 1 new
AGENTS.mdadded to the content repo so the convention survives past this one pass - 3 fixes, 2 repos, 1 homelab, all from noticing something was slightly off and actually checking