Bind9 DNS Service Failing to Start After Zone Record Edit in CyberPanel

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 messageCause
zone X/IN: loading from master file ... failed: ...Zone file syntax or integrity error (Step 3)
none:0: open: /etc/named.conf: permission deniedOwnership 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 usePort 53 conflict (Step 5)
journal rollforward failedHand-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/
See also  Nginx proxy_pass Stripping Authorization Bearer Header: Fix and Config Syntax

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).
  • MX and NS targets 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_server on 0.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-resolve on 127.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).
See also  Resolving MySQL Error 1040 "Too Many Connections" on a 1GB VPS with aaPanel

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: named may be a leftover package. Confirm with systemctl is-active pdns. If PowerDNS is authoritative, a failing named has no effect on your domains, and a record edit that “broke DNS” is a PowerDNS issue. Check journalctl -xeu pdns and pdnsutil check-all-zones, and verify the record in the cyberpanel database records table.
  • Chrooted BIND: if named-chroot.service is 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.com and the log for not loaded due to errors.
  • check-integrity and strictness options: check-integrity no; or check-wildcard no; in the options block (or zone-statement) changes what counts as fatal. A zone that loads on one server can fail on another with different named.conf options.
  • BIND version differences: BIND 9.16 through 9.18 tightened parsing (check-names, deprecated dnssec-enable, removed dnssec-lookaside). A copied named.conf from an older server can fail on the option lines rather than the zone. named-checkconf reports the exact line.
  • DNSSEC key files: with inline-signing yes or auto-dnssec maintain, missing or unreadable key files in /var/named/keys/ (or the key-directory) cause load failure. Fix ownership to named and verify with ls -l.
  • Disk full or read-only filesystem: BIND cannot write .jnl or signed zone files. Check df -h /var and mount | grep ' / '.
  • CyberPanel updates regenerating config: if a CyberPanel upgrade or DNS-related script rewrites named.conf or restarts services, manual named.conf edits can be overwritten. Keep custom zones in a separate include file and reference it with one include line.
See also  How to unban IP locked out by aaPanel Fail2ban via SSH terminal commands

Leave a Comment