<?xml version="1.0" encoding="UTF-8"?>
<feed xmlns="http://www.w3.org/2005/Atom" xml:lang="en">
    <title>hejhej.dev</title>
    <subtitle>A small blog.</subtitle>
    <link rel="self" type="application/atom+xml" href="https://hejhej.dev/atom.xml"/>
    <link rel="alternate" type="text/html" href="https://hejhej.dev"/>
    <generator uri="https://www.getzola.org/">Zola</generator>
    <updated>2026-10-30T00:00:00+00:00</updated>
    <id>https://hejhej.dev/atom.xml</id>
    <entry xml:lang="en">
        <title>An agentic home router?</title>
        <published>2026-10-30T00:00:00+00:00</published>
        <updated>2026-10-30T00:00:00+00:00</updated>
        
        <author>
          <name>
            
              Unknown
            
          </name>
        </author>
        
        <link rel="alternate" type="text/html" href="https://hejhej.dev/agentic-router/"/>
        <id>https://hejhej.dev/agentic-router/</id>
        
        <content type="html" xml:base="https://hejhej.dev/agentic-router/">&lt;figure&gt;
  &lt;img src=&quot;https:&#x2F;&#x2F;hejhej.dev&#x2F;processed_images&#x2F;pi-screen.c011abaf5dc9b919.png&quot; width=&quot;1600&quot; height=&quot;960&quot; alt=&quot;A black screen of grey bars: upload above a time axis running from late evening to morning, download hanging below it, with the line&amp;#x27;s status, today&amp;#x27;s totals and the current rate along the top&quot; loading=&quot;lazy&quot; decoding=&quot;async&quot;&gt;&lt;figcaption&gt;The Raspberry Pi&amp;#x27;s screen: the internet line&amp;#x27;s last 12 hours, upload above the axis, download below, a bar per five minutes.&lt;&#x2F;figcaption&gt;
&lt;&#x2F;figure&gt;
&lt;p&gt;My home router is a small x86 box running &lt;a rel=&quot;noopener noreferrer external&quot; target=&quot;_blank&quot; href=&quot;https:&#x2F;&#x2F;nixos.org&quot;&gt;NixOS&lt;&#x2F;a&gt;, mostly built with an AI
coding agent. That sounds risky, but the setup keeps it reasonable, and the payoff is a prompt
for any question about my network.&lt;&#x2F;p&gt;
&lt;figure style=&quot;max-width: 320px&quot;&gt;
  &lt;img src=&quot;https:&#x2F;&#x2F;hejhej.dev&#x2F;processed_images&#x2F;router.63dc0443ed215ad5.jpg&quot; width=&quot;640&quot; height=&quot;386&quot; alt=&quot;A small black fanless box with cooling fins on top and, on the front, four Ethernet ports labelled ETH0 to ETH3, two USB ports, two HDMI ports and a 12 V power jack&quot; loading=&quot;lazy&quot; decoding=&quot;async&quot;&gt;&lt;figcaption&gt;The router: a fanless mini PC with four 2.5 GbE ports (the seller&amp;#x27;s photo).&lt;&#x2F;figcaption&gt;
&lt;&#x2F;figure&gt;
&lt;h2 id=&quot;ask-it-anything&quot;&gt;Ask it anything&lt;&#x2F;h2&gt;
&lt;p&gt;The router logs every connection, DNS answer, block and drop into
&lt;a rel=&quot;noopener noreferrer external&quot; target=&quot;_blank&quot; href=&quot;https:&#x2F;&#x2F;www.postgresql.org&quot;&gt;PostgreSQL&lt;&#x2F;a&gt; on the home server, already labelled with device
names. So I just ask:&lt;&#x2F;p&gt;
&lt;ul&gt;
&lt;li&gt;“Why was there a traffic spike last night?”&lt;&#x2F;li&gt;
&lt;li&gt;“Why is my Mac uploading so much?”&lt;&#x2F;li&gt;
&lt;li&gt;“Which device started talking to a new domain?”&lt;&#x2F;li&gt;
&lt;&#x2F;ul&gt;
&lt;figure&gt;
  &lt;img src=&quot;https:&#x2F;&#x2F;hejhej.dev&#x2F;processed_images&#x2F;blocked.97b7936df5a90576.png&quot; width=&quot;1520&quot; height=&quot;1016&quot; alt=&quot;A terminal window: the question &amp;#x27;what&amp;#x27;s getting blocked the most today?&amp;#x27;, the SQL query the agent wrote, a table of blocked domains per device with counts (a Datadog log intake 614 times from the server, Teams telemetry 248 from the Mac, the Wi-Fi controller&amp;#x27;s traces 136), and the agent&amp;#x27;s answer that it&amp;#x27;s almost all telemetry&quot; loading=&quot;lazy&quot; decoding=&quot;async&quot;&gt;&lt;figcaption&gt;One question, one query: today&amp;#x27;s blocklist hits are almost all telemetry.&lt;&#x2F;figcaption&gt;
