Skip to content

bindantic

bindantic is a library for managing BIND9 DNS server configuration via Pydantic models.

Instead of manually editing named.conf, you describe the configuration in Python, and the library generates correct BIND9 syntax and (optionally) places files into the required directories.

Features

  • Full support for all named.conf blocks: acl, controls, dnssec-policy, http, key, key-store, logging, options, remote-servers, server, statistics-channels, tls, trust-anchors, view, zone.
  • All common resource record types: A, AAAA, CAA, CERT, CNAME, DNAME, DNSKEY, DS, HINFO, LOC, MX, NAPTR, NSEC, NS, PTR, RP, RRSIG, SOA, SPF, SRV, SSHFP, TLSA, TXT.
  • Built-in validation - pass strings, numbers, IP addresses, durations, and bindantic formats them correctly for BIND.
  • Syntax generation in one line - model.model_bind_syntax() for any block, or the whole named.conf.
  • Generate files without writing, or write straight to disk - config.generate_files() / config.write_files(...).
  • Python 3.10+, static typing (py.typed), 96%+ test coverage.
  • No extra dependencies - only Pydantic.

Installation

pip install bindantic

named-checkconf version

bindantic generates syntax according to the latest stable BIND 9.20.x version. If you check the configuration with an older named-checkconf, you may get errors. Always use the same version of named-checkconf as your server, if possible.

Quick start

from bindantic import (
    ARecord,
    NamedConfig,
    NSRecord,
    OptionsBlock,
    SOARecord,
    ZoneBlock,
    ZoneTypeEnum,
)

config = NamedConfig(
    options_block=OptionsBlock(
        directory="/etc/bind",
        recursion=True,
        allow_recursion=["localhost", "localnets"],
        listen_on=["any"],
        listen_on_v6=["any"],
    ),
    zone_blocks=[
        ZoneBlock(
            comment="optional comment",
            name="example.com",
            zone_type=ZoneTypeEnum.PRIMARY,
            file="zones/example.com.zone",
            resource_records=[
                SOARecord(
                    mname="ns1.example.com",
                    rname="admin.example.com",
                    serial=2026010101,
                    refresh=10800,
                    retry=3600,
                    expire=604800,
                    minimum=3600,
                    origin="example.com",
                    ttl=3600,
                ),
                NSRecord(nsdname="ns1.example.com", comment="optional comment"),
                ARecord(name="@", address="192.168.1.1"),
            ],
        )
    ],
)

print(config.model_bind_syntax())
options {
    allow-recursion {
        localhost;
        localnets;
    };
    directory "/etc/bind";
    listen-on {
        any;
    };
    listen-on-v6 {
        any;
    };
    recursion yes;
};

# optional comment
zone example.com. {
    type primary;
    file "zones/example.com.zone";
};

See Examples for split-horizon views, TSIG-secured zone transfers, and DNSSEC, and the API Reference for every model and field.