<?xml version="1.0" encoding="UTF-8"?>
<rss version="2.0" xmlns:atom="http://www.w3.org/2005/Atom">
  <channel>
    <title>Paul Rosham</title>
    <link>https://paul.rosham.com/</link>
    <atom:link href="https://paul.rosham.com/feed.xml" rel="self" type="application/rss+xml" />
    <description>Design decisions and how-to guides from running small infrastructure estates on a very low budget: OPNsense, Proxmox, Ceph, Proxmox Backup Server, NetBird, Authentik and Vault.</description>
    <language>en-au</language>
    <lastBuildDate>Tue, 06 Oct 2026 00:00:00 GMT</lastBuildDate>
    <item>
      <title>A free static Next.js blog on Cloudflare Workers</title>
      <link>https://paul.rosham.com/blog/free-blog-cloudflare-workers-tinacms/</link>
      <guid isPermaLink="true">https://paul.rosham.com/blog/free-blog-cloudflare-workers-tinacms/</guid>
      <pubDate>Tue, 06 Oct 2026 00:00:00 GMT</pubDate>
      <description>This site costs a domain registration and nothing else. Posts are Markdown in a Git repository, edited in a local CMS, built to static files and served from Cloudflare Workers. Here is the design and the three things that were decided on purpose.</description>
    </item>
    <item>
      <title>OPNsense: announce your own prefix with FRR BGP</title>
      <link>https://paul.rosham.com/blog/opnsense-frr-bgp-announce-prefix/</link>
      <guid isPermaLink="true">https://paul.rosham.com/blog/opnsense-frr-bgp-announce-prefix/</guid>
      <pubDate>Mon, 05 Oct 2026 00:00:00 GMT</pubDate>
      <description>The FRR plugin on an OPNsense pair is enough to announce a portable /24 to a transit provider. The settings that matter, the blackhole route without which nothing is advertised, strict filters both ways, and how to confirm the announcement from outside.</description>
    </item>
    <item>
      <title>Announce your own /24 from an OPNsense pair with BGP</title>
      <link>https://paul.rosham.com/blog/opnsense-bgp-own-address-space/</link>
      <guid isPermaLink="true">https://paul.rosham.com/blog/opnsense-bgp-own-address-space/</guid>
      <pubDate>Sat, 03 Oct 2026 00:00:00 GMT</pubDate>
      <description>Provider-assigned addresses lock you to a contract and turn every service IP into a migration project. A portable prefix, an ASN and FRR on OPNsense are enough. The decisions that made the first announcement boring.</description>
    </item>
    <item>
      <title>OPNsense: retire a public IP address without a blackhole</title>
      <link>https://paul.rosham.com/blog/opnsense-retire-public-ip-safely/</link>
      <guid isPermaLink="true">https://paul.rosham.com/blog/opnsense-retire-public-ip-safely/</guid>
      <pubDate>Fri, 02 Oct 2026 00:00:00 GMT</pubDate>
      <description>An alias nothing referenced was deleted during a cleanup and a routed /28 went dark for about 26 hours. The procedure that came out of it, from the inventory of references to the provider's written confirmation, dual-running the replacement, deleting on both nodes and probing from outside.</description>
    </item>
    <item>
      <title>OPNsense as the routing peer for a NetBird mesh</title>
      <link>https://paul.rosham.com/blog/opnsense-netbird-routing-peer/</link>
      <guid isPermaLink="true">https://paul.rosham.com/blog/opnsense-netbird-routing-peer/</guid>
      <pubDate>Wed, 30 Sep 2026 00:00:00 GMT</pubDate>
      <description>Install the NetBird agent on both firewalls of an HA pair, advertise one route per VLAN with the pair as routing peers, add the outbound NAT the agent's masquerade does not cover, filter on the overlay interface, and avoid the endpoint trap that drops large packets.</description>
    </item>
    <item>
      <title>Catalyst 3850: console from a Linux jumphost, config backups</title>
      <link>https://paul.rosham.com/blog/catalyst-3850-console-linux-jumphost-config-backup/</link>
      <guid isPermaLink="true">https://paul.rosham.com/blog/catalyst-3850-console-linux-jumphost-config-backup/</guid>
      <pubDate>Tue, 29 Sep 2026 00:00:00 GMT</pubDate>
      <description>A USB serial adapter on the stack's console port, the operator in the dialout group, screen at 9600 8N1, and a small expect script that captures the running configuration into the repository. Plus the break-glass path and why management egress never goes over anyone else's WiFi.</description>
    </item>
    <item>
      <title>Self-hosted NetBird with OPNsense as the routing peer</title>
      <link>https://paul.rosham.com/blog/self-hosted-netbird-operator-access/</link>
      <guid isPermaLink="true">https://paul.rosham.com/blog/self-hosted-netbird-operator-access/</guid>
      <pubDate>Mon, 28 Sep 2026 00:00:00 GMT</pubDate>
      <description>One small VM runs the control plane, with its database shipped to a warm standby every thirty seconds. The firewalls are the routing peers. NetBird policies are treated as transport; real authorisation lives at the service.</description>
    </item>
    <item>
      <title>Catalyst 3850: send syslog to a SIEM instead of polling SNMP</title>
      <link>https://paul.rosham.com/blog/catalyst-3850-syslog-to-wazuh/</link>
      <guid isPermaLink="true">https://paul.rosham.com/blog/catalyst-3850-syslog-to-wazuh/</guid>
      <pubDate>Fri, 25 Sep 2026 00:00:00 GMT</pubDate>
      <description>Point the switch at the SIEM with logging host, raise the trap level to informational, timestamp with milliseconds, log configuration changes with archive, and let Wazuh decode the rest. Port flaps, LACP changes and failed logins become events next to everything else.</description>
    </item>
    <item>
      <title>What a webshell taught a small hosting shop</title>
      <link>https://paul.rosham.com/blog/webshell-incident-lessons-small-hosting/</link>
      <guid isPermaLink="true">https://paul.rosham.com/blog/webshell-incident-lessons-small-hosting/</guid>
      <pubDate>Wed, 16 Sep 2026 00:00:00 GMT</pubDate>
      <description>A pre-authentication flaw, exploited days after the fix shipped. A read-only document root that pinned the malware in place. A rebuild reinfected within hours. The timeline, anonymised, and the controls that came out of it.</description>
    </item>
    <item>
      <title>OPNsense: keep ACME certificates valid on both HA nodes</title>
      <link>https://paul.rosham.com/blog/opnsense-acme-certificates-ha-pair/</link>
      <guid isPermaLink="true">https://paul.rosham.com/blog/opnsense-acme-certificates-ha-pair/</guid>
      <pubDate>Sat, 12 Sep 2026 00:00:00 GMT</pubDate>
      <description>The ACME client renews on the node it runs on. The backup keeps serving whatever it had, which after ninety days is an expired certificate at the worst possible moment. A daily copy, an import on the backup, and a fingerprint check that tells you when they differ.</description>
    </item>
    <item>
      <title>OPNsense: fix HA config sync that stopped syncing</title>
      <link>https://paul.rosham.com/blog/opnsense-ha-config-sync-not-working/</link>
      <guid isPermaLink="true">https://paul.rosham.com/blog/opnsense-ha-config-sync-not-working/</guid>
      <pubDate>Thu, 10 Sep 2026 00:00:00 GMT</pubDate>
      <description>The backup looks healthy and is a month behind. How to tell, what actually triggers the XMLRPC sync, what never syncs at all, and a drift check you can run from a laptop every fifteen minutes.</description>
    </item>
    <item>
      <title>OPNsense HA: VHID 1 and the sync that is not automatic</title>
      <link>https://paul.rosham.com/blog/opnsense-carp-vhid-config-sync/</link>
      <guid isPermaLink="true">https://paul.rosham.com/blog/opnsense-carp-vhid-config-sync/</guid>
      <pubDate>Mon, 07 Sep 2026 00:00:00 GMT</pubDate>
      <description>Two firewalls are only a pair if the backup holds the master's config. The VHID numbering that scales past VLAN 255, the config sync that only runs when asked, and the drift audit that caught rules living on one node.</description>
    </item>
    <item>
      <title>PBS: a lot of &quot;verify failed&quot;, and the protect-latest trick</title>
      <link>https://paul.rosham.com/blog/pbs-verify-failed-protect-latest/</link>
      <guid isPermaLink="true">https://paul.rosham.com/blog/pbs-verify-failed-protect-latest/</guid>
      <pubDate>Fri, 04 Sep 2026 00:00:00 GMT</pubDate>
      <description>When a verify job lights up dozens of snapshots at once, the first job is to stop prune from making it worse. Protect the newest snapshot in every group, read the log for the one chunk that is shared, then decide between re-uploading from the source, re-syncing from the other site, and fixing the disk.</description>
    </item>
    <item>
      <title>PBS: fix the fingerprint mismatch after a rename</title>
      <link>https://paul.rosham.com/blog/pbs-fingerprint-mismatch-after-rename/</link>
      <guid isPermaLink="true">https://paul.rosham.com/blog/pbs-fingerprint-mismatch-after-rename/</guid>
      <pubDate>Fri, 28 Aug 2026 00:00:00 GMT</pubDate>
      <description>Rename or reinstall a PBS host and it presents a new self-signed certificate. Every PVE storage entry and every remote on the other PBS has the old fingerprint pinned and refuses to connect. Where the pins live, how to read the new fingerprint, and the order to update them in.</description>
    </item>
    <item>
      <title>Proxmox: move VMs between two clusters</title>
      <link>https://paul.rosham.com/blog/proxmox-migrate-vms-between-clusters/</link>
      <guid isPermaLink="true">https://paul.rosham.com/blog/proxmox-migrate-vms-between-clusters/</guid>
      <pubDate>Fri, 21 Aug 2026 00:00:00 GMT</pubDate>
      <description>qm remote-migrate exists and is fussy. The path that works every time is a Proxmox Backup Server backup, already replicated to the other site, restored on the other cluster from a read-only storage entry with a new guest ID.</description>
    </item>
    <item>
      <title>Two roots of trust: Authentik for people, Vault for machines</title>
      <link>https://paul.rosham.com/blog/authentik-vault-identity-small-estate/</link>
      <guid isPermaLink="true">https://paul.rosham.com/blog/authentik-vault-identity-small-estate/</guid>
      <pubDate>Fri, 14 Aug 2026 00:00:00 GMT</pubDate>
      <description>People and machines have different lifecycles, so they get different roots of trust. The protocol ladder, the login policy, the credential shapes, and the one rule that neither root may depend on something it protects.</description>
    </item>
    <item>
      <title>PBS: a restore drill for one file, one guest and one site</title>
      <link>https://paul.rosham.com/blog/pbs-restore-drill-file-guest-site/</link>
      <guid isPermaLink="true">https://paul.rosham.com/blog/pbs-restore-drill-file-guest-site/</guid>
      <pubDate>Fri, 14 Aug 2026 00:00:00 GMT</pubDate>
      <description>A backup you have not restored from is a hope. Three rehearsed restores, each with its commands and its evidence: one file from a pxar archive, one guest to a new VMID on the local PBS, and one guest on the other cluster from the replica namespace. What the first drill found, how often to run it, and what to write down.</description>
    </item>
    <item>
      <title>Proxmox: SDN VLAN zones with an external IPAM</title>
      <link>https://paul.rosham.com/blog/proxmox-sdn-vlan-zones-netbox-ipam/</link>
      <guid isPermaLink="true">https://paul.rosham.com/blog/proxmox-sdn-vlan-zones-netbox-ipam/</guid>
      <pubDate>Fri, 07 Aug 2026 00:00:00 GMT</pubDate>
      <description>Two VLAN zones on the VLAN-aware bridge, a VNet per VLAN, and NetBox as the IPAM behind the tenant zone so the subnet Proxmox knows about is the one the address plan allocated. SDN does the plumbing; the firewall still does policy and NAT.</description>
    </item>
    <item>
      <title>PBS: back up a directory from a snapshot with the client</title>
      <link>https://paul.rosham.com/blog/pbs-backup-directory-proxmox-backup-client-pxar/</link>
      <guid isPermaLink="true">https://paul.rosham.com/blog/pbs-backup-directory-proxmox-backup-client-pxar/</guid>
      <pubDate>Fri, 31 Jul 2026 00:00:00 GMT</pubDate>
      <description>vzdump skips bind mounts, so the files a container serves from CephFS never reach the backup server. A nightly proxmox-backup-client run takes a pxar archive of the latest CephFS snapshot into the tenant's namespace. The token, the command, the timer, and the one-file restore that proves it.</description>
    </item>
    <item>
      <title>Proxmox: bind-mount CephFS into an unprivileged container</title>
      <link>https://paul.rosham.com/blog/proxmox-lxc-bind-mount-cephfs-unprivileged/</link>
      <guid isPermaLink="true">https://paul.rosham.com/blog/proxmox-lxc-bind-mount-cephfs-unprivileged/</guid>
      <pubDate>Tue, 28 Jul 2026 00:00:00 GMT</pubDate>
      <description>Create a CephFS subvolume with a quota, scope a cephx key to its path, mount it on every node with a systemd unit, and bind-mount it into an unprivileged container that holds no Ceph key. df inside the container shows the quota, not the cluster.</description>
    </item>
    <item>
      <title>Proxmox: fix &quot;cannot migrate local bind mount point&quot;</title>
      <link>https://paul.rosham.com/blog/proxmox-cannot-migrate-local-bind-mount-point/</link>
      <guid isPermaLink="true">https://paul.rosham.com/blog/proxmox-cannot-migrate-local-bind-mount-point/</guid>
      <pubDate>Fri, 24 Jul 2026 00:00:00 GMT</pubDate>
      <description>The error means Proxmox cannot promise the directory behind mp0 exists on the target node. Mount the same path on every node with a systemd unit, check it, and only then add shared=1.</description>
    </item>
    <item>
      <title>CephFS subvolumes under LXC: snapshots your backups can see</title>
      <link>https://paul.rosham.com/blog/cephfs-lxc-bind-mount-snapshots-pbs/</link>
      <guid isPermaLink="true">https://paul.rosham.com/blog/cephfs-lxc-bind-mount-snapshots-pbs/</guid>
      <pubDate>Tue, 21 Jul 2026 00:00:00 GMT</pubDate>
      <description>Guests are disposable; the data is not in them. Put user files on a CephFS subvolume, bind-mount it into an unprivileged container, snapshot on a schedule, and back the snapshot up, because vzdump skips bind mounts.</description>
    </item>
    <item>
      <title>Proxmox: replace a failed OSD or rejoin a reinstalled node</title>
      <link>https://paul.rosham.com/blog/proxmox-ceph-replace-osd-rejoin-node/</link>
      <guid isPermaLink="true">https://paul.rosham.com/blog/proxmox-ceph-replace-osd-rejoin-node/</guid>
      <pubDate>Fri, 03 Jul 2026 00:00:00 GMT</pubDate>
      <description>Two runbooks that share a shape. For a dead disk: identify, out, stop, destroy, swap, create, watch recovery. For a dead node: drain it, remove its Ceph roles, pvecm delnode, reinstall by PXE, pvecm add, recreate the roles, and keep HA fencing in mind throughout.</description>
    </item>
    <item>
      <title>Proxmox: a cluster API address that follows a healthy node</title>
      <link>https://paul.rosham.com/blog/proxmox-cluster-api-vip-keepalived/</link>
      <guid isPermaLink="true">https://paul.rosham.com/blog/proxmox-cluster-api-vip-keepalived/</guid>
      <pubDate>Fri, 26 Jun 2026 00:00:00 GMT</pubDate>
      <description>One address for the Proxmox API that moves to a node whose pveproxy actually answers, using keepalived VRRP with a track script. A node with a wedged API still answers ARP, so the check has to ask port 8006, not the kernel.</description>
    </item>
    <item>
      <title>Proxmox: a three-node Ceph cluster on used Dell servers</title>
      <link>https://paul.rosham.com/blog/proxmox-three-node-ceph-cluster-setup/</link>
      <guid isPermaLink="true">https://paul.rosham.com/blog/proxmox-three-node-ceph-cluster-setup/</guid>
      <pubDate>Sat, 20 Jun 2026 00:00:00 GMT</pubDate>
      <description>From three second-hand R630-class servers with IT-mode HBAs to a quorate cluster with one replicated RBD pool, HA on every guest and no local storage for guests. The commands, in order, and what to check after each.</description>
    </item>
    <item>
      <title>Ex-lease Dell Servers, one Ceph pool, no local-zfs</title>
      <link>https://paul.rosham.com/blog/proxmox-ceph-three-node-cluster-used-hardware/</link>
      <guid isPermaLink="true">https://paul.rosham.com/blog/proxmox-ceph-three-node-cluster-used-hardware/</guid>
      <pubDate>Thu, 18 Jun 2026 00:00:00 GMT</pubDate>
      <description>Second-hand servers are cheap. What costs money later is a storage decision that blocks migration. Here is the cluster layout that keeps HA, migration and backup working.</description>
    </item>
    <item>
      <title>Proxmox: automated install with an answer file and PXE</title>
      <link>https://paul.rosham.com/blog/proxmox-automated-install-answer-file-pxe/</link>
      <guid isPermaLink="true">https://paul.rosham.com/blog/proxmox-automated-install-answer-file-pxe/</guid>
      <pubDate>Tue, 16 Jun 2026 00:00:00 GMT</pubDate>
      <description>Build a self-installing Proxmox VE ISO with proxmox-auto-install-assistant, serve the TOML answer from the jumphost, boot it through iDRAC virtual media or PXE, and avoid the two traps that cost me an afternoon each.</description>
    </item>
    <item>
      <title>PBS: prune, verify and garbage collection that do not fight</title>
      <link>https://paul.rosham.com/blog/pbs-prune-verify-gc-schedules/</link>
      <guid isPermaLink="true">https://paul.rosham.com/blog/pbs-prune-verify-gc-schedules/</guid>
      <pubDate>Wed, 10 Jun 2026 00:00:00 GMT</pubDate>
      <description>Prune decides what to keep, garbage collection reclaims what nothing references, verify checks that what is kept is still readable. Each is harmless alone and all three get in each other's way when they overlap. A weekly calendar that keeps them apart, and apart from the backup window and the restore drill.</description>
    </item>
    <item>
      <title>OPNsense: split-horizon DNS with Unbound forward zones</title>
      <link>https://paul.rosham.com/blog/opnsense-unbound-split-horizon-dns/</link>
      <guid isPermaLink="true">https://paul.rosham.com/blog/opnsense-unbound-split-horizon-dns/</guid>
      <pubDate>Fri, 05 Jun 2026 00:00:00 GMT</pubDate>
      <description>Internal zones forwarded to the per-site authoritative server, public names overridden to internal addresses for internal clients, and DNS over TLS to the upstream. Plus the test that proves the public answer is right, which is not the one you run from your laptop.</description>
    </item>
    <item>
      <title>Proxmox: intra-day snapshots from cron that actually run</title>
      <link>https://paul.rosham.com/blog/proxmox-rbd-snapshots-cron-path-trap/</link>
      <guid isPermaLink="true">https://paul.rosham.com/blog/proxmox-rbd-snapshots-cron-path-trap/</guid>
      <pubDate>Fri, 29 May 2026 00:00:00 GMT</pubDate>
      <description>A snapshot script that ran from cron three times a day, reported success for months, and never created a snapshot, because cron's PATH does not include /usr/sbin and the output went to /dev/null. The fixed script, and the checks that make it fail loudly.</description>
    </item>
    <item>
      <title>PBS: sync job says TASK OK but the datastore is empty</title>
      <link>https://paul.rosham.com/blog/pbs-sync-job-task-ok-datastore-empty/</link>
      <guid isPermaLink="true">https://paul.rosham.com/blog/pbs-sync-job-task-ok-datastore-empty/</guid>
      <pubDate>Wed, 27 May 2026 00:00:00 GMT</pubDate>
      <description>A pull sync that finishes green and copies nothing has one of three causes: the namespaces do not line up, an earlier run is still holding the locks, or the token cannot see anything upstream. One check for each, and a way to see what the job sees before running it.</description>
    </item>
    <item>
      <title>PBS: pull replication between sites with a read-only token</title>
      <link>https://paul.rosham.com/blog/pbs-pull-replication-between-sites/</link>
      <guid isPermaLink="true">https://paul.rosham.com/blog/pbs-pull-replication-between-sites/</guid>
      <pubDate>Tue, 26 May 2026 00:00:00 GMT</pubDate>
      <description>The remote PBS pulls, with a token that can only read one datastore, a pinned fingerprint, and a per-source namespace so guest IDs from two clusters never collide. Every command, in order, then the storage entry that lets the surviving cluster restore.</description>
    </item>
    <item>
      <title>Proxmox Backup Server that leaves the building</title>
      <link>https://paul.rosham.com/blog/proxmox-backup-server-site-replication/</link>
      <guid isPermaLink="true">https://paul.rosham.com/blog/proxmox-backup-server-site-replication/</guid>
      <pubDate>Sun, 24 May 2026 00:00:00 GMT</pubDate>
      <description>A standalone PBS per site is the easy part. The part most setups skip is getting a copy to the other site, verified, with a token that cannot do damage.</description>
    </item>
    <item>
      <title>OPNsense: manage aliases, rules and NAT from Python</title>
      <link>https://paul.rosham.com/blog/opnsense-api-python-firewall-rules/</link>
      <guid isPermaLink="true">https://paul.rosham.com/blog/opnsense-api-python-firewall-rules/</guid>
      <pubDate>Fri, 15 May 2026 00:00:00 GMT</pubDate>
      <description>The OPNsense API is good enough to run an estate's firewall policy from a script, as long as the script reads back every write, marks what it owns, and remembers that the HA sync will not run on its own. A working pattern with requests.</description>
    </item>
    <item>
      <title>Catalyst 3850: upgrade IOS-XE on a stack in install mode</title>
      <link>https://paul.rosham.com/blog/catalyst-3850-ios-xe-upgrade-install-mode/</link>
      <guid isPermaLink="true">https://paul.rosham.com/blog/catalyst-3850-ios-xe-upgrade-install-mode/</guid>
      <pubDate>Fri, 08 May 2026 00:00:00 GMT</pubDate>
      <description>Confirm install mode, clean the flash, copy and verify the image, install it to every member in one command, reload with a console attached, and keep the old image on flash for the rollback you hope not to need.</description>
    </item>
    <item>
      <title>OPNsense: VLANs on a trunk from a Catalyst, with Kea DHCP</title>
      <link>https://paul.rosham.com/blog/opnsense-vlan-trunk-kea-dhcp/</link>
      <guid isPermaLink="true">https://paul.rosham.com/blog/opnsense-vlan-trunk-kea-dhcp/</guid>
      <pubDate>Sat, 02 May 2026 00:00:00 GMT</pubDate>
      <description>Adding a tenant VLAN to an OPNsense pair fed by a Catalyst trunk, from the switch port to the CARP gateway, the firewall rule order that keeps tenants apart, and a Kea DHCP pool for provisioning. Done twice, because there are two nodes.</description>
    </item>
    <item>
      <title>Catalyst 3850: port-channel is up but no traffic passes</title>
      <link>https://paul.rosham.com/blog/catalyst-3850-port-channel-up-no-traffic/</link>
      <guid isPermaLink="true">https://paul.rosham.com/blog/catalyst-3850-port-channel-up-no-traffic/</guid>
      <pubDate>Fri, 01 May 2026 00:00:00 GMT</pubDate>
      <description>LACP bundles, the MAC table has entries, and nothing gets through. The port is tagging the wrong way for its host class, and the switch has no reason to tell you.</description>
    </item>
    <item>
      <title>Catalyst 3850: cross-stack LACP to a Proxmox bond</title>
      <link>https://paul.rosham.com/blog/catalyst-3850-lacp-port-channel-proxmox-bond/</link>
      <guid isPermaLink="true">https://paul.rosham.com/blog/catalyst-3850-lacp-port-channel-proxmox-bond/</guid>
      <pubDate>Wed, 29 Apr 2026 00:00:00 GMT</pubDate>
      <description>One port on each stack member, a port-channel in LACP active mode, a trunk whose native VLAN does not exist, and an 802.3ad bond under a VLAN-aware bridge on the Proxmox node. Both halves, and how to check they agree.</description>
    </item>
    <item>
      <title>Catalyst 3850: trunks with a native VLAN that does not exist</title>
      <link>https://paul.rosham.com/blog/catalyst-3850-trunk-native-vlan-wan-as-vlan/</link>
      <guid isPermaLink="true">https://paul.rosham.com/blog/catalyst-3850-trunk-native-vlan-wan-as-vlan/</guid>
      <pubDate>Tue, 28 Apr 2026 00:00:00 GMT</pubDate>
      <description>Set every trunk's native VLAN to one you never create, so untagged frames vanish instead of landing in VLAN 1. Then carry the provider's WAN handoff through the stack as a tagged VLAN to both firewalls.</description>
    </item>
    <item>
      <title>Catalyst 3850: stack two switches and add a member safely</title>
      <link>https://paul.rosham.com/blog/catalyst-3850-stack-priority-add-member/</link>
      <guid isPermaLink="true">https://paul.rosham.com/blog/catalyst-3850-stack-priority-add-member/</guid>
      <pubDate>Mon, 27 Apr 2026 00:00:00 GMT</pubDate>
      <description>Cable the stack ring, set priorities in EXEC mode (not config mode), match the software before the new member joins, and power on one switch at a time. The traps are the priority command and auto-upgrade.</description>
    </item>
    <item>
      <title>Second-hand Catalyst, first-class conventions</title>
      <link>https://paul.rosham.com/blog/switch-stack-conventions-proxmox-opnsense/</link>
      <guid isPermaLink="true">https://paul.rosham.com/blog/switch-stack-conventions-proxmox-opnsense/</guid>
      <pubDate>Sun, 26 Apr 2026 00:00:00 GMT</pubDate>
      <description>A used two-member switch stack gives you cross-stack LACP for the price of a prosumer switch. The value is in the conventions, not the hardware.</description>
    </item>
    <item>
      <title>Proxmox: Ubuntu cloud-init templates with static addresses</title>
      <link>https://paul.rosham.com/blog/proxmox-cloud-init-ubuntu-template-static-ip/</link>
      <guid isPermaLink="true">https://paul.rosham.com/blog/proxmox-cloud-init-ubuntu-template-static-ip/</guid>
      <pubDate>Fri, 17 Apr 2026 00:00:00 GMT</pubDate>
      <description>Turn an Ubuntu cloud image into a Proxmox template, clone it, and give each clone a static address, gateway, nameserver, SSH key, VLAN tag and a MAC derived from the address. Every value comes from the host plan, so nothing is typed twice.</description>
    </item>
    <item>
      <title>OPNsense: port forward to a VM behind a CARP pair</title>
      <link>https://paul.rosham.com/blog/opnsense-port-forward-behind-carp/</link>
      <guid isPermaLink="true">https://paul.rosham.com/blog/opnsense-port-forward-behind-carp/</guid>
      <pubDate>Fri, 03 Apr 2026 00:00:00 GMT</pubDate>
      <description>A port forward on an HA pair has to land on the shared WAN address, not a node's own, and it has to exist on both nodes. The forward, its filter rule, why NAT reflection is the wrong fix for the inside test, and how to test from outside properly.</description>
    </item>
    <item>
      <title>A VLAN scheme you can derive in your head</title>
      <link>https://paul.rosham.com/blog/vlan-addressing-scheme-small-data-center/</link>
      <guid isPermaLink="true">https://paul.rosham.com/blog/vlan-addressing-scheme-small-data-center/</guid>
      <pubDate>Sun, 29 Mar 2026 00:00:00 GMT</pubDate>
      <description>Segmentation fails when nobody can remember it. Encode site, VLAN and role into the address so a firewall rule, a DHCP reservation and a MAC can all be derived from a tenant number.</description>
    </item>
    <item>
      <title>Infrastructure engineering on a (very low) budget</title>
      <link>https://paul.rosham.com/blog/infrastructure-on-a-very-low-budget/</link>
      <guid isPermaLink="true">https://paul.rosham.com/blog/infrastructure-on-a-very-low-budget/</guid>
      <pubDate>Sat, 28 Mar 2026 00:00:00 GMT</pubDate>
      <description>What it is like to build a multi-site estate out of open source and second-hand hardware with no support contract to call. The challenges that keep coming back, the rules that came out of them, and an index of the posts that cover each decision.</description>
    </item>
  </channel>
</rss>
