# DNS-Manager A CLI toolset to manage [Bind](https://www.isc.org/bind/) DNS zones and dynamic records. Zones are updated live via DDNS/TSIG, zone contents are read via AXFR zone transfers, and Bind itself is driven through `named-checkconf` and `rndc`. Configuration is keyed by Bind *view* and supports multiple views as well as automatic management of catalog zones. ## Requirements * [Bind](https://www.isc.org/bind/) * [Bind-Tools](https://www.isc.org/bind/) (if not bundled with Bind) * [dnspython](https://www.dnspython.org) * [prettytable](https://zetcode.com/python/prettytable/) * [pyyaml](https://pyyaml.org) A running Bind server and a config file are required to run any command. ## Installation Install directly from the git repository: ``` pip install git+ssh://git@git.ccc-rheintal.ch/spacefreak/dns-manager.git ``` ## Configuration By default the tools read `/etc/dns-manager/config.yml` (override with `-c`). A documented example config is provided in [`files/config.yml`](files/config.yml). The configuration is keyed by Bind view; the default view is `_default`. A TSIG key file is mandatory for any non-default view (and for any zone that requires a key to transfer or update). A view may also define a catalog zone, which is then managed automatically when zones are added or deleted. ## Commands | Command | Description | | ------------------- | ------------------------------------------------------ | | `dns-list-zones` | List zones (view, status, managed). | | `dns-zone-add` | Add a zone (and its catalog member, if configured). | | `dns-zone-delete` | Delete a zone (and its catalog member, if configured). | | `dns-zone-list` | Show the records of a zone. | | `dns-record-add` | Add a record via DDNS. | | `dns-record-delete` | Delete a record via DDNS. | | `dns-confgen` | Regenerate per-view Bind config and run `rndc reconfig`. | All commands support `--help` for the full list of options. Commands prompt interactively when arguments are omitted and ask for confirmation before applying changes. Pass `-b`/`--batch` to require all arguments and skip prompts for non-interactive use. ## Usage Zones are addressed as `ZONE[@VIEWS]`, where `VIEWS` is a comma-separated list of views or `*` for all views. Omitting `@VIEWS` only works when the target is unambiguously in the default view. In record names, `@` refers to the zone apex. ``` # List all managed zones dns-list-zones # Add a zone dns-zone-add example.tld # Show the records of a zone dns-zone-list example.tld # Add an A record dns-record-add example.tld www 3600 A 192.0.2.1 ``` ## Hooks Executable scripts placed in the hooks base directory (`hooks_dir`, default `/hooks`) are run around zone and record mutations. The tree narrows progressively and every level is optional: ``` hooks/ -> every action and phase (zone+record, add+delete, pre+post) zone/ -> all zone actions/phases add/ -> zone add, both phases pre/ -> zone add, pre only post/ -> zone add, post only delete/{pre,post}/ record/ add/{pre,post}/ delete/{pre,post}/ ``` For a given event `(kind, action, phase)` all matching hooks across every existing level along that event's path (`hooks/` → `hooks//` → `hooks///` → `hooks////`) are collected and run sorted by filename (run-parts style), so a numeric prefix (e.g. `50-`) controls execution order regardless of directory depth. A hook placed shallower in the tree fires for more events; distinguish the concrete event via the environment variables. Each hook inherits the terminal, so its stdout and stderr appear live and in order, and a hook may be interactive: it can print prompts and read the user's input from stdin. In batch mode (`-b`) stdin is redirected to `/dev/null`, so a hook that reads input gets an immediate EOF instead of blocking (hooks that prompt should guard on a tty/EOF). Only executable regular files are run; everything else (including the `zone`/`record`/`add`/`delete`/`pre`/`post` subdirectories) is skipped, and missing directories are no-ops. Each hook receives context via environment variables: * Common env: `DNSMGR_KIND` (zone|record), `DNSMGR_ACTION` (add|delete), `DNSMGR_PHASE` (pre|post), `DNSMGR_ZONE` (origin, no trailing dot), `DNSMGR_VIEW`. * Record-only env: `DNSMGR_RECORD_NAME`, `DNSMGR_RECORD_TTL`, `DNSMGR_RECORD_TYPE`, `DNSMGR_RECORD_VALUE` (values joined by newlines). * `DNSMGR_ZONE_FILE` (zone file path): set only for managed zones and not for zone add pre-hooks and not for zone delete post-hooks. A `pre` hook exiting non-zero aborts the operation before any change is applied (exit code 190); a `post` hook failure only prints an `ERROR:` and continues. Pass `-n`/`--no-hooks` to `dns-zone-add`, `dns-zone-delete`, `dns-record-add` or `dns-record-delete` to skip all hook execution for that run.