Terraform
Terraform is used to manage the network and hardware settings.
Directoryterraform/ network/hardware
- backend.tf configures the state file
- dns.tf configures domain stuff
- providers.tf defines the providers I’m using
- vars.tf sets what to pass in when running Terraform
- web.tf configures my web server
locals { default_ttl = 1 # auto default_proxied = false}
data "cloudflare_zones" "zones" { name = local.domain}
resource "cloudflare_dns_record" "record" { for_each = local.records
zone_id = data.cloudflare_zones.zones.result[0].id
name = each.value.name type = each.value.type content = each.value.content
ttl = try(each.value.ttl, local.default_ttl) proxied = try(each.value.proxied, local.default_proxied)
priority = try(each.value.priority, null)}Here Terraform uses Cloudflare to set all the records for my domain.
resource "mythicbeasts_pi" "web" { identifier = var.pi_identifier disk_size = 50 model = 4 memory = 4096}
resource "mythicbeasts_proxy_endpoint" "endpoint" { for_each = local.web_subdomains
domain = local.domain hostname = each.value address = mythicbeasts_pi.web.ip site = "all" proxy_protocol = true}
resource "ansible_host" "web" { name = "pi" groups = ["web"] variables = { ansible_host = "ssh.${mythicbeasts_pi.web.identifier}.hostedpi.com" ansible_port = mythicbeasts_pi.web.ssh_port ansible_user = "ops" }}Here Terraform requests the Pi and configures the Proxy endpoints using its IP address.
It also creates an ansible_host for the Pi so that Ansible can target it to configure it.
State file
Section titled “State file”The state file, that records the current state of the infrastructure that Terraform manages, is hosted on MinIO running on my NAS in my homelab.
This is configured using:
terraform { backend "s3" { bucket = "tfstate" key = "paultibbetts.uk.tfstate" region = "main" skip_credentials_validation = true skip_requesting_account_id = true skip_metadata_api_check = true skip_region_validation = true use_path_style = true }}Variables
Section titled “Variables”The variables that are my setup go in terraform/locals.tf:
locals { domain = "paultibbetts.uk"
web_subdomains = { apex = "@" www = "www" infra = "infra" dev = "dev" }
proxy_records = { for key, host in local.web_subdomains : key => { type = "CNAME" name = host content = "proxy.mythic-beasts.com" } }
records = merge( local.proxy_records, { micro = { type = "CNAME" name = "micro" content = "eu.micro.blog" }
atproto = { type = "TXT" name = "_atproto" content = "did=did:plc:adwdgyaga5q2psrjbvo4pndr" }
github_pages_challenge = { type = "TXT" name = "_github-pages-challenge-paultibbetts" content = "0d468c5988c95ab09a88f0c494dcb9" }
mythic_beasts_challenge = { type = "TXT" name = "_mythic-beasts-challenge" content = "T7eS19QKZV6VOo0og5sn2OmKDoem4dLL7IgT9tJLT7c" }
openai_domain_verification = { type = "TXT" name = "@" content = "openai-domain-verification=dv-CPJLyYLfDZ990DDlefMkxdkN" }
# Apple iCloud email # https://support.apple.com/en-gb/102374
apple_domain_verificaton = { type = "TXT" name = "@" content = "apple-domain=JTK5xOaQo9cwujIv" }
spf = { type = "TXT" name = "@" content = "v=spf1 include:icloud.com ~all" }
mx_icloud_01 = { type = "MX" name = "@" content = "mx01.mail.icloud.com" priority = 10 }
mx_icloud_02 = { type = "MX" name = "@" content = "mx02.mail.icloud.com" priority = 10 }
dkim_sig1 = { type = "CNAME" name = "sig1._domainkey" content = "sig1.dkim.paultibbetts.uk.at.icloudmailadmin.com" }
} )}Secrets
Section titled “Secrets”Terraform needs a few secrets passing to it to work.
Because it manages the domain using Cloudflare it needs a Cloudflare API token passing to it.
MinIO, which is where the state file is hosted, also needs to be told the key to use.
These secrets are exported as environment variables and read by Terraform:
source secrets.shwhere secrets.sh:
export TF_VAR_cloudflare_api_token=$(pass cloudflare_api_token_paultibbettsuk)
export AWS_ENDPOINT_URL_S3=$(pass minio_endpoint)export AWS_ACCESS_KEY_ID=$(pass minio_access_key)export AWS_SECRET_ACCESS_KEY=$(pass minio_secret_key)
export MYTHICBEASTS_KEYID=$(pass mythicbeasts_keyid)export MYTHICBEASTS_SECRET=$(pass mythicbeasts_secret)The script grabs the secrets from a pass vault before exporting them for future commands to use.