Continuously Deploying DNS records with DnsControl and CircleCI
In the previous post, I gave a quick introduction to DnsControl, what it does and how it works. In this post, I'll show you how to continuously deploy your changes to Google Cloud DNS using CircleCI.
The goal is to have a Pipeline that works like this: On each push, run dnscontrol check
to verify the file is valid, dnscontrol preview
to make sure all configuration is correct (credentials, zones, ...). And if we're on the master
branch (and the previous steps were succesful) dnscontrol push
the changes to our DNS provider.
First, we need a container containing dnscontrol
to run on CircleCI. Luckily for us there is an official one on Docker Hub: stackexchange/dnscontrol.
Next we need a .circleci/config.yml
file:
version: 2
# Job definitions
jobs:
check:
docker:
- image: stackexchange/dnscontrol
steps:
- checkout
- run: dnscontrol check
preview:
docker:
- image: stackexchange/dnscontrol
steps:
- checkout
- run: dnscontrol preview
deploy:
docker:
- image: stackexchange/dnscontrol
steps:
- checkout
- run: dnscontrol push
# Definitions of the Workflow, our "Pipeline"
workflows:
version: 2
check-preview-deploy:
jobs:
- check
- preview
- deploy:
requires:
- check
- preview
filters: # only deploy from master branch
branches:
only: master
Now we have one problem left: We have to provide the credentials. Fortunately enough, the values in creds.json
can contain ENV var names which dnscontrol then properly reads from the environment:
{
"gcloud": {
"type": "service_account",
"project_id": "$GCLOUD_PROJECT_ID",
"private_key": "$GCLOUD_PRIVATE_KEY",
"client_email": "$GCLOUD_CLIENT_EMAIL"
}
}
Unfortunately this did not work as expected. Google Cloud uses Private Key authentication for their service accounts, and I was not able to properly set an env var with the key in a for that dnscontrol could understand.
So instead I came up with something else:
- Create the
creds.json
file locally base64
encode the file- On CircleCI, set an env var
$CREDS
to the encoded string - During builds, decode and write the data to
creds.json
As only the preview
and push
commands require authentication, we only have to write the file during the preview
and deploy
jobs, for example:
# ...
deploy:
docker:
- image: stackexchange/dnscontrol
steps:
- checkout
- run: echo "$CREDS" | base64 -d > creds.json
- run: dnscontrol push
# ...
Bonus
Some people like to be a bit more careful, so they want to manually confirm a deployment. This can be done with a "hold" step in our workflow. Adjust the workflows
section of the config.yml
like this:
workflows:
version: 2
check-preview-hold-deploy:
jobs:
- check
- preview
- hold:
type: approval
requires:
- check
- preview
filters:
branches:
only: master
- deploy:
filters:
branches:
only: master
Now the workflow will pause after the check
and preview
steps.
Happy deploying continuously!