<style>
#custom-dns-current td.long {
  word-break: break-all;
}
</style>

<h2>Custom DNS</h2>

<p class="text-warning">This is an advanced configuration page.</p>

<p>It is possible to set custom DNS records on domains hosted here.</p>

<h3>Set Custom DNS Records</h3>

<p>You can set additional DNS records, such as if you have a website running on another server, to add DKIM records for external mail providers, or for various confirmation-of-ownership tests.</p>

<form class="form-horizontal" role="form" onsubmit="do_set_custom_dns(); return false;">
  <div class="form-group">
    <label for="customdnsQname" class="col-sm-1 control-label">Name</label>
    <div class="col-sm-10">
      <table style="max-width: 400px">
      <tr><td>
        <input type="text" class="form-control" id="customdnsQname" placeholder="subdomain">
      </td><td style="padding: 0 1em; font-weight: bold;">.</td><td>
        <select id="customdnsZone" class="form-control"> </select>
      </td></tr></table>
      <div class="text-info" style="margin-top: .5em">Leave the left field blank to set a record on the chosen domain name, or enter a subdomain.</div>
    </div>
  </div>
  <div class="form-group">
    <label for="customdnsType" class="col-sm-1 control-label">Type</label>
    <div class="col-sm-10">
      <select id="customdnsType" class="form-control" style="max-width: 400px" onchange="show_customdns_rtype_hint()">
        <option value="A" data-hint="Enter an IPv4 address (i.e. a dotted quad, such as 123.456.789.012).">A (IPv4 address)</option>
        <option value="AAAA" data-hint="Enter an IPv6 address.">AAAA (IPv6 address)</option>
        <option value="CNAME" data-hint="Enter another domain name followed by a period at the end (e.g. mypage.github.io.).">CNAME (DNS forwarding)</option>
        <option value="TXT" data-hint="Enter arbitrary text.">TXT (text record)</option>
        <option value="MX" data-hint="Enter record in the form of PRIORIY DOMAIN., including trailing period (e.g. 20 mx.example.com.).">MX (mail exchanger)</option>
      </select>
    </div>
  </div>
  <div class="form-group">
    <label for="customdnsValue" class="col-sm-1 control-label">Value</label>
    <div class="col-sm-10">
      <input type="text" class="form-control" id="customdnsValue" placeholder="">
      <div id="customdnsTypeHint" class="text-info" style="margin-top: .5em"></div>
    </div>
  </div>
  <div class="form-group">
    <div class="col-sm-offset-1 col-sm-11">
      <button type="submit" class="btn btn-primary">Set Record</button>
    </div>
  </div>
</form>

<table id="custom-dns-current" class="table" style="width: auto; display: none">
  <thead>
    <th>Domain Name</th>
    <th>Record Type</th>
    <th>Value</th>
    <th></th>
  </thead>
  <tbody>
    <tr><td colspan="4">Loading...</td></tr>
  </tbody>
</table>

<h3>Using a Secondary Nameserver</h3>

<p>If your TLD requires you to have two separate nameservers, you can either set up a secondary (aka &ldquo;slave&rdquo;) nameserver or, alternatively, set up <a href="#" onclick="return show_panel('external_dns')">external DNS</a> and ignore the DNS server on this box. If you choose to use a seconday/slave nameserver, you must find a seconday/slave nameserver service provider. Your domain name registrar or virtual cloud provider may provide this service for you. Once you set up the seconday/slave nameserver service, enter the hostname of <em>their</em> secondary nameserver:</p>

<form class="form-horizontal" role="form" onsubmit="do_set_secondary_dns(); return false;">
  <div class="form-group">
    <label for="secondarydnsHostname" class="col-sm-1 control-label">Hostname</label>
    <div class="col-sm-10">
      <input type="text" class="form-control" id="secondarydnsHostname" placeholder="ns1.cloudprovider.com">
    </div>
  </div>
  <div class="form-group">
    <div class="col-sm-offset-1 col-sm-11">
      <button type="submit" class="btn btn-primary">Update</button>
    </div>
  </div>
  <div id="secondarydns-clear-instructions" class="form-group" style="display: none">
    <div class="col-sm-offset-1 col-sm-11">
      <p class="small">Clear the input field above and click Update to use this machine itself as secondary DNS, which is the default/normal setup.</p>
    </div>
  </div>
</form>


<h3>Custom DNS API</h3>

<p>Use your box&rsquo;s DNS API to set custom DNS records on domains hosted here. For instance, you can create your own dynamic DNS service.</p>

<p>Send a POST request like this:</p>

<pre>curl -d "" --user {email}:{password} https://{{hostname}}/admin/dns/set/<b>qname</b>[/<b>rtype</b>[/<b>value</b>]]</pre>

<h4>HTTP POST parameters</h4>

<table class="table">
<thead><th>Parameter</th> <th>Value</th></thead>
<tr><td>email</td> <td>The email address of any administrative user here.</td></tr>
<tr><td>password</td> <td>That user&rsquo;s password.</td></tr>
<tr><td>qname</td> <td>The fully qualified domain name for the record you are trying to set.</td></tr>
<tr><td>rtype</td> <td>The resource type. <code>A</code> if omitted. Possible values: <code>A</code> (an IPv4 address), <code>AAAA</code> (an IPv6 address), <code>TXT</code> (a text string), or <code>CNAME</code> (an alias, which is a fully qualified domain name).</td></tr>
<tr><td>value</td> <td>The new record&rsquo;s value. If omitted, the IPv4 address of the remote host is used. This is handy for dynamic DNS! To delete a record, use &ldquo;__delete__&rdquo;.</td></tr>
</table>

