In this article I will walk you through setting up a domain DNS zone using the Google Cloud DNS service.
Google Cloud DNS is a high performance, resilient, and global DNS service, which allows you to easily publish and manage DNS records.
To keep this short and sweet, I assume that you know the basics of DNS.
1. Create a new Cloud Project
First you need to create a new Cloud Project. You should be already logged in using your Google domain admin account.
- Go to https://console.developers.google.com/project
- Create a new project and choose a descriptive project name such as “My DNS Project”
- Click on that project in the list of projects, and enable “Billing” under “Settings” on the left-hand menu
- Go to “APIs” under “API and auth” on the left-hand menu
- Enable “Google Cloud DNS API”
- (optional) Disable the other default enabled APIs (such as Google Cloud Storage) as they are not required for this project
2. Prepare the Google Cloud SDK
We’re going to use the gcloud command-line tool, which is part of the Google Cloud SDK. Install the SDK before you continue – the “Quick Start” instructions should be self-explanatory.
Once the Cloud SDK is installed, make sure it includes the required DNS component.
$ gcloud components list
If you don’t see “Cloud DNS Admin Command Line Interface” as “Installed”, run the following command.
$ gcloud components update dns
Next, authorize access to the Google APIs with your Google domain admin account.
$ gcloud auth login
You will be asked to give permissions to “Google Cloud SDK” to perform operations on your behalf, and the list of permissions is sufficient to use any of the tools included in the SDK. The command will prompt you to enter the project ID. Enter the value from the Developers Console that you created in the last step.
To see if your account has been successfully added run the following command.
$ gcloud auth list
3. Create a Managed DNS Zone
The SDK is installed with the required access token to your account. Now we can finally manage DNS zones and records.
Let’s create a new Cloud DNS managed zone.
$ gcloud dns managed-zone create --description="zeitgeist.se zone" --dns_name="zeitgeist.se." zeitgeistse
- –description=”zeitgeist.se zone” contains a human readable description of our zone. It’s optional.
- –dns_name=”zeitgeist.se.” is the domain name spec. Make sure you remember the trailing dot.
- zeitgeistse is the name of our managed zone. I prefer zone names to be identical to the domain name, except that dot characters are not allowed in zone names.
Output:
Creating {'dnsName': 'zeitgeist.se.', 'name': 'zeitgeistse',
'description': 'zeitgeist.se zone'} in learned-mind-567
Do you want to continue (Y/n)? y
{
"creationTime": "2014-05-01T13:25:51.959Z",
"description": "zeitgeist.se zone",
"dnsName": "zeitgeist.se.",
"id": "6484789670514247209",
"kind": "dns#managedZone",
"name": "zeitgeistse",
"nameServers": [
"ns-cloud-c1.googledomains.com.",
"ns-cloud-c2.googledomains.com.",
"ns-cloud-c3.googledomains.com.",
"ns-cloud-c4.googledomains.com."
]
}
4. Modify an existing DNS Record
For a DNS zone to do anything useful, we need to add some DNS records. Before we go into the details, let’s see what Google has added for us by default:
$ gcloud dns records --zone=zeitgeistse list
Output:
[
{
"kind": "dns#resourceRecordSet",
"name": "zeitgeist.se.",
"rrdatas": [
"ns-cloud-c1.googledomains.com.",
"ns-cloud-c2.googledomains.com.",
"ns-cloud-c3.googledomains.com.",
"ns-cloud-c4.googledomains.com."
],
"ttl": 21600,
"type": "NS"
},
{
"kind": "dns#resourceRecordSet",
"name": "zeitgeist.se.",
"rrdatas": [
"ns-cloud-c1.googledomains.com. dns-admin.google.com. 0 21600 3600 1209600 300"
],
"ttl": 21600,
"type": "SOA"
}
]
According to the output (which is in JSON notation), the DNS zone zeitgeistse has four authoritative name server (NS) records (ns-cloud-c1.googledomains.com to ns-cloud-c4.googledomains.com) and a start of authority record (SOA). The SOA record specifies the base DNS information about the domain:
- the primary name server is ns-cloud-c1.googledomains.com
- the hostmaster contact e-mail is dns-admin@google.com
- the initial serial number (which has to be incremented with every DNS update) is 0
- the refresh time that secondary DNS servers wait before querying the primary DNS server’s SOA record to check for changes is 21600 seconds
- the retry interval that a secondary server waits before retrying a failed zone transfer is 3600 seconds
- the expire time that a secondary server will keep trying to complete a zone transfer is 1209600 seconds
- the default minimum time to live is 300 seconds (used for negative caching, meaning that all the queries that don’t have a valid response are cached for this amount of seconds)
It’s perfectly fine to use your own e-mail as the SOA hostmaster address. Also, sometimes it’s recommended to encode the modification date into the serial number, following a YYYYMMDDnn scheme. Replace it with proper values for the year (YYYY, four digits), month (MM, two digits), day of month (DD, two digits) and version per day (nn, two digits). It’s not required, but I prefer it this way.
So let’s edit our SOA record.
$ gcloud dns records --zone=zeitgeistse edit
Your default editor appears with an example of a change with both the additions and deletions sections displayed in JSON notation. You can edit it by entering your additions, deletions or both.
Let’s go ahead and modify the SOA record with a new hostmaster e-mail address and the above mentioned serial number scheme. Then save your edit and close the editor. The gcloud tool will automatically apply the changes to the DNS.
{
"additions": [
{
"kind": "dns#resourceRecordSet",
"name": "zeitgeist.se.",
"rrdatas": [
"ns-cloud-c1.googledomains.com. hostmaster.zeitgeist.se 2014050101 21600 3600 1209600 300"
],
"ttl": 21600,
"type": "SOA"
}
],
"deletions": [
{
"kind": "dns#resourceRecordSet",
"name": "zeitgeist.se.",
"rrdatas": [
"ns-cloud-c1.googledomains.com. dns-admin.google.com. 0 21600 3600 1209600 300"
],
"ttl": 21600,
"type": "SOA"
}
]
}
Within a few seconds the changes should be visible:
$ dig soa zeitgeist.se @ns-cloud-c1.googledomains.com
Output:
; < <>> DiG 9.8.4-rpz2+rl005.12-P1 < <>> soa zeitgeist.se @ns-cloud-c1.googledomains.com
;; global options: +cmd
;; Got answer:
;; ->>HEADER< <- opcode: QUERY, status: NOERROR, id: 23949
;; flags: qr aa rd; QUERY: 1, ANSWER: 1, AUTHORITY: 4, ADDITIONAL: 0
;; WARNING: recursion requested but not available
;; QUESTION SECTION:
;zeitgeist.se. IN SOA
;; ANSWER SECTION:
zeitgeist.se. 21600 IN SOA ns-cloud-c1.googledomains.com. hostmaster.zeitgeist.se. 2014050101 21600 3600 1209600 300
;; AUTHORITY SECTION:
zeitgeist.se. 21600 IN NS ns-cloud-c1.googledomains.com.
zeitgeist.se. 21600 IN NS ns-cloud-c2.googledomains.com.
zeitgeist.se. 21600 IN NS ns-cloud-c3.googledomains.com.
zeitgeist.se. 21600 IN NS ns-cloud-c4.googledomains.com.
;; Query time: 42 msec
;; SERVER: 216.239.32.108#53(216.239.32.108)
;; WHEN: Thu May 1 17:53:23 2014
;; MSG SIZE rcvd: 198
Looking good!
5. Create a new DNS Record
Next, we’ll add some Mail Exchange (MX) records. Here we use Google to host our mail. Whether you modify an existing DNS record or create a new one, we always use the same command.
gcloud dns records --zone=zeitgeistse edit
{
"additions": [
{
"kind": "dns#resourceRecordSet",
"name": "zeitgeist.se.",
"rrdatas": [
"ns-cloud-c1.googledomains.com. hostmaster.zeitgeist.se. 2014050103 21600 3600 1209600 300"
],
"ttl": 21600,
"type": "SOA"
}
],
"deletions": [
{
"kind": "dns#resourceRecordSet",
"name": "zeitgeist.se.",
"rrdatas": [
"ns-cloud-c1.googledomains.com. hostmaster.zeitgeist.se. 2014050102 21600 3600 1209600 300"
],
"ttl": 21600,
"type": "SOA"
}
]
}
The gcloud tool automatically incremented the serial counter of the SOA record, which technically requires the addition of a new SEO record and the deletion of an old one, as shown above.
To insert our MX records, we add them as a new object within the “additions” array, as shown below:
{
"additions": [
{
"kind": "dns#resourceRecordSet",
"name": "zeitgeist.se.",
"rrdatas": [
"10 aspmx.l.google.com.",
"20 alt1.aspmx.l.google.com.",
"20 alt2.aspmx.l.google.com.",
"30 alt3.aspmx.l.google.com.",
"30 alt4.aspmx.l.google.com."
],
"ttl": 3600,
"type": "MX"
},
{
"kind": "dns#resourceRecordSet",
"name": "zeitgeist.se.",
"rrdatas": [
"ns-cloud-c1.googledomains.com. hostmaster.zeitgeist.se. 2014050103 21600 3600 1209600 300"
],
"ttl": 21600,
"type": "SOA"
}
],
"deletions": [
{
"kind": "dns#resourceRecordSet",
"name": "zeitgeist.se.",
"rrdatas": [
"ns-cloud-c1.googledomains.com. hostmaster.zeitgeist.se. 2014050102 21600 3600 1209600 300"
],
"ttl": 21600,
"type": "SOA"
}
]
}
Note when you have more than one resource record that has the same name and type values (like multiple MX records), you enter the values as an array in the rrdatas property.
Save, and observe how the changes propagate to the Google DNS servers.
$ dig mx zeitgeist.se @ns-cloud-c1.googledomains.com
Output:
; < <>> DiG 9.8.4-rpz2+rl005.12-P1 < <>> mx zeitgeist.se @ns-cloud-c1.googledomains.com
;; global options: +cmd
;; Got answer:
;; ->>HEADER< <- opcode: QUERY, status: NOERROR, id: 59523
;; flags: qr aa rd; QUERY: 1, ANSWER: 5, AUTHORITY: 0, ADDITIONAL: 0
;; WARNING: recursion requested but not available
;; QUESTION SECTION:
;zeitgeist.se. IN MX
;; ANSWER SECTION:
zeitgeist.se. 3600 IN MX 10 aspmx.l.google.com.
zeitgeist.se. 3600 IN MX 20 alt1.aspmx.l.google.com.
zeitgeist.se. 3600 IN MX 20 alt2.aspmx.l.google.com.
zeitgeist.se. 3600 IN MX 30 alt3.aspmx.l.google.com.
zeitgeist.se. 3600 IN MX 30 alt4.aspmx.l.google.com.
;; Query time: 42 msec
;; SERVER: 216.239.32.108#53(216.239.32.108)
;; WHEN: Thu May 1 20:38:11 2014
;; MSG SIZE rcvd: 148
6. Create new DNS Records in one batch
Nothing stops you from adding more than one new record in one step. Let’s add some more records that we require for the hosting of our website:
gcloud dns records --zone=zeitgeistse edit
{
"additions": [
{
"kind": "dns#resourceRecordSet",
"name": "zeitgeist.se.",
"rrdatas": [
"\"v=spf1 include:_spf.google.com ~all\""
],
"ttl": 21600,
"type": "TXT"
},
{
"kind": "dns#resourceRecordSet",
"name": "zeitgeist.se.",
"rrdatas": [
"\"v=spf1 include:_spf.google.com ~all\""
],
"ttl": 21600,
"type": "SPF"
},
{
"kind": "dns#resourceRecordSet",
"name": "mail.zeitgeist.se.",
"rrdatas": [
"ghs.googlehosted.com."
],
"ttl": 21600,
"type": "CNAME"
},
{
"kind": "dns#resourceRecordSet",
"name": "www.zeitgeist.se.",
"rrdatas": [
"80.74.135.85"
],
"ttl": 86400,
"type": "A"
},
{
"kind": "dns#resourceRecordSet",
"name": "zeitgeist.se.",
"rrdatas": [
"80.74.135.85"
],
"ttl": 86400,
"type": "A"
},
{
"kind": "dns#resourceRecordSet",
"name": "zeitgeist.se.",
"rrdatas": [
"ns-cloud-c1.googledomains.com. hostmaster.zeitgeist.se. 2014050104 21600 3600 1209600 300"
],
"ttl": 21600,
"type": "SOA"
}
],
"deletions": [
{
"kind": "dns#resourceRecordSet",
"name": "zeitgeist.se.",
"rrdatas": [
"ns-cloud-c1.googledomains.com. hostmaster.zeitgeist.se. 2014050103 21600 3600 1209600 300"
],
"ttl": 21600,
"type": "SOA"
}
]
}
For a list of supported record types, check out this page.
7. Update domain name servers
At this point you’ve established a managed DNS zone using Google Cloud DNS. In order for Cloud DNS to become active, we still must update the name server records with our registrar to refer to the Cloud DNS name servers.
To determine the Cloud DNS name server associated with our domain, use the following command:
$ gcloud dns managed-zone get zeitgeistse
Output:
{
"creationTime": "2014-05-01T13:25:51.959Z",
"description": "Zeitgeist.se zone",
"dnsName": "zeitgeist.se.",
"id": "6484789670514247209",
"kind": "dns#managedZone",
"name": "zeitgeistse",
"nameServers": [
"ns-cloud-c1.googledomains.com.",
"ns-cloud-c2.googledomains.com.",
"ns-cloud-c3.googledomains.com.",
"ns-cloud-c4.googledomains.com."
]
}
The domain names are listed here as ns-cloud-c1.googledomains.com to ns-cloud-c4.googledomains.com. Using the method provided by the registrar for the domain, replace the name servers in the registrar’s NS records with the four name servers we looked up in the previous step.
You’re all set. It can take up to 24-48 hours (depending on TTL settings) for the new nameservers to become fully active.
8. Other useful Google Cloud DNS commands
To list all of your DNS zones within the project:
$ gcloud dns managed-zone list
To delete a zone from your project:
$ gcloud dns managed-zone delete "zonename"
To list the records from a specific zone:
$ gcloud dns records --zone="zonename" list
Alexander, thanks for your tutorial! I was getting some errors adding SRV records, and got the typo right by seeing that one can nest rrdatas using comma.
Great tutorial! Regards,
thaks a lot for this tutorial, it was very helpful
Brilliant. Thank you
How do you delete a zone? It gives me an error saying it’s not empty. So how do I empty it?
Try with:
gcloud dns managed-zone delete "zonename" --delete-zone-contents DELETE_ZONE_CONTENTS
Using this additional flag should delete the contents of the zone first before deleting the zone (untested).
As I sit her struggling to try to get Google’s ‘kindly’ supplied migration Python script to work (not very successfully) this example of how to delete the zone AND contents has come in very handy (I didn’t realise the optional flag had to have the capitals “DELETE_ZONE_CONTENTS” after!). Thanks.
Hello,
Is there any way to choose another editor while editing the records? Because I do not like vim.
I actually prefer to edit the record file from outside and upload it to server again. Is it possible?
Thank you.
Hi,
gcloud uses the default text editor in your linux distribution (= whatever is stored in the $EDITOR environment variable). You can temporarily overwrite the default editor with something like:
$ export EDITOR=nano
To make the change permanent, if you’re using Debian, you can use the following command:
$ update-alternatives –config editor
In Ubuntu, try run:
$ select-editor
Regarding your second question – to use another editor, save it, and then somehow upload the information to gcloud – I am not aware how you could do this using the standard Google Cloud SDK.
Just want to say, Thank you!!!
Thx for the tutorial! I have gone through the steps and updated the domain name servers for my URL.
Do you know how to get Cloud DNS to point my URL to a webserver running on a compute engine instance. I can’t figure out how to do this… I can get to the web server via http://ip address// but I would like to use http://mydomain.com/.
Hi,
To contact your instance by name, you will need to have an DNS A record pointing to its external IP. By default you’re automatically assigned an ephemeral external IP address when you create an instance. You can read more about it here: https://cloud.google.com/compute/docs/instances-and-network
Keep in mind that the IP is reclaimed if you delete the instance, so if you do that, you will need to update the DNS A record again. Or, you may not want to use an ephemeral IP address at all and choose a “static” external IP address instead (which you would have to reserve first). As an alternative to reserving an IP address, an existing ephemeral IP address can also be promoted to a static IP address.
Alex
Just perfect. A bottle of Heineken from my side 🙂
Thanks for the drink. 😉
Thanks a million Alexander!!
I’ve been hacking around Google Cloud and this article is my DNS Bible for moving websites.
Hi Alexander. I am an absolute greenhorn in matters Dns. I have followed all your steps and everything works fine. My biggest challenge is when I run the edit command , I am almost unable to type anything in. When I copy and and paste my changes to addition section everything gets chaotic.
How do I even save the additions of A records, MX records. Is there a save command?
Hi Benjamin,
I am not 100% sure what the problem, but from what you’re describing it seems you’re having difficulty using the editor? It almost sounds like your default editor is vi(m), and you not familiar with it. If that is the case, we could change your default editor to something easy like nano. What’s your Linux distribution?
Thank you so much! worked perfect!
Nice tutorial – do you have any experience setting up reverse (PTR x.x.x.in-addr.arpa – and for IPv6, x.x.x.x.x.x.x.x.ip6.arpa) zones?
I know that usually the reverse zones are managed through the hosting provider, but it can be useful to manage them together with your forward zones.
your excellent article led to answer on stackoverflow, thankyou
http://stackoverflow.com/questions/32823671/google-cloud-dns-php-api-adding-multiple-cname/32825759#32825759
Please make this article in PHP too as there is not a single good article about google dns api in php online