Architecture¶
Last Updated: 2026-04-13 Purpose: How the system fits together โ diagrams and design decisions.
How a Smart Light Works¶
When you tap a light in the Home Assistant app, here's what happens:
flowchart LR
user("๐ฑ You\nPhone app / browser\nWall display")
ha("๐ Home Assistant\nPacific ยท 192.168.1.12")
bridge("๐ก Zigbee Bridge\nLiving room ยท 192.168.20.10")
bulb("๐ก Smart Bulb\nZigbee")
user -->|"Tap light on/off"| ha
ha -->|"WiFi command\nIoT VLAN"| bridge
bridge -->|"Zigbee signal\nwireless"| bulb
bulb -->|"Confirms state"| bridge
bridge -->|"State update"| ha
ha -->|"Updates display"| user
In plain English: You tap the light. Home Assistant tells the Zigbee Bridge. The bridge sends a wireless signal to the bulb. The bulb responds, and Home Assistant updates to show the new state.
If any link in that chain is broken โ the bridge has lost its connection, or Home Assistant isn't running โ the light won't respond. That's why the Zigbee Bridge fix starts by checking the bridge before going into Home Assistant.
Overall System Overview¶
flowchart TB
internet("๐ Internet")
subgraph wan["WAN"]
bt("Vodafone ADSL\nBedroom wardrobe")
end
router("๐ UniFi Router\n192.168.1.1")
subgraph office["Office Outbuilding"]
lotus("๐ฅ๏ธ Lotus\nPrimary NAS\n192.168.1.80\nDocker services")
brabham("๐ป Brabham\nDesktop PC\n192.168.1.40")
end
subgraph house["House"]
cooper("๐ฅ๏ธ Cooper\nBackup NAS\n192.168.1.60")
pacific("๐ฅ๏ธ Pacific\nProxmox NUC\n192.168.1.10")
ha("๐ Home Assistant\n192.168.1.12")
bridge("๐ก Zigbee Bridge\n192.168.20.10")
display("๐ฅ๏ธ Wall Display\nLiving room")
end
subgraph cloud["Cloud"]
cf("โ๏ธ Cloudflare\ndocs.djchome.uk")
nabu("๐ Nabu Casa\nha.djchome.uk")
tailscale("๐ Tailscale\n*.djchome.uk")
end
internet --- bt
bt --> router
router --> lotus & cooper & pacific & brabham & bridge
pacific --> ha
ha <--> bridge
ha <--> display
lotus -->|"Backups"| cooper
lotus <-->|"Reverse proxy\nSWAG"| tailscale
tailscale --- internet
cf --- internet
ha <--> nabu
nabu --- internet
External Access¶
When you access a service like ha.djchome.uk from outside the house:
flowchart LR
phone("๐ฑ Your phone\nAnywhere")
nabu("โ๏ธ Nabu Casa\nCloud relay")
ha("๐ Home Assistant\n192.168.1.12")
phone -->|"https://ha.djchome.uk"| nabu
nabu <-->|"Secure tunnel"| ha
For other services (e.g. Plex, Immich) accessed via *.djchome.uk:
flowchart LR
phone("๐ฑ Your phone\nAnywhere")
cf("โ๏ธ Cloudflare DNS\n*.djchome.uk")
ts("๐ Tailscale\nVPN mesh")
swag("๐ SWAG\nReverse proxy\nLotus")
service("๐ฆ Service\ne.g. Plex")
phone -->|"Request"| cf
cf -->|"Resolves to\nTailscale IP"| ts
ts -->|"Routes to Lotus\nvia VPN"| swag
swag -->|"Forwards to\ncorrect container"| service
No ports are open directly to the internet. Access to services (other than Nabu Casa and the docs site) requires being on the Tailscale network.
Design Decisions¶
Why two Unraid NAS devices?¶
Lotus (office) and Cooper (living room) are in separate buildings, providing physical redundancy. Lotus runs all active services; Cooper is a backup target with minimal services to avoid unnecessary disk activity.
Why Proxmox on a separate NUC?¶
Home Assistant runs best on its own hardware with full OS control (HAOS). Pacific keeps HA isolated from the Unraid servers and allows Zigbee/USB passthrough. It also hosts the Tailscale exit node independently of Lotus.
Why Tailscale + SWAG instead of open ports?¶
No ports are exposed directly to the internet. Cloudflare DNS resolves *.djchome.uk to Lotus's Tailscale IP โ only devices on the Tailnet can reach it. This means services are private by default without needing a firewall rule per service.
Documentation resilience¶
The docs site is hosted on Cloudflare Pages (docs.djchome.uk) so it remains accessible even if the entire home infrastructure is down. A local mirror on Cooper is planned for when the internet is out.