Context
DDNS allows for the dynamic update of DNS entries and attributes, a fitting name if there ever was one. This can be an extremely valuable resource for professionals and homelabbers who need to deal with dynamically assigned IP addresses in keeping things connected.
I personally use Cloudflare as a DNS proxy for my various domains, which used to be managed by Google Domains until they sold that business to Squarespace. I’ve since been moving everything to Porkbun.
Recently, I wanted to organize all of my cloud and on-prem resources better, and decided to use a singular domain name to help organize everything. I wanted to be sure that the subdomains I would be assigning out through A records would always be accurate, and thus my project began.
Setup
To update the DNS A records, there are a few simple things that need to be set up.
- There needs to be an A record in Cloudflare for ddclient to update.
- ddclient needs authentication into Cloudflare using an API token.
- ddclient needs to check its own IP address to compare against what’s on record.
Creating the A record is straightforward: open DNS, then Records, and create away.
Authenticating ddclient into Cloudflare is a little trickier. I prefer to create an API key that has read/write access to the domain zone in Cloudflare. This can be accomplished under Profile, API Keys, and then by following the wizard.
Finally, ddclient needs some way to check its own IP and see if the records need to be updated. Oddly enough, this seems to be the hardest part to keep consistently working. There are dozens of decent to great DDNS services out there that have been around for years, and yet IP checking services disappear with the winds. Go figure.
Because I have a number of VMs running among different cloud providers, running ddclient in a docker container works wonderfully. Once I install docker and docker compose, I’m easily able to use basically the same two files to keep every VM host updated.
Note
Without a pre-made
config/ddclient.conffile, the ddclient container will download a default one. That default needs to be altered slightly to actually work, see below.
My docker-compose.yml and ddclient.conf
docker-compose.yml
## docker-compose.yml
---
services:
ddclient:
image: lscr.io/linuxserver/ddclient:latest
container_name: ddclient
environment:
- PUID=<UID>
- PGID=<GID>
- TZ=UTC
volumes:
- ./config:/config
restart: unless-stoppedconfig/ddclient.conf
## ddclient.conf
use=web
web=dynamicdns.park-your-domain.com/getip
web-skip='Current IP Address'
protocol=cloudflare, \
zone=domain.tld, \
ttl=1, \
login=token, \
password=<api-token> \
test-subdomain.domain.tldOnce everything has been loaded into place, running sudo docker compose pull && sudo docker compose up -d will get it running. ddclient can be configured to log externally, though I used Portainer to view the logs and troubleshoot along the way.
Troubleshooting
I ran into several errors this most recent go-round, as well as before.
Failure to get IPv4 address
At some point, the default use=web option to get the public IP stopped working for me. Adding the specific web address seems to have mostly fixed it for good, we’ll see.
Tip
If ddclient’s IP detection starts silently failing, don’t assume ddclient itself is broken. Point
web=at a specific, known-good IP echo service first; the built in default is usually the thing that quietly stopped working.
Failure to communicate with Cloudflare's API
I had some difficulties working with the Cloudflare DDNS API as it exists in the default configuration that downloads with the docker compose pull. This seemed to be an older version of the config, which referenced the API in a way that no longer worked.
Edit, 2024-08-18: this seems to have been fixed.