Daniel Akulenok 77212eef9b
Some checks failed
Test / Lint (push) Failing after 1m40s
Test / Test (push) Has been skipped
improve molecule
2026-02-12 15:05:51 +01:00
2026-02-12 15:05:51 +01:00
2026-02-08 20:43:56 +01:00
2022-08-04 12:41:40 +02:00

bind9

A feature-complete ansible role for installing and configuring bind9. The purpose of this role is to fully template out the entire official bind9 configuration file format.

Version Compatibility

BIND9 Version Role Branch Status Supported Platforms
9.18.x (LTS) main Supported Debian 11-13, Ubuntu 20.04-24.04
9.20.x+ 9.20 🚧 Planned Debian 12-13, Ubuntu 22.04-24.04

For detailed version support policy, branching strategy, and migration guidance, see docs/VERSION_SUPPORT.md.

Minimum Requirements:

  • Ansible: 2.13+
  • Python: 3.8+

What the role does:

  • Fully configures named.conf
  • Checks that the config is valid
  • Loads the config into bind

What the role does not do:

  • Manage your zones and records
  • Maintain every aspect of bind (rndc config, etc)
  • Auto-generate and manage your secrets

Bugs

Or, as I call them "happy accidents".

  • If you need a variable to be 0 or null, you need to define it as var: '0' or var: 'null', otherwise jinja will assume you want it to be empty/null. Normal integers would be defined as var: 1, letting jinja type it as an integer.
  • If a named configuration option has the name 'key' or 'keys', it will be referenced as 'keyname' or 'keylist' respectively. key/keys are reserved values in most languages.

Role Variables

General configuration

Review the defaults for a full set of configurable parameters. Here are the most interesting ones:

bind9_backup_config: [true, false]: Backup each named.conf.* file or not. Default is 'true'. This setting is useful for testing out configuration changes but can clutter up the destination directory quite a bit if used across many updates.

bind9_debug_config: [true, false]: Print the resulting YAML configuration tree that was sent to the configuration template. Default is 'false'. Useful for comparing with the resulting named.conf files and comparing values.

bind9_config_indent: [integer]: Indentation level for the configuration template. Default is '4'. Set this value to suit your style. Tabs are not supported.

named.conf

bind configuration is set through the various bind9_*_config parameters. These are, in order of precedence:

  1. bind9_default_config
  2. bind9_group_config
  3. bind9_site_config
  4. bind9_host_config

All these configuration parameters are merged in a way where each successing config supercedes the previous one at a config-file level. To illustrate:

bind9_default_config:
  - name: named.conf.options
    options:
      recursion: true

bind9_group_config:
  - name: named.conf.options
    options:
      recursion: false
      notify: primary-only
  - name: named.conf.local
    zone:
      - name: "."
        type: mirror

bind9_site_config:
  - name: named.conf.local
    zone:
      - name: "."
        type: hint
        file: /etc/share/dns/root.hints

The resulting precedence and overwriting of variables will result in the following bind9_config passed to the configuration generator:

bind9_config:
  - name: named.conf.options
    options:
      recursion: false
      notify: primary-only
  - name: named.conf.local
    zone:
      - name: "."
        type: hint
        file: /etc/share/dns/root.hints

The named.conf.options block in bind9_default_config got completely overwritten by the bind9_group_config, and the bind9_site_config completely overwrote named.conf.local, however, named.conf.options was left intact after merging with bind9_site_config.

Configuration Grammar

The bind9 role tries to replicate the official ISC bind9 configuration format as close as possible, only re-implementing them in YAML format. This means that for the most part, section names are the same as in named.conf but kebab-case ('var-name') is replaced with snake_case ('var_name') If you are missing some statements in your resulting config, it is most likely because of this.

The main configuration variable used are a series of bind_*_config variables (See [Role Variables]) that have the following syntax

Every config starts by defining the file name. Each file can contain any amount of top-level statements, as permitted by named.conf

bind9_host_config:
  - name: FILENAME # The filename of your desired config file.
                   # You also need to specify a corresponding `include:` for the file
    SECTION_NAME: # The section name of the bind config you want to define.
                  # Can be 'acl', 'options', 'zone', etc.
                  # See: https://bind9.readthedocs.io/en/v9_18_4/reference.html#configuration-file-grammar
    SECTION_2_NAME: # Every file can have as many sections as needed. Generally, try to keep 
                    # all definitions and references together in a file.

Any option that can be defined multiple times in a named.conf, must be defined as a list

bind9_host_config:
  - name: named.conf.local
    acl:
      - name: ELEMENT_NAME
        addresses: 
          - 127.0.0.1
          - 127.0.0.2
      - name: ELEMENT_2_NAME
        addresses:
          - 127.0.0.3

Simple options are defined just as that.

      SIMPLE_OPTION: string, boolean or integer value

Some options have several optional parameters. For those, a somewhat flexible configuration format has been created. Common patterns include:

  • Address with Port/DSCP: Used by options like primaries, parental_agents (e.g., address [ port <port> ] [ dscp <dscp> ])
  • Address with Port/TLS: Used by options like forwarders (e.g., address [ port <port> ] [ tls <tls> ])
      ADDRESS_PORT_TLS_OPTION: # Example: forwarders option
      # <option> [ port <port> ] [ tls <tls> ] { <address> [ port <port> ] [ tls <tls> ]; ... }
      # has a few optional syntaxes 
      # Example 1: Simple address list
        - ADDRESS1
        - ADDRESS2
      # Example 2: To define global port/tls, use 'addresses' sub-element
        [ port: PORT ]
        [ tls: TLS_NAME ]
        addresses:
          - ADDRESS1
          - ADDRESS2
          - 127.0.0.1
      # Example 3: To define per-address port/tls, use 'addresses' as a list of dicts
        addresses:
          - address: ADDRESS
            [ port: PORT ]
            [ tls: TLS_NAME ]
          - address: 127.0.0.1
            port: 53
          - address: 127.0.0.1
            port: 853
            tls: dot-tls
          - address: 8.8.8.8
            port: 853
            tls: google-tls
      # Example 4: The various formats can be mixed and matched within the main element
        - ADDRESS1
        - address: ADDRESS2
          port: PORT
          tls: TLS_NAME

Dependencies

No dependencies

Example Playbook

Simple sample config of a recursive BIND server that allows your localnetwork to resolve addresses via

- hosts: servers
  roles:
     - bind9
  vars:
    bind9_host_config:
      - name: named.conf.local
        acl:
          - name: mylan
            addresses:
              - 10.0.0.0/8
      - name: named.conf.options
        options:
          forwarders:
            - 1.1.1.1
          allow-query:
            - mylan
          allow-recursion:
            - mylan

Documentation

Contributing

Contributions are welcome! Please see docs/VERSION_SUPPORT.md for:

  • Branching strategy
  • Testing requirements
  • Backporting policies
  • Release procedures

License

GPL-3.0-or-later

Author Information

Daniel Akulenok daniel@valid.dk Valid.dk

Description
Ansible role to install and configure bind9 on Debian systems
Readme 578 KiB
Languages
Jinja 75.8%
Python 24.2%