Blog

  • Adding images to the pipeline: an image connector, MCP, and one unverified email

    Adding images to the pipeline: an image connector, MCP, and one unverified email

    The last post covered getting Claude write access to this site through an MCP plugin. The next obvious gap was images: every post here has been text-only, mostly because I never bothered setting up a source for them. An image-search service has an MCP connector for exactly this, so I hooked it up. It did not go straight through.

    Connected, but not really

    The connector showed as installed almost immediately, but calling it just returned a generic could not connect error. No useful detail, just a dead end. Turned out the OAuth handshake was stalling because my account’s email had never been verified. Not something the connector UI surfaced. I confirmed the email, reauthorized, and the connector came back with an actual checkmark this time.

    First real run

    With the connector live, the tools showed up as expected: search photos, search illustrations, search collections, search users. I searched for something generic and homelab-appropriate, a server rack, and picked a result under a standard license rather than one of the entries demanding a specific attribution link back to the photographer’s site.

    Pulling it into the media library with the upload-from-url tool failed on the first attempt: file type not allowed. The service’s image URLs do not end in a file extension, they are just an ID with a query string, and the upload tool appears to infer file type from the URL path rather than the actual content type. Passing an explicit filename with a .jpg extension fixed it immediately. Second attempt uploaded clean, alt text and all.

    Where that leaves things

    Small saga, but a real one: a connector that looked broken for an infrastructure reason that had nothing to do with MCP at all, and an upload tool that needed a nudge on file naming to work with an external image host. Both are now filed away as known steps rather than mysteries. Image sourcing is officially part of the pipeline.

  • Tomb Raider King: Nine Episodes In Verdict

    Picked this one up mostly on the “not much else airing” logic again. It’s the one everyone’s calling Solo Leveling-adjacent: regression, revenge, magic relics, a protagonist who already knows how the next fight goes. Nine episodes in (three to go, finale’s the 23rd), here’s where I’ve landed. Watched dubbed, for what it’s worth.

    The Solo Leveling comparison. It’s uncanny how much this feels like Solo Leveling, and I can’t fully put my finger on why. The systems are different (relics vs. leveling), the setting’s different. But something about it lands the same, and my best guess is it’s the protagonist: same flavor of quiet, already-knows-how-this-goes overpowered lead who the show builds everything else around. Once you notice it you can’t unnotice it.

    The premise. Jooheon dies in the present, gets sent back to before “Tombs” and “Relics” started popping up worldwide, and spends his second run stacking advantages he shouldn’t have yet. It’s a clean enough hook on paper. The show just doesn’t do much with it beyond “he already knows, so he wins.”

    The Jooheon problem. This is the actual issue, not the premise. He’s not an underdog with foreknowledge, he’s just better than everyone at everything, and his stated motivation is closer to “be pettier than my past self” than anything resembling a goal. There’s no fight in this show where I’ve believed for a second he could lose. Once or twice that’s fine. Nine episodes of it gets old.

    Animation. Studio EEK is competent but not doing anything that’ll stick with me. Fights are readable, nothing more. Not a Heavy Knight-tier visual selling point here, it’s coasting on the source material’s popularity, not the craft.

    The dub. Cast is solid enough, but there’s one genuinely annoying quirk: the glowing status-screen pop-ups (the game-like ability notifications Jooheon interacts with constantly) don’t get translated into English. So even watching dubbed, you’re stuck flipping subtitles on anyway whenever one of those matters. A couple of reviews also flag stiff facial animation and some inconsistent censorship as ongoing issues, for what it’s worth.

    Worldbuilding. Genuinely the more interesting part, when it bothers. The relic lore (the Crow being a betrayed god-relic, the whole “abuser of relics” angle) is more compelling than the revenge plot wrapped around it. I’d almost rather watch the show about the relics than the show about Jooheon.

    Where it’s landed for me: comfortable background watching, not appointment viewing. I’ll finish it since it’s short and there’s nothing else on, but I’m not champing at the bit for episode 10.

  • News Roundup: August 27–September 6, 2026

    A quieter week than the last one, but still a few things worth patching for: a fresh WordPress migration-plugin bug with a genuinely clever exploit chain, a MikroTik security release that’s light on details, and a heavy batch of critical Cisco advisories.

    • All-in-One WP Migration and Backup patches a second-order SQL injection (CVE-2026-19949, CVSS 8.8) affecting over 3 million sites. The exploit chain is worth knowing about even if you don’t run this plugin: an attacker submits two trackbacks containing a trailing backslash and a payload URL, which the plugin fails to sanitize; once an admin exports and re-imports a site archive, that unsanitized input gets promoted into executable SQL, leaking the plugin’s secret key into a public comment. From there, an unauthenticated attacker can import a crafted archive containing a malicious must-use plugin for full RCE. Multi-step, but entirely unauthenticated end to end.
    • MikroTik shipped RouterOS 7.24.2 (stable/testing), 7.23.4 (long-term), and 6.49.21 (legacy) on September 3 as “important security updates,” deliberately withholding vulnerability details for now to give admins time to patch. Worth noting: this release adds a “Flagged” device status that RouterOS will set automatically if it detects your device has already been compromised, check your Log for it after updating. Regardless of what the underlying bug turns out to be, this is a good week to confirm Winbox, SSH, and HTTP management access are firewalled to trusted hosts only.
    • Cisco’s September 2 advisory batch included two critical (CVSS 9.8) issues worth flagging if you’re running the affected gear: an IOS XR security hardening release covering seven CVEs, and a Nexus 9000 Series Silicon One remote code execution bug (CVE-2026-20212). Neither is reported as exploited in the wild yet, but a 9.8 on core routing/switching platforms isn’t one to defer.
    • WordPress 7.1.1 is scheduled as a bug-fix-only maintenance release for September 17, with RC1 landing September 10. No security fixes listed so far, so it’s a lower-priority update than the plugin issue above, but worth having on the calendar for the current WP 7.1 stack.
  • Turning Claude loose on this WordPress site with MCP

    Turning Claude loose on this WordPress site with MCP

    This site has 17 posts going back to 2021, most of them stale in one way or another. I’ve been meaning to clean it up forever and never did, mostly because “go read every old post and check if the commands still work” is exactly the kind of task I’ll put off indefinitely. So instead I hooked Claude up to the site via an MCP-enabling WordPress plugin and had it do the pass. Here’s what that actually looked like.

    What the connector exposes

    The plugin wraps the WP REST API as a set of MCP tools: create/read/update posts and pages, media uploads, categories and tags, users, comments, custom post types, block templates, the works. A few things about it were worth noting up front:

    • New posts default to draft status unless you explicitly ask for publish (and the plugin has a setting to force draft regardless, ignoring the model).
    • Every write goes through an audit log with before/after diffs, queryable by tool, user, or date range.
    • There’s a search-and-replace tool that edits one field of a post without resending the whole thing, which matters once posts have any real length to them.

    None of that is exotic, but it’s the difference between “AI with a REST API key” and something I was actually comfortable pointing at a live site.

    The first pass: just look at everything

    First thing was just inventory: list every post regardless of status, sort by last modified, get a feel for what’s actually here. That surfaced the two abandoned drafts, the real publish/draft counts, and one post with a modified date of today that I hadn’t touched. More on that below.

    Before touching anything live, I had it walk me through what “update the outdated ones” would actually mean in practice, and we settled on: publish updates as it goes, flag anything major instead of quietly deciding on its own, batch a few posts per pass instead of one at a time. That took about thirty seconds and saved a bunch of back and forth later.

    The bug hunting was the actually useful part

    I expected this to mostly be “note that Ubuntu 20.04 is EOL” busywork. Some of it was. But going through post by post also turned up things a simple find-and-replace never would have:

    • A post titled “ext4 partition resize” that actually used xfs_growfs, an XFS-only command, in the example. Wrong filesystem entirely.
    • A typo in a Perl JSON example (Dumepr instead of Dumper) that would have just thrown an error for anyone who copy-pasted it.
    • An InfluxDB install post pinned to a repo path and package name that don’t exist anymore — InfluxDB’s on 3.x now, not 1.x.
    • A Netplan example using gateway4, which still works but is deprecated in favor of a routes: block.

    Then there was the image problem. A couple of posts had images pointing at an internal IP address that obviously doesn’t resolve from the outside — that one was a clear miss on the initial pass, since it was flagged but not fixed. When I asked to go fix it, checking the media library against what was actually in the post content turned up more of the same pattern in another post that had looked fine at a glance: right domain, wrong protocol (http instead of https), on three separate images. That one hadn’t tripped any obvious “this looks broken” signal on the first read-through. It only showed up because the correction pass checked the actual media library records against what the posts referenced, instead of trusting the URLs looked plausible.

    The mystery edit

    One post showed a modified timestamp from minutes before the session even started. Instead of guessing, the audit log answered it directly: same OAuth client, a wp_update_post call, timestamped two minutes before the first tool call in this conversation. Almost certainly a separate session on my end, not a mystery. Being able to just check that instead of speculating about it is exactly the kind of thing the audit trail is for.

    Where I still drew a line

    Not everything got auto-corrected. The two genuinely stale drafts (a Wireguard setup and a Radarr install guide, both built around dependency situations that don’t exist anymore) needed real rewrites, not patches, so those got flagged and reworked from scratch rather than papered over. And a couple of posts got an editor’s note added rather than a rewrite, because I’d rather flag “this external tool has a history of going down” than assert something I can’t fully verify.

    Net result: a handful of real bugs fixed, several posts with honest editor’s notes instead of silently stale info, and a repeatable process for the next time this backlog builds up. Given this site is mostly an excuse to tinker with self-hosting and automation in the first place, that last part is the actual point.

  • XGS-PON vs GPON: What Actually Changed

    XGS-PON vs GPON: What Actually Changed

    If you’ve spent any time around FTTH deployments, you’ve heard both terms thrown around like they’re interchangeable steps on the same ladder. They’re related, but the differences matter for anyone speccing an OLT/ONU deployment or trying to explain to a customer why “fiber” doesn’t mean one fixed speed. Here’s the breakdown, grounded in the actual ITU-T recommendations rather than marketing copy.

    GPON: ITU-T G.984

    GPON (Gigabit-capable Passive Optical Network) is defined by the ITU-T G.984 series, first standardized in 2003. It’s asymmetric:

    • Downstream: 2.488 Gbps
    • Upstream: 1.244 Gbps
    • Wavelengths: 1490 nm downstream, 1310 nm upstream
    • Encapsulation: GEM (GPON Encapsulation Method)
    • Typical split ratio: 1:32, with 1:64 supported in later profiles
    • Reach: up to 20 km. ITU-T defines several optical budget classes (A, B, B+, C, C+), ranging from 5 dB up to 32 dB depending on class; B+ (13–28 dB) is the most commonly deployed

    GPON has been the dominant residential FTTH standard for close to two decades, and it’s still what most ONTs in the field are running.

    XGS-PON: ITU-T G.9807.1

    XGS-PON (10 Gigabit-capable Symmetric PON) is the direct evolution, standardized under ITU-T G.9807.1, approved in 2016. The “S” is the whole point: unlike the earlier asymmetric XG-PON1 (G.987, 10 Gbps down / 2.5 Gbps up), XGS-PON is fully symmetric:

    • Downstream: 10 Gbps
    • Upstream: 10 Gbps
    • Wavelengths: 1577 nm downstream, 1270 nm upstream
    • Encapsulation: XGEM
    • Typical split ratio: 1:64, extending to 1:256 in some deployments
    • Reach: 20 km physical reach in the base standard (up to 60 km logical/differential distance); longer physical reach (up to 40 km) requires the separate G.9807.2 reach-extension recommendation

    The wavelength choices aren’t arbitrary. GPON and XGS-PON were deliberately assigned non-overlapping bands so that both systems can run on the same outside plant simultaneously, using WDM coexistence elements at the OLT and passive filters at the ONU. That’s the mechanism that lets an operator light a GPON and an XGS-PON service off the same PON splitter without touching the fiber plant. G.984.5 defines the enhancement band reservations that make this coexistence possible, and it gets updated as new PON generations are added to the stack.

    Why It’s Not Just “Faster GPON”

    A few things get lost when this is summarized as “XGS-PON is 4x the speed”:

    It’s symmetric, GPON isn’t. GPON’s upstream is barely half its downstream. That’s fine for residential browsing and streaming, but it’s a real constraint for anything upload-heavy — backup traffic, cloud workloads, business customers pushing data outbound. XGS-PON removes that asymmetry entirely.

    FEC is mandatory, not optional. XGS-PON specifies forward error correction as a baseline requirement to hit its higher line rates reliably over the same class of optical budget GPON uses. This is part of why XGS-PON can extend split ratios and reach without a proportional jump in optical launch power.

    It’s designed to coexist, not replace overnight. Because XGS-PON was built to share ODN infrastructure with GPON via WDM, an operator can overbuild an XGS-PON overlay onto existing GPON splitters and migrate subscribers ONT-by-ONT rather than doing a fork-lift upgrade of the outside plant. That’s a meaningfully different migration story than earlier PON generation jumps.

    Practical Takeaways

    • If you’re still running GPON at scale, you don’t need to panic-migrate. It’s a mature, well-understood standard with an enormous installed base of ONT hardware.
    • If you’re planning new builds or serving upload-sensitive customers (small business, anyone doing real cloud backup), XGS-PON is the sane default now — the ONU cost premium has come down enough that it’s not the barrier it was five years ago.
    • Coexistence means the two aren’t mutually exclusive on the same PON. You can run both off one OLT chassis with the right optics and splitter plant, which is usually how operators actually do the transition.

    The short version: GPON and XGS-PON aren’t “old” and “new” versions of the same thing so much as they’re two standards deliberately engineered to run side by side on the same glass, with XGS-PON picking up the symmetric bandwidth and split-ratio headroom that GPON’s asymmetric design never had room for.

  • The Exiled Heavy Knight Knows How to Game the System: Halfway Verdict

    Picked this up mostly because there’s not a lot else airing right now. Another “disowned for the wrong class, secretly overpowered” isekai — a premise you’ve seen a dozen times if you watch this stuff at all. What’s carrying it: the animation and the lead.

    Animation. GoHands goes hard on motion — hyper-stylized, constant camera movement, a lot going on per frame. Critics are split hard on this: some found it flat-out hard to watch, others called it the one thing that stands out in a season with forty-plus similar shows. I land in the second camp. It’s doing the heavy lifting for a plot that isn’t reinventing anything.

    Elma. Tanks are usually the dependable background piece, not the lead. This show hands the archetype the hero slot, and it works — his refusal to accept the role everyone assigns him is doing more narrative work than the power-fantasy mechanics around him. Other coverage lands on the same read.

    Pacing. The real problem. Recaps are eating real runtime — one episode-level review flagged nearly four minutes of recap at the top of a single episode, straight-up filler. Episodes are already short; that’s a big bite. Multiple reviews call out the same structural issue: flashbacks and exposition interrupting momentum instead of building it. When the show does slow down for the right reasons — breather episodes, exploration over another fight — it’s clearly got more in the tank than the recap-padded episodes let on.

    Bottom line: great animation and a lead worth rooting for, propping up a familiar skeleton and a pacing problem that’s self-inflicted, not a content shortage. Trim the recaps in the back half and this could be one of the season’s better surprises.

  • News Roundup: August 19–26, 2026

    News Roundup: August 19–26, 2026

    This week’s roundup leans heavily on WordPress plugin security — three separate critical bugs landed in the space of a few days — plus the usual crop of vendor releases for the stack this blog runs.

    • Elementor Pro 4.2.2 fixes an unauthenticated RCE (CVE-2026-32475, CVSS 9.0) in the File Upload form module — any site with a published Elementor form containing a file upload field could have a PHP file dropped and executed with no login and no nonce. The researcher reported it in mid-July and Elementor had a fix ready within a day, but sat on the release for over a month. If you run Elementor Pro forms, don’t assume “recently patched” means “recently disclosed.”
    • Everest Forms patched an unauthenticated file-upload RCE (CVE-2026-19598) affecting over 100,000 sites — a second forms plugin with essentially the same class of bug as Elementor’s this week. If you’re running any form plugin with file-upload fields, this is a good week to audit which ones are actually still needed on your site.
    • TranslatePress 3.3.2 closes a critical, unauthenticated privilege-escalation bug (CVE-2026-19632, CVSS 9.8) that let attackers hijack administrator accounts outright. Combined with the two form-plugin bugs above, it’s been a rough week for WordPress plugin security specifically — worth a pass through your installed plugins if you haven’t updated in a while.
    • WordPress core 7.0.4 is a security-only release fixing an authenticated Author+ remote code execution bug (CVE-2026-65640) on sites running Imagick with Ghostscript. Narrower than the plugin bugs above, but nastier if you accept uploads from non-admin users — don’t wait on auto-updates for this one.
    • nginx 1.31.4 (mainline) / 1.30.4 (stable) patch a heap buffer overflow in the map directive’s regex handling (CVE-2026-42533) and a memory-disclosure bug in ngx_http_slice_module (CVE-2026-60005). Routine but not optional if nginx is sitting in front of anything.
    • Proxmox VE 8 reaches end of life on August 31 — no more security patches after that date, so this is the week to schedule the upgrade to VE 9 if you haven’t already. Separately, Proxmox VE 9.2 shipped official Arm64 support with full KVM/LXC/ZFS/Ceph parity, worth a look if you’re running or considering Arm homelab hardware.
    • Linux 7.2 is out, one of the busier kernel cycles on record at nearly 600,000 lines changed. Also worth noting: Fedora is taking the first concrete step toward restricting AF_ALG, the kernel’s userspace crypto API that’s been the source of several serious bugs this year — check whether anything on your boxes touches it directly before it starts getting locked down upstream.
    • MikroTik shipped RouterOS 7.24.1 stable, a maintenance release with bridge MLAG fixes on CRS8xx switches, VRRP-on-bridge stability improvements, and container host isolation hardening. If your MikroTik box is doing edge routing, it’s an easy hour of maintenance with real payoff.
    • InfluxDB 3.8 (Core and Enterprise) is about operational maturity rather than new query features — proper systemd units on the deb/rpm packages and an official Helm chart for running Enterprise on Kubernetes. Relevant if you’re on the TICK stack for homelab metrics and haven’t looked at the 3.x line yet.
  • Unlocking a Proxmox Guest VM Using the qm Command: A Step-by-Step Guide

    If you’re unable to start, stop, or migrate a Proxmox guest VM because it’s showing as locked, you need to clear that lock using the qm command before you can act on the VM. This usually happens after an interrupted backup, snapshot, or migration leaves a stale lock in place. This article walks through how to unlock a Proxmox guest VM. Skip to the bottom for a TL;DR.

    Step 1: Access the Proxmox shell
    You’ll need shell access to the Proxmox host. Connect over SSH, or use the “Shell” option in the Proxmox web interface for the relevant node.

    Step 2: Identify the guest VM ID
    Run qm list to see all guest VMs on the host along with their IDs and current status.

    Step 3: Check the lock type (optional but recommended)
    Run qm config <VM ID> and look for a lock: line in the output. This tells you what kind of lock is in place (e.g. backup, snapshot, migrate, rollback), which is useful context if the lock keeps coming back — it usually means the underlying job (a backup, for example) is still stuck or failing.

    Step 4: Unlock the guest VM
    Run qm unlock <VM ID>. Note that a locked VM typically can’t be stopped or started normally in the first place — that’s the point of the lock — so this is usually your first real action, not something you do after stopping the VM.

    Step 5: Start or stop the VM as needed
    Once unlocked, you can manage the VM normally: qm start <VM ID> or qm stop <VM ID>.

    Unlocking a Proxmox guest VM with qm unlock is quick, but treat it as a fix for a stuck lock, not routine practice. If a VM keeps re-locking, check what job is putting the lock there (backups are the most common culprit) and address that directly rather than repeatedly clearing the symptom. Keep your login credentials secure, and keep regular backups of your VMs.

    TL;DR:

    To unlock a Proxmox guest VM:

    qm config        # optional: check lock type first
    qm unlock 
    qm start         # or: qm stop 

    Replace <VM ID> with the actual guest VM ID in each command. For LXC containers, use pct in place of qm (e.g. pct unlock <CT ID>) — the commands aren’t interchangeable between VMs and containers.

  • Using Pigz with Tar

    pigz is a drop in multi-threaded replacement for gzip. If you have plenty of cores then it’ll significantly speed things up.

    tar -c --use-compress-program=pigz -f newtarball.tar dir
  • Remove a node from a Proxmox cluster

    Open a shell on one of the working nodes.

    #Get cluster status
    root@pve24:~#pvecm status

    If you don’t have a quorum then it may be necessary to change the number of expected votes. To do that issue the following command(s).

    root@pve24:~#pvecm expected 1

    Remove the node with:

    root@pve24:~#pvecm delnode pve25

    It may be necessary to restart corosync with:

    root@pve24:~#service corosync restart

    Reload the proxmox webgui if the node doesn’t go away and you are all set.