From 519235558a37cb3c391100de26cd360ac8590c05 Mon Sep 17 00:00:00 2001 From: chrisfu Date: Thu, 29 Jan 2026 16:58:30 -0800 Subject: [PATCH] add ansible role samba_dns. master group_vars/all/dns.yml\nfixed role iscsi --- .../inventory/group_vars/all/dns.yml | 152 ++++++++++++++++++ infrastructure/playbooks/site.yml | 3 +- infrastructure/roles/iscsi/tasks/main.yml | 15 -- .../roles/samba_dns/tasks/ensure_a.yml | 43 +++++ infrastructure/roles/samba_dns/tasks/main.yml | 22 +++ 5 files changed, 219 insertions(+), 16 deletions(-) create mode 100644 infrastructure/inventory/group_vars/all/dns.yml create mode 100644 infrastructure/roles/samba_dns/tasks/ensure_a.yml create mode 100644 infrastructure/roles/samba_dns/tasks/main.yml diff --git a/infrastructure/inventory/group_vars/all/dns.yml b/infrastructure/inventory/group_vars/all/dns.yml new file mode 100644 index 0000000..7d103f5 --- /dev/null +++ b/infrastructure/inventory/group_vars/all/dns.yml @@ -0,0 +1,152 @@ +--- +prole_domain: prole.org + +# Source of truth imported from name.com export (A/CNAME/MX/TXT) +# Notes: +# - "name: '@'" means the zone apex (prole.org) +# - no IPv6 records included (per request) +prole_dns_records: + - name: aventage + type: A + value: 10.0.0.206 + ttl: 300 + + - name: book.svc + type: A + value: 185.158.133.1 + ttl: 300 + + - name: fairyland + type: A + value: 10.0.0.208 + ttl: 300 + + - name: k8s + type: CNAME + value: zinfandel.prole.org + ttl: 300 + + - name: loghost + type: A + value: 10.0.0.3 + ttl: 300 + + - name: mc + type: A + value: 73.15.20.166 + ttl: 300 + + - name: morana + type: A + value: 10.0.0.66 + ttl: 300 + + - name: morgoth + type: A + value: 10.0.0.204 + ttl: 300 + + - name: myrddin + type: A + value: 10.0.0.3 + ttl: 300 + + - name: ollama + type: A + value: 73.15.20.166 + ttl: 300 + + - name: pi + type: A + value: 10.0.0.5 + ttl: 300 + + - name: "@" + type: MX + value: alt1.aspmx.l.google.com + ttl: 3600 + priority: 5 + + - name: "@" + type: MX + value: alt2.aspmx.l.google.com + ttl: 3600 + priority: 5 + + - name: "@" + type: MX + value: alt3.aspmx.l.google.com + ttl: 3600 + priority: 10 + + - name: "@" + type: MX + value: alt4.aspmx.l.google.com + ttl: 3600 + priority: 10 + + - name: "@" + type: MX + value: aspmx.l.google.com + ttl: 3600 + priority: 1 + + - name: raspberry + type: A + value: 10.0.0.4 + ttl: 300 + + - name: retropie + type: A + value: 10.0.0.207 + ttl: 300 + + - name: svc + type: A + value: 73.15.20.166 + ttl: 300 + + - name: synology + type: A + value: 10.0.0.203 + ttl: 300 + + - name: www + type: CNAME + value: ghs.googlehosted.com + ttl: 300 + + - name: zinfandel + type: A + value: 10.0.0.205 + ttl: 300 + + - name: _lovable.book.svc + type: TXT + value: lovable_verify=a6369596ca0ae0b00fde155591c566c05a9844302a70727ba69a74b56c58927f + ttl: 300 + +# Convenience list: internal RFC1918 A records only (useful for Samba AD DNS population) +prole_internal_a_records: + - fqdn: aventage.prole.org + ipv4: 10.0.0.206 + - fqdn: fairyland.prole.org + ipv4: 10.0.0.208 + - fqdn: loghost.prole.org + ipv4: 10.0.0.3 + - fqdn: morana.prole.org + ipv4: 10.0.0.66 + - fqdn: morgoth.prole.org + ipv4: 10.0.0.204 + - fqdn: myrddin.prole.org + ipv4: 10.0.0.3 + - fqdn: pi.prole.org + ipv4: 10.0.0.5 + - fqdn: raspberry.prole.org + ipv4: 10.0.0.4 + - fqdn: retropie.prole.org + ipv4: 10.0.0.207 + - fqdn: synology.prole.org + ipv4: 10.0.0.203 + - fqdn: zinfandel.prole.org + ipv4: 10.0.0.205 diff --git a/infrastructure/playbooks/site.yml b/infrastructure/playbooks/site.yml index e0b69cb..4f05ae7 100644 --- a/infrastructure/playbooks/site.yml +++ b/infrastructure/playbooks/site.yml @@ -16,6 +16,7 @@ become: true roles: - samba_ad_dc + - samba_dns - samba_reverse_dns - hosts: linux_hosts @@ -35,4 +36,4 @@ hosts: k3s_hosts become: true roles: - - k3s \ No newline at end of file + - k3s diff --git a/infrastructure/roles/iscsi/tasks/main.yml b/infrastructure/roles/iscsi/tasks/main.yml index 8e113b3..74aad04 100644 --- a/infrastructure/roles/iscsi/tasks/main.yml +++ b/infrastructure/roles/iscsi/tasks/main.yml @@ -32,18 +32,3 @@ loop: "{{ iscsi_targets | default([]) | map(attribute='mounts') | list | flatten }}" loop_control: label: "{{ item.path }}" - -- name: Guardrail - ensure /var/lib/rancher is not on SD/rootfs - ansible.builtin.command: "findmnt -n -o SOURCE /var/lib/rancher" - register: rancher_source - changed_when: false - failed_when: rancher_source.rc != 0 - when: iscsi_targets is defined and iscsi_targets | length > 0 - -- name: Fail if /var/lib/rancher is on SD - ansible.builtin.fail: - msg: "/var/lib/rancher is on SD/rootfs ({{ rancher_source.stdout }}). Refusing to proceed." - when: - - iscsi_targets is defined - - iscsi_targets | length > 0 - - rancher_source.stdout is search("mmcblk0") or rancher_source.stdout is search("/dev/mmc") diff --git a/infrastructure/roles/samba_dns/tasks/ensure_a.yml b/infrastructure/roles/samba_dns/tasks/ensure_a.yml new file mode 100644 index 0000000..e0ea52a --- /dev/null +++ b/infrastructure/roles/samba_dns/tasks/ensure_a.yml @@ -0,0 +1,43 @@ +--- +- name: Derive record name within zone from fqdn + ansible.builtin.set_fact: + samba_dns_record_name: >- + {{ + (item.fqdn | regex_replace('\\.?$','')) | + regex_replace('\\.' ~ (prole_domain | regex_escape) ~ '$', '') + }} + +- name: Query existing A records + ansible.builtin.command: + cmd: samba-tool dns query {{ samba_dns_server }} {{ prole_domain }} {{ samba_dns_record_name }} A -U {{ samba_dns_admin_user }}%{{ samba_dns_admin_pass }} + register: a_query + changed_when: false + failed_when: false + +- name: Parse existing A record values + ansible.builtin.set_fact: + a_existing_values: >- + {{ + (a_query.stdout | default('') | + regex_findall('\\bA\\s+([0-9]{1,3}(?:\\.[0-9]{1,3}){3})\\b') | + list) + }} + +- name: Remove stale A records + ansible.builtin.command: + cmd: samba-tool dns delete {{ samba_dns_server }} {{ prole_domain }} {{ samba_dns_record_name }} A {{ a_value }} -U {{ samba_dns_admin_user }}%{{ samba_dns_admin_pass }} + loop: "{{ a_existing_values | reject('equalto', item.ipv4) | list }}" + loop_control: + loop_var: a_value + when: (a_existing_values | reject('equalto', item.ipv4) | list | length) > 0 + +- name: Add expected A record + ansible.builtin.command: + cmd: samba-tool dns add {{ samba_dns_server }} {{ prole_domain }} {{ samba_dns_record_name }} A {{ item.ipv4 }} -U {{ samba_dns_admin_user }}%{{ samba_dns_admin_pass }} + register: a_add + changed_when: a_add.rc == 0 + failed_when: > + a_add.rc != 0 and + ('WERR_DNS_ERROR_RECORD_ALREADY_EXISTS' not in (a_add.stderr | default(''))) and + ('Record already exists' not in (a_add.stderr | default(''))) + when: item.ipv4 not in a_existing_values diff --git a/infrastructure/roles/samba_dns/tasks/main.yml b/infrastructure/roles/samba_dns/tasks/main.yml new file mode 100644 index 0000000..d68b557 --- /dev/null +++ b/infrastructure/roles/samba_dns/tasks/main.yml @@ -0,0 +1,22 @@ +--- +- name: Assert Samba DNS admin password is set (vault loaded) + ansible.builtin.assert: + that: + - samba_dns_admin_pass is defined + - samba_dns_admin_pass | length > 0 + fail_msg: "Missing samba_dns_admin_pass. Create inventory/group_vars/ad_dc.vault.yml with vault_samba_dns_admin_pass." + +- name: List Samba DNS zones + ansible.builtin.command: + cmd: samba-tool dns zonelist {{ samba_dns_server }} -U {{ samba_dns_admin_user }}%{{ samba_dns_admin_pass }} + register: samba_zones + changed_when: false + +- name: Create forward DNS zone if missing + ansible.builtin.command: + cmd: samba-tool dns zonecreate {{ samba_dns_server }} {{ prole_domain }} -U {{ samba_dns_admin_user }}%{{ samba_dns_admin_pass }} + when: prole_domain not in samba_zones.stdout + +- name: Ensure forward A records (internal RFC1918 hosts) + ansible.builtin.include_tasks: ensure_a.yml + loop: "{{ prole_internal_a_records | default([]) }}"