· 4 min read

Use git for your DNS and mailing lists

Distributed and versioned infrastructure for your organization

Distributed and versioned infrastructure for your organization

Infrastructure as code (IaC) is great!

Using IaC, you get:

  • full visibility into what is going into your production system.
  • easy contributions (git!).
  • audit trails.
  • notification when things change.
  • backups and rollbacks when things go wrong.

IaC is not only for your FAANG-style hyper scaleup. It’s easy to set up, and the benefits start at one person. If you have two persons contributing to your organization, you should use IaC for your DNS and mailing lists.

Here’s how I’ve been doing it lately and it’s been serving me well.

DNS with OctoDNS

OctoDNS provides a set of tools & patterns that make it easy to manage your DNS records across multiple providers.

While you can also use Terraform for your DNS, OctoDNS makes it easier to switch providers. Also has the nice bonus that you don’t need to maintain a separate Terraform state.

You can take a look at the PAUG dns configuration for an example:

---
? ''
: - ttl: 21600
    type: A
    value: 199.36.158.100
  - ttl: 21600
    type: MX
    values:
    - exchange: aspmx.l.google.com.
      preference: 1
    - exchange: alt1.aspmx.l.google.com.
      preference: 5
    - exchange: alt2.aspmx.l.google.com.
      preference: 5
    - exchange: aspmx2.googlemail.com.
      preference: 10
    - exchange: aspmx3.googlemail.com.
      preference: 10
  - ttl: 21600
    type: TXT
    values:
    - google-site-verification=CF5OccWvfQMQZwQ9n9QM2H3tpTneSYwzd9ZZay0TTDQ
    - hosting-site=website-73f72
    - v=spf1 mx include:_spf.google.com include:mx.ovh.com ~all

I’m not the biggest yaml fan, but for things like this, it’s good enough.

And you can add comments!

This is all automated through GitHub Actions. A pull request creates a plan, the merge triggers an update of the records:

on:
  push:
    branches: [main]

jobs:
  apply:
    runs-on: ubuntu-latest
    steps:
      - uses: actions/checkout@v4
      - uses: actions/setup-python@v5
      - run: pip install -r requirements.txt
      - run: octodns-sync --config-file=config/octodns.yaml --doit
        env:
          GANDI_TOKEN: ${{ secrets.GANDI_TOKEN }}
        

Google Workspace with Terraform

Because user management is not as standardized as DNS records, we’ll have to use Terraform here.

Until Terraform can import automatically, you’ll have to import your users and groups manually if you have an existing organization:

import {
  to = googleworkspace_user.mb
  id = "mb@paug.fr"
}

Calling terraform plan -generate-config-out=generated_resources.tf pulls the full config for that user:

resource "googleworkspace_user" "mb" {
  aliases                        = ["martin@paug.fr"]
  archived                       = false
  change_password_at_next_login  = false
  hash_function                  = null
  include_in_global_address_list = true
  ip_allowlist                   = false
  is_admin                       = true
  org_unit_path                  = "/"
  password                       = null # sensitive
  primary_email                  = "mb@paug.fr"
  recovery_email                 = "martin@mbonnin.net"
  recovery_phone                 = "+33688082143"
  suspended                      = false
  emails {
    address     = "mb@paug.fr"
    custom_type = null
    primary     = true
    type        = "other"
  }
  emails {
    address     = "martin@paug.fr"
    custom_type = null
    primary     = false
    type        = "other"
  }
  name {
    family_name = "Bonnin"
    given_name  = "Martin"
  }
}

Which you can then manage with Terraform:

$terraform plan
...
Apply complete! Resources: 0 added, 49 changed, 0 destroyed.

You can also manage groups with Terraform:

resource "googleworkspace_group" "bureau" {
  aliases     = []
  description = null
  email       = "bureau@paug.fr"
  name        = "Bureau"
  timeouts {
    create = null
    update = null
  }
}

resource "googleworkspace_group_member" "bureau__mb" {
  delivery_settings = "ALL_MAIL"
  email             = "mb@paug.fr"
  group_id          = googleworkspace_group.bureau.id
  role              = "MEMBER"
  type              = "USER"
  timeouts {
    create = null
    update = null
  }
}

As for DNS, this is all automated through GitHub Actions. A pull request creates a plan, the merge triggers an update of the records:

jobs:
  apply:
    name: Apply
    runs-on: ubuntu-latest

    steps:
      - uses: actions/checkout@v4
      - uses: google-github-actions/auth@v2
        with:
          credentials_json: ${{ secrets.GCP_SA_KEY }}
      - uses: hashicorp/setup-terraform@v3
        with:
          terraform_version: "~> 1.9"
      - run: terraform init
      - run: terraform apply -auto-approve -input=false

Conclusion

This is just an example. You could manage everything in Terraform, or use OpenTofu or even Pulumi.

The important thing is to:

  1. Give visibility to the team about the structure of your organization.
  2. Empower the team to do the changes.

At this point, documentation, backup and rollbacks are the cherry on top. In all cases, there’s really no reason to not use infrastructure as code for your organization in 2026.


Photo by nika tchokhonelidze

    Share:
    Back to Blog