Homelab.
The hardware that runs everything else on this site.
Two parts that act like one. A segmented network (an open-source firewall, several VLANs) and a self-learning climate + energy system (a custom controller, with a BigQuery store behind it). The other technical projects on this site run on top of this. The configuration itself lives in private repos — this page is the deliberately high-level public version, light on the specifics on purpose.
Several VLANs, segmented on purpose.
The network exists so the rest of the system can. Every service that runs locally — climate, audio, surveillance, automations — sits on a VLAN that matches its trust level. A misbehaving device gets blast-radiused by its segment, not by the firewall's patience.
| VLAN | Purpose |
|---|---|
| Management | Network infrastructure itself — firewall, switches, controllers. |
| Secure | High-trust devices, including camera recording. Tight egress. |
| Trusted | Personal laptops, phones, workstations. |
| IoT | Smart-home devices that should never talk to anything they don't have a reason to talk to. |
| Guest | Anyone visiting. No lateral access. |
| Bootstrap (legacy) | A path that exists only to bootstrap, so a misconfiguration on a VLAN never locks the network out of itself. |
The shape of the hardware
| Layer | Detail |
|---|---|
| Firewall | An open-source firewall/router OS handles routing, DHCP and the WAN handoff. The ISP delivers WAN on a tagged VLAN — that single handoff is the load-bearing piece between the house and the internet. |
| Switching | A managed switching stack: a 10Gb aggregation layer down to 1Gb distribution over fibre. |
| Wireless | Several access points from a single vendor. Two SSIDs broadcast — one bound to the Trusted VLAN, one to the IoT VLAN — so a smart bulb never lands on the same broadcast domain as a laptop. |
| Cameras | A segmented surveillance system on a dedicated recorder. Recording stays on the Secure VLAN; egress is firewalled at the network boundary. |
| Inter-VLAN services | mDNS reflection, UDP broadcast relay, and IGMP Proxy configured per-VLAN. Required to make AirPlay and multi-brand multiroom discovery work across segments. |
One hub, one custom controller.
The climate side is a self-learning thermostat with real feedback loops, not a thermostat with an app. Lighting and presence run on the same hub through the same scripting layer.
| Layer | Detail |
|---|---|
| Controller | A custom controller — seasonal ranges, cold-feet prevention, a comfort-signal model. Earlier controller versions are kept as references so behaviour drift is debuggable. |
| Heating | Several floor-heating zones via Z-Wave relays, with more pending. The heat pump is driven by a wall relay rather than its own built-in thermostat. |
| Air conditioning | Multiple AC units behind a vendor cloud API. That API is rate-limited, so the controller treats polling cadence as a fixed budget. |
| Sensors | Temperature sensors feeding a thermal model. Per-room thermal lag is measured and used by the controller's lookahead. |
| Heating-rate ceiling | Per-room heating-rate ceilings are measured. The controller respects them — anything faster is a sensor reporting wrong, not a comfort win. |
| Lighting | Dozens of flows and scripts. Presence-aware, scene-aware, motion-aware per room. 'Adaptive' in the sense that the rules adapt to the time of day and the mode of the house, not in the sense that an LLM picks the temperature. |
The house front-runs the grid.
Dynamic Dutch energy prices change every hour and tomorrow's curve lands after 13:00. The controller plans heating, EV charging, and battery dispatch against the next 24 hours — not the current price.
| System | Role |
|---|---|
| Dynamic price feed | A Dutch dynamic-pricing feed (tomorrow's prices land after 13:00). The controller plans heating + EV charging against the price curve, not against the clock. |
| Solar + battery | Solar production and a house battery. The battery dispatches against the same price curve the heating reads. |
| EV charging | EV wall-charging, driven by the price feed. Charge during low-price windows by default; override by hand when needed. |
| Load shedding | The moment grid draw approaches the contract cap, the controller sheds the lowest-priority loads (deferred-acceptable ones first) instead of tripping the main. |
| EVs | Vehicle state-of-charge reports into the same data plane; charging syncs against the same price + load curve. |
Multi-brand audio — on one fabric.
Multi-brand audio on a segmented network is mostly a multicast problem. mDNS reflection, IGMP Querier and STP priority are the unglamorous primitives that make multiroom "just work" across VLANs.
| Brand | Detail |
|---|---|
| Primary multiroom stack | A paired set that needs tight clock sync — handled at the switch — plus a vendor API. Does multiroom and Apple AirPlay across rooms. |
| Second multiroom brand | Configured with STP priority + IGMP Querier so multicast discovery survives the VLAN-segmented network. |
| WiFi-only pair | Deliberately kept on the same VLAN as the controller, on 5GHz, so the vendor's auto-pairing works at all. |
Hub → Cloud Run → BigQuery.
The same data plane behind every interesting decision in the house. Every device, every five minutes — a real time-series, validated on ingest and persisted long-term for analysis.
| Layer | Detail |
|---|---|
| Capture | The hub polls every device every 5 minutes — sensors, switches, climate units, EV chargers, the lot. |
| Validate + ingest | A Cloud Run worker validates the payload, drops malformed rows, and inserts into BigQuery. |
| Analyse | BigQuery is the long-term store. Thermal-model fitting, energy-arbitrage backtests, lighting-pattern analysis — all SQL against the same data. |
| Loop back | Lessons from the offline analysis become controller-version bumps. The production loop stays simple; the analysis loop stays curious. |
The lessons the network learned the hard way.
- Segment before you optimise
- The IoT segment exists so a smart appliance with questionable firmware physically cannot pivot to a workstation. Every other 'smart home' problem is easier once that's true.
- Keep a bootstrap path
- A bootstrap path to the firewall stays around. Not for production — for the day a VLAN change is wrong and the firewall has to be reached without the config that's broken.
- One source of truth per service
- One DHCP service, not three. Configurations that 'mostly' work because multiple services are mostly-coordinating are how networks rot in private.
- Inter-VLAN services are explicit, not implicit
- mDNS reflection, UDP broadcast relay, IGMP Proxy. Each one written down per-VLAN, because every audio brand needs a slightly different one and forgetting one breaks the multiroom in a subtle way.
- Climate is a controller, not a chatbot
- The thermostat is a deterministic model with seasonal ranges and cold-feet prevention. No LLM picks the setpoint. AI lives in the offline analytics layer that explains why a zone behaved oddly — not in the production loop.
- Energy arbitrage uses tomorrow's prices
- The next day's price curve publishes after 13:00. Heating windows + EV charging schedule against the next 24h, not the current hour. The house front-runs the grid.
- Cloud APIs have budgets, not guidelines
- Some vendor cloud APIs are rate-limited. The controller treats the cap as a hard budget — adapting polling cadence so it's never hit and the API stays responsive.
- Logs are the ground truth
- Every measurement, every controller decision, every device state lands in BigQuery. Every weird behaviour can be back-traced. The data plane is the debugger.
Half of it is craft for craft's sake — running a real network at home is a privilege and a hobby. The other half is operational: if Luminary needs a fresh checkout to deploy from, or Shop Life needs a private WhatsApp webhook to land, or Bedtime Stories needs a place to render that isn't metered — the homelab is the floor everything else stands on. Worth writing down for that reason alone.