An Ansible role to install and configure BIND 9 as a caching resolver, forwarder, and/or authoritative server with optional DNS-over-TLS, and DNS-over-HTTP listeners and optional auto-updating Response Policy Zones (RPZ).
The role supports Alpine, RedHat and OpenSUSE Linux variants.
It renders a complete named.conf,
sets up optional logging,
manages local RPZ files,
and can generate self-signed certificates for TLS endpoints.
It contains a stand-alone Python program that converts the domain/URL blocklists into RPZ zone files.
It also contains a shell script that invokes the Python program periodically via cron,
after downloading the latest version of the blocklist.
- Ansible 2.14+ (tested with 2.16+)
- Target OS: Alpine Linux, Rocky Linux 9 (RedHat family), openSUSE Tumbleweed
- Python 3 available on managed hosts
- Authoritative primary and secondary zones
- Caching resolver with configurable forwarders (forward first/only)
- Response Policy Zones (primary and secondary), with ocron-driven updates
- DNS-over-TLS and DNS-over-HTTP listeners, with automatic self-signed certs
Variables are grouped by feature. See “Full variable reference” below for all options and their types.
- Core
-
bind_usergroup(default:named) -
bind_service_name(default:named) -
bind_dnssec_validation(default:false) -
bind_query_logging(default:false) -
bind_queries_logfile(path, optional) -
bind_acls,bind_query_acls,bind_recursion_acls(access control) -
bind_listen_interfaces,bind_listen_interfaces_v6(listener addresses) -
Forwarding and zones
-
bind_forward_only(default:false),bind_forwarders(list) -
bind_forward_zones(list of forward zones) -
bind_primary_zones(list of primary zones),bind_primary_zone_allow_update(default:none) -
bind_secondary_zones(list of secondary zones),bind_secondary_zone_allow_transfer(default:none) -
bind_ixfr_from_differences(default:true) -
Named root a.k.a., root.hints file
-
bind_named_root(OS default path) -
bind_named_root_url(default:https://www.internic.net/domain/named.root) -
RPZ
-
bind_response_policy_zones(primary RPZ definitions) -
bind_response_policy_secondary_zones(secondary RPZ definitions) -
bind_rpz_domains,bind_rpz_passthru_domains(local overrides inrpzzone) -
bind_rpz_logfile,bind_rpz_passthru_logfile(optional logging) -
TLS/DoT/DoH
-
bind_tls(list of TLS contexts; each definesname,key_file,cert_file, optionalca_fileand listen interfaces) -
bind_http(list of HTTP endpoints bound to TLS contexts) -
bind_tls_common_name(CN for self-signed certs if not provided per item) -
bind_tls_subject_alt_name(SANs for self-signed certs; default empty) -
bind_tls_key_type(defaultRSA),bind_tls_key_size(default2048) -
bind_tls_selfsigned_not_after(default+1825d) -
bind_tls_dhparam_file(OS default path),bind_tls_dhparam_size(default2048)
-
OS-specific paths such as bind_conf_file, bind_directory, bind_primary_zone_directory, bind_secondary_zone_directory, and bind_tls_dhparam_file are set via vars/ per-family and can be overridden if needed.
The role notifies handlers to reconfigure/reload via RNDC and attempts to enable/start the named service. In containerized CI, service start may be a no-op; configuration rendering and file setup are still validated in Molecule.
templates/conf.j2rendersnamed.confbased on all variables above.templates/rpz.j2renders a local RPZ zone with passthrough and blocked domains.files/genrpz.pyconverts text, CSV or JSON files containing domains or URLs into response policy zones.files/update-rpz.shdownloads the latest RPZ or blocklist and runs genrpz.py on it in the latter case.
---
- hosts: dns
become: true
roles:
- role: amigus.bind
vars:
bind_forward_only: true
bind_forwarders: [8.8.8.8, 8.8.4.4]
bind_tls_common_name: localhost
bind_tls_subject_alt_name:
- DNS:localhost
- IP:127.0.0.1
bind_tls:
- name: dns_tls
key_file: /etc/named/dns_tls.key
cert_file: /etc/named/dns_tls.crt
bind_http:
- name: local
tls: dns_tlsThere are more in examples.
install– install packages, create log dirsconf– rendernamed.confand zonesrpz– render local RPZ base zonenamedroot– update root hints from internictls,selfsigned,dhparam– certificate and DH parameter generationcron,scripts– RPZ update scripts and scheduling
See meta/argument_specs.yml for type-checked option definitions, defaults, and nested structures. This file is kept in sync with defaults/ and vars/.
This repository includes a Molecule scenario with a small matrix of Alpine, Rocky 9, and openSUSE Tumbleweed containers that exercise:
- Forwarder-only configuration with logging
- RPZ primary and secondary zones with cron-ready scripts
- DNS-over-TLS/HTTP with self-signed certificates and DH params
Run the scenario locally (requires Podman):
molecule testMIT
Adam Migus adam@migus.org