Root Cause Diagnosis
named fails to start when named-checkconf or the daemon’s startup load finds a fatal error, and a manually edited zone file is the usual trigger (unquoted ; in a TXT record, a CNAME coexisting with other records, an in-zone NS with no A/AAAA record, a missing SOA). On RHEL-family systems (AlmaLinux, Rocky, CentOS), named.service runs named-checkconf -z as ExecStartPre, so one bad zone blocks the whole service; on Ubuntu, a bad zone is normally skipped and start failures come from named.conf, permissions, AppArmor, or a port 53 conflict. CyberPanel’s built-in DNS is PowerDNS backed by MySQL, so edits in DNS → Add/Delete Records never touch BIND zone files, and BIND only breaks if it was installed separately, either by hand-editing its files or by contending with pdns for port 53.
Quick Fix
# 1. Find the exact failing file and line
named-checkconf -z 2>&1 | grep -viE "loaded serial|^$"
# 2. Validate the suspect zone directly
named-checkzone example.com /var/named/example.com.db # RHEL-family
named-checkzone example.com /etc/bind/zones/db.example.com # Debian/Ubuntu (adjust path)
# 3. After fixing the reported line
named-checkconf -z && systemctl restart named # or: systemctl restart bind9
If the service must come up immediately and you can’t fix the zone yet, on RHEL-family systems set DISABLE_ZONE_CHECKING="yes" in /etc/sysconfig/named, then systemctl restart named. The broken zone will simply not be served.
Step-by-Step Resolution
1. Read the actual failure
systemctl status named -l --no-pager # Ubuntu unit alias: bind9
journalctl -xeu named --no-pager | tail -50
Interpret the output:
| Log message | Cause |
|---|---|
zone X/IN: loading from master file ... failed: ... | Zone file syntax or integrity error (Step 3) |
none:0: open: /etc/named.conf: permission denied | Ownership or SELinux (Step 4) |
/etc/bind/named.conf.local:N: unknown option / missing ';' | named.conf syntax error (Step 2) |
could not listen on UDP/TCP socket: address in use | Port 53 conflict (Step 5) |
journal rollforward failed | Hand-edited dynamic zone (Step 6) |
2. Validate the main configuration
named-checkconf /etc/named.conf # RHEL-family
named-checkconf /etc/bind/named.conf # Debian/Ubuntu
Config paths:
- RHEL-family: /etc/named.conf, zones in /var/named/
- Ubuntu/Debian: /etc/bind/named.conf, /etc/bind/named.conf.local, /etc/bind/named.conf.options, zones commonly in /etc/bind/ or /var/lib/bind/
Every zone stanza needs a terminating }; and a file path that exists.
3. Fix the zone file
named-checkzone example.com /var/named/example.com.db
Most common errors after a manual edit:
; WRONG: CNAME cannot coexist with any other record at the same name
www IN CNAME example.com.
www IN A 203.0.113.10
; WRONG: unquoted semicolons start a comment and truncate the record
_dkim IN TXT v=DKIM1; k=rsa; p=MIIB...
; RIGHT
_dkim IN TXT "v=DKIM1; k=rsa; p=MIIB..."
; WRONG: single TXT string over 255 bytes. RIGHT: split into chunks
default._domainkey IN TXT ( "v=DKIM1; k=rsa; p=MIIBIjANBgkq..."
"...remaining key chunk..." )
; WRONG: relative name missing trailing dot (becomes ns1.example.com.example.com.)
@ IN NS ns1.example.com
; RIGHT
@ IN NS ns1.example.com.
; WRONG: in-zone NS with no address record
; RIGHT: add
ns1 IN A 203.0.113.10
Also check:
- Exactly one SOA record, and it is the first record.
- Balanced parentheses in multi-line SOA/TXT.
- No leading whitespace on a line that should start a new owner name (it inherits the previous owner).
MXandNStargets are not CNAMEs.
After editing, increment the SOA serial (YYYYMMDDNN), otherwise secondaries will not pick up the change.
4. Fix ownership, mode, and SELinux context
Files created as root with mode 600 cannot be read by the named user.
# RHEL-family
chown root:named /var/named/example.com.db
chmod 640 /var/named/example.com.db
restorecon -Rv /var/named/
# Debian/Ubuntu
chown root:bind /etc/bind/zones/db.example.com
chmod 644 /etc/bind/zones/db.example.com
On Ubuntu, AppArmor blocks zone files outside allowed paths. Check with journalctl -k | grep -i 'apparmor.*named' and either move the file into /etc/bind/ or /var/lib/bind/, or add the path to /etc/apparmor.d/local/usr.sbin.named, then systemctl reload apparmor.
5. Resolve the port 53 conflict with PowerDNS or systemd-resolved
ss -lntup | grep ':53 '
pdns_serveron0.0.0.0:53: CyberPanel’s PowerDNS is already serving DNS. Do not run both on the same address. Either stop BIND (systemctl disable --now named) and manage records in the panel, or stop PowerDNS and bind BIND elsewhere.systemd-resolveon127.0.0.53:53(Ubuntu): bind BIND to specific addresses in /etc/bind/named.conf.options:
options {
listen-on { 203.0.113.10; 127.0.0.1; };
listen-on-v6 { none; };
};
- To run both services, give each its own IP. For PowerDNS set
local-address=in /etc/pdns/pdns.conf (RHEL-family) or /etc/powerdns/pdns.conf (Ubuntu).
6. Recover a hand-edited dynamic zone
If the zone is updated via nsupdate or allow-update, a stale .jnl file conflicts with manual changes:
systemctl stop named
rm /var/named/example.com.db.jnl # path matches the zone file
systemctl start named
For future edits to dynamic zones, use rndc freeze example.com, edit, then rndc thaw example.com.
7. Restart and verify
named-checkconf -z && systemctl restart named
systemctl is-active named
dig @127.0.0.1 example.com SOA +short
For subsequent edits, rndc reload example.com reloads a single zone without restarting the service.
Why This Fails for Some Users
- CyberPanel is running PowerDNS, not BIND:
namedmay be a leftover package. Confirm withsystemctl is-active pdns. If PowerDNS is authoritative, a failingnamedhas no effect on your domains, and a record edit that “broke DNS” is a PowerDNS issue. Checkjournalctl -xeu pdnsandpdnsutil check-all-zones, and verify the record in the cyberpanel databaserecordstable. - Chrooted BIND: if
named-chroot.serviceis enabled (RHEL-family), zone files must live under /var/named/chroot/var/named/. Editing the non-chroot copy has no effect, and the two units conflict if both are enabled. Run only one. - RHEL vs. Ubuntu unit behavior: the RHEL-family pre-check turns any zone error into a hard start failure. Ubuntu starts anyway and silently skips the zone, so “service running but domain returns SERVFAIL” is the Ubuntu symptom. Check
rndc zonestatus example.comand the log fornot loaded due to errors. check-integrityand strictness options:check-integrity no;orcheck-wildcard no;in theoptionsblock (orzone-statement) changes what counts as fatal. A zone that loads on one server can fail on another with differentnamed.confoptions.- BIND version differences: BIND 9.16 through 9.18 tightened parsing (
check-names, deprecateddnssec-enable, removeddnssec-lookaside). A copiednamed.conffrom an older server can fail on the option lines rather than the zone.named-checkconfreports the exact line. - DNSSEC key files: with
inline-signing yesorauto-dnssec maintain, missing or unreadable key files in /var/named/keys/ (or thekey-directory) cause load failure. Fix ownership tonamedand verify withls -l. - Disk full or read-only filesystem: BIND cannot write
.jnlor signed zone files. Checkdf -h /varandmount | grep ' / '. - CyberPanel updates regenerating config: if a CyberPanel upgrade or DNS-related script rewrites named.conf or restarts services, manual
named.confedits can be overwritten. Keep custom zones in a separate include file and reference it with oneincludeline.