<p style="margin-top: 1em">Note that <code>-d ""</code> is merely to ensure curl sends a POST request. You do not need to put anything inside the quotes. You can also pass the value using typical form encoding in the POST body.</p>

<p>Strict <a href="http://tools.ietf.org/html/rfc4408">SPF</a> and <a href="https://datatracker.ietf.org/doc/draft-kucherawy-dmarc-base/?include_text=1">DMARC</a> records will be added to all custom domains unless you override them.</p>

<h4>Examples:</h4>

<pre># sets laptop.mydomain.com to point to the IP address of the machine you are executing curl on
curl -d "" --user me@mydomain.com:###### https://{{hostname}}/admin/dns/set/laptop.mydomain.com

# sets an alias
curl -d "" --user me@mydomain.com:###### https://{{hostname}}/admin/dns/set/foo.mydomain.com/cname/bar.mydomain.com

# clears the alias
curl -d "" --user me@mydomain.com:###### https://{{hostname}}/admin/dns/set/bar.mydomain.com/cname/__delete__

# sets a TXT record using the alternate value syntax
curl -d "value=something%20here" --user me@mydomain.com:###### https://{{hostname}}/admin/dns/set/foo.mydomain.com/txt

# sets a <a href="http://en.wikipedia.org/wiki/SRV_record">SRV record</a> for the "service" and "protocol" hosted on "target" server
curl -d "" --user me@mydomain.com:###### https://{{hostname}}/admin/dns/set/_service._protocol.{{hostname}}/srv/"priority weight port target"

# sets a SRV record using the value syntax
curl -d "value=priority weight port target" --user me@mydomain.com:###### https://{{hostname}}/admin/dns/set/_service._protocol.host/srv
</pre>

<script>
function show_custom_dns() {
  api(
    "/dns/secondary-nameserver",
    "GET",
    { },
    function(data) {
      $('#secondarydnsHostname').val(data.hostname ? data.hostname : '');
      $('#secondarydns-clear-instructions').toggle(data.hostname != null);
    });

  api(
    "/dns/zones",
    "GET",
    { },
    function(data) {
      $('#customdnsZone').text('');
      for (var i = 0; i < data.length; i++) {
        $('#customdnsZone').append($('<option/>').text(data[i]));
      }
    });

  show_current_custom_dns();
  show_customdns_rtype_hint();
}

function show_current_custom_dns() {
  api(
    "/dns/set",
    "GET",
    { },
    function(data) {
      if (data.length > 0)
        $('#custom-dns-current').fadeIn();
      else
        $('#custom-dns-current').fadeOut();

      $('#custom-dns-current').find("tbody").text('');
      for (var i = 0; i < data.length; i++) {
        var tr = $("<tr/>");
        $('#custom-dns-current').find("tbody").append(tr);
        tr.attr('data-qname', data[i].qname);
        tr.attr('data-rtype', data[i].rtype);
        tr.append($('<td class="long"/>').text(data[i].qname));
        tr.append($('<td/>').text(data[i].rtype));
        tr.append($('<td class="long"/>').text(data[i].value));
        tr.append($('<td>[<a href="#" onclick="return delete_custom_dns_record(this)">delete</a>]</td>'));
      }
    });
}

function delete_custom_dns_record(elem) {
  var qname = $(elem).parents('tr').attr('data-qname');
  var rtype = $(elem).parents('tr').attr('data-rtype');
  do_set_custom_dns(qname, rtype, "__delete__");
  return false;
}

function do_set_secondary_dns() {
 api(
    "/dns/secondary-nameserver",
    "POST",
    {
      hostname: $('#secondarydnsHostname').val()
    },
    function(data) {
      if (data == "") return; // nothing updated
      show_modal_error("Secondary DNS", $("<pre/>").text(data));
      $('#secondarydns-clear-instructions').slideDown();
    },
    function(err) {
      show_modal_error("Secondary DNS", $("<pre/>").text(err));
    });
}

function do_set_custom_dns(qname, rtype, value) {
  if (!qname) {
    if ($('#customdnsQname').val() != '')
      qname = $('#customdnsQname').val() + '.' + $('#customdnsZone').val();
    else
      qname = $('#customdnsZone').val();
    rtype = $('#customdnsType').val();
    value = $('#customdnsValue').val();
  }

  api(
    "/dns/set/" + qname + "/" + rtype,
    "POST",
    {
      value: value
    },
    function(data) {
      if (data == "") return; // nothing updated
      show_modal_error("Custom DNS", $("<pre/>").text(data));
      show_current_custom_dns();
    },
    function(err) {
      show_modal_error("Custom DNS", $("<pre/>").text(err));
    });
}

function show_customdns_rtype_hint() {
  $('#customdnsTypeHint').text($("#customdnsType").find('option:selected').attr('data-hint'));
}
</script>