<?xml version="1.0" encoding="utf-8" standalone="yes"?><rss version="2.0" xmlns:atom="http://www.w3.org/2005/Atom" xmlns:content="http://purl.org/rss/1.0/modules/content/"><channel><title>Automation on Andy Little</title><link>https://andylittle.net/tags/automation/</link><description>Recent content in Automation on Andy Little</description><generator>Hugo</generator><language>en-us</language><lastBuildDate>Wed, 22 Jul 2026 13:30:00 -0500</lastBuildDate><atom:link href="https://andylittle.net/tags/automation/index.xml" rel="self" type="application/rss+xml"/><item><title>Turning a Home Network into Real Infrastructure</title><link>https://andylittle.net/blog/2026/home-network-observability-automation/</link><pubDate>Wed, 22 Jul 2026 13:30:00 -0500</pubDate><guid>https://andylittle.net/blog/2026/home-network-observability-automation/</guid><description>A small Proxmox cluster, a managed switch or two, some IP cameras, and Home Assistant eventually stop being a pile of gadgets and start being infrastructure. Here&amp;rsquo;s how I built observability, a live topology graph, and an AI-assisted ops layer for mine — without letting anything have unsupervised write access to the network.</description><content:encoded><![CDATA[<p>At some point a home network stops being &ldquo;a router and some WiFi&rdquo; and starts
being infrastructure: a small Proxmox cluster, a couple of managed switches, a
NAS, Home Assistant, some IP cameras, a pile of single-purpose VMs. Once it
gets to that size, the two things a data-center network takes for granted —
<em>knowing what&rsquo;s actually out there</em> and <em>knowing when something breaks</em> —
stop being free. This is the story of building both, plus a layer that lets
Claude Code act as an ops copilot for the network without handing it the
keys unsupervised.</p>
<h2 id="the-problem-it-grew-past-i-just-know">The problem: it grew past &ldquo;I just know&rdquo;</h2>
<p>For a while, the mental model of the network lived entirely in my head. That
works until a switch port flaps, a VM migrates, or a device gets a new IP,
and you find out about it by symptom rather than by signal — the &ldquo;why is the
Wi-Fi pod offline&rdquo; question that turns into twenty minutes of SSHing into
things to check link status one port at a time.</p>
<p>The fix was to stop treating the network as a black box and start treating
it like the rest of my infrastructure: observable, documented, and — where
it&rsquo;s safe to do so — automatable.</p>
<h2 id="a-small-internal-webapp">A small internal webapp</h2>
<p>The centerpiece is a small internal dashboard with a handful of tabs:</p>
<ul>
<li><strong>Topology</strong> — a live, auto-generated map of the LAN: router, switches,
and every device, drawn from an actual scan rather than a diagram someone
has to remember to update.</li>
<li><strong>Graph</strong> — the same topology, but as an actual graph database (Neo4j)
rebuilt from scratch every 15 minutes. It&rsquo;s deliberately <em>current-state
only</em>, not a history store — every sync wipes and rebuilds the graph, so
a query always reflects what&rsquo;s plugged in right now. The tab embeds the
real Neo4j Browser so I can run ad-hoc Cypher queries against my own LAN
(&ldquo;what&rsquo;s connected to this switch port,&rdquo; &ldquo;show me every device with no
hostname&rdquo;) instead of grepping through ARP tables.</li>
<li><strong>Monitoring</strong> — Grafana/Prometheus, for the metrics side of things.</li>
<li><strong>Switch</strong> — port status and traffic for the managed switches, without
opening their web UIs.</li>
<li><strong>Syslog</strong> — the one that ended up mattering most in practice.</li>
</ul>
<h3 id="syslog-making-the-logs-actually-watch-something">Syslog: making the logs actually watch something</h3>
<p>Every host on the network already ships logs to a central syslog collector —
hundreds of sources&rsquo; worth. The problem was that nothing was <em>reading</em> them.
The answer to &ldquo;why did the WiFi pod drop&rdquo; was sitting in a switch&rsquo;s log the
whole time (a port link-down event), completely unwatched.</p>
<p>The Syslog tab adds two things on top of the raw collector: a searchable,
multi-host log viewer (term/regex filters, time ranges — with hundreds of
sources and a lot of history, filtering has to happen server-side, not in
the browser), and user-defined <strong>notification rules</strong>. A small engine runs
every minute, tails only the new bytes each watched log has grown by,
matches them against the rules, and — on a match, respecting a per-rule
cooldown so one flapping port doesn&rsquo;t turn into a hundred pages — fires a
webhook into Home Assistant, which turns it into a phone notification.</p>
<p>It&rsquo;s a small feature, but it&rsquo;s the difference between &ldquo;the network told me
something broke&rdquo; and &ldquo;I noticed something was broken.&rdquo;</p>
<h2 id="giving-claude-code-supervised-hands-on-the-network">Giving Claude Code supervised hands on the network</h2>
<p>The more interesting piece, for me, was building an MCP (Model Context
Protocol) layer so Claude Code can act on the network directly instead of me
relaying <code>show</code> command output back and forth by hand. There&rsquo;s a small set
of MCP servers, each scoped to one thing:</p>
<ul>
<li>One that talks to the router — reads configuration and running state, and
can apply changes (like adding a static host mapping) over SSH.</li>
<li>One that reads switch port status and traffic over SNMP.</li>
<li>One that lists and controls VMs/containers on the Proxmox cluster via its
API.</li>
<li>One that reads the centralized logs.</li>
<li>A generic SSH connector for anything else on the LAN.</li>
</ul>
<p>The point isn&rsquo;t &ldquo;let an AI reconfigure my network unsupervised&rdquo; — it&rsquo;s
narrowing the interface. Each server exposes a specific, reviewable set of
actions instead of a raw shell, so when I&rsquo;m working through something like a
VLAN migration or a switch swap with Claude Code, it can genuinely read the
live state of the router and switches and reason about port assignments and
firewall rules against what&rsquo;s <em>actually</em> deployed — not against my
possibly-stale mental model of it — while every actual change still goes
through review before it&rsquo;s applied.</p>
<h2 id="the-vlan-problem-consumer-mesh-wifi-cant-solve">The VLAN problem consumer mesh WiFi can&rsquo;t solve</h2>
<p>The most concrete recent project this stack enabled: putting IoT devices and
IP cameras on their own isolated VLAN, firewalled off from the trusted
network, while leaving everything else alone.</p>
<p>The obvious approach — tag a dedicated SSID to a VLAN on the existing mesh
WiFi — turned out to be a dead end. Consumer-tier mesh systems generally
don&rsquo;t support mapping individual SSIDs to VLANs; that&rsquo;s an enterprise-AP
feature. Rather than replace a perfectly good mesh system, the fix was to
add a couple of cheap, dedicated access points running OpenWrt, configured
as <strong>dumb bridges</strong> rather than routers: no DHCP, no routing, no firewall of
their own, just WiFi bridged straight onto a switch port that&rsquo;s hard-set to
the IoT VLAN. The switch does all the VLAN tagging; the access point doesn&rsquo;t
need to know VLANs exist at all.</p>
<p>On the router side, that VLAN gets its own subnet, its own DHCP scope, and a
firewall policy that defaults to <em>drop</em> everything inbound except:</p>
<ul>
<li>established/related traffic (so replies to connections IoT devices
themselves initiated still work),</li>
<li>a narrow allow rule for the one thing that has to reach in — MQTT traffic
to the home-automation host, so IoT devices can publish to it,</li>
<li>and outbound internet access, since these devices still need it for NTP,
firmware updates, and cloud features.</li>
</ul>
<p>Everything else from the IoT VLAN toward the trusted network is dropped by
default. Traffic in the other direction (trusted → IoT) stays unrestricted,
since it&rsquo;s the automation/monitoring hosts polling <em>into</em> the IoT VLAN, not
the reverse, that needs to keep working.</p>
<p>The one wrinkle worth calling out for anyone doing this themselves: mDNS and
similar local-discovery protocols don&rsquo;t cross VLAN boundaries. Anything that
relies on discovery (some smart-home integrations) needs a static
IP/reservation instead of &ldquo;just works&rdquo; auto-discovery once it&rsquo;s segmented.</p>
<h2 id="naming-things-like-infrastructure-not-like-guesses">Naming things like infrastructure, not like guesses</h2>
<p>A smaller but satisfying piece of this: formalizing a DNS naming standard.
Some of my hostnames dated back to a previous job&rsquo;s naming convention (CLLI
codes, if you know, you know) and had long since stopped meaning anything to
anyone but me. The new standard is boring on purpose — a short role code
plus a number for physical hosts (router, switch, storage, etc.), the
purpose itself as the name for single-role VMs, and a separate tier of
service aliases that point at whichever host currently provides a service
and move with it if that ever changes. It&rsquo;s a small thing, but &ldquo;the name
tells you what it is&rdquo; pays for itself every time you&rsquo;re debugging at 11pm.</p>
<h2 id="where-this-leaves-things">Where this leaves things</h2>
<p>None of this is exotic — a graph database, a syslog watcher, some MCP
servers, and a VLAN. What made it worth doing was treating a home network
like it deserves the same basic care as any other system I run: know what&rsquo;s
on it, get told when it breaks, and keep the blast radius of any one
compromised device small. The AI-copilot layer is the part I&rsquo;d call
genuinely new — not because it does anything a human couldn&rsquo;t, but because
it turns &ldquo;let me SSH into six things to check&rdquo; into a conversation grounded
in what the network actually looks like right now.</p>
]]></content:encoded></item></channel></rss>