enable auth-dns role to actually configure useful zones

This commit is contained in:
lilly 2026-04-30 22:53:07 +02:00
commit 7086b189b9
Signed by: lilly
SSH key fingerprint: SHA256:y9T5GFw2A20WVklhetIxG1+kcg/Ce0shnQmbu1LQ37g
8 changed files with 184 additions and 16 deletions

View file

@ -0,0 +1,3 @@
---
knot__remotes: []

View file

@ -1,8 +1,17 @@
- tags: [ 02-auth-dns ] - tags: [ auth-dns ]
name: restart knot name: restart knot
become: true become: true
notify: restart knot
ansible.builtin.systemd: ansible.builtin.systemd:
name: knot.service name: knot.service
state: restarted state: restarted
- tags: [ auth-dns ]
name: reload knot zones
become: true
ansible.builtin.command: "knotc zone-reload"
- tags: [ auth-dns ]
name: netplan apply
become: true
ansible.builtin.command: "netplan apply"

View file

@ -0,0 +1,61 @@
---
argument_specs:
main:
options:
knot__dnssec_key_id:
description: The id of the TSIG key which knot will use for zone transfer signing
type: str
required: true
knot__dnssec_key_secret:
description: The secret value of the TSIG key which knot will use for zone transfer signing
type: str
required: true
knot__remotes:
description:
- A list of definitions for remote nameservers that are used for different purposes
- See https://www.knot-dns.cz/docs/latest/html/reference.html#remote-section for details
type: list
element: dict
required: false
options:
id:
type: str
required: true
address:
type: list
required: true
element: str
knot__catalog_zones:
description: A list of catalog zones that will be served by knot
type: list
element: dict
required: true
options:
domain:
type: str
required: true
notify_targets:
type: list
element: str
required: false
knot__zones:
description: A list of user zones that will be served by knot
type: list
element: dict
required: true
options:
domain:
type: str
required: true
notify_targets:
type: list
element: str
required: false
catalog_member:
type: str
required: false
content:
type: str
required: true

View file

@ -2,5 +2,9 @@
name: Install knot name: Install knot
become: true become: true
package: package:
name: [ knot, knot-exporter ] name:
- knot
- knot-exporter
- knot-dnssecutils
- knot-dnsutils
- knot-host

View file

@ -1,3 +1,14 @@
- tags: [ auth-dns ]
name: Ensure required directories exist
become: true
loop: [ "/etc/knot", "/etc/knot/zones" ]
ansible.builtin.file:
path: "{{ item }}"
state: directory
owner: knot
group: knot
mode: u=rwx,g=rx,o=
- tags: [ auth-dns ] - tags: [ auth-dns ]
name: Deploy knot configuration file name: Deploy knot configuration file
become: true become: true
@ -9,3 +20,34 @@
group: knot group: knot
mode: u=rw,g=r,o= mode: u=rw,g=r,o=
- tags: [ auth-dns ]
name: Deploy configured zones
become: true
notify: reload knot zones
loop: "{{ knot__zones }}"
loop_control:
label: "{{ item.domain }}"
vars:
zone_content: "{{ item.content }}"
template:
src: zone.j2
dest: "/etc/knot/zones/{{ item.domain }}zone"
owner: knot
group: knot
mode: u=rw,g=r
# this seems weird but hear me out:
# if we don't disable SLAAC, the node automatically gets an address based on IPv6 Router-Advertisements
# this results in outgoing zone transfers failing because knot will prefer to use the dynamic address over the statically configured one.
# so because we are configuring a DNS Nameserver where known IP-Addresses are actually important for ACL reasons, SLAAC is disabled
- tags: [ auth-dns ]
name: Disable IPv6 SLAAC
become: true
notify: netplan apply
ansible.builtin.template:
src: "netplan-disable-ra.yaml"
dest: "/etc/netplan/10-disable-ra.yaml"
owner: root
group: root
mode: u=rw,g=,o=

View file

