IaC

    Setting up my Micro.blog sub-domain using IaC, Terraform and Cloudflare

    The last step to setting up my new Micro.blog was to use it from my own domain.

    I debated using it exclusively at paultibbetts.uk but I want to work on my own blog for that address.

    So I’m going to use Micro.blog as… my microblog… at micro.paultibbetts.uk.

    Instead of doing it by hand on Cloudflare’s website I wrote it down as code.

    Infrastructure as Code

    Writing down your infrastructure as code has a lot of benefits:

    • it’s in one central place instead of spread out in different UIs on different sites
    • it can be version controlled
    • it can be readable by robots as well as other humans

    You can use tools like Terraform, OpenTofu or Pulumi to do this.

    Terraform

    I’m using Terraform at the moment. I might look into Pulumi in the future.

    Terraform uses HCL for its configuration.

    main.tf

    terraform {
      required_providers {
        cloudflare = {
          source  = "cloudflare/cloudflare"
          version = "~> 4.0"
        }
      }
    }
    

    My domain is managed by Cloudflare so at the start of my code I tell Terraform to use the cloudflare/cloudflare provider. This means I can manage different things in Cloudflare using a few settings.

    provider "cloudflare" {
      api_token = var.cloudflare_api_token
    }
    

    Next I tell the Cloudflare provider to use a variable for my API token.

    data "cloudflare_zone" "paultibbetts_dot_uk" {
      name = "paultibbetts.uk"
    }
    

    Originally I asked ChatGPT how to do this, and it was technically correct, but it wanted me to go on the Cloudflare site, go to my domain, and copy the zone_id to pass in as a variable. Which is missing the point of doing this with code.

    Instead, using data means this block is a data source, called paultibbetts_dot_uk, which uses Cloudflare’s cloudflare_zone module to get a zone (domain) with a name of paultibbetts.uk.

    I don’t know or care what the ID is and I can automate the process of finding it out.

    resource "cloudflare_record" "microblog" {
      zone_id = data.cloudflare_zone.paultibbetts_dot_uk.id
      name    = "micro"
      type    = "CNAME"
      value   = "paultibbetts.micro.blog"
      ttl     = 300
    }
    

    When I create a cloudflare_record resource, called microblog, I can use the data source to get the ID of the zone for which domain the CNAME record should be added to.

    vars.tf

    variable "cloudflare_api_token" {
      type        = string
      description = "api token"
    }
    

    Because I don’t want to write down my API token in my code I set it up as a variable.

    I can now pass in the token when I run Terraform:

    terraform apply \ 
    -var cloudflare_api_token="********" \ 
    

    but I prefer loading it in as an environment variable.

    You can do this by prefixing the variable with TF_VAR:

    # secrets.sh
    export TF_VAR_cloudflare_api_token=********
    

    and remembering to source this file before you run Terraform commands

    source secrets.sh
    terraform apply
    

    apply

    Now I can run terraform apply, confirm the proposed changes, and Terraform will use the Cloudlfare API to add the CNAME to my domain for me.

    After making a quick change in Micro.blog I’m live at my own domain 🥳