# {{ 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 %}