From cce33373ba871ac40a4625fa8bcebad0919b8e93 Mon Sep 17 00:00:00 2001 From: Kevin Veen-Birkenbach Date: Fri, 12 Sep 2025 04:30:59 +0200 Subject: [PATCH] sys-svc-dns: add apex A/AAAA records for SYS_SVC_DNS_BASE_DOMAINS via task_include This update introduces apex (@) A and optional AAAA records for all base SLD domains. The tasks were moved into a new 02_apex.yml file and are looped using SYS_SVC_DNS_BASE_DOMAINS. CAA record loops were updated accordingly. See details: https://chatgpt.com/share/68c385c3-1804-800f-8c78-8614bc853f77 --- roles/sys-svc-dns/README.md | 10 +++++++--- roles/sys-svc-dns/tasks/01_core.yml | 9 ++++++++- roles/sys-svc-dns/tasks/02_apex.yml | 28 ++++++++++++++++++++++++++++ roles/sys-svc-dns/vars/main.yml | 2 +- 4 files changed, 44 insertions(+), 5 deletions(-) create mode 100644 roles/sys-svc-dns/tasks/02_apex.yml diff --git a/roles/sys-svc-dns/README.md b/roles/sys-svc-dns/README.md index 2142d0a6..4a251de3 100644 --- a/roles/sys-svc-dns/README.md +++ b/roles/sys-svc-dns/README.md @@ -3,7 +3,8 @@ Bootstrap and maintain **DNS prerequisites** for your web stack on Cloudflare. This role validates credentials and (by default) ensures: -- **Wildcard A/AAAA records** (`*.parent`) for parent hosts via `sys-dns-wildcards` (no base/apex records) +- **A (and optional AAAA) records** on the **apex** (`@`) for all **base SLD domains** +- **Wildcard A/AAAA records** (`*.parent`) for parent hosts via `sys-dns-wildcards` - *(Optional)* **CAA** records for Let’s Encrypt (kept as a commented block you can re-enable) Runs **once per play** and is safe to include in stacks that roll out many domains. @@ -13,10 +14,13 @@ Runs **once per play** and is safe to include in stacks that roll out many domai ## What it does 1. **Validate `CLOUDFLARE_API_TOKEN`** is present (early fail if missing). -2. **Ensure wildcard parent DNS exists** (`*.parent` derived from children): +2. **Ensure apex A/AAAA exist** for every **base SLD** in `SYS_SVC_DNS_BASE_DOMAINS`: + - Writes `@ A` → `networks.internet.ip4` + - Writes `@ AAAA` → `networks.internet.ip6` (only if global and present) +3. *(Optional)* **CAA records** for all base SLDs (commented in the tasks; enable if you want CAA managed here). +4. **Ensure wildcard parent DNS exists** (`*.parent` derived from children): - Delegates to [`sys-dns-wildcards`](../sys-dns-wildcards/README.md) - Creates `A` (and `AAAA` if enabled) wildcard records on the Cloudflare zone, optionally proxied. -3. *(Optional)* **CAA records** for all base SLDs (commented in the tasks; enable if you want CAA managed here). > Parent hosts example: > `c.wiki.example.com` → **parent** `wiki.example.com` (plus `example.com` apex) diff --git a/roles/sys-svc-dns/tasks/01_core.yml b/roles/sys-svc-dns/tasks/01_core.yml index b7ccbbbb..d562a9f0 100644 --- a/roles/sys-svc-dns/tasks/01_core.yml +++ b/roles/sys-svc-dns/tasks/01_core.yml @@ -5,6 +5,13 @@ The variable "CLOUDFLARE_API_TOKEN" must be defined and cannot be empty! when: (CLOUDFLARE_API_TOKEN | default('') | trim) == '' +- name: "Apply apex A/AAAA for base domains" + include_tasks: 02_apex.yml + loop: "{{ SYS_SVC_DNS_BASE_DOMAINS | list }}" + loop_control: + loop_var: base_domain + label: "{{ base_domain }}" + - name: "Ensure all CAA records are present" community.general.cloudflare_dns: api_token: "{{ CLOUDFLARE_API_TOKEN }}" @@ -16,7 +23,7 @@ value: "{{ item.1.value }}" ttl: 1 state: present - loop: "{{ base_sld_domains | product(caa_entries) | list }}" + loop: "{{ SYS_SVC_DNS_BASE_DOMAINS | product(caa_entries) | list }}" loop_control: label: "{{ item.0 }} → {{ item.1.tag }}" async: "{{ ASYNC_TIME if ASYNC_ENABLED | bool else omit }}" diff --git a/roles/sys-svc-dns/tasks/02_apex.yml b/roles/sys-svc-dns/tasks/02_apex.yml new file mode 100644 index 00000000..ab11ec66 --- /dev/null +++ b/roles/sys-svc-dns/tasks/02_apex.yml @@ -0,0 +1,28 @@ +--- +- name: "Ensure A @ for {{ base_domain }}" + community.general.cloudflare_dns: + api_token: "{{ CLOUDFLARE_API_TOKEN }}" + zone: "{{ base_domain }}" + type: A + name: "@" + content: "{{ networks.internet.ip4 }}" + proxied: false + ttl: 1 + state: present + async: "{{ ASYNC_TIME if ASYNC_ENABLED | bool else omit }}" + poll: "{{ ASYNC_POLL if ASYNC_ENABLED | bool else omit }}" + +- name: "Ensure AAAA @ for {{ base_domain }} (if IPv6 is global)" + community.general.cloudflare_dns: + api_token: "{{ CLOUDFLARE_API_TOKEN }}" + zone: "{{ base_domain }}" + type: AAAA + name: "@" + content: "{{ networks.internet.ip6 }}" + proxied: false + ttl: 1 + state: present + when: + - (networks.internet.ip6 | default('') | trim) != '' + async: "{{ ASYNC_TIME if ASYNC_ENABLED | bool else omit }}" + poll: "{{ ASYNC_POLL if ASYNC_ENABLED | bool else omit }}" diff --git a/roles/sys-svc-dns/vars/main.yml b/roles/sys-svc-dns/vars/main.yml index 03343533..ddd896e6 100644 --- a/roles/sys-svc-dns/vars/main.yml +++ b/roles/sys-svc-dns/vars/main.yml @@ -1,4 +1,4 @@ caa_entries: - tag: issue value: letsencrypt.org -base_sld_domains: '{{ CURRENT_PLAY_DOMAINS_ALL | generate_base_sld_domains }}' +SYS_SVC_DNS_BASE_DOMAINS: '{{ CURRENT_PLAY_DOMAINS_ALL | generate_base_sld_domains }}'