DsDDNS is the Dual-Stack Dynamic DNS client. A dynamic DNS client keeps your DNS records in sync with the IP addresses associated with your home Internet connection, which are subject to reassignment by your ISP.
DsDDNS is the world's first dynamic DNS client built from the ground-up for IPv6. In comparison to other dynamic DNS clients available on the Internet, including some others that support IPv6, DsDDNS features:
- First-class support for IPv6, including the ability to update multiple hostnames within a dynamically allocated prefix—not just the one that refers to the host system.
- Support for determining the lower bits of the address either manually or with SLAAC.
- Support for managing multiple domains across multiple accounts and services.
- A single binary and a single configuration file that can be deployed anywhere.
- A YAML configuration format that supports the DRY ("don't repeat yourself") principle.
Currently, DsDDNS can manage A and AAAA records for the following services:
- Cloudflare
- Duck DNS
- Google Domains
- No-IP (and other services that use the protocol)
Grab Linux, Windows, and MacOS binaries from the releases page.
Or, to build and install your own copy,
$ go get -u github.com/YoRyan/dsddns
For Linux servers, here is the suggested systemd service definition:
[Unit]
Description=DsDDNS Dynamic DNS Client
[Service]
ExecStart=/path/to/dsddns /etc/dsddns.conf
Restart=always
[Install]
WantedBy=multi-user.target
If you are a Docker fan, a DsDDNS Dockerfile and Docker image are available. As Docker does not enable IPv6 support out of the box, you should use host networking, or assign a prefix to the container's network. Otherwise, containers will not be able to use IPv6, and DsDDNS will not be able to manage AAAA records.
To use the Docker image, bind mount the configuration file to /etc/dsddns.conf
.
The configuration file is in YAML format. Its path should be supplied to as the sole argument to DsDDNS:
dsddns /etc/dsddns.conf
This file contains a list of records to manage under the records
key. Here is a simple example configuration:
records:
- type: A
service: cloudflare,
api_token: XXXXXXXXXXXXXXXXXX_XXXXXXXXXXXXXXXXXXXXX
record_id: XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX
zone_id: XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX
name: ipv4.youngryan.com
- type: AAAA
service: cloudflare,
api_token: XXXXXXXXXXXXXXXXXX_XXXXXXXXXXXXXXXXXXXXX
record_id: XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX
zone_id: XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX
name: ipv6.youngryan.com
To test the configuration file without making any changes to your DNS records, you can add the -dryrun
flag:
dsddns -dryrun /etc/dsddns.conf
(To see the other command-line flags available, run dsddns -help
.)
Some keys apply to all kinds of records, regardless of service. The following keys must be specified:
Key | Type | Value |
---|---|---|
type | string | Specifies the type of DNS record. Can be A (IPv4) or AAAA (IPv6). |
service | string | Specifies the dynamic DNS service that manages this record. Must be one of the following values:
|
The following keys are optional:
Key | Type | Value |
---|---|---|
interface | string | Selects the source network interface to use when reading the current IP address. This setting refers to the interface used by the HTTP client; DsDDNS always reads the current IP address from a web service. The interface should be specified by its name, such as eth0 . If it is not specified, the operating system selects the interface. |
ip_mask_bits | number | Zeroes out the specified number of lower bits from the IP address. The value 64 can be used to zero out the interface identifier portion (right half) of an IPv6 address. |
ip_offset | string | Sets the lower bits of the IP address once they have been masked with ip_mask_bits . The value should be an "offset" IP address, such as ::1 , which will be added to the masked address. |
ip_slaac | string | Sets the lower 64 bits of the IP address using the provided MAC address, such as 11:22:33:44:55:66 . The EUI-64 method is used, matching the addresses generated by SLAAC. This setting overrides ip_mask_bits and ip_offset . |
Other keys only apply to records managed by specific services. Some of them are required by the service.
Cloudflare
Cloudflare API requests can be authenticated using your account's global API key or by issuing individual API tokens. Specify a global API key or an API token, but not both.
The following keys are mandatory for Cloudflare-managed records:
Key | Type | Value |
---|---|---|
api_key | string | If using your global API key, provide it here. |
api_email | string | If using your global API key, provide your Cloudflare login here. |
api_token | string | If using an API token, provide it here. |
name | string | Specify the full domain managed by this record, including its suffix. |
zone_id | string | Specify the identifier of your domain's DNS zone. You can obtain this with the List Zones API call. |
record_id | string | Specify the identifier of your DNS record. You can obtain this with the List DNS Records API call. |
The following keys are optional:
Key | Type | Value |
---|---|---|
ttl | number | Sets the TTL for this record's updates. If it is not specified, the value 1 (automatic) is used. |
Duck DNS
The following keys are mandatory for Duck DNS-managed records:
Key | Type | Value |
---|---|---|
subname | string | The domain managed by this record. Should not include the ".duckdns.org" suffix. |
token | string | The API token for this dynamic DNS client. |
Generic No-IP service
The No-IP dynamic DNS protocol is used not only by noip.com, but also many other service providers. So even if DsDDNS doesn't explicitly support your provider, it may still be possible to interact with it using this generic client.
The No-IP protocol requires a username, password, and hostname. The endpoint—the destination address for all HTTP requests, such as https://dynupdate.no-ip.com/nic/update
—is also mandatory. The protocol supports both A and AAAA records, but not all service providers actually have support for AAAA.
Key | Type | Value |
---|---|---|
username | string | The username to send. |
password | string | The password to send. |
hostname | string | The hostname to send. |
endpoint | string | The HTTP endpoint to use, such as https://dynupdate.no-ip.com/nic/update . |
Google Domains
Google Domains uses the No-IP protocol. To use dynamic DNS, you have to set up a synthetic record for the hostname you want to manage, and then generate a username/password combination for the client.
The following keys are mandatory for Google-managed records:
Key | Type | Value |
---|---|---|
username | string | The username generated for this dynamic DNS client. |
password | string | The password generated for this client. |
hostname | string | The FQDN for this record. |
No-IP
The No-IP dynamic DNS service available at noip.com, unsurprisingly, uses the No-IP protocol.
The following keys are mandatory for records managed by No-IP:
Key | Type | Value |
---|---|---|
username | string | Your No-IP email address. |
password | string | The password associated with your hostname. |
hostname | string | The hostname to update. |
Because the configuration file uses YAML, you can use YAML's anchor, alias, and merge key features to consolidate information that repeats itself.
Here is an example of a configuration file that uses merge keys to centralize authentication information:
my_merges:
- &CfYoungryanCom {
service: cloudflare,
api_token: XXXXXXXXXXXXXXXXXX_XXXXXXXXXXXXXXXXXXXXX,
zone_id: XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX
}
records:
- << : *CfYoungryanCom
type: AAAA
record_id: XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX
name: radio-free.youngryan.com
ip_mask_bits: 64
ip_offset: ::1
- << : *CfYoungryanCom
type: AAAA
record_id: XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX
name: arvin.radio-free.youngryan.com
ip_slaac: c8:5b:76:xx:xx:xx
- << : *CfYoungryanCom
type: AAAA
record_id: XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX
name: shafter.radio-free.youngryan.com
ip_slaac: 10:60:4b:xx:xx:xx