feat(dns): add sys-svc-dns role and extend parent DNS handling

Introduce sys-svc-dns to bootstrap Cloudflare DNS prerequisites. Validates CLOUDFLARE_API_TOKEN, (optionally) manages CAA for base SLDs, and delegates parent record creation to sys-dns-parent-hosts. Wired into sys-stk-front-pure.

sys-dns-parent-hosts: new parent_dns filter builds A/AAAA for each parent host and wildcard children (*.parent). Supports dict/list inputs for CURRENT_PLAY_DOMAINS, optional IPv6, proxied flag, and optional *.apex. Exposes a single parent_build_records entry point.

Let’s Encrypt role cleanup: remove DNS/C AA management from sys-svc-letsencrypt; it now focuses on webroot challenge config and renew timer. Fixed path joins and run_once guards.

Tests: update unit tests to allow wildcard outputs and dict-based CURRENT_PLAY_DOMAINS. Add generate_base_sld_domains filter. Documentation updates for both roles.

Conversation: https://chatgpt.com/share/68c342f7-d20c-800f-b61f-cefeebcf1cd8
This commit is contained in:
2025-09-11 23:47:27 +02:00
parent dc16b7d21c
commit a552ea175d
19 changed files with 457 additions and 16 deletions

View File

@@ -0,0 +1,22 @@
# sys-svc-dns
Bootstrap and maintain **DNS prerequisites** for your web stack on Cloudflare.
This role validates credentials and (by default) ensures:
- **Parent host A/AAAA records** (incl. the **apex** SLD.TLD) via `sys-dns-parent-hosts`
- *(Optional)* **CAA** records for Lets 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.
---
## What it does
1. **Validate `CLOUDFLARE_API_TOKEN`** is present (early fail if missing).
2. **Ensure parent DNS exists** (apex + “parent” FQDNs derived from children):
- Delegates to [`sys-dns-parent-hosts`](../sys-dns-parent-hosts/README.md)
- Creates A (and AAAA if enabled upstream) 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)

View File

@@ -0,0 +1,26 @@
galaxy_info:
author: "Kevin Veen-Birkenbach"
description: "Cloudflare DNS bootstrap: parent host A/AAAA (and optional CAA) — runs once per play."
license: "Infinito.Nexus NonCommercial License"
license_url: "https://s.infinito.nexus/license"
company: |
Kevin Veen-Birkenbach
Consulting & Coaching Solutions
https://www.veen.world
min_ansible_version: "2.12"
platforms:
- name: Archlinux
versions: [rolling]
galaxy_tags:
- dns
- cloudflare
- automation
- letsencrypt
- nginx
repository: "https://s.infinito.nexus/code"
issue_tracker_url: "https://s.infinito.nexus/issues"
documentation: "https://docs.infinito.nexus"
logo:
class: "fa-solid fa-cloud"
run_after: []
dependencies: []

View File

@@ -0,0 +1,32 @@
---
- name: "Validate CLOUDFLARE_API_TOKEN"
fail:
msg: >
The variable "CLOUDFLARE_API_TOKEN" must be defined and cannot be empty!
when: (CLOUDFLARE_API_TOKEN|default('')|trim) == ''
- name: "Ensure all CAA records are present"
community.general.cloudflare_dns:
api_token: "{{ CLOUDFLARE_API_TOKEN }}"
zone: "{{ item.0 }}"
record: "@"
type: CAA
flag: 0
tag: "{{ item.1.tag }}"
value: "{{ item.1.value }}"
ttl: 1
state: present
loop: "{{ base_sld_domains | product(caa_entries) | list }}"
loop_control:
label: "{{ item.0 }} → {{ item.1.tag }}"
async: "{{ ASYNC_TIME if ASYNC_ENABLED | bool else omit }}"
poll: "{{ ASYNC_POLL if ASYNC_ENABLED | bool else omit }}"
- name: "Ensure parent DNS (apex + parent FQDNs) exists"
include_role:
name: sys-dns-parent-hosts
vars:
parent_dns_proxied: false
when: run_once_sys_dns_parent_hosts is not defined
- include_tasks: utils/run_once.yml

View File

@@ -0,0 +1,4 @@
- block:
- include_tasks: 01_core.yml
when: DNS_PROVIDER == 'cloudflare'
when: run_once_sys_svc_dns is not defined

View File

@@ -0,0 +1,4 @@
caa_entries:
- tag: issue
value: letsencrypt.org
base_sld_domains: '{{ CURRENT_PLAY_DOMAINS_ALL | generate_base_sld_domains }}'