Tonight I finally ran the one test I'd been putting off: a full cold reboot of the switch with real traffic depending on the outcome. Every piece of config built on it since router mode went in — the three SVIs, the lab VLAN's access list, the DHCP reservation for the switch's own address — had only ever been proven to work while running. A saved config that doesn't come back correctly after power loss is a config that only looks finished, and I'd been avoiding finding out which one this was.
What made the test safe to run
The reason I could finally do this was a DHCP reservation added on the router beforehand, tying the switch's MAC to a fixed address. Without that reservation, the switch's management address — the one every return route on the router points at — was only staying the same by habit, not guarantee. If a reboot had come back with a different address, it could have taken down the virtualization host, its VMs, and the public sites, in a way that wouldn't have obviously pointed at DHCP as the cause. Nothing like that actually happened tonight — the reservation held — but that's the risk the reservation was removing before I was willing to pull the trigger.
The procedure itself was plain: save the running config, watch connectivity continuously from a second machine, then issue the reload and see what comes back. It came back at the reserved address, and everything I checked afterward matched what was there before the reboot — router mode, all three SVIs valid, the lab VLAN's access list still attached to its port, connectivity to the virtualization host, the hypervisor's web console loading, and the live site loading. Config, VLANs, and the ACL all survived a cold reload intact. Worth remembering: this had never been tested before, and now it has, and it passed.
VLAN 10 gets its own ACL
With that settled, I built a policy for the production VLAN the same way I built the lab VLAN's earlier: write the rules, verify the list, bind it to the physical port, then test by function — never trust that a config which was accepted is a config that actually works. The guiding idea is least privilege, not maximum lockdown: production gets exactly the access it needs and nothing more. The policy denies traffic from production toward the lab, denies traffic to the switch's own management login, and permits everything else — including the path back toward the general/management VLAN.
Why that last part stays open — the part worth remembering
This is the piece I actually want future-me to understand, not just see passed in a test table. It would have been tempting to also deny the path back to the management VLAN, mirroring the lab VLAN's policy exactly. That would have broken management entirely.
The switch's access lists are stateless. When the workstation opens a connection to the virtualization host, the request leaves on the management VLAN and is unaffected either way — but the reply travels from production back to the management VLAN. A stateless ACL can't tell "a reply to a connection the workstation opened" apart from "a new connection production is initiating." Blocking one blocks both, and that would cut off the ability to manage the host and the switch at all.
So that direction stays open, and I'm writing this down specifically so I don't mistake it for an oversight later: it's a known, accepted limitation. In a properly segmented network, management traffic runs on its own dedicated VLAN, separate from everything else. Here, the general VLAN is both "the management network" and "everything that isn't production or lab," so anything reachable on it can reach the virtualization host's login page. Fixing that properly means adding a fourth, dedicated management VLAN — a real future project, not a quick fix, and exactly what an enterprise network would do differently here.
I verified the policy afterward by function rather than just by "it was accepted": of the destinations I checked, the ones expected to be blocked were blocked and the ones expected to work still worked, while DNS resolution and the public sites were unaffected. Same split-proves-the-policy pattern as every ACL test in this project.
Still open: the clock and the docs
Two threads are still hanging. The switch's clock is set manually and reports dates from 2011, which makes it useless for lining its own logs up against anything else in the lab. The fix is SNTP — a lighter version of NTP, its own top-level command separate from clock — but nothing is configured yet, only the command tree explored. The actual next step is three specific sub-commands I haven't checked, and the one that matters most decides whether this switch can be pointed at a hostname for its time source, like a well-known public NTP provider, or only at a raw address — which depends on whether it can do DNS lookups at all. Picking this up means reading those three first, then choosing a server and timezone, then verifying the same build-then-verify way as everything else here.
The other open thread is a documentation restructure, discussed and deliberately deferred rather than rushed. The dated runbook history is accurate but not something to hand to someone — or future-me — who just wants to know what the network looks like right now. The plan is a separate, short set of current-state docs living alongside the dated runbooks, not replacing them: the new structure describes how things are now, the runbooks stay exactly as they are describing how it got that way, and nothing gets deleted. Not built yet, just the plan.
So where this leaves things: both the production and lab segments now carry written, tested ACL policy, and the switch's saved state has been proven to survive a cold reboot. NTP and the documentation restructure are still open. The one line I most want to not forget is the VLAN 10 → VLAN 1 reasoning — it's correct for now, and it has an expiration date tied to building a real management VLAN, not a permanent shrug.