DNS is an integral service to most modern networks. The Domain Name System, or DNS is comprised of hierarchical and decentralized Domain Name Servers, or DNS Servers. This is how we connect to computers and the websites that reside on computers by their names, rather than having to memorize the IP addresses of every single computer out there. So you get to type krypted.com and come to my website instead of typing the IP address. Or more likely, Facebook.com, but just because my website is older, I’m not mad about that. No really…

So you have a macOS Server and you need to take your DNS records out of it and move them to another solution. Luckily, DNS on any operating system is one of the easiest to manage. So let’s start by dumping all of our zone records and settings using the dnsconfig command:

/Applications/Server.app/Contents/ServerRoot/System/Library/PrivateFrameworks/DNSManager.framework/dnsconfig list

ACLs:
com.apple.ServerAdmin.DNS.public
Options:
directory: /Library/Server/named
allow-recursion: com.apple.ServerAdmin.DNS.public 
allow-transfer: none 
forwarders: 8.8.8.8 4.4.4.4 
Views:
com.apple.ServerAdmin.DNS.public
Zones:
test.com
Options:
allow-transfer: none 
allow-update: none 
Resource Recs:
testalias.test.com (CNAME)
test.com (SOA)
test.com (NS)
test.com (MX)
test.test.com (A)
Resource Recs:
no resource recs
0.0.127.in-addr.arpa
Options:
allow-update: none 
Resource Recs:
0.0.127.in-addr.arpa (SOA)
0.0.127.in-addr.arpa (NS)
1.0.0.127.in-addr.arpa (PTR)
0.0.10.in-addr.arpa
Options:
allow-transfer: none 
allow-update: none 
Resource Recs:
1.0.0.10.in-addr.arpa (PTR)
0.0.10.in-addr.arpa (SOA)
0.0.10.in-addr.arpa (NS)

Now that we have our records, let’s think of how to use them in the new server. In the above example, we list test.com as a zone. And in that zone we have an A record for test.test.com and a CNAME for testalias.test.com that points to test.test.com – but we don’t know where test.test.com resolves to. Each of those domains has a corresponding file that starts with db. followed by the name of the domain in the /Library/Server/named directory. So we can cat the test.com file as follows:

cat /Library/Server/named/db.test.com

test.com.   10800 IN SOA test.com. admin.test.com. (
2018033001
3600
900
1209600
86400)
 10800 IN NS test.test.com.
 10800 IN MX 0 test.test.com.
test.test.com.   10800 IN A 10.0.0.1
testalias.test.com.   10800 IN CNAME test.test.com.

Now we know the IP address that each record points to and can start building them out in other systems. If you only have 5-20 records, this is pretty quick and easy. If you have hundreds, then you’re in luck, as those db files per domain are portable between hosts. Some of the settings to look out for from macOS Server include:
  • Primary Zone: The DNS “Domain”. For example, www.krypted.com would likely have a primary zone of krypted.com.
  • Machine Record: An A record for a computer, or a record that tells DNS to resolve whatever name is indicated in the “machine” record to an IP address, whether the IP address is reachable or not.
  • Name Server: NS record, indicates the authoritative DNS server for each zone. If you only have one DNS server then this should be the server itself.
  • Reverse Zone: Zone that maps each name that IP addresses within the zone answer with. Reverse Zones are comprised of Reverse Mappings and each octal change in an IP scheme that has records mapped represents a new Reverse Zone.
  • Reverse Mapping: PTR record, or a record that indicates the name that should respond for a given IP address. These are automatically created for the first IP address listed in a Machine Record.
  • Alias Record: A CNAME, or a name that points to another name.
  • Service Record: Records that can hold special types of data that describe where to look for services for a given zone. For example, iCal can leverage service records so that users can just type the username and password during the setup process.
  • Mail Exchanger Record (aka MX record): Mail Exchanger, points to the IP address of the mail server for a given domain (aka Primary or Secondary Zone).
  • Secondary Zone: A read only copy of a zone that is copied from the server where it’s a Primary Zone when created and routinely through what is known as a Zone Transfer.
