From 96a44d5da6080e91edc2a80ae994cb3d7264ba18 Mon Sep 17 00:00:00 2001 From: beatz174-bit Date: Wed, 13 May 2026 05:18:02 +1000 Subject: [PATCH 1/3] Add dynu_root_domain variable for domain import flow --- infrastructure/terraform/dynu/README.md | 39 +++++++++---------- infrastructure/terraform/dynu/domains.tf | 8 +++- .../terraform/dynu/imports.tf.example | 17 ++++---- infrastructure/terraform/dynu/provider.tf | 1 - infrastructure/terraform/dynu/records.tf | 23 +++++++++++ .../terraform/dynu/terraform.tfvars.example | 2 + infrastructure/terraform/dynu/variables.tf | 7 ++++ infrastructure/terraform/dynu/versions.tf | 3 +- 8 files changed, 69 insertions(+), 31 deletions(-) diff --git a/infrastructure/terraform/dynu/README.md b/infrastructure/terraform/dynu/README.md index 2bd99f9..f2da1cd 100644 --- a/infrastructure/terraform/dynu/README.md +++ b/infrastructure/terraform/dynu/README.md @@ -7,33 +7,28 @@ Dynu remains the authoritative DNS provider for existing records. Terraform here ## Provider - Source: `beatz174-bit/dynu` -- Version constraint: `>= 0.1.0` - -Authentication is local-only and must not be committed. +- Provider version is intentionally unpinned in this root to use the latest published release. +- Provider block uses `api_key` auth argument from the published provider schema. ## Credentials and auth -Use local `terraform.tfvars` (or environment variables if supported by the provider release you use). +Use local `terraform.tfvars` (or provider-supported environment variables). -Variables included: +- Required variable: `dynu_api_key` +- Domain variable: `dynu_root_domain` (defaults to `lan.ddnsgeek.com`) +- Optional placeholders for future provider auth changes: `dynu_username`, `dynu_password` -- `dynu_api_key` (sensitive) -- `dynu_username` (optional, sensitive) -- `dynu_password` (optional, sensitive) +Never commit: -> Keep real values out of git and out of shared logs. - -## Safety - -- Do not commit `terraform.tfvars`, `.tfstate*`, or `.terraform/`. -- Import/reconcile one domain or record at a time. -- Treat generated config as draft input, not final truth. +- `terraform.tfvars` +- `.terraform/` +- `*.tfstate*` +- credentials/secrets ## Safe validation commands ```bash cd infrastructure/terraform/dynu - terraform fmt -check -recursive terraform init -backend=false -input=false terraform validate @@ -48,11 +43,11 @@ terraform init terraform plan ``` -## Import workflow (placeholder examples) +## Import workflow (one object at a time) ```bash -terraform import dynu_dns_domain.lan_ddnsgeek_com '' -terraform state show dynu_dns_domain.lan_ddnsgeek_com +terraform import dynu_domain.lan_ddnsgeek_com '' +terraform state show dynu_domain.lan_ddnsgeek_com terraform plan ``` @@ -64,4 +59,8 @@ $EDITOR imports.tf terraform plan -generate-config-out=generated-dynu.tf ``` -Confirm exact resource types and import ID formats from the provider docs before running imports. +Notes: + +1. Confirm exact import ID formats from the provider docs. +2. For DNS records, add one `dynu_dns_record` resource at a time after confirming required arguments (`hostname`, `record_type`) from `terraform providers schema`. +3. Treat generated config as draft input; keep only stable, meaningful attributes in hand-maintained `.tf`. diff --git a/infrastructure/terraform/dynu/domains.tf b/infrastructure/terraform/dynu/domains.tf index 28fa409..6d5b9a9 100644 --- a/infrastructure/terraform/dynu/domains.tf +++ b/infrastructure/terraform/dynu/domains.tf @@ -1,3 +1,9 @@ locals { - dynu_domain = "lan.ddnsgeek.com" + dynu_domain = var.dynu_root_domain +} + +# Import-first resource skeleton for the production Dynu zone. +# `name` is required by provider schema and can be reconciled after import. +resource "dynu_domain" "lan_ddnsgeek_com" { + name = local.dynu_domain } diff --git a/infrastructure/terraform/dynu/imports.tf.example b/infrastructure/terraform/dynu/imports.tf.example index d693c07..f16c231 100644 --- a/infrastructure/terraform/dynu/imports.tf.example +++ b/infrastructure/terraform/dynu/imports.tf.example @@ -1,11 +1,14 @@ -# Copy this file to imports.tf and adjust values after confirming the -# published provider docs for resource type names and import ID formats. +# Copy this file to imports.tf and adjust IDs after confirming the +# published provider docs for import ID formats. +# For dynu_domain, import ID is commonly the root domain name. -# Example placeholder shape only: -# import { -# to = dynu_dns_domain.lan_ddnsgeek_com -# id = "REPLACE_WITH_DYNU_DOMAIN_IMPORT_ID" -# } +import { + to = dynu_domain.lan_ddnsgeek_com + id = var.dynu_root_domain +} + +# DNS record imports are intentionally examples only because the provider +# requires explicit record_type/hostname in config before import. # # import { # to = dynu_dns_record.grafana_lan_ddnsgeek_com diff --git a/infrastructure/terraform/dynu/provider.tf b/infrastructure/terraform/dynu/provider.tf index 8a12311..bb3cfe3 100644 --- a/infrastructure/terraform/dynu/provider.tf +++ b/infrastructure/terraform/dynu/provider.tf @@ -1,5 +1,4 @@ provider "dynu" { # Keep auth local-only; do not commit credentials. - # Provider schema must be confirmed against registry docs before changing fields. api_key = var.dynu_api_key } diff --git a/infrastructure/terraform/dynu/records.tf b/infrastructure/terraform/dynu/records.tf index 42e48e3..1aa7ca7 100644 --- a/infrastructure/terraform/dynu/records.tf +++ b/infrastructure/terraform/dynu/records.tf @@ -143,5 +143,28 @@ locals { target = null proxied = null } + + searxng = { + fqdn = "searxng.lan.ddnsgeek.com" + hostname = "searxng" + service = "searxng" + source = "apps/searxng/docker-compose.yml" + purpose = "SearXNG search endpoint" + record_type = null + ttl = null + target = null + proxied = null + } + traefik = { + fqdn = "traefik.lan.ddnsgeek.com" + hostname = "traefik" + service = "traefik" + source = "core/traefik/docker-compose.yml" + purpose = "Traefik dashboard/API endpoint" + record_type = null + ttl = null + target = null + proxied = null + } } } diff --git a/infrastructure/terraform/dynu/terraform.tfvars.example b/infrastructure/terraform/dynu/terraform.tfvars.example index 05632f8..a68819a 100644 --- a/infrastructure/terraform/dynu/terraform.tfvars.example +++ b/infrastructure/terraform/dynu/terraform.tfvars.example @@ -2,3 +2,5 @@ dynu_api_key = "replace-with-dynu-api-key" dynu_username = null dynu_password = null + +dynu_root_domain = "lan.ddnsgeek.com" diff --git a/infrastructure/terraform/dynu/variables.tf b/infrastructure/terraform/dynu/variables.tf index 3614969..4b6b24c 100644 --- a/infrastructure/terraform/dynu/variables.tf +++ b/infrastructure/terraform/dynu/variables.tf @@ -1,3 +1,10 @@ + +variable "dynu_root_domain" { + description = "Dynu root domain name to reconcile/import (for example: lan.ddnsgeek.com)." + type = string + default = "lan.ddnsgeek.com" +} + variable "dynu_api_key" { description = "Dynu API key/token used by the Dynu Terraform provider." type = string diff --git a/infrastructure/terraform/dynu/versions.tf b/infrastructure/terraform/dynu/versions.tf index 32b6064..3bbe029 100644 --- a/infrastructure/terraform/dynu/versions.tf +++ b/infrastructure/terraform/dynu/versions.tf @@ -3,8 +3,7 @@ terraform { required_providers { dynu = { - source = "beatz174-bit/dynu" - version = ">= 0.1.0" + source = "beatz174-bit/dynu" } } } From c9e4aeb8d6cfa2302e775bc82f2b8b203b939ea2 Mon Sep 17 00:00:00 2001 From: beatz174-bit Date: Wed, 13 May 2026 05:28:27 +1000 Subject: [PATCH 2/3] Add dynu_record_import_id variable for record imports --- infrastructure/terraform/dynu/README.md | 1 + infrastructure/terraform/dynu/imports.tf.example | 2 +- infrastructure/terraform/dynu/terraform.tfvars.example | 1 + infrastructure/terraform/dynu/variables.tf | 6 ++++++ 4 files changed, 9 insertions(+), 1 deletion(-) diff --git a/infrastructure/terraform/dynu/README.md b/infrastructure/terraform/dynu/README.md index f2da1cd..e71aceb 100644 --- a/infrastructure/terraform/dynu/README.md +++ b/infrastructure/terraform/dynu/README.md @@ -17,6 +17,7 @@ Use local `terraform.tfvars` (or provider-supported environment variables). - Required variable: `dynu_api_key` - Domain variable: `dynu_root_domain` (defaults to `lan.ddnsgeek.com`) - Optional placeholders for future provider auth changes: `dynu_username`, `dynu_password` +- Import helper variable: `dynu_record_import_id` (set per record import operation) Never commit: diff --git a/infrastructure/terraform/dynu/imports.tf.example b/infrastructure/terraform/dynu/imports.tf.example index f16c231..d41f3df 100644 --- a/infrastructure/terraform/dynu/imports.tf.example +++ b/infrastructure/terraform/dynu/imports.tf.example @@ -12,5 +12,5 @@ import { # # import { # to = dynu_dns_record.grafana_lan_ddnsgeek_com -# id = "REPLACE_WITH_DYNU_RECORD_IMPORT_ID" +# id = var.dynu_record_import_id # } diff --git a/infrastructure/terraform/dynu/terraform.tfvars.example b/infrastructure/terraform/dynu/terraform.tfvars.example index a68819a..0ba977f 100644 --- a/infrastructure/terraform/dynu/terraform.tfvars.example +++ b/infrastructure/terraform/dynu/terraform.tfvars.example @@ -4,3 +4,4 @@ dynu_username = null dynu_password = null dynu_root_domain = "lan.ddnsgeek.com" +dynu_record_import_id = "REPLACE_WITH_DYNU_RECORD_IMPORT_ID" diff --git a/infrastructure/terraform/dynu/variables.tf b/infrastructure/terraform/dynu/variables.tf index 4b6b24c..1379c57 100644 --- a/infrastructure/terraform/dynu/variables.tf +++ b/infrastructure/terraform/dynu/variables.tf @@ -25,3 +25,9 @@ variable "dynu_password" { sensitive = true default = null } + +variable "dynu_record_import_id" { + description = "Placeholder import ID for a single dynu_dns_record during one-at-a-time reconciliation." + type = string + default = "REPLACE_WITH_DYNU_RECORD_IMPORT_ID" +} From a9b21912dbd487892e9efda5b657683f89299ab7 Mon Sep 17 00:00:00 2001 From: beatz174-bit Date: Wed, 13 May 2026 05:28:32 +1000 Subject: [PATCH 3/3] Derive Dynu record FQDNs from configured root domain --- infrastructure/terraform/dynu/records.tf | 25 ++++++++---------------- 1 file changed, 8 insertions(+), 17 deletions(-) diff --git a/infrastructure/terraform/dynu/records.tf b/infrastructure/terraform/dynu/records.tf index 1aa7ca7..00847bd 100644 --- a/infrastructure/terraform/dynu/records.tf +++ b/infrastructure/terraform/dynu/records.tf @@ -1,7 +1,6 @@ locals { - dynu_dns_records_catalog = { + dynu_dns_records_catalog_base = { auth = { - fqdn = "auth.lan.ddnsgeek.com" hostname = "auth" service = "authelia" source = "core/authelia/docker-compose.yml" @@ -12,7 +11,6 @@ locals { proxied = null } gitea = { - fqdn = "gitea.lan.ddnsgeek.com" hostname = "gitea" service = "gitea" source = "apps/gitea/docker-compose.yml" @@ -23,7 +21,6 @@ locals { proxied = null } gotify = { - fqdn = "gotify.lan.ddnsgeek.com" hostname = "gotify" service = "gotify" source = "monitoring/gotify/docker-compose.yml" @@ -34,7 +31,6 @@ locals { proxied = null } grafana = { - fqdn = "grafana.lan.ddnsgeek.com" hostname = "grafana" service = "grafana" source = "monitoring/grafana/docker-compose.yml" @@ -45,7 +41,6 @@ locals { proxied = null } familytree = { - fqdn = "familytree.lan.ddnsgeek.com" hostname = "familytree" service = "gramps" source = "apps/gramps/docker-compose.yml" @@ -56,7 +51,6 @@ locals { proxied = null } influxdb = { - fqdn = "influxdb.lan.ddnsgeek.com" hostname = "influxdb" service = "influxdb" source = "monitoring/influxdb/docker-compose.yml" @@ -67,7 +61,6 @@ locals { proxied = null } monitor_kuma = { - fqdn = "monitor-kuma.lan.ddnsgeek.com" hostname = "monitor-kuma" service = "uptime-kuma" source = "monitoring/uptime-kuma/docker-compose.yml" @@ -78,7 +71,6 @@ locals { proxied = null } mtls_bridge = { - fqdn = "mtls-bridge.lan.ddnsgeek.com" hostname = "mtls-bridge" service = "mtls-bridge" source = "monitoring/mtls-bridge/docker-compose.yml" @@ -89,7 +81,6 @@ locals { proxied = null } nextcloud = { - fqdn = "nextcloud.lan.ddnsgeek.com" hostname = "nextcloud" service = "nextcloud-webapp" source = "apps/nextcloud/docker-compose.yml" @@ -100,7 +91,6 @@ locals { proxied = null } node_red = { - fqdn = "node-red.lan.ddnsgeek.com" hostname = "node-red" service = "node-red" source = "monitoring/node-red/docker-compose.yml" @@ -111,7 +101,6 @@ locals { proxied = null } passbolt = { - fqdn = "passbolt.lan.ddnsgeek.com" hostname = "passbolt" service = "passbolt-webapp" source = "apps/passbolt/docker-compose.yml" @@ -122,7 +111,6 @@ locals { proxied = null } portainer = { - fqdn = "portainer.lan.ddnsgeek.com" hostname = "portainer" service = "portainer" source = "monitoring/portainer/docker-compose.yml" @@ -133,7 +121,6 @@ locals { proxied = null } prometheus = { - fqdn = "prometheus.lan.ddnsgeek.com" hostname = "prometheus" service = "prometheus" source = "monitoring/prometheus/docker-compose.yml" @@ -143,9 +130,7 @@ locals { target = null proxied = null } - searxng = { - fqdn = "searxng.lan.ddnsgeek.com" hostname = "searxng" service = "searxng" source = "apps/searxng/docker-compose.yml" @@ -156,7 +141,6 @@ locals { proxied = null } traefik = { - fqdn = "traefik.lan.ddnsgeek.com" hostname = "traefik" service = "traefik" source = "core/traefik/docker-compose.yml" @@ -167,4 +151,11 @@ locals { proxied = null } } + + dynu_dns_records_catalog = { + for key, record in local.dynu_dns_records_catalog_base : + key => merge(record, { + fqdn = format("%s.%s", record.hostname, local.dynu_domain) + }) + } }