ansible-infra/roles/knot/templates/knot.conf.j2
lilly 4bdd36b8f7
update knot role to support more operational variety
Now secondary zones, dynamic zones, interpeted catalog zones, etc.
are supported by our knot role
2026-09-11 10:52:33 +02:00

190 lines
6.1 KiB
Django/Jinja

# {{ ansible_managed }}
# See knot.conf(5) or refer to the server documentation.
server:
rundir: "/run/knot"
user: knot:knot
automatic-acl: on
listen: [ "0.0.0.0@53", "::@53" ]
log:
- target: syslog
any: {{ knot__log_level }}
database:
storage: "/var/lib/knot"
key:
{% for i_key in knot__keys -%}
- id: "{{ i_key.id }}"
algorithm: "{{ i_key.algorithm | default("hmac-sha256") }}"
secret: "{{ i_key.secret }}"
{% endfor %}
remote:
# static, external and public remote used for DNSSEC KSK checking
- id: quad9
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 %} ]
{% if i_remote.via | default(None) -%}
via: [ {% for i_via in i_remote.via %}"{{ i_via }}"{% if not loop.last %}, {% endif %}{% endfor %} ]
{% endif -%}
{% if i_remote.key | default(None) -%}
key: "{{ i_remote.key }}"
{% endif %}
{% endfor %}
{% endif %}
# define how the presence of parent KSK keys is checked
# in this case, we just ask quad9 which is an open resolver
submission:
- id: default
parent: quad9
parent-delay: 1h
# define how dnssec signing is done
# in this case we don't do anything special but teach knot how to check for KSK presence
policy:
- id: default
ksk-submission: default
nsec3: true
nsec3-salt-length: 0
# explicit acl configurations
# we mostly rely on automatic ACLs but for some dynamic zones, explicit allow stanzas are required
acl:
{% for i_acl in knot__acls -%}
- id: "{{ i_acl.id }}"
{% if i_acl.address | default(None) -%}
address: [ {% for i_addr in i_acl.address %}"{{ i_addr}}"{% if not loop.last %}, {% endif %}{% endfor %} ]
{% endif -%}
{% if i_acl.key | default(None) -%}
key: "{{ i_acl.key }}"
{% endif -%}
{% if i_acl.remote | default(None) -%}
remote: "{{ i_acl.remote }}"
{% endif -%}
{% if i_acl.action | default(None) -%}
action: "{{ i_acl.action }}"
{% endif -%}
{% if i_acl.update_type | default(None) -%}
update-type: [ {% for i_addr in i_acl.update_type %}"{{ i_addr}}"{% if not loop.last %}, {% endif %}{% endfor %} ]
{% endif %}
{% endfor %}
# define default settings that apply to all zones
template:
# template for general-purpose primary zones
- id: primary
storage: "/etc/knot/zones"
file: "%s.zone"
semantic-checks: on
zonefile-sync: -1
zonefile-load: difference-no-serial
serial-policy: dateserial
journal-content: all
dnssec-signing: on
dnssec-policy: default
# template for generic secondary zones
- id: secondary
storage: "/var/lib/knot/secondary_zones/"
dnssec-signing: off
# template for zones that support dynamic updates
- id: dynamic-primary
storage: "/var/lib/knot/dynamic_zones/"
zonefile-load: whole
journal-content: changes
dnssec-signing: on
dnssec-policy: default
# template for automatically created special zones
- id: catalog
catalog-role: generate
dnssec-signing: off
storage: "/var/lib/knot/catalog_zones/"
# template for secondary catalog zones (they are interpreted and generate secondary zones based on their content)
- id: catalog-secondary
catalog-role: interpret
dnssec-signing: off
storage: "/var/lib/knot/secondary_zones/"
# templates for secondary catalog member zones
# these templates are for zones which get spawned by catalog zones
# unfortunately we need one template per interpreted catalog zone because it must include all information required for that zone to work as secondary
# it reuses master and notify values from the catalog zones
{% for i_zone in knot__catalog_secondary_zones -%}
- id: catalog-secondary-member-{{ i_zone.domain }}
storage: "/var/lib/knot/secondary_zones/"
dnssec-signing: off
master: {{ i_zone.primary }}
{% endfor %}
# define zones on this server
# See https://www.knot-dns.cz/docs/3.4/html/reference.html#zone-section
zone:
# catalog zones
{% for i_zone in knot__catalog_zones -%}
- 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 %}
# primary zones
{% for i_zone in knot__primary_zones -%}
- domain: "{{ i_zone.domain }}"
template: primary
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 %}
# dynamic primary zones
{% for i_zone in knot__dynamic_zones -%}
- domain: "{{ i_zone.domain }}"
template: "dynamic-primary"
notify: [ {% for i_notif in i_zone.notify_targets | default([]) %}"{{ i_notif }}"{% if not loop.last %}, {% endif %}{% endfor %} ]
acl: [ {% for i_acl in i_zone.acl %}"{{ i_acl }}"{% if not loop.last %}, {% endif %}{% endfor %} ]
{% if i_zone.catalog_member | default(False) -%}
catalog-role: member
catalog-zone: "{{ i_zone.catalog_member }}"
{% endif %}
{% endfor %}
# secondary zones
{% for i_zone in knot__secondary_zones -%}
- domain: "{{ i_zone.domain }}"
template: secondary
master: {{ i_zone.primary }}
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 %}
# secondary catalog zones
{% for i_zone in knot__catalog_secondary_zones -%}
- domain: "{{ i_zone.domain }}"
template: catalog-secondary
catalog-template: catalog-secondary-member-{{ i_zone.domain }}
master: {{ i_zone.primary }}
notify: [ {% for i_notif in i_zone.notify_targets | default([]) %}"{{ i_notif }}"{% if not loop.last %}, {% endif %}{% endfor %} ]
{% endfor %}