9.6 KiB
Technitium DNS
Docker deployment for Technitium DNS Server. Run all commands from the repository root.
Persistent Data
Technitium configuration, zones, and application state are stored in the
Docker-managed named volume technitium_data.
Existing deployments that use appdata/technitium must copy that data into
the named volume before recreating the container.
Installation
-
Create
.envif it does not exist:cp -n .env.sample .env -
Check the host addresses, then set the required values in
.env:ip -br addressTZ=Africa/Johannesburg DNS_BIND_IP=10.0.10.5 TECHNITIUM_ADMIN_PASSWORD=<strong-password> TECHNITIUM_WEB_BIND_IP=0.0.0.0 TECHNITIUM_WEB_PORT=5380 TECHNITIUM_MEM_LIMIT=512m DOCKERLOGGING_MAXFILE=3 DOCKERLOGGING_MAXSIZE=10mDNS_BIND_IPmust be assigned to the host. Use0.0.0.0to listen on every host interface. -
Render the template:
./substitute_env.sh docker-compose-files/technitium/template.yaml docker-compose.technitium.yml .envdocker-compose.technitium.ymlcontains the rendered admin password and is ignored by Git. -
Validate and start Technitium:
docker compose -f docker-compose.technitium.yml config --quiet docker compose -f docker-compose.technitium.yml up -d -
Verify the container and open
http://10.0.10.5:5380:docker compose -f docker-compose.technitium.yml ps docker compose -f docker-compose.technitium.yml logs --tail=100 technitium-dns
Apply Configuration Changes
After changing .env or template.yaml, render the Compose file and recreate
the container:
./substitute_env.sh docker-compose-files/technitium/template.yaml docker-compose.technitium.yml .env
docker compose -f docker-compose.technitium.yml config --quiet
docker compose -f docker-compose.technitium.yml up -d
Initial Setup
In the Technitium admin interface:
- Create the primary internal zone, for example
home.example.com. - Add records for internal services that do not use Caddy.
- If using Caddy, add an
Arecord namedcaddypointing to10.0.15.5, then add a wildcardCNAMEnamed*pointing tocaddy.home.example.com. - Configure DHCP to advertise the Technitium host as the DNS server.
- Configure the recommended blocklists below.
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.
Enable On UDM Pro SE
Use this sequence with the latest UniFi OS and UniFi Network. It follows the current zone migration design:
- Technitium:
10.0.10.5, Office VLAN 10,TRUSTEDzone - Caddy:
10.0.15.5, DMZ VLAN 15,DMZzone - Current client VLANs: LAN, Office, Family, IoT, Media, and Guest
Complete Use Technitium Now first. The custom-zone and DNS-enforcement steps are later migration work; do not configure them until normal DNS works from every VLAN.
Use Technitium Now
1. Confirm Technitium Answers DNS
From an Office VLAN client:
nslookup google.com 10.0.10.5
Expected result: the command returns one or more addresses and identifies
10.0.10.5 as the DNS server.
2. Confirm Technitium Allows Your VLANs
The Compose template initializes Technitium with recursion enabled for private networks. To verify or change this in the latest Technitium web console:
- Open
http://10.0.10.5:5380. - Open Settings from the main navigation.
- Find the Recursion section on the Settings page.
- Set Recursion to Use Specified Network ACL.
- In Recursion Network ACL, allow these networks in this order:
127.0.0.1/32
::1/128
10.0.1.0/24
10.0.10.0/24
10.0.15.0/24
10.0.20.0/24
10.0.30.0/24
10.0.40.0/24
10.0.50.0/24
- Save the Settings page.
Recursion Network ACL is the current field name. There is no separate
Settings > DNS Server menu.
Technitium reads the Docker recursion environment variables only when creating its configuration for the first time. For an existing installation, the saved value shown on the Settings page is authoritative.
3. Test Direct DNS From Every VLAN
Connect a client to each current VLAN and run:
nslookup google.com 10.0.10.5
Expected result: every VLAN receives a DNS answer from 10.0.10.5.
If a VLAN times out, create a temporary firewall allow before continuing:
- In UniFi Network, open Settings > Policy Engine > Policy Table.
- Create a new Firewall policy with action Allow.
- Select the VLAN's current source zone and the specific source network.
- Set destination zone to
TRUSTED. - Set destination matcher to IP and enter
10.0.10.5. - Select IPv4, protocol TCP/UDP, and destination port
53. - Save the policy and retest the direct query.
Do not create final FAMILY, MEDIA, IOT, GUEST, or DMZ zone policies until those custom zones exist.
4. Advertise Technitium Through UDM DHCP
Repeat these steps for LAN, Office, Family, IoT, Media, and Guest:
- In UniFi Network, open Settings > Networks.
- Select the network.
- Find the DHCP settings. In the current UI this is normally under DHCP Service Management.
- Set the DHCP DNS server/name server to Manual.
- Enter only
10.0.10.5. Do not add a public secondary resolver. - Save the network.
- Reconnect the client or renew its DHCP lease.
This is a per-network DHCP setting. Do not change the UDM's WAN/Internet DNS setting.
5. Verify Clients Use Technitium
From one renewed client on each VLAN:
nslookup google.com
Expected result: the output identifies 10.0.10.5 as the server and returns a
DNS answer. The Technitium Dashboard query counters and client statistics
should increase.
Stop here until normal DNS works from every VLAN.
Later: Apply Final Zone Policies
Create these only while migrating each VLAN into its target custom zone:
| Name | Source zone | Destination zone | Destination IP | Protocol | Destination port |
|---|---|---|---|---|---|
ALLOW DMZ to DNS |
DMZ |
TRUSTED |
10.0.10.5 |
TCP/UDP | 53 |
ALLOW FAMILY to DNS |
FAMILY |
TRUSTED |
10.0.10.5 |
TCP/UDP | 53 |
ALLOW MEDIA to DNS |
MEDIA |
TRUSTED |
10.0.10.5 |
TCP/UDP | 53 |
ALLOW IOT to DNS |
IOT |
TRUSTED |
10.0.10.5 |
TCP/UDP | 53 |
ALLOW GUEST to DNS |
GUEST |
TRUSTED |
10.0.10.5 |
TCP/UDP | 53 |
Place each DNS allow above that zone's RFC1918 and terminal block policies. Remove the matching temporary rule after the final rule works.
For the exact field-by-field policy form, use How the policy tables map to the Create Policy panel.
Later: Enable DNS Enforcement
UniFi Network 10.4.57 does not expose supported LAN-facing DNS DNAT. After the final zone policies and DHCP-provided DNS work, follow DNS Handling - DNAT Redirect Strategy to verify that each restricted zone can query Technitium and that port 53 queries to other destinations are blocked.
Do not block public DNS from TRUSTED or DMZ. Office clients are trusted,
and Caddy in DMZ must query public resolvers for ACME DNS-01.
Network Requirements
- Allow client networks to reach Technitium on TCP and UDP port
53. - Restrict the web admin port
5380to trusted administration networks. - If
DNS_BIND_IP=0.0.0.0, use firewall rules to restrict DNS access. - Ensure no other service on the host is already using port
53.
Test DNS from a client:
nslookup google.com 10.0.10.5
nslookup proxmox.home.example.com 10.0.10.5
Replace 10.0.10.5 and home.example.com with your configured values.
Troubleshooting
The following error means DNS_BIND_IP is not assigned to the host:
failed to bind host port 10.0.10.5:53/tcp: cannot assign requested address
Check the host addresses and port usage:
ip -br address
sudo ss -lntup '( sport = :53 )'
Set DNS_BIND_IP to an assigned address or 0.0.0.0, render the template
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:
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:
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:
sudo reboot
docker info | grep -i warning
docker stats --no-stream technitium-dns
Useful Commands
# Published admin port
docker compose -f docker-compose.technitium.yml port technitium-dns 5380
Backup
Back up the technitium_data named volume. It contains the DNS configuration,
zones, and application state.