The goal of this repository is to demonstrate how to get caddy working with bind9 over dynamic updates (RFC 2136).
I open sourced this because I don't see any tests online.
Why I did this:
- I didn't see many tests of getting xcaddy working
- I wanted the build to support multi platform builds
- I wanted to simplify my DNS management
- As I already specify the domains in my Caddyfile, I wondered if caddy could update my DNS
- I run this in on own internal network
- I found very little easy to understand information on RFC 2136
I am by no means a caddy, bind9, RFC 2136, or a dns expert.
Run
docker compose upBind expects the zone files to belong to the bind user in the container, else the nsupdate won't work. This only needs to be done once. If you create new zone files, make sure to run this again.
docker exec -it bind chown -R bind:bind /etc/bind/zones/You can check permissions to see if it worked.
docker exec -it bind ls -l /etc/bind/zonesQuery the dns to see if it works.
dig @localhost bind.test.comThese are things I encountered, gotchas, learned along the way, design decisions, and configuration choices.
See my list of References
- Acme is disabled to simplify the example.
As the intention is to use this in an internal network, I didn't want dynamic dns to use the public ip.
I configured the Caddyfile to use a static_ip.
An alternative solution would be:
- Get the Docker container to use the host network
- Specify in the Caddyfile to use host network interface
test:
In docker-compose.yaml:
services:
caddy:
network: hostIn Caddyfile, in the dynamic_dns block, assuming your interface is eth0:
dynamic_dns {
ip_source interface eth0
}
The Dockerfile supports cross compilation / multi-platform builds.
To cross compile run:
docker build \
--platform linux/amd64,linux/arm64 \
.Grep docker logs for dynamic_dns
docker logs -f caddy 2>&1 | grep dynamic_dnsGotchas:
- Out of the box, when running the docker container, there is no logging.
- I enabled logging
- Configuration files terminate each line with a semi colon.
- Bind will exit if there are problems with the configuration files
Ensure there is a new line at the end of the file.
The simplest way I found to verify the zone file is to grep the docker logs.
docker logs -f bind 2>&1 | grep testtest errors you will see:
general: warning: /etc/bind/zones/test.com.zone:47: file does not end with newline
zoneload: error: zone test.com/IN: loading from master file /etc/bind/zones/test.com.zone failed: unknown class/typeAfter an update the test.com.zone file may not be immediately updated because of how journal files work.
You can see if a test.com.zone.jnl file is created after running caddy
docker exec -it bind ls -l /etc/bind/zonesTo force a sync of the journal file you can run:
docker exec -it bind rndc sync test.comKEY_NAME="new-key"
docker exec -it bind tsig-keygen $KEY_NAME > bind/tsig/$KEY_NAME.keydig is used to query dns information
dig @localhost test.comExample response for example.com:
; <<>> DiG 9.18.28-1~deb12u2-Debian <<>> example.com
;; global options: +cmd
;; Got answer:
;; ->>HEADER<<- opcode: QUERY, status: NOERROR, id: 53553
;; flags: qr rd ra; QUERY: 1, ANSWER: 1, AUTHORITY: 0, ADDITIONAL: 1
;; OPT PSEUDOSECTION:
; EDNS: version: 0, flags:; udp: 1232
;; QUESTION SECTION:
;example.com. IN A
;; ANSWER SECTION:
example.com. 2645 IN A 93.184.215.14
;; Query time: 16 msec
;; SERVER: 192.168.13.5#53(192.168.13.5) (UDP)
;; WHEN: Sat Oct 19 08:55:19 +08 2024
;; MSG SIZE rcvd: 56nsupdate is used to update bind.
When searching online, there is a lot inconsistent information on nsupdate online. I suggest sticking to the Administrator Reference Manual.
You can send commands via a file or standard input.
Via file:
nsupdate nsupdate-examples/add.txtPiping via stdin:
cat <<EOF | nsupdate
server 127.0.0.1 53
zone test.com.
key hmac-sha256:nsupdate sHJp801e5gFuu//pHHYQdPMwdyxBQPYtStPkxBWLsjo=
update add nsupdate.test.com. 60 A 192.168.1.1
show
send
EOFOr just use nsupdate and enter the commands.
docker stats --no-stream --format "table {{.Name}}\t{{.CPUPerc}}\t{{.MemUsage}}"NAME CPU % MEM USAGE / LIMIT
caddy 0.00% 10.88MiB / 1GiB
bind 0.00% 11.27MiB / 1GiB