@ -15,13 +15,21 @@ database:
storage: "/var/lib/knot" storage: "/var/lib/knot"
key: key:
- id: auth-dns.hamburg.ccc.de - id: {{ knot__dnssec_key_id }}
algorithm: hmac-sha512 algorithm: hmac-sha512
secret: "" secret: "{{ knot__dnssec_key_secret }}"
remote: remote:
# static, external and public remote used for DNSSEC KSK checking
- id: quad9 - id: quad9
address: "2620:fe::fe" address: "2620:fe::fe"
{% if knot__remotes -%}
# additional remotes used in the config
{% for i_remote in knot__remotes -%}
- id: "{{ i_remote.id }}"
address: [ {% for i_addr in i_remote.address %}"{{ i_addr}}"{% if not loop.last %},{% endif %} {% endfor %} ]
{% endfor %}
{% endif %}
# define how the presence of parent KSK keys is checked # define how the presence of parent KSK keys is checked
# in this case, we just ask quad9 which is an open resolver # in this case, we just ask quad9 which is an open resolver
@ -31,7 +39,7 @@ submission:
parent-delay: 1h parent-delay: 1h
# define how dnssec signing is done # define how dnssec signing is done
# in this case we don't do anything special but teach knot how to check of KSK presence # in this case we don't do anything special but teach knot how to check for KSK presence
policy: policy:
- id: default - id: default
ksk-submission: default ksk-submission: default
@ -40,25 +48,48 @@ policy:
# define default settings that apply to all zones # define default settings that apply to all zones
template: template:
# template for general-purpose user zones
- id: default - id: default
storage: "/etc/knot/zones" storage: "/etc/knot/zones"
file: "%s.zone" file: "%s.zone"
semantic-checks: on semantic-checks: on
zonefile-sync: -1 zonefile-sync: -1
zonefile-load: difference-no-serial zonefile-load: difference-no-serial
serial-policy: dateserial
journal-content: all journal-content: all
default-ttl: 60 default-ttl: 7200
catalog-role: member
catalog-zone: hamburg.ccc.de.catalog.
dnssec-signing: on dnssec-signing: on
dnssec-policy: default dnssec-policy: default
{# notify: ["ns1.hanse.de", "ns.bsd.network."] #}
- id: minimal {# catalog-role: member #}
{# notify: ["ns1.hanse.de", "ns.bsd.network."] #} {# catalog-zone: hamburg.ccc.de.catalog. #}
# template for automatically created special zones
- id: catalog
catalog-role: generate
dnssec-signing: on
dnssec-policy: default
# define zones on this server
# See https://www.knot-dns.cz/docs/3.4/html/reference.html#zone-section
zone: zone:
{# - domain: onsite.eurofurence.catalog. #} # catalog zones
{# template: minimal #} {% for i_zone in knot__catalog_zones -%}
{# catalog-role: generate #} - domain: "{{ i_zone.domain }}"
template: catalog
notify: [ {% for i_notif in i_zone.notify_targets | default([]) %}"{{ i_notif }}"{% if not loop.last %}, {% endif %}{% endfor %} ]
{% endfor %}
# normal zones
{% for i_zone in knot__zones -%}
- domain: "{{ i_zone.domain }}"
template: default
notify: [ {% for i_notif in i_zone.notify_targets | default([]) %}"{{ i_notif }}"{% if not loop.last %}, {% endif %}{% endfor %} ]
{% if i_zone.catalog_member | default(False) -%}
catalog-role: member
catalog-zone: "{{ i_zone.catalog_member }}"
{% endif %}
{% endfor %}
{# - domain: "onsite.eurofurence.org" #} {# - domain: "onsite.eurofurence.org" #}

View file

@ -0,0 +1,14 @@
# {{ ansible_managed }}
network:
ethernets:
{%- for i_iface_name in ansible_interfaces -%}
{%- if i_iface_name != "lo" -%}
{%- set i_iface = ansible_facts[i_iface_name] %}
{{ i_iface_name }}:
match:
macaddress: "{{ i_iface.macaddress }}"
accept-ra: false
{% endif %}
{% endfor %}

View file

@ -0,0 +1,4 @@
; {{ ansible_managed }}
{{ zone_content }}