Managing OPNsense upgrades with a stateful SSH script + Claude MCP server

Started by builderall, March 07, 2026, 09:54:52 PM

Previous topic - Next topic
I've been working on tools to make OPNsense upgrades more reliable and recently wrote up the experience:

I gave Claude access to my OPNsense firewall — here's what happened

Two tools in one project:

A stateful Python upgrade script that runs over SSH — handles the pkg ABI mismatch after base/kernel upgrades and auto-resumes after reboots
A Claude MCP server that connects Claude Code to the OPNsense REST API for conversational firewall management
Tested on a live 26.1.2 → 26.1.3 upgrade this week, with two bugs found and fixed mid-session.

Code: https://github.com/builderall/opnsense-upgrade

Happy to answer questions or take feedback.


Well, I am nearly lost for words...

Quote from: builderall on March 07, 2026, 09:54:52 PMconversational firewall management

I mean, really? I can imagine my future self referring you back to this when things will have gone awry and saying "Entirely avoidable.".

Not to insult you, but you must be one of the guys who turn on the AI auto-pilot in your car and then read a book during the ride.

P.S.: I never saw that purported upgrade problem happening since starting to use OpnSense back in 2023 (and counting).
Intel N100, 4* I226-V, 2* 82559, 16 GByte, 500 GByte NVME, Leox LXT-010H-D

1100 down / 450 up, Bufferbloat A+

Fair skepticism — giving an AI write access to a firewall does sound alarming on the surface.

A few clarifications:

The MCP server connects via a restricted API key scoped only to firmware and diagnostics endpoints. It cannot touch firewall rules, VPN, DHCP, or any other config.
Write tools require explicit confirmation — Claude asks before running any update, upgrade, or reboot. It's more like a structured CLI than an autopilot.
OPNSENSE_READ_ONLY=true disables all write tools entirely if you only want monitoring.
Every API call is logged under System > Log Files > Audit.
As for the upgrade problem — glad you haven't hit it. It typically surfaces during major version upgrades (branch changes), not minor updates. The pkg ABI mismatch after a base/kernel upgrade is a known issue, just not one everyone encounters.

The SSH script exists precisely for people who want zero AI involvement and full control — it's a standalone Python script with no external dependencies.

Thank you for your comments.

Quote from: builderall on March 07, 2026, 09:54:52 PMA stateful Python upgrade script
As someone who hopes that the world will be 'Python Free' at some point (...and I don't mean the snake...) I will kindly pass and even more so because a 'Machine Learning Chatbot' influenced the whole thing!
Weird guy who likes everything Linux and *BSD on PC/Laptop/Tablet/Mobile and funny little ARM based boards :)

Quote from: builderall on March 07, 2026, 09:54:52 PMI've been working on tools to make OPNsense upgrades more reliable and recently wrote up the experience:

I gave Claude access to my OPNsense firewall — here's what happened

Two tools in one project:

A stateful Python upgrade script that runs over SSH — handles the pkg ABI mismatch after base/kernel upgrades and auto-resumes after reboots
A Claude MCP server that connects Claude Code to the OPNsense REST API for conversational firewall management
Tested on a live 26.1.2 → 26.1.3 upgrade this week, with two bugs found and fixed mid-session.

Code: https://github.com/builderall/opnsense-upgrade sprunki

Happy to answer questions or take feedback.


Creating a stateful upgrade script that can recover from failures and integrating an MCP server for easier administration shows promise

> handles the pkg ABI mismatch after base/kernel upgrades

We already know what happens:

base/kernel installs fine, but packages abort

We also know the fix:

# opnsense-update -upr 26.7 -a FreeBSD:15:amd64/26.7
(reboot)

What we don't know is why packages are not installing.

Knowing this would help improve the current code or at least put more upgrade checks in place.

Another thing to note is that we don't test updates with third party repositories for a few reasons:

1. We don't know what was enabled by the user.
2. Incompatible packages could be installed that cause runtime issues.
3. Incompatible packages could be installed that cause later upgrade issues.
4. Even if we knew what to fix we have an upgrade schedule to adhere to and don't have access to third party repos.

This is also why you can see this in the latest release notes:

https://github.com/opnsense/changelog/blob/de1d2dc557a/community/26.7/26.7#L99


Cheers,
Franco

BTW:

> https://dev.to/builderall_uniq/i-gave-claude-access-to-my-opnsense-firewall-heres-what-happened-nif

QuoteThe FreeBSD base and kernel get upgraded first, triggering a reboot. After that reboot, the new base ships a different pkg ABI — and the old pkg binary can no longer install or upgrade anything. The web UI has no recovery path for this. You're on your own.

That's an interesting theory, but since the given opnsense-update script can fix that in situ this explanation is wrong.

The more straight-forward answer lies in the upgrade log, because it most certainly starts upgrading packages, but then fails for one reason or another.

# opnsense-update -gG

The fact that the system can't recover is unfortunately plentiful since we've had to deal with stricter pf syntax WRT route-to, new OpenSSL 3.5 validation killing connections on HTTPS when DTLS is misconfigured and Realtek and CPU microcode third party issues.

To be frank I don't think we can really achieve to fix all of this within the time we have for a major release, but that also means a script proposed such as this will fail for similar reasons as you get closer to the root of the particular problem.


Cheers,
Franco