&lt;&#x2F;figure&gt;
&lt;p&gt;The agent writes the SQL and explains the answer. Questions that keep coming back become
&lt;a rel=&quot;noopener noreferrer external&quot; target=&quot;_blank&quot; href=&quot;https:&#x2F;&#x2F;grafana.com&#x2F;oss&#x2F;grafana&#x2F;&quot;&gt;Grafana&lt;&#x2F;a&gt; panels, or the
&lt;a rel=&quot;noopener noreferrer external&quot; target=&quot;_blank&quot; href=&quot;https:&#x2F;&#x2F;www.raspberrypi.com&quot;&gt;Raspberry Pi&lt;&#x2F;a&gt; screen at the top.&lt;&#x2F;p&gt;
&lt;h2 id=&quot;why-it-works&quot;&gt;Why it works&lt;&#x2F;h2&gt;
&lt;ul&gt;
&lt;li&gt;&lt;strong&gt;Config in git.&lt;&#x2F;strong&gt; The router is a &lt;a rel=&quot;noopener noreferrer external&quot; target=&quot;_blank&quot; href=&quot;https:&#x2F;&#x2F;wiki.nixos.org&#x2F;wiki&#x2F;Flakes&quot;&gt;Nix flake&lt;&#x2F;a&gt;; every
change is a diff I can read.&lt;&#x2F;li&gt;
&lt;li&gt;&lt;strong&gt;Tested in VMs.&lt;&#x2F;strong&gt; NixOS’s
&lt;a rel=&quot;noopener noreferrer external&quot; target=&quot;_blank&quot; href=&quot;https:&#x2F;&#x2F;nixos.org&#x2F;manual&#x2F;nixos&#x2F;stable&#x2F;#sec-nixos-tests&quot;&gt;test framework&lt;&#x2F;a&gt; boots a router
between a fake ISP and LAN clients; a red test stops the deploy.&lt;&#x2F;li&gt;
&lt;li&gt;&lt;strong&gt;Deploys undo themselves&lt;&#x2F;strong&gt; unless I confirm within 120 seconds.&lt;&#x2F;li&gt;
&lt;li&gt;&lt;strong&gt;I decide when it ships.&lt;&#x2F;strong&gt;&lt;&#x2F;li&gt;
&lt;&#x2F;ul&gt;
&lt;h2 id=&quot;privacy-and-security&quot;&gt;Privacy and security&lt;&#x2F;h2&gt;
&lt;p&gt;Network logs are personal, and some of them are written by strangers (User-Agents, domain
names), which an agent could be steered by. So the sensitive part stays home:&lt;&#x2F;p&gt;
&lt;ul&gt;
&lt;li&gt;&lt;strong&gt;A local model reads the raw logs&lt;&#x2F;strong&gt; and hands the hosted agent only a summary.&lt;&#x2F;li&gt;
&lt;li&gt;&lt;strong&gt;Queries use a read-only database role.&lt;&#x2F;strong&gt;&lt;&#x2F;li&gt;
&lt;li&gt;&lt;strong&gt;Log questions run without deploy keys.&lt;&#x2F;strong&gt;&lt;&#x2F;li&gt;
&lt;&#x2F;ul&gt;
&lt;p&gt;Depending on the model you use, this may not be a great idea for your security or privacy.&lt;&#x2F;p&gt;
&lt;h2 id=&quot;was-it-worth-it&quot;&gt;Was it worth it?&lt;&#x2F;h2&gt;
&lt;p&gt;For most people, no: the router from the ISP does everything they need. If you want more,
there are good options that just work: a mesh system like
&lt;a rel=&quot;noopener noreferrer external&quot; target=&quot;_blank&quot; href=&quot;https:&#x2F;&#x2F;store.google.com&#x2F;category&#x2F;connected_home&quot;&gt;Google Nest Wifi&lt;&#x2F;a&gt;, a
&lt;a rel=&quot;noopener noreferrer external&quot; target=&quot;_blank&quot; href=&quot;https:&#x2F;&#x2F;ui.com&#x2F;cloud-gateways&quot;&gt;UniFi&lt;&#x2F;a&gt; gateway with a nice dashboard, or
&lt;a rel=&quot;noopener noreferrer external&quot; target=&quot;_blank&quot; href=&quot;https:&#x2F;&#x2F;opnsense.org&quot;&gt;OPNsense&lt;&#x2F;a&gt; and &lt;a rel=&quot;noopener noreferrer external&quot; target=&quot;_blank&quot; href=&quot;https:&#x2F;&#x2F;openwrt.org&quot;&gt;OpenWrt&lt;&#x2F;a&gt; if you want more control. But if
you’re curious how networks are
put together (zones, DHCP, DNS, what your devices actually do all day), building one like this
teaches a lot, and any question about my network is now one sentence away.&lt;&#x2F;p&gt;
</content>
        
    </entry>
</feed>
