feat: Added DNS control to tofu
This commit is contained in:
@@ -17,6 +17,26 @@ locals {
|
||||
|
||||
# IDs for every named key in var.ssh_key_names - installed on every server.
|
||||
ssh_key_ids = [for k in data.hcloud_ssh_key.main : k.id]
|
||||
|
||||
# Every A record currently referenced by a Traefik Host() rule anywhere under
|
||||
# services/ - kept in sync with the actual compose files, not aspirational.
|
||||
# "dev.luke-else.co.uk" is a *website* served from prod (a dev-tagged build of
|
||||
# luke-else.co.uk), not the dev server - don't confuse the two.
|
||||
dns_records = [
|
||||
{ zone = "luke-else.co.uk", name = "@", value = module.prod.ipv4 },
|
||||
{ zone = "luke-else.co.uk", name = "dev", value = module.prod.ipv4 },
|
||||
{ zone = "luke-else.co.uk", name = "metarius", value = module.prod.ipv4 },
|
||||
{ zone = "luke-else.co.uk", name = "traefik", value = module.prod.ipv4 },
|
||||
{ zone = "luke-else.co.uk", name = "status", value = module.prod.ipv4 },
|
||||
{ zone = "luke-else.co.uk", name = "bitwarden", value = module.prod.ipv4 },
|
||||
{ zone = "luke-else.co.uk", name = "rd", value = module.prod.ipv4 },
|
||||
{ zone = "luke-else.co.uk", name = "git", value = module.dev.ipv4 },
|
||||
{ zone = "luke-else.co.uk", name = "traefik.cicd", value = module.dev.ipv4 },
|
||||
{ zone = "luke-else.co.uk", name = "vpn", value = module.vpn.ipv4 },
|
||||
{ zone = "luke-else.co.uk", name = "traefik.vpn", value = module.vpn.ipv4 },
|
||||
{ zone = "divine-couture.co.uk", name = "www", value = module.prod.ipv4 },
|
||||
{ zone = "snexo.co.uk", name = "@", value = module.prod.ipv4 },
|
||||
]
|
||||
}
|
||||
|
||||
module "network" {
|
||||
@@ -77,3 +97,10 @@ module "vpn" {
|
||||
bootstrap_script = local.bootstrap_script
|
||||
ssh_private_key_path = var.ssh_private_key_path
|
||||
}
|
||||
|
||||
module "dns" {
|
||||
source = "./modules/dns"
|
||||
|
||||
zone_names = var.dns_zones
|
||||
records = local.dns_records
|
||||
}
|
||||
|
||||
@@ -0,0 +1,28 @@
|
||||
# One Hetzner DNS zone per domain in var.zone_names. Hetzner becomes
|
||||
# authoritative for these once the domain's registrar NS records are pointed at
|
||||
# the nameservers in the `nameservers` output - that step happens at whichever
|
||||
# registrar the domain was bought through, and can't be done from here.
|
||||
resource "hcloud_zone" "this" {
|
||||
for_each = toset(var.zone_names)
|
||||
|
||||
name = each.value
|
||||
mode = "primary"
|
||||
delete_protection = true # API-level guard, in addition to prevent_destroy below
|
||||
|
||||
lifecycle {
|
||||
prevent_destroy = true
|
||||
}
|
||||
}
|
||||
|
||||
resource "hcloud_zone_rrset" "a" {
|
||||
for_each = { for r in var.records : "${r.zone}/${r.name}" => r }
|
||||
|
||||
zone = hcloud_zone.this[each.value.zone].id
|
||||
name = each.value.name
|
||||
type = "A"
|
||||
ttl = each.value.ttl
|
||||
|
||||
records = [
|
||||
{ value = each.value.value }
|
||||
]
|
||||
}
|
||||
@@ -0,0 +1,9 @@
|
||||
output "zone_ids" {
|
||||
description = "Map of domain name to Hetzner zone ID."
|
||||
value = { for name, z in hcloud_zone.this : name => z.id }
|
||||
}
|
||||
|
||||
output "nameservers" {
|
||||
description = "Map of domain name to the nameservers Hetzner assigned it - point your registrar's NS records at these to delegate DNS."
|
||||
value = { for name, z in hcloud_zone.this : name => z.authoritative_nameservers.assigned }
|
||||
}
|
||||
@@ -0,0 +1,15 @@
|
||||
variable "zone_names" {
|
||||
description = "Domains to create as Hetzner DNS zones."
|
||||
type = list(string)
|
||||
}
|
||||
|
||||
variable "records" {
|
||||
description = "A records to create across the zones in var.zone_names. Use name = \"@\" for the zone apex."
|
||||
type = list(object({
|
||||
zone = string
|
||||
name = string
|
||||
value = string
|
||||
ttl = optional(number, 300)
|
||||
}))
|
||||
default = []
|
||||
}
|
||||
@@ -17,3 +17,8 @@ output "prod_private_ipv4" {
|
||||
output "vpn_ipv4" {
|
||||
value = module.vpn.ipv4
|
||||
}
|
||||
|
||||
output "dns_nameservers" {
|
||||
description = "Nameservers Hetzner assigned each zone - point each domain's registrar NS records at these to delegate DNS to Hetzner."
|
||||
value = module.dns.nameservers
|
||||
}
|
||||
|
||||
@@ -24,3 +24,4 @@ ssh_private_key_path = "~/.ssh/id_ed25519"
|
||||
# allowed_ssh_source_ips = ["203.0.113.4/32"]
|
||||
# deploy_user = "deploy"
|
||||
# dev_runner_count = 3
|
||||
# dns_zones = ["luke-else.co.uk", "divine-couture.co.uk", "snexo.co.uk"]
|
||||
|
||||
@@ -97,3 +97,9 @@ variable "dev_runner_count" {
|
||||
type = number
|
||||
default = 1
|
||||
}
|
||||
|
||||
variable "dns_zones" {
|
||||
description = "Domains to manage as Hetzner DNS zones. Point each domain's registrar NS records at tofu output dns_nameservers for Hetzner to actually become authoritative."
|
||||
type = list(string)
|
||||
default = ["luke-else.co.uk", "divine-couture.co.uk", "snexo.co.uk"]
|
||||
}
|
||||
|
||||
+1
-1
@@ -4,7 +4,7 @@ terraform {
|
||||
required_providers {
|
||||
hcloud = {
|
||||
source = "hetznercloud/hcloud"
|
||||
version = "~> 1.45"
|
||||
version = "~> 1.54" # hcloud_zone / hcloud_zone_rrset (DNS) require >= 1.54.0
|
||||
}
|
||||
local = {
|
||||
source = "hashicorp/local"
|
||||
|
||||
Reference in New Issue
Block a user