Light container updating DNS A and/or AAAA records periodically for multiple DNS providers
- Updates periodically A records for different DNS providers:
- Cloudflare
- DDNSS.de
- DigitalOcean
- DonDominio
- DNSOMatic
- DNSPod
- Dreamhost
- DuckDNS
- DynDNS
- FreeDNS
- Gandi
- GoDaddy
- He.net
- Infomaniak
- Linode
- LuaDNS
- Namecheap
- NoIP
- Njalla
- OpenDNS
- OVH
- Selfhost.de
- Spdyn
- Strato.de
- Want more? Create an issue for it!
- Web User interface
- 14MB Docker image based on a Go static binary in a Scratch Docker image with ca-certificates and timezone data
- Persistence with a JSON file updates.json to store old IP addresses with change times for each record
- Docker healthcheck verifying the DNS resolution of your domains
- Highly configurable
- Sends notifications to your Android phone, see the Gotify section (it's free, open source and self hosted π)
- Compatible with
amd64
,386
,arm64
,arm32v7
(Raspberry Pis) CPU architectures.
The program reads the configuration from a JSON object, either from a file or from an environment variable.
-
Create a directory of your choice, say data with a file named config.json inside:
mkdir data touch data/config.json # Owned by user ID of Docker container (1000) chown -R 1000 data # all access (for creating json database file data/updates.json) chmod 700 data # read access only chmod 400 data/config.json
(You could change the user ID, for example with
1001
, by running the container with--user=1001
) -
Write a JSON configuration in data/config.json, for example:
{ "settings": [ { "provider": "namecheap", "domain": "example.com", "host": "@", "password": "e5322165c1d74692bfa6d807100c0310" } ] }
You can find more information in the configuration section to customize it.
-
Run the container with
docker run -d -p 8000:8000/tcp -v "$(pwd)"/data:/updater/data qmcgaw/ddns-updater
-
(Optional) You can also set your JSON configuration as a single environment variable line (i.e.
{"settings": [{"provider": "namecheap", ...}]}
), which takes precedence over config.json. Note however that if you don't bind mount the/updater/data
directory, there won't be a persistent database file/updater/updates.json
but it will still work.
You can also use docker-compose.yml with:
docker-compose up -d
You can update the image with docker pull qmcgaw/ddns-updater
. Other Docker image tags are available.
Start by having the following content in config.json, or in your CONFIG
environment variable:
{
"settings": [
{
"provider": "",
},
{
"provider": "",
}
]
}
For each setting, you need to fill in parameters. Check the documentation for your DNS provider:
- Cloudflare
- DDNSS.de
- DigitalOcean
- DonDominio
- DNSOMatic
- DNSPod
- Dreamhost
- DuckDNS
- DynDNS
- DynV6
- FreeDNS
- Gandi
- GoDaddy
- He.net
- Infomaniak
- Linode
- LuaDNS
- Namecheap
- NoIP
- Njalla
- OpenDNS
- OVH
- Selfhost.de
- Spdyn
- Strato.de
Note that:
- you can specify multiple hosts for the same domain using a comma separated list. For example with
"host": "@,subdomain1,subdomain2",
.
Environment variable | Default | Description |
---|---|---|
CONFIG |
One line JSON object containing the entire config (takes precendence over config.json file) if specified | |
PERIOD |
5m |
Default period of IP address check, following this format |
PUBLICIP_FETCHERS |
all |
Comma separated fetcher types to obtain the public IP address from http and dns |
PUBLICIP_HTTP_PROVIDERS |
all |
Comma separated providers to obtain the public IP address (ipv4 or ipv6). See the Public IP section |
PUBLICIPV4_HTTP_PROVIDERS |
all |
Comma separated providers to obtain the public IPv4 address only. See the Public IP section |
PUBLICIPV6_HTTP_PROVIDERS |
all |
Comma separated providers to obtain the public IPv6 address only. See the Public IP section |
PUBLICIP_DNS_PROVIDERS |
all |
Comma separated providers to obtain the public IP address (IPv4 and/or IPv6). See the Public IP section |
UPDATE_COOLDOWN_PERIOD |
5m |
Duration to cooldown between updates for each record. This is useful to avoid being rate limited or banned. |
HTTP_TIMEOUT |
10s |
Timeout for all HTTP requests |
LISTENING_PORT |
8000 |
Internal TCP listening port for the web UI |
ROOT_URL |
/ |
URL path to append to all paths to the webUI (i.e. /ddns for accessing https://example.com/ddns through a proxy) |
BACKUP_PERIOD |
0 |
Set to a period (i.e. 72h15m ) to enable zip backups of data/config.json and data/updates.json in a zip file |
BACKUP_DIRECTORY |
/updater/data |
Directory to write backup zip files to if BACKUP_PERIOD is not 0 . |
LOG_LEVEL |
info |
Level of logging, info , warning or error |
LOG_CALLER |
hidden |
Show caller per log line, hidden or short |
GOTIFY_URL |
(optional) HTTP(s) URL to your Gotify server | |
GOTIFY_TOKEN |
(optional) Token to access your Gotify server | |
TZ |
Timezone to have accurate times, i.e. America/Montreal |
By default, all public IP fetching types are used and cycled (over DNS and over HTTPs).
On top of that, for each fetching method, all echo services available are cycled on each request.
This allows you not to be blocked for making too many requests.
You can otherwise customize it with the following:
PUBLICIP_HTTP_PROVIDERS
gets your public IPv4 or IPv6 address. It can be one or more of the following:opendns
using https://diagnostic.opendns.com/myipifconfig
using https://ifconfig.io/ipipinfo
using https://ipinfo.io/ipddnss
using https://ddnss.de/meineip.phpgoogle
using https://domains.google.com/checkip- You can also specify an HTTPS URL such as
https://ipinfo.io/ip
PUBLICIPV4_HTTP_PROVIDERS
gets your public IPv4 address only. It can be one or more of the following:ipify
using https://api.ipify.orgnoip
using http://ip1.dynupdate.no-ip.com- You can also specify an HTTPS URL such as
https://ipinfo.io/ip
PUBLICIPV6_HTTP_PROVIDERS
gets your public IPv6 address only. It can be one or more of the following:ipify
using https://api6.ipify.orgnoip
using http://ip1.dynupdate6.no-ip.com- You can also specify an HTTPS URL such as
https://ipinfo.io/ip
PUBLICIP_DNS_PROVIDERS
gets your public IPv4 address only or IPv6 address only or one of them (see #136). It can be one or more of the following:google
cloudflare
If you have a host firewall in place, this container needs the following ports:
- TCP 443 outbound for outbound HTTPS
- TCP 80 outbound if you use a local unsecured HTTP connection to your Gotify server
- UDP 53 outbound for outbound DNS resolution
- TCP 8000 inbound (or other) for the WebUI
At program start and every period (5 minutes by default):
- Fetch your public IP address
- For each record:
- DNS resolve it to obtain its current IP address(es)
- If the resolution fails, update the record with your public IP address by calling the DNS provider API and finish
- Check if your public IP address is within the resolved IP addresses
- Yes: skip the update
- No: update the record with your public IP address by calling the DNS provider API
- DNS resolve it to obtain its current IP address(es)
π‘ We do DNS resolution every period so it detects a change made to the record manually, for example on the DNS provider web UI π‘ As DNS resolutions are essentially free and without rate limiting, these are great to avoid getting banned for too many requests.
For Cloudflare records with the proxied
option, the following is done.
At program start and every period (5 minutes by default), for each record:
- Fetch your public IP address
- For each record:
- Check the last IP address (persisted in
updates.json
) for that record- If it doesn't exist, update the record with your public IP address by calling the DNS provider API and finish
- Check if your public IP address matches the last IP address you updated the record with
- Yes: skip the update
- No: update the record with your public IP address by calling the DNS provider API
- Check the last IP address (persisted in
This is the only way as doing a DNS resolution on the record will give the IP address of a Cloudflare server instead of your server.
Gotify is a simple server for sending and receiving messages, and it is free, private and open source
- It has an Android app to receive notifications
- The app does not drain your battery π
- The notification server is self hosted, see how to set it up with Docker
- The notifications only go through your own server (ideally through HTTPS though)
To set it up with DDNS updater:
- Go to the Web GUI of Gotify
- Login with the admin credentials
- Create an app and copy the generated token to the environment variable
GOTIFYTOKEN
(for this container) - Set the
GOTIFYURL
variable to the URL of your Gotify server address (i.e.http://127.0.0.1:8080
orhttps://bla.com/gotify
)
- The automated healthcheck verifies all your records are up to date using DNS lookups
- You can also manually check, by:
- Going to your DNS management webpage
- Setting your record to
127.0.0.1
- Run the container
- Refresh the DNS management webpage and verify the update happened
- Contribute with code
- Github workflows to know what's building
- List of issues and feature requests
- Kanban board
This repository is under an MIT license
Sponsor me on Github or donate to paypal.me/qmcgaw
Many thanks to J. Famiglietti for supporting me financially π₯π