Import DNS zone files (bind)

Hello everyone,

I have been running HestiaCP v1.3.2 on Debian 10.6.

Is there any tool that can import bind zone files into HestiaCP?

I have zone files with a few hundred records being served from other servers running bind, and want to import them into HestiaCP without the need to manually add records one by one.

Thanks,
Sot.

Check the following command

Thank you very much for your reply.

root@potato:/usr/local/hestia# v-insert-dns-records
Usage: v-insert-dns-records USER DOMAIN DATAFILE [RESTART]

How do I convert my zone file to datafile format ?

datafiles are like this
root@potato:/usr/local/hestia# more data/users/L19/dns/l19.eu.conf
ID=‘1’ RECORD=‘@’ TYPE=‘NS’ PRIORITY=‘’ VALUE=‘potato.irc.gr.’ SUSPENDED=‘no’ TIME=‘01:07:56’ DATE=‘2020-11-26’
ID=‘2’ RECORD=‘@’ TYPE=‘NS’ PRIORITY=‘’ VALUE=‘ns1.he.net.’ SUSPENDED=‘no’ TIME=‘01:08:47’ DATE=‘2020-11-26’ TTL=‘14400’
ID=‘9’ RECORD=‘@’ TYPE=‘A’ PRIORITY=‘’ VALUE=‘95.111.231.144’ SUSPENDED=‘no’ TIME=‘01:07:56’ DATE=‘2020-11-26’
ID=‘10’ RECORD=‘www’ TYPE=‘A’ PRIORITY=‘’ VALUE=‘95.111.231.144’ SUSPENDED=‘no’ TIME=‘01:07:56’ DATE=‘2020-11-26’

my zone file is like this

root@potato:/usr/local/hestia# more /home/L19/conf/dns/l19.eu.db
$TTL 14400
@    IN    SOA    potato.irc.gr.    root.l19.eu. (
                                            2020112612
                                            7200
                                            3600
                                            1209600
                                            180 )

@       14400   IN      NS              potato.irc.gr.
@       14400   IN      NS              ns1.he.net.
@       14400   IN      A               95.111.231.144
www     14400   IN      A               95.111.231.144

Hmm, smells like some shell scripting incoming :slight_smile:. You probaly need to create your own script which converts or directly inserts it over api.

Would be nice to have an upgrade script to handle this… For in the future…

1 Like

Yes it would.

I had to migrate 140 domains last week. A tool like that could definetly ease the transition to hestia.

Here something I quickly hacked to do the job
You need to “pip3 install dnspython” if it’s not already installed in your system.

stsimb@tesla4:~$ cat v-import-dns-zone.py
#!/usr/bin/env python3
# https://forum.hestiacp.com/t/import-dns-zone-files-bind/2373
""" import bind dns zone file to hestia """

import sys
import os
import dns.zone
import dns.ipv4
from dns.exception import DNSException
#from dns.rdataclass import *
from dns.rdatatype import *

if len(sys.argv) != 3:
    print ("Usage: %s USER ZONEFILE" % sys.argv[0])
    sys.exit(1)

user = sys.argv[1]
zone_file = sys.argv[2]
domain = os.path.basename(zone_file)

try:
    zone = dns.zone.from_file(zone_file, domain)
    for name, node in zone.nodes.items():
        rdatasets = node.rdatasets
        for rdataset in rdatasets:
            for rdata in rdataset:
                if rdataset.rdtype in [A, AAAA]:
                    print ("v-add-dns-record %s %s %s %s %s '' '' no %s" %
		      (user, domain, name, rdataset.rdtype.to_text(rdataset.rdtype),
		      rdata.address, rdataset.ttl))
                elif rdataset.rdtype in [CNAME, NS]:
                    target = str(rdata.target)
                    if target == '@':
                        target = domain + '.'
                    elif target[-1] != '.':
                        target = target + '.' + domain + '.'
                    print ("v-add-dns-record %s %s %s %s %s '' '' no %s" %
		      (user, domain, name, rdataset.rdtype.to_text(rdataset.rdtype),
		      target, rdataset.ttl))
                elif rdataset.rdtype == MX:
                    exchange = str(rdata.exchange)
                    if exchange == '@':
                        exchange = domain + '.'
                    elif exchange[-1] != '.':
                        exchange = exchange + '.' + domain + '.'
                    print ("v-add-dns-record %s %s %s MX %s %s '' no %s" %
		      (user, domain, name, exchange, rdata.preference, rdataset.ttl))
                elif rdataset.rdtype in [TXT, SPF]:
                    print ("v-add-dns-record %s %s %s %s '%s' '' '' no %s" %
		      (user, domain, name, rdataset.rdtype.to_text(rdataset.rdtype),
		      b''.join(rdata.strings).decode('utf-8'), rdataset.ttl))
                else:
                    print ("#skipped %s %s %s" %
		      (name, rdataset.rdtype.to_text(rdataset.rdtype), rdata))
except DNSException as ex:
    print (ex.__class__, ex)

Instructions: suppose you want to import records from the zone file called “mitsos.gr” for hestiacp user mitsos.

v-add-dns-domain mitsos mitsos.gr 1.2.3.4 #1.2.3.4 is the ip of your server
python3 v-import-dns-zone.py mitsos mitsos.gr | tee -a import
bash -x import
rm -f import

This will add the domain in HestiaCP for user mitsos, generate a file called “import” with the commands that will add the corresponding records to hestia, and execute the commands.

Caveat: the default dns template contains about 10 records and the domain serial number increments with each record we import. If the zone file we import contains more than 90 records, then the serial number will be > 100. This is out of range for bind, and the zone will fail to load. You need to manually fix that by editing /usr/local/hestiacp/data/users/$USER/$DOMAIN.conf.
In fact, this is a more general limitation, because of the serial number format and auto-incrementing with every change, we cannot make more than 100 changes in a single day.

4 Likes