Update DNS host deployment details

This commit is contained in:
Brian Pooe 2026-06-15 11:19:21 +02:00
parent 708f260cfc
commit 7628ddac36
5 changed files with 100 additions and 36 deletions

View file

@ -100,7 +100,7 @@ CADDY_OFFICE_PREFIX=10.0.10
# DNS stack (Technitium) # DNS stack (Technitium)
# Bind IP for DNS service (Technitium on Office VLAN 10) # Bind IP for DNS service (Technitium on Office VLAN 10)
DNS_BIND_IP=10.0.10.3 DNS_BIND_IP=10.0.10.5
TECHNITIUM_WEB_BIND_IP=0.0.0.0 TECHNITIUM_WEB_BIND_IP=0.0.0.0
TECHNITIUM_WEB_PORT=5380 TECHNITIUM_WEB_PORT=5380
TECHNITIUM_WEB_CONTAINER_PORT=5380 TECHNITIUM_WEB_CONTAINER_PORT=5380

View file

@ -81,7 +81,7 @@ zigbee.{{CADDY_BASE_DOMAIN:-home.example.com}} {
## 2) DNS services ## 2) DNS services
dns01.{{CADDY_BASE_DOMAIN:-home.example.com}} { dns01.{{CADDY_BASE_DOMAIN:-home.example.com}} {
import common import common
reverse_proxy {{DNS_BIND_IP:-10.0.10.3}}:5380 reverse_proxy {{DNS_BIND_IP:-10.0.10.5}}:5380
} }
## 3) Office services ## 3) Office services

View file

@ -39,7 +39,7 @@ project root.
CADDY_LAN_PREFIX=10.0.1 CADDY_LAN_PREFIX=10.0.1
CADDY_OFFICE_PREFIX=10.0.10 CADDY_OFFICE_PREFIX=10.0.10
CADDY_IOT_PREFIX=10.0.30 CADDY_IOT_PREFIX=10.0.30
DNS_BIND_IP=10.0.10.3 DNS_BIND_IP=10.0.10.5
CADDY_MEM_LIMIT=256m CADDY_MEM_LIMIT=256m
DOCKERLOGGING_MAXFILE=3 DOCKERLOGGING_MAXFILE=3
@ -99,7 +99,7 @@ docker compose -f docker-compose.caddy.yml exec caddy caddy reload --config /etc
In your internal DNS server: In your internal DNS server:
1. Add an `A` record named `caddy` pointing to the Caddy host. 1. Add an `A` record named `caddy` pointing to the Caddy host at `10.0.15.5`.
2. Add a wildcard `CNAME` named `*` pointing to 2. Add a wildcard `CNAME` named `*` pointing to
`caddy.home.example.com`. `caddy.home.example.com`.
@ -125,6 +125,31 @@ docker compose -f docker-compose.caddy.yml logs --tail=100 caddy
If certificate issuance fails, confirm the Cloudflare token permissions and If certificate issuance fails, confirm the Cloudflare token permissions and
ensure Caddy's public DNS queries are not redirected to internal DNS. ensure Caddy's public DNS queries are not redirected to internal DNS.
### Raspberry Pi OS Memory Limits
If Docker reports the following warning, Caddy still starts, but Docker ignores
`CADDY_MEM_LIMIT`:
```text
Your kernel does not support memory limit capabilities or the cgroup is not mounted. Limitation discarded.
```
Enable memory cgroups by appending these parameters to the existing single line
in `/boot/firmware/cmdline.txt`:
```text
cgroup_enable=memory cgroup_memory=1
```
Older Raspberry Pi OS releases may use `/boot/cmdline.txt`. Do not add a new
line to either file. Reboot and verify:
```bash
sudo reboot
docker info | grep -i warning
docker stats --no-stream caddy
```
## Useful Commands ## Useful Commands
```bash ```bash

View file

@ -34,7 +34,7 @@ project root.
```dotenv ```dotenv
TZ=Africa/Johannesburg TZ=Africa/Johannesburg
DNS_BIND_IP=10.0.10.3 DNS_BIND_IP=10.0.10.5
TECHNITIUM_ADMIN_PASSWORD=<strong-password> TECHNITIUM_ADMIN_PASSWORD=<strong-password>
TECHNITIUM_WEB_BIND_IP=0.0.0.0 TECHNITIUM_WEB_BIND_IP=0.0.0.0
@ -67,7 +67,7 @@ project root.
docker compose -f docker-compose.technitium.yml up -d docker compose -f docker-compose.technitium.yml up -d
``` ```
5. Verify the container and open `http://<HOST_IP>:5380`: 5. Verify the container and open `http://10.0.10.5:5380`:
```bash ```bash
docker compose -f docker-compose.technitium.yml ps docker compose -f docker-compose.technitium.yml ps
@ -91,13 +91,27 @@ In the Technitium admin interface:
1. Create the primary internal zone, for example `home.example.com`. 1. Create the primary internal zone, for example `home.example.com`.
2. Add records for internal services that do not use Caddy. 2. Add records for internal services that do not use Caddy.
3. If using Caddy, add an `A` record named `caddy` pointing to the Caddy host, 3. If using Caddy, add an `A` record named `caddy` pointing to `10.0.15.5`,
then add a wildcard `CNAME` named `*` pointing to then add a wildcard `CNAME` named `*` pointing to `caddy.home.example.com`.
`caddy.home.example.com`.
4. Configure DHCP to advertise the Technitium host as the DNS server. 4. Configure DHCP to advertise the Technitium host as the DNS server.
5. Configure the recommended blocklists below.
Use relative record names such as `caddy` and `*`, not full domain names. Use relative record names such as `caddy` and `*`, not full domain names.
### Recommended Blocklists
In **Settings > Blocking > Block List URLs**, add the lists you need:
| Purpose | URL |
|---|---|
| Ads and trackers | `https://cdn.jsdelivr.net/gh/hagezi/dns-blocklists@latest/wildcard/pro-onlydomains.txt` |
| Porn / NSFW | `https://cdn.jsdelivr.net/gh/hagezi/dns-blocklists@latest/wildcard/nsfw-onlydomains.txt` |
| Gambling | `https://cdn.jsdelivr.net/gh/hagezi/dns-blocklists@latest/wildcard/gambling-onlydomains.txt` |
The wildcard `onlydomains` format uses less memory than hosts-format lists.
Avoid `tif-onlydomains.txt` with the default 512 MB limit because it can cause
`OutOfMemoryException`. Click **Update Now** after changing the lists.
## Network Requirements ## Network Requirements
- Allow client networks to reach Technitium on TCP and UDP port `53`. - Allow client networks to reach Technitium on TCP and UDP port `53`.
@ -108,18 +122,18 @@ Use relative record names such as `caddy` and `*`, not full domain names.
Test DNS from a client: Test DNS from a client:
```bash ```bash
nslookup google.com 10.0.10.3 nslookup google.com 10.0.10.5
nslookup proxmox.home.example.com 10.0.10.3 nslookup proxmox.home.example.com 10.0.10.5
``` ```
Replace `10.0.10.3` and `home.example.com` with your configured values. Replace `10.0.10.5` and `home.example.com` with your configured values.
## Troubleshooting ## Troubleshooting
The following error means `DNS_BIND_IP` is not assigned to the host: The following error means `DNS_BIND_IP` is not assigned to the host:
```text ```text
failed to bind host port 10.0.10.3:53/tcp: cannot assign requested address failed to bind host port 10.0.10.5:53/tcp: cannot assign requested address
``` ```
Check the host addresses and port usage: Check the host addresses and port usage:
@ -132,6 +146,31 @@ sudo ss -lntup '( sport = :53 )'
Set `DNS_BIND_IP` to an assigned address or `0.0.0.0`, render the template Set `DNS_BIND_IP` to an assigned address or `0.0.0.0`, render the template
again, and restart the stack. again, and restart the stack.
### Raspberry Pi OS Memory Limits
If Docker reports the following warning, Technitium still starts, but Docker
ignores `TECHNITIUM_MEM_LIMIT`:
```text
Your kernel does not support memory limit capabilities or the cgroup is not mounted. Limitation discarded.
```
Enable memory cgroups by appending these parameters to the existing single line
in `/boot/firmware/cmdline.txt`:
```text
cgroup_enable=memory cgroup_memory=1
```
Older Raspberry Pi OS releases may use `/boot/cmdline.txt`. Do not add a new
line to either file. Reboot and verify:
```bash
sudo reboot
docker info | grep -i warning
docker stats --no-stream technitium-dns
```
## Useful Commands ## Useful Commands
```bash ```bash

View file

@ -12,7 +12,7 @@ Public-safe notation:
- Internal domain represented as `home.example.com`. - Internal domain represented as `home.example.com`.
Current deployment: Current deployment:
- Technitium runs in Docker on the Raspberry Pi at `10.0.10.3` on Office VLAN - Technitium runs in Docker on the Raspberry Pi at `10.0.10.5` on Office VLAN
10. 10.
- Office VLAN 10 is assigned to `TRUSTED`, so Technitium is a trusted-zone - Office VLAN 10 is assigned to `TRUSTED`, so Technitium is a trusted-zone
service. Explicit DNS allow rules are still required from restricted zones. service. Explicit DNS allow rules are still required from restricted zones.
@ -21,7 +21,7 @@ Current deployment:
Complete the migration in this dependency order: Complete the migration in this dependency order:
1. **Technitium DNS first:** make `10.0.10.3` authoritative for the internal 1. **Technitium DNS first:** make `10.0.10.5` authoritative for the internal
zone and verify direct DNS queries from every current VLAN. zone and verify direct DNS queries from every current VLAN.
2. **Caddy and DMZ second:** create VLAN 15, move Caddy to `10.0.15.5`, update 2. **Caddy and DMZ second:** create VLAN 15, move Caddy to `10.0.15.5`, update
Technitium's `caddy` record, and verify reverse-proxy and Netbird traffic. Technitium's `caddy` record, and verify reverse-proxy and Netbird traffic.
@ -64,7 +64,7 @@ UniFi 9.x permits custom zones. The defaults (`Internal`, `IoT`, `Hotspot`, `DMZ
| Zone | Type | VLAN(s) | Members | Consolidates | | Zone | Type | VLAN(s) | Members | Consolidates |
|---|---|---|---|---| |---|---|---|---|---|
| **TRUSTED** | Custom | 1 (`10.0.1.0/24`), 10 (`10.0.10.0/24`) | UDM, switch + AP mgmt, workstations, Proxmox host + app VMs, UNAS Pro, and **Technitium DNS (`10.0.10.3`)** | LAN + Office | | **TRUSTED** | Custom | 1 (`10.0.1.0/24`), 10 (`10.0.10.0/24`) | UDM, switch + AP mgmt, workstations, Proxmox host + app VMs, UNAS Pro, and **Technitium DNS (`10.0.10.5`)** | LAN + Office |
| **DMZ** | Custom | 15 (`10.0.15.0/24`) | **Dedicated Caddy host (`10.0.15.5`)** running Netbird agent | New | | **DMZ** | Custom | 15 (`10.0.15.0/24`) | **Dedicated Caddy host (`10.0.15.5`)** running Netbird agent | New |
| **FAMILY** | Custom | 20 (`10.0.20.0/24`) | Family phones / tablets / laptops | Family | | **FAMILY** | Custom | 20 (`10.0.20.0/24`) | Family phones / tablets / laptops | Family |
| **MEDIA** | Custom | 40 (`10.0.40.0/24`) | PS5, Samsung TV, Apple TV | Media | | **MEDIA** | Custom | 40 (`10.0.40.0/24`) | PS5, Samsung TV, Apple TV | Media |
@ -87,7 +87,7 @@ firewall policy only when its rollout phase tells you to do so.
Step 5 is complete when you have confirmed: Step 5 is complete when you have confirmed:
- Caddy will use static/reserved address `10.0.15.5`. - Caddy will use static/reserved address `10.0.15.5`.
- Technitium DNS uses static/reserved address `10.0.10.3`. - Technitium DNS uses static/reserved address `10.0.10.5`.
- The Caddy upstream addresses and ports in §5.4 match the current - The Caddy upstream addresses and ports in §5.4 match the current
`docker-compose-files/caddy/Caddyfile_template`. `docker-compose-files/caddy/Caddyfile_template`.
- SLZB-06U uses `10.0.30.5` and the Home Automation host uses `10.0.30.6`. - SLZB-06U uses `10.0.30.5` and the Home Automation host uses `10.0.30.6`.
@ -204,11 +204,11 @@ Create one allow policy for each listed source zone:
| Policy name | Action | Source zone | Source IP | Destination zone | Destination IP | Protocol / destination port | | Policy name | Action | Source zone | Source IP | Destination zone | Destination IP | Protocol / destination port |
|---|---|---|---|---|---|---| |---|---|---|---|---|---|---|
| `ALLOW DMZ to DNS` | Allow | `DMZ` | Any | `TRUSTED` | `10.0.10.3` | TCP and UDP `53` | | `ALLOW DMZ to DNS` | Allow | `DMZ` | Any | `TRUSTED` | `10.0.10.5` | TCP and UDP `53` |
| `ALLOW FAMILY to DNS` | Allow | `FAMILY` | Any | `TRUSTED` | `10.0.10.3` | TCP and UDP `53` | | `ALLOW FAMILY to DNS` | Allow | `FAMILY` | Any | `TRUSTED` | `10.0.10.5` | TCP and UDP `53` |
| `ALLOW MEDIA to DNS` | Allow | `MEDIA` | Any | `TRUSTED` | `10.0.10.3` | TCP and UDP `53` | | `ALLOW MEDIA to DNS` | Allow | `MEDIA` | Any | `TRUSTED` | `10.0.10.5` | TCP and UDP `53` |
| `ALLOW IOT to DNS` | Allow | `IOT` | Any | `TRUSTED` | `10.0.10.3` | TCP and UDP `53` | | `ALLOW IOT to DNS` | Allow | `IOT` | Any | `TRUSTED` | `10.0.10.5` | TCP and UDP `53` |
| `ALLOW GUEST to DNS` | Allow | `GUEST` | Any | `TRUSTED` | `10.0.10.3` | TCP and UDP `53` | | `ALLOW GUEST to DNS` | Allow | `GUEST` | Any | `TRUSTED` | `10.0.10.5` | TCP and UDP `53` |
### 5.4 Caddy to TRUSTED backend policies (`BACKEND_APPS`) ### 5.4 Caddy to TRUSTED backend policies (`BACKEND_APPS`)
@ -228,7 +228,7 @@ Every policy in this table uses:
| Policy name | Destination IP | Destination port(s) | Current upstream purpose | | Policy name | Destination IP | Destination port(s) | Current upstream purpose |
|---|---|---|---| |---|---|---|---|
| `ALLOW CADDY to LAN web devices` | `10.0.1.5`, `10.0.1.8` | `80` | Lite-8 and TP-Link switch UIs | | `ALLOW CADDY to LAN web devices` | `10.0.1.5`, `10.0.1.8` | `80` | Lite-8 and TP-Link switch UIs |
| `ALLOW CADDY to Technitium UI` | `10.0.10.3` | `5380` | Technitium admin UI | | `ALLOW CADDY to Technitium UI` | `10.0.10.5` | `5380` | Technitium admin UI |
| `ALLOW CADDY to NAS apps` | `10.0.10.24` | `5000,5055,6767,7878,8000,8080,8096,8191,8282,8989,9696` | NAS and media-stack apps | | `ALLOW CADDY to NAS apps` | `10.0.10.24` | `5000,5055,6767,7878,8000,8080,8096,8191,8282,8989,9696` | NAS and media-stack apps |
| `ALLOW CADDY to PBS` | `10.0.10.8` | `8007` | Proxmox Backup Server | | `ALLOW CADDY to PBS` | `10.0.10.8` | `8007` | Proxmox Backup Server |
| `ALLOW CADDY to Proxmox` | `10.0.10.10` | `8006` | Proxmox | | `ALLOW CADDY to Proxmox` | `10.0.10.10` | `8006` | Proxmox |
@ -305,7 +305,7 @@ UniFi default.
| 1 | TRUSTED | TRUSTED | Allow | any | Intra-zone (Proxmox ↔ apps ↔ NAS ↔ workstations) | | 1 | TRUSTED | TRUSTED | Allow | any | Intra-zone (Proxmox ↔ apps ↔ NAS ↔ workstations) |
| 2 | TRUSTED | any | Allow | any | Admin path; Trusted is the management zone | | 2 | TRUSTED | any | Allow | any | Admin path; Trusted is the management zone |
DNS for TRUSTED: DHCP option 6 → `10.0.10.3`. This design does not force DNAT DNS for TRUSTED: DHCP option 6 → `10.0.10.5`. This design does not force DNAT
for TRUSTED because workstations are trusted. Office clients and Technitium for TRUSTED because workstations are trusted. Office clients and Technitium
share `10.0.10.0/24`, so their DNS traffic does not traverse the UDM Pro SE and share `10.0.10.0/24`, so their DNS traffic does not traverse the UDM Pro SE and
cannot be redirected there. LAN VLAN 1 traffic is routed, but remains cannot be redirected there. LAN VLAN 1 traffic is routed, but remains
@ -383,7 +383,7 @@ Legend: ✅ allow · ❌ block · ⚠ allow only listed flows.
Footnotes: Footnotes:
1. **DMZ → TRUSTED pinhole:** Caddy IP only, targeting `BACKEND_APPS` IPs on app-specific TCP ports. Include only routes actually published in `docker-compose-files/caddy/Caddyfile_template`, including Technitium TCP 5380 when `dns01` is enabled. Drop all other DMZ → TRUSTED traffic. 1. **DMZ → TRUSTED pinhole:** Caddy IP only, targeting `BACKEND_APPS` IPs on app-specific TCP ports. Include only routes actually published in `docker-compose-files/caddy/Caddyfile_template`, including Technitium TCP 5380 when `dns01` is enabled. Drop all other DMZ → TRUSTED traffic.
2. **DNS via DNAT redirect** (§8) — destination `10.0.10.3:53` on UDP/TCP only; all other `:53` is silently rewritten. 2. **DNS via DNAT redirect** (§8) — destination `10.0.10.5:53` on UDP/TCP only; all other `:53` is silently rewritten.
3. **Proxy access:** TCP `80, 443` to Caddy IP only. 3. **Proxy access:** TCP `80, 443` to Caddy IP only.
## 8. DNS Handling — DNAT Redirect Strategy ## 8. DNS Handling — DNAT Redirect Strategy
@ -404,12 +404,12 @@ complexity without matching the policy objective.
### Rules ### Rules
| Zone | DHCP option 6 | DNAT rule | `:53` block | | Zone | DHCP option 6 | DNAT rule | `:53` block |
|---|---|---|---| |---|---|---|---|
| TRUSTED | `10.0.10.3` | None | None (trust workstations) | | TRUSTED | `10.0.10.5` | None | None (trust workstations) |
| DMZ | `10.0.10.3` | — | None (Caddy needs ACME DNS-01 out to WAN) | | DMZ | `10.0.10.5` | — | None (Caddy needs ACME DNS-01 out to WAN) |
| FAMILY | `10.0.10.3` | dst `!10.0.10.3` UDP/TCP 53 → `10.0.10.3:53` | — (DNAT replaces) | | FAMILY | `10.0.10.5` | dst `!10.0.10.5` UDP/TCP 53 → `10.0.10.5:53` | — (DNAT replaces) |
| MEDIA | `10.0.10.3` | same as FAMILY | — | | MEDIA | `10.0.10.5` | same as FAMILY | — |
| IOT | `10.0.10.3` | same as FAMILY | — | | IOT | `10.0.10.5` | same as FAMILY | — |
| GUEST | `10.0.10.3` | same as FAMILY | — | | GUEST | `10.0.10.5` | same as FAMILY | — |
Practically, this is one DNAT entry with source = group of {FAMILY, MEDIA, IOT, GUEST}. Practically, this is one DNAT entry with source = group of {FAMILY, MEDIA, IOT, GUEST}.
@ -477,19 +477,19 @@ Media devices (TV, PS5, Apple TV) are wired to TL-SG108 with port-based VLAN 40
### Phase 1 — Establish Technitium DNS ### Phase 1 — Establish Technitium DNS
1. Deploy Technitium at `10.0.10.3` by following the 1. Deploy Technitium at `10.0.10.5` by following the
[Technitium deployment guide](../../docker-compose-files/technitium/README.md). [Technitium deployment guide](../../docker-compose-files/technitium/README.md).
2. Configure the internal primary zone and verify recursion, blocking, and 2. Configure the internal primary zone and verify recursion, blocking, and
direct lookups from LAN and Office. direct lookups from LAN and Office.
3. Add all current and target client networks to Technitium Allowed Networks 3. Add all current and target client networks to Technitium Allowed Networks
(§8), including the future DMZ subnet `10.0.15.0/24`. (§8), including the future DMZ subnet `10.0.15.0/24`.
4. Configure every current VLAN's DHCP option 6 to advertise `10.0.10.3`. 4. Configure every current VLAN's DHCP option 6 to advertise `10.0.10.5`.
5. Add temporary firewall allows for UDP/TCP 53 from every current VLAN to 5. Add temporary firewall allows for UDP/TCP 53 from every current VLAN to
destination IP `10.0.10.3`. Do not add DNS DNAT yet. destination IP `10.0.10.5`. Do not add DNS DNAT yet.
6. Renew a client lease on each VLAN and verify both direct and normal resolver 6. Renew a client lease on each VLAN and verify both direct and normal resolver
queries: queries:
``` ```
dig @10.0.10.3 example.com dig @10.0.10.5 example.com
dig example.com dig example.com
``` ```
7. Continue only after Technitium's query log shows successful requests from 7. Continue only after Technitium's query log shows successful requests from
@ -533,7 +533,7 @@ passes without rule misses.
### DNS gate ### DNS gate
1. DHCP on every VLAN advertises `10.0.10.3`. 1. DHCP on every VLAN advertises `10.0.10.5`.
2. Direct and normal DNS queries work from every VLAN. 2. Direct and normal DNS queries work from every VLAN.
3. Technitium's query log identifies requests from every client subnet. 3. Technitium's query log identifies requests from every client subnet.
4. Technitium web administration is reachable only from `TRUSTED`. 4. Technitium web administration is reachable only from `TRUSTED`.