Home Assistant now pulls homelab-blueprint from Forgejo through Caddy, which needed both a UniFi zone rule (IoT -> CADDY) and a ufw allow on the Caddy host itself for the IoT subnet — two independent enforcement layers, both previously missing/misconfigured.
7.5 KiB
Caddy Firewall Policies — Missing and Incorrect Rules
Note
For the complete list of custom firewall rules, see firewall-rules.md.
Audit findings from the zone policy review. Apply these in UniFi
Settings → Policy Engine → Policy Table in the order shown. All
custom policies must be above the built-in Block All Traffic terminal
rule.
0. Immediate Cleanup — Redundant and Incorrect Rules
Sort these out before adding anything new.
Delete — completely redundant
| Policy | Why |
|---|---|
Allow CADDY to Gateway DNS |
The Caddy Pi's resolv.conf points to Technitium at 10.0.10.5 (TRUSTED). Allow CADDY to DNS already covers that. The UDM Gateway DNS forwarder is not in use. |
Keep — intra-zone rules that are actually required
UniFi's documentation implies intra-zone traffic is allowed by default, but in practice this does not apply to custom zones — removing these breaks intra-zone traffic.
| Policy | Why to keep |
|---|---|
Allow TRUSTED to TRUSTED Any |
Without this rule, devices within TRUSTED cannot reach each other (confirmed: removing it broke SSH to Technitium). |
Allow IoT to IoT Any |
Same — IoT intra-zone traffic requires an explicit allow for custom zones. |
Fix — wrong action
| Policy | Problem | Fix |
|---|---|---|
Allow FAMILY to CADDY |
Action is set to Block instead of Allow. FAMILY devices cannot reach Caddy at all. | Edit the policy and change Action to Allow. |
Review — direct pinholes that bypass Caddy
These work but contradict the network design (§7.3/7.4), which says MEDIA
and FAMILY should only reach internal services through Caddy. Once the
ALLOW CADDY to arr stack backend policy (§2 below) is in place, both
zones can reach Emby via emby.yourdomain.com through Caddy instead.
| Policy | Impact of keeping | Impact of removing |
|---|---|---|
Allow MEDIA to Emby |
Apple TV can connect directly to LXC — wider attack surface, bypasses Caddy logging and auth. | Apple TV must use emby.yourdomain.com via Caddy. Requires Caddy backend policy in place first. |
Allow FAMILY to EMBY |
Family devices bypass Caddy for Emby. | Family devices must use emby.yourdomain.com via Caddy. Requires Caddy backend policy in place first. |
Remove these only after the ALLOW CADDY to arr stack policy is
created and confirmed working.
1. Fix: Allow FAMILY to CADDY (currently set to Block)
The existing Allow FAMILY to CADDY policy has Action = Block. Edit
it and change the action to Allow.
| Field | Value |
|---|---|
| Name | Allow FAMILY to CADDY |
| Action | Allow (currently wrong — set to Block) |
| Source zone | FAMILY |
| Source IP | Any |
| Destination zone | CADDY |
| Destination IP | Any |
| Destination port | 443 |
| Protocol | TCP |
2. CADDY → TRUSTED Backend App Policies
Caddy at 10.0.15.5 cannot proxy to any backend apps in the TRUSTED zone
until these policies exist. Create one policy per row.
Every policy in this table uses:
- Action: Allow
- Source zone:
CADDY - Source IP:
10.0.15.5 - Destination zone:
TRUSTED - Protocol: TCP
| Policy name | Destination IP | Destination port(s) | Purpose |
|---|---|---|---|
ALLOW CADDY to arr stack |
10.0.10.20 |
5055,6767,7878,8000,8080,8096,8191,8282,8989,9696 |
Arr-stack LXC (bazarr, radarr, gluetun, qbittorrent, emby, flaresolverr, sabnzbd, sonarr, prowlarr, seerr) |
ALLOW CADDY to Technitium UI |
10.0.10.5 |
5380 |
Technitium admin UI |
ALLOW CADDY to Proxmox |
10.0.10.10 |
8006 |
Proxmox VE |
ALLOW CADDY to PBS |
10.0.10.8 |
8007 |
Proxmox Backup Server |
ALLOW CADDY to LAN web devices |
10.0.1.6 |
80 |
Lite-8 PoE switch UI |
ALLOW CADDY to Beszel |
10.0.10.13 |
8090 |
Beszel monitoring |
ALLOW CADDY to Gramps |
10.0.10.17 |
80 |
Gramps Web |
ALLOW CADDY to Immich |
10.0.10.15 |
2283 |
Immich |
ALLOW CADDY to IT Tools |
10.0.10.7 |
80 |
IT Tools |
ALLOW CADDY to Paperless |
10.0.10.11 |
8000 |
Paperless-ngx |
ALLOW CADDY to YTD |
10.0.10.14 |
3087 |
Youtarr |
ALLOW CADDY to Bento PDF |
10.0.10.6 |
8080 |
Bento PDF |
ALLOW CADDY to Koffan |
10.0.10.12 |
8080 |
Koffan (LXC 111) |
ALLOW CADDY to Hermes |
10.0.10.19 |
9119 |
Hermes Agent dashboard (LXC 113) |
ALLOW CADDY to Forgejo |
10.0.10.18 |
3000 |
Forgejo (LXC 114) |
3. CADDY → IoT Backend Policies
Caddy cannot proxy to Home Assistant or Zigbee until these exist.
Every policy in this table uses:
- Action: Allow
- Source zone:
CADDY - Source IP:
10.0.15.5 - Destination zone:
IoT - Protocol: TCP
| Policy name | Destination IP | Destination port(s) | Purpose |
|---|---|---|---|
ALLOW CADDY to Home Automation |
10.0.30.6 |
8080,8123 |
Zigbee2MQTT and Home Assistant |
ALLOW CADDY to Zigbee |
10.0.30.5 |
80 |
SLZB-06U Zigbee coordinator UI |
3a. IoT → CADDY Policies (reverse direction)
The Home Assistant host itself also needs to reach Caddy directly — it
pulls homelab-blueprint from Forgejo (git.home.brianpooe.com, proxied
through Caddy) to deploy its own docker-compose stack.
Two independent layers enforce traffic into the Caddy host — both must allow it, and both were found misconfigured while wiring this up:
-
UniFi zone-based firewall (router-level, VLAN → VLAN):
Policy name Source zone Source IP Src. Port Destination zone Destination IP Destination port(s) Purpose Allow HA to CaddyIoT10.0.30.6(Home Assistant IP)AnyCADDY10.0.15.5(Caddy IP)443git fetch/pull of homelab-blueprint from Forgejo Src. Port must be
Any, not restricted to HA's own listening ports (8080/8123) — this is outbound traffic from HA, so the source port is a random ephemeral port, not the port HA listens on. Setting Src. Port to a "Home Assistant" port object here was the original bug: the rule never matched, so traffic fell through toBlock All Trafficbelow it. -
ufwon the Caddy host itself (10.0.15.5) — a second, separate enforcement point the UniFi rule doesn't touch. It allow-lists inbound 80/443 per source subnet and did not include the IoT VLAN (10.0.30.0/24):sudo ufw allow from 10.0.30.0/24 to any port 80,443 proto tcpufw statuson that host is the fastest way to check which subnets can already reach it before assuming a UniFi rule is the problem.
4. Public DNS Block Policies (per zone)
Without these, devices can bypass Technitium by querying public resolvers
(8.8.8.8, 1.1.1.1, etc.) directly. Place each policy above the
broad External allow for its zone.
Every policy in this table uses:
- Action: Block
- Source IP: Any
- Destination zone:
External - Destination IP: Any
- Protocol: TCP/UDP
- Destination port:
53
| Policy name | Source zone |
|---|---|
BLOCK FAMILY public DNS |
FAMILY |
BLOCK MEDIA public DNS |
MEDIA |
BLOCK IoT public DNS |
IoT |
BLOCK GUEST public DNS |
GUEST |
Policy Order Reference
Within each zone's rule set, the evaluation order must be:
specific allows (DNS, DHCP, Caddy, app pinholes)
public DNS block (above the External allow)
External allow
Gateway DHCP allow
Gateway block
Block All Traffic ← built-in terminal rule
If a broad block rule sits above a specific allow, the block wins and the intended traffic is dropped. Use Reorder in UniFi to verify positions after adding new policies.