- Add ignore_ns_records flag (default: true) to automatically ignore NS records - Add options_ignore_list to zones and records to allow extra keys (e.g., comment, type) - Update documentation to reflect NS records are now ignored by default - Add changelog entry for v1.3.3 release
6.0 KiB
6.0 KiB
Quick Start Guide - nsupdate_zone Module
Installation
The module is part of the community.general collection:
ansible-galaxy collection install community.general
Install Python dependencies:
pip install dnspython
Minimal Example
- name: Update DNS zone
community.general.nsupdate_zone:
key_name: "nsupdate"
key_secret: "your-tsig-key-here=="
zones:
- name: example.com
dns_server: ns1.example.com
records:
- record: 'example.com.'
type: A
value: 192.168.1.1
- record: www
type: A
value: 192.168.1.10
Note: By default, SOA, NS, and DNSSEC records are ignored, and record validation is enabled.
Tip: Run with -v flag to see detailed per-record actions.
DNS Server Setup (BIND Example)
- Generate TSIG key:
tsig-keygen -a hmac-sha256 nsupdate
- Configure BIND (
/etc/named.conf):
key "nsupdate" {
algorithm hmac-sha256;
secret "generated-secret-here==";
};
zone "example.com" {
type master;
file "/var/named/example.com.zone";
allow-update { key nsupdate; };
allow-transfer { key nsupdate; };
};
- Reload BIND:
sudo systemctl reload named
First Playbook
Create update-dns.yml:
---
- name: Manage DNS zones
hosts: localhost
gather_facts: false
tasks:
- name: Update example.com zone
community.general.nsupdate_zone:
key_name: "nsupdate"
key_secret: "{{ lookup('env', 'DNS_KEY') }}"
key_algorithm: hmac-sha256
protocol: tcp
zones:
- name: example.com
dns_server: ns1.example.com
records:
# Zone apex
- record: 'example.com.'
type: A
value: 192.168.1.1
ttl: 3600
# Web server
- record: www
type: A
value:
- 192.168.1.10
- 192.168.1.11
ttl: 300
# Email
- record: 'example.com.'
type: MX
value:
- "10 mail.example.com."
- record: mail
type: A
value: 192.168.1.20
register: result
- name: Show what changed
debug:
msg: "Zone {{ item.zone }}: {{ item.changes.adds }} adds, {{ item.changes.deletes }} deletes, {{ item.changes.updates }} updates"
loop: "{{ result.results }}"
Run it:
export DNS_KEY="your-tsig-key-here=="
ansible-playbook update-dns.yml
Verify It Works
Check mode (dry run):
ansible-playbook update-dns.yml --check
Verify DNS records:
dig @ns1.example.com example.com A
dig @ns1.example.com www.example.com A
dig @ns1.example.com example.com MX
Common Use Cases
1. Load Zone from Variable File
zones/example.com.yml:
---
- record: 'example.com.'
type: A
value: 192.168.1.1
- record: www
type: A
value: 192.168.1.10
Playbook:
- name: Load and apply zone
hosts: localhost
vars_files:
- zones/example.com.yml
tasks:
- name: Update zone
community.general.nsupdate_zone:
key_name: "nsupdate"
key_secret: "{{ vault_dns_key }}"
zones:
- name: example.com
dns_server: ns1.example.com
records: "{{ zones }}"
2. Ignore Dynamic Records and Use Global Server
- name: Update zone (ignore ACME challenges, use global server)
community.general.nsupdate_zone:
key_name: "nsupdate"
key_secret: "{{ vault_dns_key }}"
dns_server: ns1.dns.com # Global server for all zones
# SOA and DNSSEC records are ignored by default
ignore_record_patterns:
- '^_acme-challenge\..*'
zones:
- name: example.com
records: "{{ static_records }}"
3. Multiple Zones with Shared Server
- name: Update all zones
community.general.nsupdate_zone:
key_name: "nsupdate"
key_secret: "{{ vault_dns_key }}"
dns_server: ns1.dns.com # Shared server for all zones
zones:
- name: example.com
records: "{{ example_com_records }}"
- name: example.org
records: "{{ example_org_records }}"
Troubleshooting
"AXFR failed: connection timeout"
- Check firewall allows port 53
- Verify
allow-transferin BIND config - Test manually:
dig @ns1.example.com example.com AXFR
"UPDATE failed: REFUSED"
- Check
allow-updatein BIND config - Verify TSIG key matches
- Check zone name is correct
"TSIG key error"
- Verify key_secret is base64-encoded
- Check key_algorithm matches server config
- Ensure key_name matches server key name
"CNAME conflict"
- Cannot have CNAME with other record types at same name
- Remove conflicting records from YAML
- Or use different subdomain
Best Practices
-
Use ansible-vault for keys:
ansible-vault encrypt_string 'your-key' --name dns_key -
Use TCP protocol:
protocol: tcp # More reliable for large zones -
Leverage defaults:
# SOA and DNSSEC records are ignored by default # Record validation is enabled by default # Just add patterns for dynamic records ignore_record_patterns: - '^_acme-challenge\..*' -
Use verbose mode for visibility:
verbose: true # See Added, Removed, Changed, Skipped for each record -
Test with check and diff mode:
ansible-playbook playbook.yml --check --diff -
Use global dns_server:
dns_server: ns1.dns.com # Applies to all zones without dns_server
Next Steps
- Read full documentation:
docs/nsupdate_zone_guide.md - See examples:
examples/nsupdate_zone_example.yml - Check sample zone:
examples/sample_zone_format.yml
Support
For issues and questions: