diff --git a/defaults/main.yml b/defaults/main.yml index 2812db5..7f653f2 100644 --- a/defaults/main.yml +++ b/defaults/main.yml @@ -1,7 +1,7 @@ --- -unbound_config_file: "/etc/unbound/unbound.conf" +unbound_config_directory: "/etc/unbound" unbound_log_file: "/var/log/unbound.log" -unbound_syslog: no +unbound_syslog: false unbound_user: "unbound" unbound_group: "unbound" unbound_pidfile: "/var/run/unbound.pid" @@ -11,13 +11,21 @@ unbound_interfaces: - "127.0.0.1" unbound_verbosity: 0 unbound_port: 53 -unbound_udp_listen: yes -unbound_tcp_listen: yes +unbound_udp_listen: true +unbound_tcp_listen: true +unbound_do_not_query_localhost: true +unbound_ipv6: false unbound_directory: "/var/lib/unbound" unbound_forward_zones: [] -unbound_forward_default: no +unbound_forward_default: false unbound_forward_default_addresses: [] unbound_private_domains: [] -unbound_service: yes -unbound_resolv: no +unbound_service: true +unbound_resolv: false unbound_resolv_search: [] + +unbound_compat_14: false +unbound_root_hints_fetch: false +unbound_root_hints_url: "http://www.internic.net/domain/named.root" +unbound_prefetch: false +unbound_rrset_roundrobin: false diff --git a/meta/main.yml b/meta/main.yml index 3ca5293..bfb2f65 100644 --- a/meta/main.yml +++ b/meta/main.yml @@ -3,7 +3,7 @@ galaxy_info: author: Jonathan Freedman company: ANXS description: "Install and configure unbound DNS" - min_ansible_version: 2.3 + min_ansible_version: 2.7.2 license: MIT platforms: - name: Ubuntu diff --git a/tasks/config.yml b/tasks/config.yml new file mode 100644 index 0000000..70c9bc5 --- /dev/null +++ b/tasks/config.yml @@ -0,0 +1,39 @@ +--- +- name: "generate forward zones" + template: + src: "unbound-forwards.conf.j2" + dest: "{{unbound_forwards_file}}" + owner: "root" + group: "{{unbound_group}}" + mode: "0660" + validate: "unbound-checkconf %s" + register: unbound_forward_zones + when: "unbound_forward_zones|length > 0" + +- name: "remove forward zones" + file: + path: "{{unbound_forwards_file}}" + state: "absent" + when: unbound_forward_zones|length == 0 + register: remove_unbound_forward_zones + +- name: "generate configuration" + template: + src: "unbound.conf.j2" + dest: "{{unbound_config_file}}" + owner: "root" + group: "{{unbound_group}}" + mode: "0644" + validate: "unbound-checkconf %s" + register: unbound_config + +- name: "generate sub configurations" + template: + src: "{{item}}.conf.j2" + dest: "{{unbound_config_directory}}/unbound.conf.d/{{item}}.conf" + owner: "root" + group: "{{unbound_group}}" + mode: "0644" + validate: "unbound-checkconf %s" + with_items: "{{unbound_config_files}}" + register: unbound_sub_configs diff --git a/tasks/main.yml b/tasks/main.yml index 33423cb..50f972f 100644 --- a/tasks/main.yml +++ b/tasks/main.yml @@ -3,6 +3,7 @@ apt: pkg: "unbound" state: "present" + - name: "ensure user exists" user: name: "{{unbound_user}}" @@ -12,6 +13,7 @@ home: "{{unbound_directory}}" shell: "/bin/false" state: "present" + # this allows the creation of new directories but does # not overwrite existing system level folders - name: "check for unbound directories" @@ -19,6 +21,7 @@ path: "{{item}}" with_items: "{{unbound_directories|unique}}" register: unbound_directories_check + - name: "create unbound directories" file: path: "{{item}}" @@ -28,6 +31,7 @@ mode: "0770" with_items: "{{unbound_directories_check.results}}" when: not item.stat.exists + - name: "ensure log file exists with proper perms" file: path: "{{unbound_log_file}}" @@ -35,25 +39,35 @@ group: "{{unbound_group}}" mode: "0660" state: "touch" -- name: "generate forward zones" - template: - src: "unbound-forwards.conf.j2" - dest: "{{unbound_forwards_file}}" + +- name: "download root hints" + get_url: + url: "{{unbound_root_hints_url}}" + dest: "{{unbound_root_hints_file}}" owner: "{{unbound_user}}" group: "{{unbound_group}}" mode: "0660" - validate: "unbound-checkconf %s" - notify: "reload unbound" - when: "unbound_forward_zones|length > 0" -- name: "generate configuration" - template: - src: "unbound.conf.j2" - dest: "{{unbound_config_file}}" + when: unbound_root_hints_fetch +# this file needs to exist in order to validate configs on first run +# so if it's not there, we make sure it is + +- name: "check for root.key" + stat: + path: "{{unbound_root_key}}" + register: unbound_root_key_stat + +- name: "copy root.key if required" + copy: + src: "{{unbound_root_key_src}}" + dest: "{{unbound_root_key}}" owner: "{{unbound_user}}" group: "{{unbound_group}}" - mode: "0660" - validate: "unbound-checkconf %s" - notify: "reload unbound" + mode: "0644" + remote_src: true + when: not unbound_root_key_stat.stat.exists|default(False) + +- include_tasks: "config.yml" + - name: "update resolvconf" template: src: "resolv.conf.j2" @@ -62,8 +76,21 @@ group: "root" mode: "0664" when: unbound_resolv + - name: "ensure unbound is running" service: name: "unbound" enabled: "yes" state: "started" + register: unbound_started + +- name: "reload unbound" + service: + name: "unbound" + state: "reloaded" + when: > + not unbound_started.changed and + (unbound_forward_zones.changed or + remove_unbound_forward_zones.changed or + unbound_config.changed or + unbound_sub_configs.changed) diff --git a/templates/dns.conf.j2 b/templates/dns.conf.j2 new file mode 100644 index 0000000..7ce13ee --- /dev/null +++ b/templates/dns.conf.j2 @@ -0,0 +1,30 @@ +# {{ansible_managed}} anxs-unbound dns configuration +{# seemingly empty lines are important; forcing j2 newlines #} +server: + hide-version: yes + hide-identity: yes +{% if not unbound_compat_14 %} + hide-trustanchor: yes +{% if unbound_root_hints_fetch %} + root-file: {{unbound_root_hints_file}} +{% endif %} +{% endif %} + do-not-query-localhost: {% if unbound_do_not_query_localhost %}yes{% else %}no{% endif %} + + prefetch: {% if unbound_prefetch %}yes{% else %}no{% endif %} + + rrset-roundrobin: {% if unbound_rrset_roundrobin %}yes{% else %}no{% endif %} + +{% for domain in unbound_private_domains %} +{{' '}}private-domain: {{domain}} +{% endfor %} +{% for address in unbound_private_addresses %} +{{' '}}private-address: {{address}} +{% endfor %} +{% if unbound_forward_default %} +forward-zone: + name: "." +{% for address in unbound_forward_default_addresses %} +{{' '}}forward-addr: "{{address}}" +{% endfor %} +{% endif %} diff --git a/templates/network.conf.j2 b/templates/network.conf.j2 new file mode 100644 index 0000000..39fec25 --- /dev/null +++ b/templates/network.conf.j2 @@ -0,0 +1,17 @@ +# {{ansible_managed}} anxs-unbound network configuration +{# seemingly empty lines are important; forcing j2 newlines #} +server: + port: {{unbound_port}} + + do-ip6: {% if unbound_ipv6 %}yes{% else %}no{% endif %} + + do-udp: {% if unbound_udp_listen %}yes{% else %}no{% endif %} + + do-tcp: {% if unbound_tcp_listen %}yes{% else %}no{% endif %} + +{% for interface in unbound_interfaces %} +{{' '}}interface: {{interface}} +{% endfor %} +{% for acl in unbound_acl %} +{{' '}}access-control: {{acl.network}} {{acl.permission|default('allow')}} +{% endfor %} diff --git a/templates/server.conf.j2 b/templates/server.conf.j2 new file mode 100644 index 0000000..406d96d --- /dev/null +++ b/templates/server.conf.j2 @@ -0,0 +1,13 @@ +# {{ansible_managed}} anxs-unbound server configuration +server: + logfile: "{{unbound_log_file}}" + log-time-ascii: yes + use-syslog: {% if unbound_syslog %}yes{% else %}no{% endif %} + + pidfile: "{{unbound_pidfile}}" + verbosity: {{unbound_verbosity}} + username: "{{unbound_user}}" + directory: "{{unbound_directory}}" + +remote-control: + control-enable: yes diff --git a/templates/unbound-forwards.conf.j2 b/templates/unbound-forwards.conf.j2 index 8d72b77..baa5bd1 100644 --- a/templates/unbound-forwards.conf.j2 +++ b/templates/unbound-forwards.conf.j2 @@ -1,5 +1,11 @@ -# Unbound forward zones -# {{ansible_managed}} +# {{ansible_managed}} anxs-unbound forwards +{% if unbound_forward_zones|length > 0 %} +server: +{% for forward in unbound_forward_zones %} +{{' '}}private-domain: {{forward.name}} +{% endfor %} +{% endif %} + {% for forward in unbound_forward_zones %} forward-zone: name: "{{forward.name}}" diff --git a/templates/unbound.conf.j2 b/templates/unbound.conf.j2 index 55e5773..d24907c 100644 --- a/templates/unbound.conf.j2 +++ b/templates/unbound.conf.j2 @@ -1,45 +1,2 @@ -# Core unbound configuration -# {{ansible_managed}} -{# seemingly empty lines are important; forcing j2 newlines #} -server: - logfile: "{{unbound_log_file}}" - log-time-ascii: yes - use-syslog: {% if unbound_syslog %}yes{% else %}no{% endif %} - - pidfile: "{{unbound_pidfile}}" - hide-version: yes - hide-identity: yes - hide-trustanchor: yes - verbosity: {{unbound_verbosity}} - port: {{unbound_port}} - username: "{{unbound_user}}" - directory: "{{unbound_directory}}" - do-udp: {% if unbound_udp_listen %}yes{% else %}no{% endif %} - - do-tcp: {% if unbound_tcp_listen %}yes{% else %}no{% endif %} - -{% for domain in unbound_private_domains %} -{{' '}}private-domain: {{domain}} -{% endfor %} -{% for forward in unbound_forward_zones %} -{{' '}}private-domain: {{forward.name}} -{% endfor %} -{% for acl in unbound_acl %} -{{' '}}access-control: {{acl.network}} {{acl.permission|default('allow')}} -{% endfor %} -{% for interface in unbound_interfaces %} -{{' '}}interface: {{interface}} -{% endfor %} -{% for address in unbound_private_addresses %} -{{' '}}private-address: {{address}} -{% endfor %} -{% if unbound_forward_default %} -forward-zone: - name: "." -{% for address in unbound_forward_default_addresses %} -{{' '}}forward-addr: "{{address}}" -{% endfor %} -{% endif %} -{% if unbound_forward_zones|length > 0 %} -include: "{{unbound_forwards_file}}" -{% endif %} +# {{ansible_managed}} anxs-unbound base configuration +include: "/etc/unbound/unbound.conf.d/*.conf" diff --git a/vars/main.yml b/vars/main.yml index 19031f9..3ce246c 100644 --- a/vars/main.yml +++ b/vars/main.yml @@ -11,3 +11,12 @@ unbound_directories: - "{{unbound_directory}}" - "{{unbound_config_file|dirname}}" - "{{unbound_extras_directory}}" +unbound_root_hints_file: "{{unbound_config_file|dirname}}/root.hints" +unbound_config_files: + - "dns" + - "network" + - "server" +unbound_config_file: "{{unbound_config_directory}}/unbound.conf" + +unbound_root_key: "/var/lib/unbound/root.key" +unbound_root_key_src: "/usr/share/dns/root.key"