Use Ansible to Setup Google MX Records

We've all done it. After purchasing that shiny new domain name from our favorite registrar (one of mine happens to be namecheap), we go to set it up. Part of that setup likely includes changing the domain's MX records to point to "your own" mail servers, of which there is a good chance that "your own" actually means Google owned:

  • ASPMX.L.GOOGLE.COM. 1
  • ALT1.ASPMX.L.GOOGLE.COM. 5
  • ALT2.ASPMX.L.GOOGLE.COM. 5
  • ASPMX2.GOOGLEMAIL.COM. 10
  • ASPMX3.GOOGLEMAIL.COM. 10

Ah, a list familiar to most of us. So up to this point, it's been a manual process for me (I know... shame on me). But, today, I decided setting up domain MX records manually would end. Ansible to the rescue! Everything is built into the current version:

ansible --version
ansible 2.7.9

Thus no external modules are required. The only required module https://docs.ansible.com/ansible/latest/modules/cloudflare_dns_module.html is built in. I'll show how to do this both from a plain playbook standpoint (since I did it that way first), and then using a role.

Playbook Method

The Ansible play is a simple one and consists of only 2 files, cloudflare_google_mx.yml and cloudflare.yml. The main playbook is as simple as this:

$ more playbook/cloudflare_google_mx.yml
---
- hosts: localhost
  vars_files:
    - "{{ playbook_dir }}/../vars/cloudflare.yml"

  tasks:
    - name: Create Google MX Records
      cloudflare_dns:
        zone: "{{ zone }}"
        name: "{{ zone }}"
        record: "{{ item.server }}"
        value: "{{ item.server }}"
        type: MX
        priority: "{{ item.priority }}"
        account_email: "{{ email }}"
        account_api_token: "{{ cloudflare.apikey | replace('\n', '') }}"
        state: present
      loop:
        - { server: ASPMX.L.GOOGLE.COM., priority: 1 }
        - { server: ALT1.ASPMX.L.GOOGLE.COM., priority: 5 }
        - { server: ALT2.ASPMX.L.GOOGLE.COM., priority: 5 }
        - { server: ASPMX2.GOOGLEMAIL.COM., priority: 10 }
        - { server: ASPMX3.GOOGLEMAIL.COM., priority: 10 }

And the cloudflare.yml file under var_files holds an encrypted version of my cloudflare api key.

$ more vars/cloudflare.yml
---
cloudflare:
  apikey: !vault |
    $ANSIBLE_VAULT;1.1;AES256
    65633238643730616136353238616464313063336131396338633066653231653464333733396330
    3166613930386639653332333162383963333164303665380a373539616361633362653363636637
    66343331666132356562333262626333396137363739313436343134666235363136336536333263
    3035373738623963630a346330386630313530643162303263303738633961303066316539373533
    31316632306438323334653332386662643962396637316237306536613766663164326336333861
    3264366265333866393830326363383937383830383564386466

Role Method

If you instead want to install a role, I've made one available on Ansible Galaxy (Ansible's role repository):
https://galaxy.ansible.com/june07/ansible_cloudflare_google_mx

After installing the role via:
ansible-galaxy install june07.ansible_cloudflare_google_mx

You could then simply replace the tasks: section in your playbook/cloudflare_google_mx.yml playbook file with roles: instead, like this:

---
- hosts: localhost
  vars_files:
    - "{{ playbook_dir }}/../vars/cloudflare.yml"
  roles:
    - june07.cloudflare-google-mx

What's Going On

Because of the number (COUNT THEM... FIVE) of MX records that Google recommends in it's G Suite Admin documentation, I decided a loop would be useful in providing the neccessary server/priority values to the task I named "Create Google MX Records", which in turn is simply calling the cloudflare_dns module that Michael Gruener (@mgruener) contributed.

The Ansible command that brings it all together is:

ansible-playbook -e "zone=mydomain.com email=me@email.com" playbook/cloudflare_google_mx.yml --vault-password-file ./.vault.json

Per the documentation for the module, there are 3 required parameters. The Cloudflare API Key, the zone (mydomain.com), and the account_email (me@email.com). Everything else found under the loop variables will remain the same regardless of which new domain is setup. In the future when I decide to grab that newer, shinier domain name, with grandious plans of what it will serve as a beginning to, setting up Google MX Records will now be that simple.

ansible-playbook -e "zone=newershinierdomain.com email=me@email.com" playbook/cloudflare_google_mx.yml --vault-password-file ./.vault.json

No more time waste with manually setting these DNS records up manually. Done!