Add support for publishing DNS to Cloudflare
authorTom Hughes <tom@compton.nu>
Fri, 7 Feb 2020 00:23:23 +0000 (00:23 +0000)
committerTom Hughes <tom@compton.nu>
Fri, 7 Feb 2020 15:37:47 +0000 (15:37 +0000)
12 files changed:
.gitignore
Makefile
bin/mkgeo
dnsconfig.js [new file with mode: 0644]
include/.gitkeep [new file with mode: 0644]
src/opengeodata.js [new file with mode: 0644]
src/openstreetmap-uk.js [new file with mode: 0644]
src/openstreetmap-za.js [new file with mode: 0644]
src/openstreetmap.js [new file with mode: 0644]
src/osmfoundation.js [new file with mode: 0644]
src/stateofthemap.js [new file with mode: 0644]
src/switch2osm.js [new file with mode: 0644]

index 02a0651100acb678f9a84276d9b70fe50520b791..1ef454d06df3df2117e96fb7841be9dcd33a4769 100644 (file)
@@ -1,5 +1,7 @@
+creds.json
 data/
 gdns/
+include/
 json/
 kml/
 origins/
index 3875694cee5375d406aa15f67de7f1ad556ff0b7..0b27d0d7284c18869a5ad7ab4201f17af3429f62 100644 (file)
--- a/Makefile
+++ b/Makefile
@@ -1,29 +1,38 @@
-all: data/openstreetmap.org data/openstreetmap.com data/openstreetmap.net \
-     data/openstreetmap.ca data/openstreetmap.eu data/openstreetmap.pro \
-     data/openstreetmaps.org data/osm.org data/openmaps.org \
-     data/openstreetmap.io data/osm.io \
-     data/openworldmap.org data/freeosm.org data/open-maps.org data/open-maps.com data/osmbugs.org \
-     data/openstreetmap.uk data/openstreetmap.org.uk data/openstreetmap.co.uk \
-     data/openstreetmap.org.za data/osm.org.za \
-     data/osmfoundation.org \
-     data/stateofthemap.org data/stateofthemap.com data/sotm.org \
-     data/stateofthemap.eu \
-     data/opengeodata.org \
-     data/switch2osm.org data/switch2osm.com \
-     data/tile.openstreetmap.org \
-     data/render.openstreetmap.org
+preview: preview_bytemark preview_cloudflare
 
