Two HP thin clients joined the lab this round: one for monitoring, one slated to become the firewall. Getting Linux and OPNsense onto them turned out to be the smallest part of the work. The rest was a BIOS flash that took a detour through the wrong machine, three separate OPNsense near-misses while getting it reachable at all, and an audit afterward that caught a switch clock that had drifted by most of a week.
Assign roles by what the hardware is good at, not by arrival order
Plan A was straightforward: the box with the newer BIOS and more cores becomes the firewall, the other one does monitoring. Then the hardware comparison told a different story. One has a real SSD. The other has flash memory behind a bridge chip — eMMC-style, built for light duty, not for being written to constantly. Monitoring is the write-heavy job: graphs, logs, eventually packet captures. That belongs on the real SSD. A firewall, once it's up, barely writes anything, so it's the one that benefits more from the newer BIOS and the extra cores. I reversed the assignment.
Worth writing down because it's the kind of thing that's obvious in hindsight and easy to get backwards in the moment: assign roles by what each workload actually needs — writes, CPU, firmware age — not by which box happened to get set up first.
The BIOS flash that took longer because of the wrong machine
The monitoring box needed a BIOS update before anything else felt safe to install. HP's flash tool is supposed to run on the thin client itself, under Windows. I tried running it from a separate Windows laptop instead, and it attempted to load a driver that tripped Windows' vulnerable-driver blocklist. The block stayed on. Disabling a security control on a different machine to fix a problem on this one is never the fix, even when it's tempting at the end of a long session.
So I reproduced HP's normal Windows-based update procedure by hand, on Linux: copied the vendor's update folder onto the EFI system partition, used the firmware's own BIOS Config Utility to flip a flag that tells the firmware to run the flasher on next boot, restored the saved settings, rebooted. HP's flasher ran on its own at that point and pushed the BIOS from v01.09 to v01.24. The one gotcha in that sequence: the config file the utility reads and writes is UTF-16LE with a byte-order mark, so plain grep finds nothing in it — needed iconv to read and edit it, then convert it back before handing it to the firmware.
After the flash, the box wouldn't boot at all — hung early, right around the point where the firmware measures the initrd into a platform configuration register for secure boot. Two things I tried did not help. What did fix it was going back into firmware setup and choosing Apply Defaults and Exit.
A Debian install done with no network cable
First install attempt on the monitoring box was done without a cable plugged in. It silently skipped three things: the internet package sources (fell back to the install disc only), the SSH server, and bringing the network interface up at all. None of that threw an error — it just quietly did less than I asked for. Wiping and reinstalling with the cable connected fixed all three in one pass.
The settings I locked in on that install: Debian 13.7, netinst, no desktop. Root login disabled, root password left blank. One named account has sudo. Unattended upgrades are on. SSH is key-only — password authentication and root login both off — and I verified that from a second, independent session rather than trusting the first one. A reboot test afterward came back clean: same address, same key, no surprises.
One side note on the key: the laptop I was working from only had one SSH key, already tied to an unrelated external host. Rather than reuse it, I generated a separate key just for the home lab and set IdentitiesOnly yes, so SSH never offers that other key to anything on this network.
Three near-misses getting OPNsense talking
The firewall box's hardware check in live mode was clean — one NIC found, one disk identified (the flash module, with about 58G usable), and some Wi-Fi-chip firmware errors in the log that were safe to ignore since that chip isn't used for anything. Secure Boot was already off, which is expected since FreeBSD-based OPNsense doesn't support it.
Getting it actually configured took three distinct near-misses, each one caught and fixed:
The installer auto-assigned the one network interface to the LAN role, which comes with a default private subnet and its own DHCP server, on the same network segment as the router — not the lab's other, separately segmented VLANs. For a few minutes the new box was an unintended DHCP server on that shared network. A check from another machine afterward found no damage — addresses hadn't changed, and the switch and a hypervisor host both answered normally. Separately: nothing in the setup guidance had warned in advance that an interface-role prompt was coming, or what to answer when it did.
Second: even after reconfiguring the box as WAN-only with no LAN, a DHCP server process was still listening, because the underlying configuration still held the old LAN address range. I stopped it manually before plugging the network cable back in.
Third: after finishing the setup wizard, a reboot showed the interface quietly reassigned back to the LAN role. Caught it, confirmed it against the saved configuration file, and corrected it from the console menu. It held through a second reboot.
Getting into the GUI afterward was its own small puzzle, because the firewall blocks inbound connections by default — including to its own admin interface. The sequence that worked: disable the packet filter briefly from the console, check the web GUI's certificate fingerprint against the one the console prints, add a firewall rule permitting HTTPS management access from two specific known management devices, then re-enable the filter and confirm the GUI still loads. Worth remembering for next time: finishing the setup wizard reloads the ruleset and re-locks everything until that management rule actually exists.
Where it landed at session's end: hostname set, WAN is DHCP-assigned, LAN is none yet — a VLAN segment behind the firewall is planned for a later phase — and GUI access is restricted to the two management devices over HTTPS.
What the audit actually found
Ran a check from the management laptop against the switch, a hypervisor host, and both of its VMs. Two named ACL policies were confirmed present on the switch, each a short deny list followed by a general permit. The hypervisor's switch port was up at gigabit, full duplex. Both VMs were on their expected network segment with their own recorded internal addresses. The switch had SNTP settings configured but no server — more on that below.
One line from the audit worth keeping verbatim, because it's a good reminder on its own: "Several notes outside the repo still said 'ACLs not yet written' and 'VMs staged.' The repo was right; the notes were stale." That's a statement about some notes kept outside the repo, not a verdict on documentation generally — but it's exactly the kind of drift that's easy to miss if you don't actually go check.
Four separate findings came out of that same audit, each its own thing:
- A switch port measuring only 100 Mbps turned out to be explained by one specific laptop's Fast-Ethernet-only network card — nothing to do with the new firewall box. Moved that laptop's cable to a different port.
- A container service got killed by the kernel for memory twice, days apart. Fixed for now with a manual restart plus a policy that restarts it automatically when it hits its memory limit. The actual mechanism — container memory limits and restart policy versus the systemd equivalents — still needs to be written up properly in a separate doc. Standing watch item: if it keeps restarting often, that's not fine, that's a leak hiding behind the restart policy.
- A login to one internal service came from an address that isn't identified yet. Open item, with checking a client list as the obvious next step — not resolved this session.
- One hypervisor host is still accepting root-password SSH login. Not a new discovery — this just confirms an SSH-hardening item that was already on the list.
Finally, a clock the logs agree on
Configured the switch to sync time from a public NTP source, using a raw address specifically so the switch doesn't need DNS to find it. Result: synchronized, stratum 3.
The offset before this fix was about 5.4 days — 469,333,167 milliseconds, measured directly off the switch. Every log entry from the switch, before this session, was off by that much relative to everything else, which means logs from different devices in the lab couldn't be lined up against each other to reconstruct what happened when. The switch stays on UTC on purpose.
Port map correction, and an accident that doubled as a test
The management laptop's cable had been sitting on the port reserved for the firewall's future trunk. Moving it off went wrong once, by accident, before going right: it landed on a different wrong port first. That accident turned into an unplanned isolation test — the interface came up with no address at all while Wi-Fi was off, which is exactly what should happen on that segment given its DHCP and ACL setup. I'm reading that as a pass. The cable then went to its intended port.
The switch log from that final move showed the link coming up and reaching spanning-tree forwarding about five seconds later — fast enough that it has to be Rapid STP rather than classic STP, which converges closer to 30 seconds.
What's still open
One item from this session closed out a leftover from the previous one — the switch clock. Ten more are still open, no outcome yet on any of them:
- Confirm the switch configuration was actually saved to its startup config.
- Confirm a background DNS/DHCP helper service on the firewall box stays disabled at boot.
- Download a config backup from the firewall box.
- Apply the firewall box's pending updates — 91 of them — plus one named driver plugin, then reboot and retest.
- Set up SNMP against the switch, LibreNMS, and a syslog receiver for the monitoring box, with log rotation sorted from day one.
- Write up the container restart mechanism properly, and keep watching the restart count.
- Figure out where that unidentified login actually came from.
- Harden the hypervisor's SSH the same way the monitoring box's already is — key-only, no root password.
- Build the firewall's next phase: the trunk port and a VLAN segment actually living behind it.
- Build the networking folder that's been carried over, open, since the previous session.
Eleven threads total by the end of this one. One closed.