Router-Hosts dnsmasq Cutover Design
Goal: Complete the router-hosts integration by adding missing DNS entries and enabling the dnsmasq cutover so the Firewalla reads from the router-hosts managed hosts file.
Status: The router-hosts server, K8s operator, and Terraform provider are all operational. This is the final cutover step.
Current State
Section titled “Current State”| Component | Status |
|---|---|
| router-hosts server | ✅ Running on Firewalla (v0.8.7) |
| Vault Agent mTLS | ✅ Auto-renewing certificates |
| Terraform provider | ✅ Managing infrastructure hosts |
| K8s operator | ✅ Managing IngressRoute/IngressRouteTCP hosts |
| dnsmasq integration | ❌ Still reading from /extdata/hosts (old location) |
Gap: dnsmasq reads from /extdata/hosts (manual), not /extdata/router-hosts/hosts (managed).
Missing Entries
Section titled “Missing Entries”Entries in old /extdata/hosts/main not yet in router-hosts:
| Entry | Type | IP | Resolution |
|---|---|---|---|
argocd.fzymgc.house | K8s Ingress | .145 | Add annotation to Helm values |
grafana.fzymgc.house | K8s Ingress (grafana-operator) | .145 | Add annotation to Grafana CR |
loki.fzymgc.house | LoadBalancer (no ingress) | .146 | Add to Terraform |
logs.fzymgc.house | Alias for loki | .146 | Add to Terraform |
k8s-cluster.fzymgc.house | Legacy alias | .140 | Add alias to k8s-api TF entry |
garage.fzymgc.house | NAS app | .201 | Add to Terraform |
s3.garage.fzymgc.house | NAS app | .201 | Add to Terraform |
admin.garage.fzymgc.house | NAS app | .201 | Add to Terraform |
nas-portainer.fzymgc.house | NAS app | .201 | Add to Terraform |
nas-storj.fzymgc.house | NAS app | .201 | Add to Terraform |
nas-syncthing-sean.fzymgc.house | NAS app | .201 | Add to Terraform |
nas-app-proxy.fzymgc.house | NAS app | .201 | Add to Terraform |
nas-apps-proxy.fzymgc.house | NAS app | .201 | Add to Terraform |
nas-npm.fzymgc.house | NAS app | .201 | Add to Terraform |
Dropped entries (not migrating):
- mc1 cluster (192.168.21.x) - different subnet, unused
tp-alpha-*naming - old convention,tpi-alpha-*is correctnas.fzymgc.house- usenas-alpha.fzymgc.house- IPv6 NAS entries - not needed
- windmill - being decommissioned
Implementation Tasks
Section titled “Implementation Tasks”Task 1: Add ArgoCD Ingress Annotation
Section titled “Task 1: Add ArgoCD Ingress Annotation”File: argocd/app-configs/argocd/values.yaml
Add to server ingress annotations:
server: ingress: annotations: router-hosts.fzymgc.house/enabled: "true"Task 2: Add Grafana Ingress Annotation
Section titled “Task 2: Add Grafana Ingress Annotation”File: Grafana CR in argocd/app-configs/grafana/
Add annotation to ingress configuration in the Grafana custom resource.
Task 3: Add Terraform Entries
Section titled “Task 3: Add Terraform Entries”File: tf/router-hosts/hosts.tf
# Legacy alias for k8s-api# Update existing k8s-api entry to include aliasresource "routerhosts_entry" "k8s_api" { hostname = "k8s-api" ip = "192.168.20.140" aliases = ["k8s-cluster"] # Add legacy alias comment = "Kubernetes API VIP (kube-vip)" tags = ["terraform", "infrastructure", "kubernetes"]}
# Loki (separate LoadBalancer IP)resource "routerhosts_entry" "loki" { hostname = "loki" ip = "192.168.20.146" aliases = ["logs"] comment = "Loki log aggregation" tags = ["terraform", "infrastructure", "observability"]}
# NAS Apps (on nas-alpha NPM)resource "routerhosts_entry" "garage" { hostname = "garage" ip = "192.168.20.201" aliases = ["s3.garage", "admin.garage"] comment = "Garage S3-compatible storage" tags = ["terraform", "infrastructure", "nas"]}
resource "routerhosts_entry" "nas_portainer" { hostname = "nas-portainer" ip = "192.168.20.201" comment = "NAS Portainer management" tags = ["terraform", "infrastructure", "nas"]}
resource "routerhosts_entry" "nas_storj" { hostname = "nas-storj" ip = "192.168.20.201" comment = "NAS Storj node" tags = ["terraform", "infrastructure", "nas"]}
resource "routerhosts_entry" "nas_syncthing_sean" { hostname = "nas-syncthing-sean" ip = "192.168.20.201" comment = "NAS Syncthing for sean" tags = ["terraform", "infrastructure", "nas"]}
resource "routerhosts_entry" "nas_app_proxy" { hostname = "nas-app-proxy" ip = "192.168.20.201" aliases = ["nas-apps-proxy"] comment = "NAS application proxy" tags = ["terraform", "infrastructure", "nas"]}
resource "routerhosts_entry" "nas_npm" { hostname = "nas-npm" ip = "192.168.20.201" comment = "NAS Nginx Proxy Manager" tags = ["terraform", "infrastructure", "nas"]}Task 4: Enable dnsmasq Cutover
Section titled “Task 4: Enable dnsmasq Cutover”Method: Run Ansible playbook with cutover variable:
ansible-playbook -i inventory/hosts.yml router-hosts-playbook.yml \ -e router_hosts_enable_dnsmasq_cutover=trueThis will:
- Deploy
local-hosts.confpointing to/extdata/router-hosts/hosts - Reload dnsmasq
Task 5: Verify Cutover
Section titled “Task 5: Verify Cutover”# Verify dnsmasq config updatedssh pi@192.168.20.1 "cat ~/.firewalla/config/dnsmasq_local/local-hosts.conf"
# Test DNS resolutiondig @192.168.20.1 argocd.fzymgc.house +shortdig @192.168.20.1 grafana.fzymgc.house +shortdig @192.168.20.1 loki.fzymgc.house +shortdig @192.168.20.1 garage.fzymgc.house +short
# Verify all entries presentrouter-hosts host list | wc -lRollback
Section titled “Rollback”If issues occur after cutover:
# Revert dnsmasq to old hosts filessh pi@192.168.20.1 "echo 'hostsdir=/extdata/hosts' > ~/.firewalla/config/dnsmasq_local/local-hosts.conf"ssh pi@192.168.20.1 "sudo systemctl reload firerouter_dns"Post-Cutover Cleanup
Section titled “Post-Cutover Cleanup”After successful cutover and verification:
- Archive the old
/extdata/hosts/mainfile - Archive this design doc to
docs/plans/archive/ - Update
docs/operations/router-hosts.mdif needed