The settings for the domains are as follows:
  • allow-transfer Takes one or more address match list entry. Address match list entries consist of any of these forms: IP addresses, Subnets or Keywords.
  • allow-recursion Takes one or more address match list entry.
  • allow-update Takes one or more address match list entry.
  • allow-query Takes one or more address match list entry.
  • allow-query-cache Takes one or more address match list entry.
  • forwarders Takes one or more IP addresses, e.g. 10.1.1.1
  • directory Takes a directory path
  • tkey-gssapi-credential Takes a kerberos service principal
  • tkey-domain Takes a kerberos realm
  • update-policy Takes one complete update-policy entry where you can grant or deny various matched objects and specify the dentity of the user/machine that is allowed/disallowed to update.. You can also identify match-type (Type of match to be used in evaulating the entry) and match-name (Name used to match) as well as rr-types (Resource record types that can be updated)
You can also use the serveradmin command, and should certainly back up all of your settings and records this way. This is easily done using the serveradmin command as follows:

serveradmin settings dns

And the output would look something like this: 

dns:acls:_array_index:0:name = “com.apple.ServerAdmin.DNS.public”
dns:acls:_array_index:0:addressMatchList:_array_index:0 = “localhost”
dns:acls:_array_index:0:addressMatchList:_array_index:1 = “localnets”
dns:forwarders:_array_index:0 = “8.8.8.8”
dns:forwarders:_array_index:1 = “4.4.4.4”
dns:views:_array_id:com.apple.ServerAdmin.DNS.public:reverseZones:_array_id:0.0.10.in-addr.arpa:aliases = _empty_array
dns:views:_array_id:com.apple.ServerAdmin.DNS.public:reverseZones:_array_id:0.0.10.in-addr.arpa:expire = 1209600
dns:views:_array_id:com.apple.ServerAdmin.DNS.public:reverseZones:_array_id:0.0.10.in-addr.arpa:serial = 2018033001
dns:views:_array_id:com.apple.ServerAdmin.DNS.public:reverseZones:_array_id:0.0.10.in-addr.arpa:allow-update = no
dns:views:_array_id:com.apple.ServerAdmin.DNS.public:reverseZones:_array_id:0.0.10.in-addr.arpa:adminEmail = “admin@0.0.10.in-addr.arpa”
dns:views:_array_id:com.apple.ServerAdmin.DNS.public:reverseZones:_array_id:0.0.10.in-addr.arpa:machines = _empty_array
dns:views:_array_id:com.apple.ServerAdmin.DNS.public:reverseZones:_array_id:0.0.10.in-addr.arpa:nameservers:_array_index:0:name = “0.0.10.in-addr.arpa”
dns:views:_array_id:com.apple.ServerAdmin.DNS.public:reverseZones:_array_id:0.0.10.in-addr.arpa:nameservers:_array_index:0:value = “test.test.com.”
dns:views:_array_id:com.apple.ServerAdmin.DNS.public:reverseZones:_array_id:0.0.10.in-addr.arpa:refresh = 3600
dns:views:_array_id:com.apple.ServerAdmin.DNS.public:reverseZones:_array_id:0.0.10.in-addr.arpa:mailExchangers = _empty_array
dns:views:_array_id:com.apple.ServerAdmin.DNS.public:reverseZones:_array_id:0.0.10.in-addr.arpa:reverseMappings:_array_index:0:value = “test.test.com.”
dns:views:_array_id:com.apple.ServerAdmin.DNS.public:reverseZones:_array_id:0.0.10.in-addr.arpa:reverseMappings:_array_index:0:ipAddress = “10.0.0.1”
dns:views:_array_id:com.apple.ServerAdmin.DNS.public:reverseZones:_array_id:0.0.10.in-addr.arpa:retry = 900
dns:views:_array_id:com.apple.ServerAdmin.DNS.public:reverseZones:_array_id:0.0.10.in-addr.arpa:timeToLive = 86400
dns:views:_array_id:com.apple.ServerAdmin.DNS.public:reverseZones:_array_id:0.0.10.in-addr.arpa:serviceRecords = _empty_array
dns:views:_array_id:com.apple.ServerAdmin.DNS.public:reverseZones:_array_id:0.0.10.in-addr.arpa:name = “0.0.10.in-addr.arpa”
dns:views:_array_id:com.apple.ServerAdmin.DNS.public:reverseZones:_array_id:0.0.10.in-addr.arpa:allowZoneTransfer = no
dns:views:_array_id:com.apple.ServerAdmin.DNS.public:primaryZones:_array_id:test.com:aliases:_array_index:0:name = “testalias.test.com.”
dns:views:_array_id:com.apple.ServerAdmin.DNS.public:primaryZones:_array_id:test.com:aliases:_array_index:0:value = “test.test.com.”
dns:views:_array_id:com.apple.ServerAdmin.DNS.public:primaryZones:_array_id:test.com:expire = 1209600
dns:views:_array_id:com.apple.ServerAdmin.DNS.public:primaryZones:_array_id:test.com:serial = 2018033001
dns:views:_array_id:com.apple.ServerAdmin.DNS.public:primaryZones:_array_id:test.com:allow-update = no
dns:views:_array_id:com.apple.ServerAdmin.DNS.public:primaryZones:_array_id:test.com:adminEmail = “admin@test.com”
dns:views:_array_id:com.apple.ServerAdmin.DNS.public:primaryZones:_array_id:test.com:machines:_array_index:0:name = “test.test.com.”
dns:views:_array_id:com.apple.ServerAdmin.DNS.public:primaryZones:_array_id:test.com:machines:_array_index:0:ipAddresses:_array_index:0:ipAddress = “10.0.0.1”
dns:views:_array_id:com.apple.ServerAdmin.DNS.public:primaryZones:_array_id:test.com:nameservers:_array_index:0:name = “test.com”
dns:views:_array_id:com.apple.ServerAdmin.DNS.public:primaryZones:_array_id:test.com:nameservers:_array_index:0:value = “test.test.com.”
dns:views:_array_id:com.apple.ServerAdmin.DNS.public:primaryZones:_array_id:test.com:refresh = 3600
dns:views:_array_id:com.apple.ServerAdmin.DNS.public:primaryZones:_array_id:test.com:mailExchangers:_array_index:0:address = “test.test.com.”
dns:views:_array_id:com.apple.ServerAdmin.DNS.public:primaryZones:_array_id:test.com:mailExchangers:_array_index:0:priority = 0
dns:views:_array_id:com.apple.ServerAdmin.DNS.public:primaryZones:_array_id:test.com:reverseMappings = _empty_array
dns:views:_array_id:com.apple.ServerAdmin.DNS.public:primaryZones:_array_id:test.com:retry = 900
dns:views:_array_id:com.apple.ServerAdmin.DNS.public:primaryZones:_array_id:test.com:timeToLive = 86400
dns:views:_array_id:com.apple.ServerAdmin.DNS.public:primaryZones:_array_id:test.com:serviceRecords = _empty_array
dns:views:_array_id:com.apple.ServerAdmin.DNS.public:primaryZones:_array_id:test.com:name = “test.com”
dns:views:_array_id:com.apple.ServerAdmin.DNS.public:primaryZones:_array_id:test.com:allowZoneTransfer = no
dns:views:_array_id:com.apple.ServerAdmin.DNS.public:name = “com.apple.ServerAdmin.DNS.public”
dns:views:_array_id:com.apple.ServerAdmin.DNS.public:secondaryZones = _empty_array

Or to output it to a file, just pipe it as follows:

sudo serveradmin settings dns > test.dns