Overview
Choose one of the following installation methods:
brew install dnscontrol
sudo port install dnscontrol
docker run --rm \
-it \
-v $(pwd)/dnsconfig.js:/dns/dnsconfig.js \
-v $(pwd)/creds.json:/dns/creds.json \
-v $(pwd)/spfcache.updated.json:/dns/spfcache.updated.json \
-v $(pwd)/spfcache.json:/dns/spfcache.json \
-v $(pwd)/zones/:/dns/zones/ \
-u $(id -u ${USER}):$(id -g ${USER}) \
stackexchange/dnscontrol \
preview
Download binaries from GitHub for Linux (binary, tar, RPM, DEB), FreeBSD (tar), Windows (exec, ZIP) for 32-bit, 64-bit, and ARM.
DNSControl can be built from source with Go version 1.18 or higher.
The
go install
command will download the source, compile it, and install dnscontrol
in your $GOBIN
directory.To install, simply run
go install github.com/StackExchange/dnscontrol/[email protected]
To download the source
git clone https://github.com/StackExchange/dnscontrol
Create a directory where you'll store your configuration files. We highly recommend storing these files in a Git repo, but for simple tests anything will do.
Create a subdirectory called
zones
in the same directory as the configuration files. (mkdir zones
). zones
is where the BIND provider writes the zonefiles it creates. Even if you don't use BIND for DNS service, it is useful for testing.dnsconfig.js
is the main configuration and defines providers, DNS domains, and so on.The file looks like:
dnsconfig.js
var REG_NONE = NewRegistrar("none");
var DNS_BIND = NewDnsProvider("bind");
D("example.com", REG_NONE, DnsProvider(DNS_BIND),
A("@", "1.2.3.4")
);
Modify this file to match your particular providers and domains. See the DNSConfig docs and the provider docs for more details.
Create a file called
creds.json
for storing provider configurations (API tokens and other account information). For example, to use both name.com and Cloudflare, you would have:creds.json
{
"cloudflare": { // The provider name used in dnsconfig.js
"TYPE": "CLOUDFLAREAPI", // The provider type identifier
"accountid": "your-cloudflare-account-id", // credentials
"apitoken": "your-cloudflare-api-token" // credentials
},
"namecom": { // The provider name used in dnsconfig.js
"TYPE": "NAMEDOTCOM", // The provider type identifier
"apikey": "key", // credentials
"apiuser": "username" // credentials
},
"none": { "TYPE": "NONE" } // The no-op provider
}
There are 2 types of providers:
A "Registrar" is with whom you register the domain. Start with
NONE
, which is a provider that never talks to or updates the registrar. You can define your registrar later when you want to use advanced features.A "DnsProvider" is the service that actually provides DNS service (port 53) and may be the same or a different registrar. Even if both your Registrar and DnsProvider are the same company, two different definitions must be included in
dnsconfig.js
.creds.json
stores credentials and a few global settings. It is only needed if any providers require credentials (API keys, usernames, passwords, etc.).The file looks like:
creds.json
{
"bind": {
"TYPE": "BIND"
},
"r53_accountname": {
"TYPE": "ROUTE53",
"KeyId": "change_to_your_keyid",
"SecretKey": "change_to_your_secretkey"
}
}
Ignore the
r53_accountname
section. It is a placeholder and will be ignored. You can use it later when you define your first set of API credentials.Note that
creds.json
is a JSON file. JSON is very strict about commas and other formatting. There are a few different ways to check for typos:Python:
python -m json.tool creds.json
jq:
jq . < creds.json
FYI:
creds.json
fields can be read from an environment variable. The field must begin with a $
followed by the variable name. No other text. For example:creds.json
{
"apikey": "$GANDI_V5_APIKEY"
}
Before you edit the sample files, verify that the system is working.
First run
dnscontrol preview
and ensure it completes without error(s). The preview command is the "dry run" mode that shows only what changes need to be made and never makes any actual changes. It will use APIs if needed to find out what DNS entries currently exist.(All output assumes the
--full
flag)It should look something like this:
dnscontrol preview
Initialized 1 registrars and 1 dns service providers.
******************** Domain: example.com
----- Getting nameservers from: bind
----- DNS Provider: bind... 1 correction
#1: GENERATE_ZONEFILE: example.com
(2 records)
----- Registrar: none
Done. 1 corrections.
Next, run
dnscontrol push
to actually make the changes. In this case, the change will be to create a zone file where one didn't previously exist.dnscontrol push
Initialized 1 registrars and 1 dns service providers.
******************** Domain: example.com
----- Getting nameservers from: bind
----- DNS Provider: bind... 1 correction
#1: GENERATE_ZONEFILE: example.com
(2 records)
CREATING ZONEFILE: zones/example.com.zone
SUCCESS!
----- Registrar: none
Done. 1 corrections.
Try making a change to
dnsconfig.js
. For example, change the IP address of in A('@', '1.2.3.4')
or add an additional A record.In our case, we changed the IP address to 10.10.10.10. Previewing our change looks like this:
dnscontrol preview
Initialized 1 registrars and 1 dns service providers.
******************** Domain: example.com
----- Getting nameservers from: bind
----- DNS Provider: bind... 1 correction
#1: GENERATE_ZONEFILE: example.com
MODIFY A example.com: (1.2.3.4 300) -> (10.10.10.10 300)
----- Registrar: none
Done. 1 corrections.
Notice that it read the old zone file and was able to produce a "diff" between the old
A
record and the new one. If the zonefile didn't exist, the output would look different because the zone file was being created from scratch.Run
dnscontrol push
to see the system generate a new zone file.Other providers use an API to do updates. In those cases the individual changes will translate into API calls that update the specific records.
Take a look at the
zones/example.com.zone
file. It should look like:$TTL 300
@ IN SOA DEFAULT_NOT_SET. DEFAULT_NOT_SET. 1 3600 600 604800 1440
IN A 10.10.10.10
You can change the "DEFAULT_NOT_SET" text by following the documentation for the BIND provider to set the "master" and "mbox" settings. Try that now.
Now that we know the system is working for test data, try controlling a real domain (or a test domain if you have one).
Set up the provider: Add the providers's definition to
dnsconfig.js
and list any credentials in creds.json
. Each provider is different. See the provider docs for specifics.Edit the domain: Add the
D()
entry for the domain, or repurpose the example.com
domain. Add individual A()
, MX()
and other records as needed. Remember that the first parameter to D()
is always a Registrar.Run
dnscontrol preview
to test your work. It may take a few tries to list all the DNS records that make up the domain. When preview
shows no changes required, then you know you are at record parity.The Migrating doc has advice about converting from other systems. You can manually create the
D()
statements, or you can generate them automatically using the dnscontrol get-zones command to import the zone from (most) providers and output it as code that can be added to dnsconfig.js
and used with very little modification.Now you can make changes to the domain(s) and run
dnscontrol preview
If you are going to use this in production, we highly recommend the following:
- Store the configuration files in Git.
- Encrypt the
creds.json
file before storing it in Git. Do NOT store API keys or other credentials without encrypting them. - Use a CI/CD tool like GitLab, Jenkins, CircleCI, GitHub Actions, etc. to automatically push DNS changes.
Last modified 2d ago