-clean:
-       rm -f data/* json/* origins/*
+preview_bytemark: data/openstreetmap.org data/openstreetmap.com data/openstreetmap.net \
+                 data/openstreetmap.ca data/openstreetmap.eu data/openstreetmap.pro \
+                 data/openstreetmaps.org data/osm.org data/openmaps.org \
+                 data/openstreetmap.io data/osm.io \
+                 data/openworldmap.org data/freeosm.org data/open-maps.org data/open-maps.com data/osmbugs.org \
+                 data/openstreetmap.uk data/openstreetmap.org.uk data/openstreetmap.co.uk \
+                 data/openstreetmap.org.za data/osm.org.za \
+                 data/osmfoundation.org \
+                 data/stateofthemap.org data/stateofthemap.com data/sotm.org \
+                 data/stateofthemap.eu \
+                 data/opengeodata.org \
+                 data/switch2osm.org data/switch2osm.com \
+                 data/tile.openstreetmap.org \
+                 data/tile.openstreetmap.org \
+                 data/render.openstreetmap.org
+
+preview_cloudflare: data/tile.openstreetmap.org data/render.openstreetmap.org
+       dnscontrol preview
 
-update: update_bytemark update_geodns
+update: update_bytemark update_cloudflare update_geodns
 
-update_bytemark: all
+update_bytemark: preview_bytemark
        bin/update
 
-update_geodns: all
+update_cloudflare: data/tile.openstreetmap.org data/render.openstreetmap.org
+       dnscontrol push --providers cloudflare
+
+update_geodns: gdns/tile.map gdns/tile.resource gdns/tile.weighted
        parallel --will-cite rsync --quiet --recursive --checksum gdns/ {}::geodns ::: ${GEODNS_SERVERS}
 
+clean:
+       rm -f data/* json/* origins/* gdns/*
+
 lib/countries.xml:
        curl -s -o $@ http://api.geonames.org/countryInfo?username=demo
 
@@ -60,11 +69,11 @@ data/stateofthemap.eu: src/stateofthemap-eu
 origins/tile.openstreetmap.yml: bin/mkcountries lib/countries.xml bandwidth/tile.openstreetmap.yml
        bin/mkcountries bandwidth/tile.openstreetmap.yml origins/tile.openstreetmap.yml
 
-data/tile.openstreetmap.org json/tile.openstreetmap.org.json origins/render.openstreetmap.yml: bin/mkgeo origins/tile.openstreetmap.yml src/tile.openstreetmap
-       bin/mkgeo origins/tile.openstreetmap.yml src/tile.openstreetmap tile.openstreetmap.org origins/render.openstreetmap.yml tile
+data/tile.openstreetmap.org json/tile.openstreetmap.org.json origins/render.openstreetmap.yml gdns/tile.map gdns/tile.resource gdns/tile.weighted: bin/mkgeo origins/tile.openstreetmap.yml src/tile.openstreetmap
+       bin/mkgeo origins/tile.openstreetmap.yml src/tile.openstreetmap tile.openstreetmap.org tile origins/render.openstreetmap.yml tile
 
 data/render.openstreetmap.org json/render.openstreetmap.org.json: bin/mkgeo origins/render.openstreetmap.yml src/render.openstreetmap
-       bin/mkgeo origins/render.openstreetmap.yml src/render.openstreetmap render.openstreetmap.org origins/total.openstreetmap.yml
+       bin/mkgeo origins/render.openstreetmap.yml src/render.openstreetmap render.openstreetmap.org render origins/total.openstreetmap.yml
 
 data/%:
        sed -r -e 's/$(notdir $<)(:|$$)/$(notdir $@)\1/g' < $< > $@
index f23d0c56c5d02c752aff6a17187f733e1e4ac8a5..76316b08e1b0b92032381cdd85ff00586c3fdf3f 100755 (executable)
--- a/bin/mkgeo
+++ b/bin/mkgeo
@@ -14,6 +14,7 @@ use YAML;
 my $originfile = shift @ARGV;
 my $clusterfile = shift @ARGV;
 my $zone = shift @ARGV;
+my $jszone = shift @ARGV;
 my $targetoriginfile = shift @ARGV;
 my $origins = YAML::LoadFile($originfile);
 my $clusters = YAML::LoadFile($clusterfile);
@@ -205,8 +206,12 @@ my @json;
 
 # Open output files
 my $zonefile = IO::File->new("> data/${zone}") || die "$!";
+my $jszonefile = IO::File->new("> include/${jszone}.js") || die "$!";
 my $jsonfile = IO::File->new("> json/${zone}.json") || die "$!";
 
+# Output headers
+$jszonefile->print("var \U${jszone}\E_RECORDS = [\n");
+
 # Output details for each country
 foreach my $origin (sort { $a->{name} cmp $b->{name} } values %$origins)
 {
@@ -228,6 +233,8 @@ foreach my $origin (sort { $a->{name} cmp $b->{name} } values %$origins)
     $zonefile->print("# $origin->{name}\n");
     $zonefile->print("C\L$origin->{code}\E.${zone}:$cluster->{name}.${zone}:600\n");
 
+    $jszonefile->print("  CNAME(\"\L$origin->{code}\E.${jszone}\", \"$cluster->{name}.${zone}.\", TTL(\"10m\")),\n");
+
     push @json, {
         type => "Feature",
         geometry => {
@@ -254,11 +261,11 @@ foreach my $cluster (sort { $a->{name} cmp $b->{name} } values %$clusters)
 
     if (my $default = $cluster->{default})
     {
-        output_server($zonefile, "${default}.${zone}", $cluster);
+        output_server($zonefile, $jszonefile, "${default}.${zone}", "${default}.${jszone}", $cluster);
     }
     elsif (exists($cluster->{default}))
     {
-        output_server($zonefile, "${zone}", $cluster);
+        output_server($zonefile, $jszonefile, "${zone}", "${jszone}", $cluster);
     }
 }
 
@@ -270,19 +277,23 @@ foreach my $cluster (sort { $a->{name} cmp $b->{name} } values %$clusters)
 {
     my $name = $cluster->{name};
 
-    output_server($zonefile, "${name}.${zone}", $cluster);
+    output_server($zonefile, $jszonefile, "${name}.${zone}", "${name}.${jszone}", $cluster);
 
     if (@{$cluster->{servers}} > 1)
     {
-        output_server($zonefile, "${name}-%02d.${zone}", $cluster);
+        output_server($zonefile, $jszonefile, "${name}-%02d.${zone}", "${name}-%02d.${jszone}", $cluster);
     }
 }
 
 # Output the GeoJSON text
 $jsonfile->print(encode_json(\@json));
 
+# Output footers
+$jszonefile->print("];\n");
+
 # Close the output files
 $jsonfile->close();
+$jszonefile->close();
 $zonefile->close();
 
 # Output gdnsd configuration
@@ -341,7 +352,7 @@ if (defined($gdnsname))
                 {
                     my $number = sprintf("%02d", $index + 1);
                     my $bandwidth = $server->{bandwidth};
-                
+
                     $gdnsweightedfile->print("  ${name}-${number} = [ ${name}-${number}.${zone}., ${bandwidth} ]\n");
                 }
             }
@@ -517,7 +528,9 @@ sub compare_bandwidth
 sub output_server
 {
     my $zonefile = shift;
+    my $jszonefile = shift;
     my $name = shift;
+    my $jsname = shift;
     my $cluster = shift;
 
     while (my($index,$server) = each @{$cluster->{servers}})
@@ -525,10 +538,16 @@ sub output_server
         if ($server->{status} eq "up")
         {
             $zonefile->printf("+${name}:$server->{ipv4}:600\n", $index + 1);
+            $jszonefile->printf("  A(\"${jsname}\", \"$server->{ipv4}\", TTL(\"10m\")),\n", $index + 1);
 
             if ($server->{ipv6})
             {
+                my $ipv6 = $server->{ipv6};
+
+                $ipv6 =~ s/([0-9a-f]{4})(?=.)/\1:/ig;
+
                 $zonefile->printf("3${name}:$server->{ipv6}:600\n", $index + 1);
+                $jszonefile->printf("  AAAA(\"${jsname}\", \"${ipv6}\", TTL(\"10m\")),\n", $index + 1);
             }
         }
     }
diff --git a/dnsconfig.js b/dnsconfig.js
new file mode 100644 (file)
index 0000000..ab69248
--- /dev/null
@@ -0,0 +1,82 @@
+var REGISTRAR = NewRegistrar("none", "NONE");
+var PROVIDER = NewDnsProvider("cloudflare", "CLOUDFLAREAPI");
+
+var CF_TTL_ANY = TTL(1);
+
+DEFAULTS(DefaultTTL("24h"));
+
+var DOMAIN;
+var DYNAMIC_RECORDS;
+
+var QUALIFY = function (name) {
+  return name + "." + DOMAIN + ".";
+};
+
+function loadTemplate(template) {
+  return function (domain) {
+    DOMAIN = domain;
+    DYNAMIC_RECORDS = [];
+    
+    for (var i = 1; i < arguments.length; i++) {
+      DYNAMIC_RECORDS = DYNAMIC_RECORDS.concat(arguments[i]);
+    }
+    
+    require("src/" + template + ".js");
+  };
+}
+
+var OPENSTREETMAP = loadTemplate("openstreetmap");
+
+require("include/tile.js");
+require("include/render.js");
+
+OPENSTREETMAP("openstreetmap.org", TILE_RECORDS, RENDER_RECORDS);
+OPENSTREETMAP("openstreetmap.com");
+OPENSTREETMAP("openstreetmap.net");
+OPENSTREETMAP("openstreetmap.ca");
+OPENSTREETMAP("openstreetmap.eu");
+OPENSTREETMAP("openstreetmap.pro");
+OPENSTREETMAP("openstreetmaps.org");
+OPENSTREETMAP("osm.org");
+OPENSTREETMAP("openmaps.org");
+OPENSTREETMAP("openstreetmap.io");
+OPENSTREETMAP("osm.io");
+OPENSTREETMAP("openworldmap.org");
+OPENSTREETMAP("freeosm.org");
+OPENSTREETMAP("open-maps.org");
+OPENSTREETMAP("open-maps.com");
+OPENSTREETMAP("osmbugs.org");
+
+var OPENSTREETMAP_UK = loadTemplate("openstreetmap-uk");
+
+OPENSTREETMAP_UK("openstreetmap.uk");
+OPENSTREETMAP_UK("openstreetmap.org.uk");
+OPENSTREETMAP_UK("openstreetmap.co.uk");
+
+var OPENSTREETMAP_ZA = loadTemplate("openstreetmap-za");
+
+OPENSTREETMAP_UK("openstreetmap.org.za");
+OPENSTREETMAP_UK("osm.org.za");
+
+var OSMFOUNDATION = loadTemplate("osmfoundation");
+
+OSMFOUNDATION("osmfoundation.org");
+
+var STATEOFTHEMAP = loadTemplate("stateofthemap");
+
+STATEOFTHEMAP("stateofthemap.org");
+STATEOFTHEMAP("stateofthemap.com");
+STATEOFTHEMAP("sotm.org");
+
+var STATEOFTHEMAP_EU = loadTemplate("stateofthemap-eu");
+
+STATEOFTHEMAP("stateofthemap.eu");
+
+var OPENGEODATA = loadTemplate("opengeodata");
+
+OPENGEODATA("opengeodata.org");
+
+var SWITCH2OSM = loadTemplate("switch2osm");
+
+SWITCH2OSM("switch2osm.org");
+SWITCH2OSM("switch2osm.com");
diff --git a/include/.gitkeep b/include/.gitkeep
new file mode 100644 (file)
index 0000000..e69de29
diff --git a/src/opengeodata.js b/src/opengeodata.js
new file mode 100644 (file)
index 0000000..815b840
--- /dev/null
@@ -0,0 +1,15 @@
+D(DOMAIN, REGISTRAR, DnsProvider(PROVIDER),
+
+  // Publish CAA records indicating that only letsencrypt should issue certificates
+
+  CAA("@", "issue", "letsencrypt.org", CF_TTL_ANY),
+  CAA("@", "issuewild", "letsencrypt.org", CF_TTL_ANY),
+  CAA("@", "iodef", "mailto:hostmaster@openstreetmap.org"),
+
+  // Main web server and it's aliases
+
+  A("@", "193.60.236.19", TTL("10m")),
+  A("old", "193.60.236.19", TTL("10m")),
+  A("www", "193.60.236.19", TTL("10m"))
+
+);
diff --git a/src/openstreetmap-uk.js b/src/openstreetmap-uk.js
new file mode 100644 (file)
index 0000000..492e695
--- /dev/null
@@ -0,0 +1,69 @@
+D(DOMAIN, REGISTRAR, DnsProvider(PROVIDER),
+
+  // Publish CAA records indicating that only letsencrypt should issue certificates
+
+  CAA("@", "issue", "letsencrypt.org", CF_TTL_ANY),
+  CAA("@", "issuewild", "letsencrypt.org", CF_TTL_ANY),
+  CAA("@", "iodef", "mailto:hostmaster@openstreetmap.org"),
+
+  // Let the main domain handle the email
+
+  MX("@", 10, "a.mx.openstreetmap.org."),
+
+  // Delegate SPF policy to the main domain
+
+  TXT("@", "v=spf1 include:openstreetmap.org -all"),
+
+  // Delegate MTA-STS policy to the main domain
+
+  CNAME("_mta-sts", "_mta-sts.openstreetmap.org."),
+
+  // Main web site
+
+  ALIAS("@", "www.openstreetmap.org."),
+  CNAME("www", "www.openstreetmap.org."),
+  CNAME("api", "api.openstreetmap.org."),
+
+  // Shaun McDonald's taginfo instance
+
+  CNAME("taginfo", "proxy.mythic-beasts.com."),
+
+  // Aerial imagery sites
+
+  A("hampshire.aerial", "178.250.74.36", TTL("1h")),
+  AAAA("hampshire.aerial", "2a02:1658:4:0:dad3:85ff:fe5d:875e", TTL("1h")),
+  A("a.hampshire.aerial", "178.250.74.36", TTL("1h")),
+  AAAA("a.hampshire.aerial", "2a02:1658:4:0:dad3:85ff:fe5d:875e", TTL("1h")),
+  A("b.hampshire.aerial", "178.250.74.36", TTL("1h")),
+  AAAA("b.hampshire.aerial", "2a02:1658:4:0:dad3:85ff:fe5d:875e", TTL("1h")),
+  A("c.hampshire.aerial", "178.250.74.36", TTL("1h")),
+  AAAA("c.hampshire.aerial", "2a02:1658:4:0:dad3:85ff:fe5d:875e", TTL("1h")),
+
+  A("surrey.aerial", "178.250.74.36", TTL("1h")),
+  AAAA("surrey.aerial", "2a02:1658:4:0:dad3:85ff:fe5d:875e", TTL("1h")),
+  A("a.surrey.aerial", "178.250.74.36", TTL("1h")),
+  AAAA("a.surrey.aerial", "2a02:1658:4:0:dad3:85ff:fe5d:875e", TTL("1h")),
+  A("b.surrey.aerial", "178.250.74.36", TTL("1h")),
+  AAAA("b.surrey.aerial", "2a02:1658:4:0:dad3:85ff:fe5d:875e", TTL("1h")),
+  A("c.surrey.aerial", "178.250.74.36", TTL("1h")),
+  AAAA("c.surrey.aerial", "2a02:1658:4:0:dad3:85ff:fe5d:875e", TTL("1h")),
+
+  A("os", "178.250.74.36", TTL("1h")),
+  AAAA("os", "2a02:1658:4:0:dad3:85ff:fe5d:875e", TTL("1h")),
+  A("a.os", "178.250.74.36", TTL("1h")),
+  AAAA("a.os", "2a02:1658:4:0:dad3:85ff:fe5d:875e", TTL("1h")),
+  A("b.os", "178.250.74.36", TTL("1h")),
+  AAAA("b.os", "2a02:1658:4:0:dad3:85ff:fe5d:875e", TTL("1h")),
+  A("c.os", "178.250.74.36", TTL("1h")),
+  AAAA("c.os", "2a02:1658:4:0:dad3:85ff:fe5d:875e", TTL("1h")),
+
+  A("ea", "178.250.74.36", TTL("1h")),
+  AAAA("ea", "2a02:1658:4:0:dad3:85ff:fe5d:875e", TTL("1h")),
+  A("a.ea", "178.250.74.36", TTL("1h")),
+  AAAA("a.ea", "2a02:1658:4:0:dad3:85ff:fe5d:875e", TTL("1h")),
+  A("b.ea", "178.250.74.36", TTL("1h")),
+  AAAA("b.ea", "2a02:1658:4:0:dad3:85ff:fe5d:875e", TTL("1h")),
+  A("c.ea", "178.250.74.36", TTL("1h")),
+  AAAA("c.ea", "2a02:1658:4:0:dad3:85ff:fe5d:875e", TTL("1h"))
+
+);
diff --git a/src/openstreetmap-za.js b/src/openstreetmap-za.js
new file mode 100644 (file)
index 0000000..a7a4150
--- /dev/null
@@ -0,0 +1,63 @@
+D(DOMAIN, REGISTRAR, DnsProvider(PROVIDER),
+
+  // Publish CAA records indicating that only letsencrypt should issue certificates
+
+  CAA("@", "issue", "letsencrypt.org", CF_TTL_ANY),
+  CAA("@", "issuewild", "letsencrypt.org", CF_TTL_ANY),
+  CAA("@", "iodef", "mailto:hostmaster@openstreetmap.org"),
+
+  // Let the main domain handle the email
+
+  MX("@", 10, "a.mx.openstreetmap.org."),
+
+  // Delegate SPF policy to the main domain
+
+  TXT("@", "v=spf1 include:openstreetmap.org -all"),
+
+  // Delegate MTA-STS policy to the main domain
+
+  CNAME("_mta-sts", "_mta-sts.openstreetmap.org."),
+
+  // Main web site
+
+  ALIAS("@", "www.openstreetmap.org."),
+  CNAME("www", "www.openstreetmap.org."),
+  CNAME("api", "api.openstreetmap.org."),
+
+  // Aerial imagery sites on draco
+
+  A("aerial", "193.60.236.12", TTL("10m")),
+  A("a.aerial", "193.60.236.12", TTL("10m")),
+  A("b.aerial", "193.60.236.12", TTL("10m")),
+  A("c.aerial", "193.60.236.12", TTL("10m")),
+
+  // Aerial imagery sites on kessie
+
+  A("coct.aerial", "178.250.74.36", TTL("30m")),
+  AAAA("coct.aerial", "2a02:1658:4:0:dad3:85ff:fe5d:875e", TTL("30m")),
+  A("a.coct.aerial", "178.250.74.36", TTL("30m")),
+  AAAA("a.coct.aerial", "2a02:1658:4:0:dad3:85ff:fe5d:875e", TTL("30m")),
+  A("b.coct.aerial", "178.250.74.36", TTL("30m")),
+  AAAA("b.coct.aerial", "2a02:1658:4:0:dad3:85ff:fe5d:875e", TTL("30m")),
+  A("c.coct.aerial", "178.250.74.36", TTL("30m")),
+  AAAA("c.coct.aerial", "2a02:1658:4:0:dad3:85ff:fe5d:875e", TTL("30m")),
+
+  A("topo", "178.250.74.36", TTL("30m")),
+  AAAA("topo", "2a02:1658:4:0:dad3:85ff:fe5d:875e", TTL("30m")),
+  A("a.topo", "178.250.74.36", TTL("30m")),
+  AAAA("a.topo", "2a02:1658:4:0:dad3:85ff:fe5d:875e", TTL("30m")),
+  A("b.topo", "178.250.74.36", TTL("30m")),
+  AAAA("b.topo", "2a02:1658:4:0:dad3:85ff:fe5d:875e", TTL("30m")),
+  A("c.topo", "178.250.74.36", TTL("30m")),
+  AAAA("c.topo", "2a02:1658:4:0:dad3:85ff:fe5d:875e", TTL("30m")),
+
+  A("namibia-topo", "178.250.74.36", TTL("30m")),
+  AAAA("namibia-topo", "2a02:1658:4:0:dad3:85ff:fe5d:875e", TTL("30m")),
+  A("a.namibia-topo", "178.250.74.36", TTL("30m")),
+  AAAA("a.namibia-topo", "2a02:1658:4:0:dad3:85ff:fe5d:875e", TTL("30m")),
+  A("b.namibia-topo", "178.250.74.36", TTL("30m")),
+  AAAA("b.namibia-topo", "2a02:1658:4:0:dad3:85ff:fe5d:875e", TTL("30m")),
+  A("c.namibia-topo", "178.250.74.36", TTL("30m")),
+  AAAA("c.namibia-topo", "2a02:1658:4:0:dad3:85ff:fe5d:875e", TTL("30m")),
+
+);
diff --git a/src/openstreetmap.js b/src/openstreetmap.js
new file mode 100644 (file)
index 0000000..e892ff1
--- /dev/null
@@ -0,0 +1,559 @@
+D(DOMAIN, REGISTRAR, DnsProvider(PROVIDER),
+
+  // Publish CAA records indicating that only letsencrypt should issue certificates
+
+  CAA("@", "issue", "letsencrypt.org", CF_TTL_ANY),
+  CAA("@", "issuewild", "letsencrypt.org", CF_TTL_ANY),
+  CAA("@", "iodef", "mailto:hostmaster@openstreetmap.org"),
+
+  // Use shenron as the MX host
+
+  MX("@", 10, QUALIFY("a.mx")),
+  MX("messages", 10, QUALIFY("a.mx")),
+  MX("noreply", 10, QUALIFY("a.mx")),
+  MX("otrs", 10, QUALIFY("a.mx")),
+  A("a.mx", "212.110.172.32"),
+  AAAA("a.mx", "2001:41c9:1:400::32"),
+
+  // Publish SPF records indicating that only shenron sends mail
+
+  TXT("@", "v=spf1 ip4:212.110.172.32 ip6:2001:41c9:1:400::32 mx -all"),
+  TXT("otrs", "v=spf1 ip4:212.110.172.32 ip6:2001:41c9:1:400::32 mx -all"),
+
+  // Announce MTA-STS policy and TLSRPT policy for error reports
+
+  TXT("_mta-sts", "v=STSv1; id=202001291805Z"),
+  TXT("_smtp._tls", "v=TLSRPTv1; rua=mailto:postmaster@openstreetmap.org"),
+
+  // Delegate MTA-STS policy for subdomains
+
+  CNAME("_mta-sts.messages", QUALIFY("_mta-sts")),
+  CNAME("_mta-sts.noreply", QUALIFY("_mta-sts")),
+  CNAME("_mta-sts.otrs", QUALIFY("_mta-sts")),
+
+  // Google postmaster tools verification
+
+  CNAME("af323lytato5", "gv-o4v3qh5pfayqex.dv.googlehosted.com."),
+
+  // Delegate geo.openstreetmap.org to PowerDNS
+
+  NS("geo", QUALIFY("saphira")),
+  NS("geo", QUALIFY("ridgeback")),
+  NS("geo", QUALIFY("jakelong")),
+  NS("geo", QUALIFY("katie")),
+  NS("geo", QUALIFY("stormfly-02")),
+  NS("geo", QUALIFY("chrysophylax")),
+
+  // Main web servers and their aliases
+
+  A("spike-01", "130.117.76.6"),
+  AAAA("spike-01", "2001:978:2:2c::172:6"),
+  // A("@", "130.117.76.6", TTL("10m")),
+  // AAAA("@", "2001:978:2:2c::172:6", TTL("10m")),
+  // A("www", "130.117.76.6" TTL("10m")),
+  // AAAA("www", "2001:978:2:2c::172:6", TTL("10m")),
+  // A("api", "130.117.76.6", TTL("10m")),
+  // AAAA("api", "2001:978:2:2c::172:6", TTL("10m")),
+  // A("maps", "130.117.76.6", TTL("10m")),
+  // AAAA("maps", "2001:978:2:2c::172:6", TTL("10m")),
+  // A("mapz", "130.117.76.6", TTL("10m")),
+  // AAAA("mapz", "2001:978:2:2c::172:6", TTL("10m")),
+  A("spike-01.ams", "10.0.48.6"),
+  A("spike-01.oob", "10.0.49.6"),
+
+  A("spike-02", "130.117.76.7"),
+  AAAA("spike-02", "2001:978:2:2c::172:7"),
+  // A("@", "130.117.76.7", TTL("10m")),
+  // AAAA("@", "2001:978:2:2c::172:7", TTL("10m")),
+  // A("www", "130.117.76.7", TTL("10m")),
+  // AAAA("www", "2001:978:2:2c::172:7", TTL("10m")),
+  // A("api", "130.117.76.7", TTL("10m")),
+  // AAAA("api", "2001:978:2:2c::172:7", TTL("10m")),
+  // A("maps", "130.117.76.7", TTL("10m")),
+  // AAAA("maps", "2001:978:2:2c::172:7", TTL("10m")),
+  // A("mapz", "130.117.76.7", TTL("10m")),
+  // AAAA("mapz", "2001:978:2:2c::172:7", TTL("10m")),
+  A("spike-02.ams", "10.0.48.7"),
+  A("spike-02.oob", "10.0.49.7"),
+
+  A("spike-03", "130.117.76.8"),
+  AAAA("spike-03", "2001:978:2:2c::172:8"),
+  // A("@", "130.117.76.8", TTL("10m")),
+  // AAAA("@", "2001:978:2:2c::172:8", TTL("10m")),
+  // A("www", "130.117.76.8", TTL("10m")),
+  // AAAA("www", "2001:978:2:2c::172:8", TTL("10m")),
+  // A("api", "130.117.76.8", TTL("10m")),
+  // AAAA("api", "2001:978:2:2c::172:8", TTL("10m")),
+  // A("maps", "130.117.76.8", TTL("10m")),
+  // AAAA("maps", "2001:978:2:2c::172:8", TTL("10m")),
+  // A("mapz", "130.117.76.8", TTL("10m")),
+  // AAAA("mapz", "2001:978:2:2c::172:8", TTL("10m")),
+  A("spike-03.ams", "10.0.48.8"),
+  A("spike-03.oob", "10.0.49.8"),
+
+  A("spike-04", "89.16.162.21"),
+  AAAA("spike-04", "2001:41c9:2:d6::21"),
+  // A("@", "89.16.162.21", TTL("10m")),
+  // AAAA("@", "2001:41c9:2:d6::21", TTL("10m")),
+  // A("www", "89.16.162.21", TTL("10m")),
+  // AAAA("www", "2001:41c9:2:d6::21", TTL("10m")),
+  // A("api", "89.16.162.21", TTL("10m")),
+  // AAAA("api", "2001:41c9:2:d6::21", TTL("10m")),
+  // A("maps", "89.16.162.21", TTL("10m")),
+  // AAAA("maps", "2001:41c9:2:d6::21", TTL("10m")),
+  // A("mapz", "89.16.162.21", TTL("10m")),
+  // AAAA("mapz", "2001:41c9:2:d6::21", TTL("10m")),
+  A("spike-04.bm", "10.0.32.21"),
+  A("spike-04.oob", "10.0.33.21"),
+
+  A("spike-05", "89.16.162.22"),
+  AAAA("spike-05", "2001:41c9:2:d6::22"),
+  // A("@", "89.16.162.22", TTL("10m")),
+  // AAAA("@", "2001:41c9:2:d6::22", TTL("10m")),
+  // A("www", "89.16.162.22", TTL("10m")),
+  // AAAA("www", "2001:41c9:2:d6::22", TTL("10m")),
+  // A("api", "89.16.162.22", TTL("10m")),
+  // AAAA("api", "2001:41c9:2:d6::22", TTL("10m")),
+  // A("maps", "89.16.162.22", TTL("10m")),
+  // AAAA("maps", "2001:41c9:2:d6::22", TTL("10m")),
+  // A("mapz", "89.16.162.22", TTL("10m")),
+  // AAAA("mapz", "2001:41c9:2:d6::22", TTL("10m")),
+  A("spike-05.bm", "10.0.32.22"),
+  A("spike-05.oob", "10.0.33.22"),
+
+  A("spike-06", "130.117.76.11"),
+  AAAA("spike-06", "2001:978:2:2c::172:B"),
+  A("@", "130.117.76.11", TTL("10m")),
+  AAAA("@", "2001:978:2:2c::172:B", TTL("10m")),
+  A("www", "130.117.76.11", TTL("10m")),
+  AAAA("www", "2001:978:2:2c::172:B", TTL("10m")),
+  A("api", "130.117.76.11", TTL("10m")),
+  AAAA("api", "2001:978:2:2c::172:B", TTL("10m")),
+  A("maps", "130.117.76.11", TTL("10m")),
+  AAAA("maps", "2001:978:2:2c::172:B", TTL("10m")),
+  A("mapz", "130.117.76.11", TTL("10m")),
+  AAAA("mapz", "2001:978:2:2c::172:B", TTL("10m")),
+  A("spike-06.ams", "10.0.48.11"),
+  A("spike-06.oob", "10.0.49.11"),
+
+  A("spike-07", "130.117.76.12"),
+  AAAA("spike-07", "2001:978:2:2c::172:C"),
+  A("@", "130.117.76.12", TTL("10m")),
+  AAAA("@", "2001:978:2:2c::172:C", TTL("10m")),
+  A("www", "130.117.76.12", TTL("10m")),
+  AAAA("www", "2001:978:2:2c::172:C", TTL("10m")),
+  A("api", "130.117.76.12", TTL("10m")),
+  AAAA("api", "2001:978:2:2c::172:C", TTL("10m")),
+  A("maps", "130.117.76.12", TTL("10m")),
+  AAAA("maps", "2001:978:2:2c::172:C", TTL("10m")),
+  A("mapz", "130.117.76.12", TTL("10m")),
+  AAAA("mapz", "2001:978:2:2c::172:C", TTL("10m")),
+  A("spike-07.ams", "10.0.48.12"),
+  A("spike-07.oob", "10.0.49.12"),
+
+  A("spike-08", "130.117.76.13"),
+  AAAA("spike-08", "2001:978:2:2c::172:D"),
+  A("@", "130.117.76.13", TTL("10m")),
+  AAAA("@", "2001:978:2:2c::172:D", TTL("10m")),
+  A("www", "130.117.76.13", TTL("10m")),
+  AAAA("www", "2001:978:2:2c::172:D", TTL("10m")),
+  A("api", "130.117.76.13", TTL("10m")),
+  AAAA("api", "2001:978:2:2c::172:D", TTL("10m")),
+  A("maps", "130.117.76.13", TTL("10m")),
+  AAAA("maps", "2001:978:2:2c::172:D", TTL("10m")),
+  A("mapz", "130.117.76.13", TTL("10m")),
+  AAAA("mapz", "2001:978:2:2c::172:D", TTL("10m")),
+  A("spike-08.ams", "10.0.48.13"),
+  A("spike-08.oob", "10.0.49.13"),
+
+  // Rails application servers
+
+  A("thorn-01.ams", "10.0.48.51"),
+  A("rails1.ams", "10.0.48.51"),
+  A("thorn-01.oob", "10.0.49.51"),
+
+  A("thorn-02.ams", "10.0.48.52"),
+  A("rails2.ams", "10.0.48.52"),
+  A("thorn-02.oob", "10.0.49.52"),
+
+  A("thorn-03.ams", "10.0.48.53"),
+  A("rails3.ams", "10.0.48.53"),
+  A("thorn-03.oob", "10.0.49.53"),
+
+  A("thorn-04.bm", "10.0.32.41"),
+  A("rails4.bm", "10.0.32.41"),
+  A("thorn-04.oob", "10.0.33.41"),
+
+  A("thorn-05.bm", "10.0.32.42"),
+  A("rails5.bm", "10.0.32.42"),
+  A("thorn-05.oob", "10.0.33.42"),
+
+  // Nominatim servers
+
+  A("pummelzacken", "193.60.236.18"),
+  // A("nominatim", "193.60.236.18", TTL("10m")),
+  A("pummelzacken.ucl", "10.0.0.20"),
+  A("pummelzacken.oob", "10.0.1.20"),
+
+  A("dulcy", "130.117.76.9"),
+  AAAA("dulcy", "2001:978:2:2c::172:9"),
+  A("nominatim", "130.117.76.9", TTL("10m")),
+  AAAA("nominatim", "2001:978:2:2c::172:9", TTL("10m")),
+  A("dulcy.ams", "10.0.48.9"),
+  A("dulcy.oob", "10.0.49.9"),
+
+  // Taginfo server
+
+  A("grindtooth", "193.60.236.15"),
+  A("taginfo", "193.60.236.15", TTL("10m")),
+  A("grindtooth.ucl", "10.0.0.19"),
+  A("grindtooth.oob", "10.0.1.19"),
+
+  A("stormfly-01", "140.211.167.104"),
+  AAAA("stormfly-01", "2605:bc80:3010:700::8cde:a768"),
+  // A("taginfo", "140.211.167.104", TTL("10m")),
+  // AAAA("taginfo", "2605:bc80:3010:700::8cde:a768", TTL("10m")),
+  A("stormfly-01.oob", "10.0.0.99"),
+
+  // Tile servers
+
+  A("orm", "130.117.76.3"),
+  AAAA("orm", "2001:978:2:2c::172:3"),
+  A("orm.ams", "10.0.48.3"),
+  A("orm.oob", "10.0.49.3"),
+
+  A("odin", "130.117.76.15"),
+  AAAA("odin", "2001:978:2:2c::172:f"),
+  A("odin.ams", "10.0.48.15"),
+  A("odin.oob", "10.0.49.15"),
+
+  A("ysera", "193.60.236.22"),
+  A("ysera.ucl", "10.0.0.15"),
+  A("ysera.oob", "10.0.1.15"),
+
+  A("scorch", "176.31.235.79"),
+  AAAA("scorch", "2001:41d0:2:fc4f::1"),
+
+  A("rhaegal", "161.53.248.77"),
+
+  A("pyrene", "140.211.167.98"),
+  AAAA("pyrene", "2605:bc80:3010:700::8cd3:a762"),
+  A("pyrene.oob", "10.0.0.40"),
+
+  A("bowser", "138.44.68.106"),
+
+  CNAME("tile", QUALIFY("tile.geo")),
+  CNAME("a.tile", QUALIFY("tile.geo")),
+  CNAME("b.tile", QUALIFY("tile.geo")),
+  CNAME("c.tile", QUALIFY("tile.geo")),
+
+  // Services machine
+
+  A("ironbelly", "130.117.76.10"),
+  AAAA("ironbelly", "2001:978:2:2c::172:a"),
+  A("backup", "130.117.76.10", TTL("10m")),
+  AAAA("backup", "2001:978:2:2c::172:a", TTL("10m")),
+  A("planet", "130.117.76.10", TTL("10m")),
+  AAAA("planet", "2001:978:2:2c::172:a", TTL("10m")),
+  A("logstash", "130.117.76.10"),
+  AAAA("logstash", "2001:978:2:2c::172:a"),
+  A("ironbelly.ams", "10.0.48.10"),
+  A("ironbelly.oob", "10.0.49.10"),
+
+  A("grisu", "89.16.162.20"),
+  AAAA("grisu", "2001:41c9:2:d6::20"),
+  // A("backup", "89.16.162.20", TTL("10m")),
+  // AAAA("backup", "2001:41c9:2:d6::20", TTL("10m")),
+  // A("planet", "89.16.162.20", TTL("10m")),
+  // AAAA("planet", "2001:41c9:2:d6::20", TTL("10m")),
+  A("grisu.bm", "10.0.32.20"),
+  A("grisu.oob", "10.0.33.20"),
+
+  // Database servers
+
+  A("karm.ams", "10.0.48.50"),
+  A("karm.oob", "10.0.49.50"),
+
+  A("eddie.ucl", "10.0.0.10"),
+  A("eddie.oob", "10.0.1.10"),
+
+  A("katla.bm", "10.0.32.40"),
+  A("katla.oob", "10.0.33.40"),
+
+  A("ramoth.ams", "10.0.48.5"),
+  A("ramoth.oob", "10.0.49.5"),
+
+  // Development server with wildcard alias for user sites
+
+  A("errol", "193.60.236.13"),
+  A("dev", "193.60.236.13"),
+  A("*.dev", "193.60.236.13"),
+  A("ooc", "193.60.236.13"),
+  A("a.ooc", "193.60.236.13"),
+  A("b.ooc", "193.60.236.13"),
+  A("c.ooc", "193.60.236.13"),
+  A("npe", "193.60.236.13"),
+  A("errol.ucl", "10.0.0.14"),
+  A("errol.oob", "10.0.1.14"),
+
+  // Foundation server
+
+  A("ridley", "193.60.236.19"),
+  A("otrs", "193.60.236.19"),
+  A("blog", "193.60.236.19"),
+  A("foundation", "193.60.236.19"),
+  A("hot", "193.60.236.19"),
+  A("dmca", "193.60.236.19"),
+  A("ridley.ucl", "10.0.0.3"),
+  A("ridley.oob", "10.0.1.3"),
+
+  // Piwik server
+
+  A("eustace", "193.60.236.14"),
+  A("piwik", "193.60.236.14"),
+  A("eustace.ucl", "10.0.0.9"),
+  A("eustace.oob", "10.0.1.9"),
+
+  // Imagery servers
+
+  A("draco", "193.60.236.12"),
+  A("draco.ucl", "10.0.0.11"),
+  A("draco.oob", "10.0.1.11"),
+
+  A("kessie", "178.250.74.36"),
+  AAAA("kessie", "2a02:1658:4:0:dad3:85ff:fe5d:875e"),
+  A("agri", "178.250.74.36", TTL("1h")),
+  AAAA("agri", "2a02:1658:4:0:dad3:85ff:fe5d:875e", TTL("1h")),
+  A("a.agri", "178.250.74.36", TTL("1h")),
+  AAAA("a.agri", "2a02:1658:4:0:dad3:85ff:fe5d:875e", TTL("1h")),
+  A("b.agri", "178.250.74.36", TTL("1h")),
+  AAAA("b.agri", "2a02:1658:4:0:dad3:85ff:fe5d:875e", TTL("1h")),
+  A("c.agri", "178.250.74.36", TTL("1h")),
+  AAAA("c.agri", "2a02:1658:4:0:dad3:85ff:fe5d:875e", TTL("1h")),
+  A("os", "178.250.74.36", TTL("1h")),
+  AAAA("os", "2a02:1658:4:0:dad3:85ff:fe5d:875e", TTL("1h")),
+  A("a.os", "178.250.74.36", TTL("1h")),
+  AAAA("a.os", "2a02:1658:4:0:dad3:85ff:fe5d:875e", TTL("1h")),
+  A("b.os", "178.250.74.36", TTL("1h")),
+  AAAA("b.os", "2a02:1658:4:0:dad3:85ff:fe5d:875e", TTL("1h")),
+  A("c.os", "178.250.74.36", TTL("1h")),
+  AAAA("c.os", "2a02:1658:4:0:dad3:85ff:fe5d:875e", TTL("1h")),
+  A("kessie.oob", "178.250.74.37"),
+
+  // Munin server
+
+  A("urmel", "193.60.236.21"),
+  A("munin", "193.60.236.21"),
+  A("urmel.ucl", "10.0.0.6"),
+  A("urmel.oob", "10.0.1.6"),
+
+  // Chef server
+
+  A("sarel", "193.60.236.20"),
+  A("chef", "193.60.236.20"),
+  A("hardware", "193.60.236.20"),
+  A("acme", "193.60.236.20"),
+  A("git", "193.60.236.20", TTL("10m")),
+  A("dns", "193.60.236.20", TTL("10m")),
+  A("sarel.ucl", "10.0.0.12"),
+  A("sarel.oob", "10.0.1.12"),
+
+  // Forum server
+
+  A("clifford", "193.60.236.11"),
+  A("forum", "193.60.236.11", TTL("10m")),
+  A("clifford.ucl", "10.0.0.17"),
+  A("clifford.oob", "10.0.1.17"),
+
+  // KVMs
+
+  A("kvm1.ucl", "10.0.0.21"),
+
+  // Managed network switches
+
+  A("switch1", "130.117.76.2"),
+  AAAA("switch1", "2001:978:2:2c::172:2"),
+
+  // Managed power strips
+
+  A("pdu1.ams", "10.0.48.100"),
+  A("pdu2.ams", "10.0.48.101"),
+
+  // Bytemark machine, and the services which operate from it
+
+  A("shenron", "212.110.172.32"),
+  AAAA("shenron", "2001:41c9:1:400::32"),
+  A("mail", "212.110.172.32"),
+  AAAA("mail", "2001:41c9:1:400::32"),
+  A("mta-sts", "212.110.172.32"),
+  AAAA("mta-sts", "2001:41c9:1:400::32"),
+  A("lists", "212.110.172.32"),
+  AAAA("lists", "2001:41c9:1:400::32"),
+  A("svn", "212.110.172.32"),
+  AAAA("svn", "2001:41c9:1:400::32"),
+  A("trac", "212.110.172.32"),
+  AAAA("trac", "2001:41c9:1:400::32"),
+  A("irc", "212.110.172.32"),
+  AAAA("irc", "2001:41c9:1:400::32"),
+  A("help", "212.110.172.32"),
+  AAAA("help", "2001:41c9:1:400::32"),
+  A("blogs", "212.110.172.32", TTL("10m")),
+  AAAA("blogs", "2001:41c9:1:400::32", TTL("10m")),
+  A("shenron.bm", "10.0.16.3"),
+
+  // Wiki servers
+
+  A("ouroboros", "130.117.76.4"),
+  AAAA("ouroboros", "2001:978:2:2c::172:4"),
+  // A("wiki", "130.117.76.4", TTL("10m")),
+  // AAAA("wiki", "2001:978:2:2c::172:4", TTL("10m")),
+  A("ouroboros.ams", "10.0.48.4"),
+  A("ouroboros.oob", "10.0.49.4"),
+
+  A("tabaluga", "130.117.76.14"),
+  AAAA("tabaluga", "2001:978:2:2c::172:e"),
+  A("wiki", "130.117.76.14", TTL("10m")),
+  AAAA("wiki", "2001:978:2:2c::172:e", TTL("10m")),
+  A("tabaluga.ams", "10.0.48.14"),
+  A("tabaluga.oob", "10.0.49.14"),
+
+  // GPS tile server
+
+  A("noquiklos", "193.60.236.16"),
+  A("gps-tile", "193.60.236.16"),
+  A("a.gps-tile", "193.60.236.16"),
+  A("b.gps-tile", "193.60.236.16"),
+  A("c.gps-tile", "193.60.236.16"),
+  A("gps.tile", "193.60.236.16"),
+  A("gps-a.tile", "193.60.236.16"),
+  A("gps-b.tile", "193.60.236.16"),
+  A("gps-c.tile", "193.60.236.16"),
+  A("noquiklos.ucl", "10.0.0.13"),
+  A("noquiklos.oob", "10.0.1.13"),
+
+  // Tile cache servers
+
+  A("gorynych", "5.45.248.21"),
+  AAAA("gorynych", "2a02:6b8:b010:5065::a001"),
+  A("trogdor", "134.90.146.26"),
+  A("trogdor.oob", "134.90.146.30"),
+  A("ridgeback", "31.169.50.10"),
+  A("ridgeback.oob", "31.169.50.14"),
+  A("jakelong", "71.19.155.177"),
+  AAAA("jakelong", "2605:2700:0:17:a800:ff:fe3e:cdca"),
+  A("nepomuk", "77.95.65.39"),
+  AAAA("nepomuk", "2a03:9180:0:100::7"),
+  A("simurgh", "94.20.20.55"),
+  A("katie", "144.76.70.77"),
+  AAAA("katie", "2a01:4f8:191:834c::2"),
+  A("konqi", "81.7.11.83"),
+  AAAA("konqi", "2a02:180:1:1::517:b53"),
+  A("longma", "140.110.240.7"),
+  AAAA("longma", "2001:e10:2000:240::7"),
+  A("viserion", "193.198.233.211"),
+  AAAA("viserion", "2001:b68:4cff:3::3"),
+  A("drogon", "161.53.30.107"),
+  AAAA("drogon", "2001:b68:c0ff:0:221:5eff:fe40:c7c4"),
+  A("saphira", "185.73.44.30"),
+  AAAA("saphira", "2001:ba8:0:2c1e::"),
+  A("toothless", "185.73.44.167"),
+  AAAA("toothless", "2001:ba8:0:2ca7::"),
+  A("sarkany", "37.17.173.8"),
+  AAAA("sarkany", "2001:4c48:2:bf04:250:56ff:fe8f:5c81"),
+  A("cmok", "31.130.201.40"),
+  AAAA("cmok", "2001:67c:2268:1005:21e:8cff:fe8c:8d3b"),
+  A("stormfly-02", "140.211.167.105"),
+  AAAA("stormfly-02", "2605:bc80:3010:700::8cde:a769"),
+  A("stormfly-02.oob", "10.0.0.108"),
+  A("rimfaxe", "130.225.254.109"),
+  AAAA("rimfaxe", "2001:878:346::109"),
+  A("culebre", "155.210.4.103"),
+  A("kalessin", "185.66.195.245"),
+  AAAA("kalessin", "2a03:2260:2000:1::5"),
+  A("angor", "196.10.54.165"),
+  // AAAA("angor", "2001:43f8:1f4:b00:b283:feff:fed8:dd45"),
+  A("ladon", "83.212.2.116"),
+  AAAA("ladon", "2001:648:2ffe:4::116"),
+  A("ascalon", "184.107.48.228"),
+  A("noomoahk", "91.224.148.166"),
+  AAAA("noomoahk", "2a03:7220:8080:a600::1"),
+  A("cherufe", "200.91.44.37"),
+  A("norbert", "89.234.186.100"),
+  AAAA("norbert", "2a00:5884:821c::1"),
+  A("chrysophylax", "217.71.244.22"),
+  AAAA("chrysophylax", "2001:8e0:40:2039::10"),
+  A("necrosan", "80.67.167.77"),
+  AAAA("necrosan", "2a0b:cbc0:110d:1::1c"),
+  A("keizer", "195.201.226.63"),
+  AAAA("keizer", "2a01:4f8:1c1c:bc54::1"),
+  A("vipertooth", "176.122.99.101"),
+  AAAA("vipertooth", "2001:67c:2d40::65"),
+  A("tuatara", "114.23.141.203"),
+  AAAA("tuatara", "2406:1e00:b410:c24:529a:4cff:fe79:bc3b"),
+  A("waima", "103.197.61.160"),
+  A("nidhogg", "130.236.254.221"),
+  AAAA("nidhogg", "2001:6b0:17:f0a0::dd"),
+  A("boitata", "200.236.31.207"),
+  AAAA("boitata", "2801:82:80ff:8002:216:ccff:feaa:21"),
+  A("fafnir", "130.239.18.114"),
+  AAAA("fafnir", "2001:6b0:e:2a18::114"),
+  A("fume", "147.228.60.16"),
+  A("balerion", "138.44.68.134"),
+  A("naga", "185.116.130.151"),
+
+  // Blades
+
+  A("tiamat-00", "193.60.236.40"),
+  A("tiamat-00.ucl", "10.0.0.40"),
+  A("tiamat-00.oob", "10.0.1.40"),
+  A("tiamat-01", "193.60.236.41"),
+  A("tiamat-01.ucl", "10.0.0.41"),
+  A("tiamat-01.oob", "10.0.1.41"),
+  A("tiamat-02", "193.60.236.42"),
+  A("tiamat-02.ucl", "10.0.0.42"),
+  A("tiamat-02.oob", "10.0.1.42"),
+  A("tiamat-03", "193.60.236.43"),
+  A("tiamat-03.ucl", "10.0.0.43"),
+  A("tiamat-03.oob", "10.0.1.43"),
+  A("tiamat-10", "193.60.236.44"),
+  A("tiamat-10.ucl", "10.0.0.44"),
+  A("tiamat-10.oob", "10.0.1.44"),
+  A("tiamat-11", "193.60.236.45"),
+  A("tiamat-11.ucl", "10.0.0.45"),
+  A("tiamat-11.oob", "10.0.1.45"),
+  A("tiamat-12", "193.60.236.46"),
+  A("tiamat-12.ucl", "10.0.0.46"),
+  A("tiamat-12.oob", "10.0.1.46"),
+  A("tiamat-13", "193.60.236.47"),
+  A("tiamat-13.ucl", "10.0.0.47"),
+  A("tiamat-13.oob", "10.0.1.47"),
+  A("tiamat-20", "193.60.236.48"),
+  A("tiamat-20.ucl", "10.0.0.48"),
+  A("tiamat-20.oob", "10.0.1.48"),
+  A("tiamat-21", "193.60.236.49"),
+  A("tiamat-21.ucl", "10.0.0.49"),
+  A("tiamat-21.oob", "10.0.1.49"),
+  A("tiamat-22", "193.60.236.50"),
+  A("tiamat-22.ucl", "10.0.0.50"),
+  A("tiamat-22.oob", "10.0.1.50"),
+  A("tiamat-23", "193.60.236.51"),
+  A("tiamat-23.ucl", "10.0.0.51"),
+  A("tiamat-23.oob", "10.0.1.51"),
+
+  // Donation site
+
+  A("donate", "193.60.236.19", TTL("10m")),
+
+  // Uptime site at StatusCake
+
+  CNAME("uptime", "uptimessl.statuscake.com."),
+
+  // Custom Domain for https://github.com/osmfoundation/welcome-mat/
+
+  CNAME("welcome", "osmfoundation.github.io."),
+
+  // Dynamic DNS records
+
+  DYNAMIC_RECORDS
+
+);
diff --git a/src/osmfoundation.js b/src/osmfoundation.js
new file mode 100644 (file)
index 0000000..86c3f2b
--- /dev/null
@@ -0,0 +1,59 @@
+D(DOMAIN, REGISTRAR, DnsProvider(PROVIDER),
+
+  // Publish CAA records indicating that only letsencrypt should issue certificates
+
+  CAA("@", "issue", "letsencrypt.org", CF_TTL_ANY),
+  CAA("@", "issuewild", "letsencrypt.org", CF_TTL_ANY),
+  CAA("@", "iodef", "mailto:hostmaster@openstreetmap.org"),
+
+  // Let google handle email
+
+  MX("@", 1, "aspmx.l.google.com.", TTL("1h")),
+  MX("@", 5, "alt1.aspmx.l.google.com.", TTL("1h")),
+  MX("@", 5, "alt2.aspmx.l.google.com.", TTL("1h")),
+  MX("@", 10, "alt3.aspmx.l.google.com.", TTL("1h")),
+  MX("@", 10, "alt4.aspmx.l.google.com.", TTL("1h")),
+
+  // Handle mail for the join subdomain ourselves
+
+  MX("join", 10, "a.mx.openstreetmap.org."),
+
+  // SPF policy
+
+  TXT("@", "v=spf1 ip4:212.110.172.32 ip6:2001:41c9:1:400::32 a mx include:_spf.google.com -all"),
+
+  // DKIM key
+
+  TXT("google._domainkey", "v=DKIM1; k=rsa; p=MIGfMA0GCSqGSIb3DQEBAQUAA4GNADCBiQKBgQCJmTBAkYRCocCCNtVsdRNMlQel8kNfjPYJpjEm7woEgZh9yZeDzxImtz+u73oUF4+7bXzrNYbP946WNQIwAba1J69he8L1qfPBJLd3Z/fgmuaGdWcxpDno2EY4cQ8PrzvI6Vfm+6YAFANl8w09CIg41ykdlzH4iUJXD35k3SIl3wIDAQAB", TTL("15m")),
+
+  // XMPP chat servers
+
+  SRV("_xmpp-server._tcp", 5, 0, 5269, "xmpp-server.l.google.com."),
+  SRV("_xmpp-server._tcp", 20, 0, 5269, "xmpp-server1.l.google.com."),
+  SRV("_xmpp-server._tcp", 20, 0, 5269, "xmpp-server2.l.google.com."),
+  SRV("_xmpp-server._tcp", 20, 0, 5269, "xmpp-server3.l.google.com."),
+  SRV("_xmpp-server._tcp", 20, 0, 5269, "xmpp-server4.l.google.com."),
+
+  // Aliases for google services
+
+  CNAME("login", "ghs.google.com."),
+  CNAME("docs", "ghs.google.com."),
+  CNAME("mail", "ghs.google.com."),
+  CNAME("calendar", "ghs.google.com."),
+  CNAME("sites", "ghs.google.com."),
+
+  // Main web server and it's aliases
+
+  A("@", "193.60.236.19", TTL("10m")),
+  A("old", "193.60.236.19", TTL("10m")),
+  A("www", "193.60.236.19", TTL("10m")),
+  A("wiki", "193.60.236.19", TTL("10m")),
+  A("blog", "193.60.236.19", TTL("10m")),
+  A("crm", "193.60.236.19", TTL("10m")),
+  A("join", "193.60.236.19", TTL("10m")),
+  A("board", "193.60.236.19", TTL("10m")),
+  A("dwg", "193.60.236.19", TTL("10m")),
+  A("mwg", "193.60.236.19", TTL("10m")),
+  A("operations", "193.60.236.19", TTL("10m"))
+
+);
diff --git a/src/stateofthemap.js b/src/stateofthemap.js
new file mode 100644 (file)
index 0000000..47076f5
--- /dev/null
@@ -0,0 +1,38 @@
+D(DOMAIN, REGISTRAR, DnsProvider(PROVIDER),
+
+  // Publish CAA records indicating that only letsencrypt should issue certificates
+
+  CAA("@", "issue", "letsencrypt.org", CF_TTL_ANY),
+  CAA("@", "issuewild", "letsencrypt.org", CF_TTL_ANY),
+  CAA("@", "iodef", "mailto:hostmaster@openstreetmap.org"),
+
+  // Let google handle email
+
+  MX("@", 1, "aspmx.l.google.com.", TTL("1h")),
+  MX("@", 5, "alt1.aspmx.l.google.com.", TTL("1h")),
+  MX("@", 5, "alt2.aspmx.l.google.com.", TTL("1h")),
+  MX("@", 10, "alt3.aspmx.l.google.com.", TTL("1h")),
+  MX("@", 10, "alt4.aspmx.l.google.com.", TTL("1h")),
+
+  // Aliases for google services
+
+  CNAME("login", "ghs.google.com."),
+
+  // Main web server and it's aliases
+
+  A("@", "193.60.236.19", TTL("10m")),
+  A("www", "193.60.236.19", TTL("10m")),
+  A("2020", "193.60.236.19", TTL("10m")),
+  A("2019", "193.60.236.19", TTL("10m")),
+  A("2018", "193.60.236.19", TTL("10m")),
+  A("2017", "193.60.236.19", TTL("10m")),
+  A("2016", "193.60.236.19", TTL("10m")),
+  A("2014", "193.60.236.19", TTL("10m")),
+  A("2013", "193.60.236.19", TTL("10m")),
+  A("2011", "193.60.236.19", TTL("10m")),
+  A("2010", "193.60.236.19", TTL("10m")),
+  A("2009", "193.60.236.19", TTL("10m")),
+  A("2008", "193.60.236.19", TTL("10m")),
+  A("2007", "193.60.236.19", TTL("10m"))
+
+);
diff --git a/src/switch2osm.js b/src/switch2osm.js
new file mode 100644 (file)
index 0000000..38422fa
--- /dev/null
@@ -0,0 +1,14 @@
+D(DOMAIN, REGISTRAR, DnsProvider(PROVIDER),
+
+  // Publish CAA records indicating that only letsencrypt should issue certificates
+
+  CAA("@", "issue", "letsencrypt.org", CF_TTL_ANY),
+  CAA("@", "issuewild", "letsencrypt.org", CF_TTL_ANY),
+  CAA("@", "iodef", "mailto:hostmaster@openstreetmap.org"),
+
+  // Main web server and it's aliases
+
+  A("@", "193.60.236.19", TTL("10m")),
+  A("www", "193.60.236.19", TTL("10m"))
+
+);