Lightweight API driven Authoritative DNS server. Extracted from Project Pending.

Source can be found from Github.





$ npm install --production
$ npm start

Run as SystemD service

If you want to run PendingDNS as a SystemD service, then there's an example service file with comments.

1. Setup commands

As root run the following commands to set up PendingDNS:

$ cd /opt
$ git clone git://
$ cd pending-dns
$ npm install --production
$ cp systemd/pending-dns.service /etc/systemd/system
$ cp config/default.toml /etc/pending-dns.toml

2. Configuration

Edit the configuration file /etc/pending-dns.toml and make sure that you have correct configuration.

Also make sure that /etc/systemd/system/pending-dns.service looks correct.

3. Start

Run the following commands as root

$ systemctl enable pending-dns
$ systemctl start pending-dns

General Name Server setup

Conflicts on port 53

There might be already a recursive DNS server listening on (or more commonly, SystemD stub resolver on so you can't bind your DNS server to Instead bind directly to your outbound interface, you can usually find these by running ip a.

$ ip a
  inet brd scope global ens5
  port = 53
  host = ""

Glue records

If you want to use PendingDNS as an authoritative DNS server for your domains then you need at least 2 instances of the server.

Additionally you need to set up both A and so-called GLUE records for the domain names of your name servers. Not all DNS providers allow to set GLUE records.

Here's an example how A records are set up for and that manage domains hosted on Project Pending:

Registrar and DNS provider for these domains is OVH but you can use any registrar with GLUE support

And the corresponding GLUE records:

Without proper setup domain registrars do not allow your name server domain names to be used. Here's an example for a successful name server setup:


You can see the entire API docs from the swagger page at

List Zone entries

GET /v1/zone/{zone}/records

$ curl -X GET ""
    "zone": "",
    "records": [
            "id": "Y29tLm1haWx0YW5rZXIBQQEzc3lKWkkzbGo",
            "type": "A",
            "address": ""
            "id": "Y29tLm1haWx0YW5rZXIud3d3AUNOQU1FAXhhV1lnbnFaMA",
            "type": "CNAME",
            "subdomain": "www",
            "target": ""

NB! system records (NS, SOA) have id=null and these records can not be modified over API

Create new Resource Record

POST /v1/zone/{zone}/records

$ curl -X POST "" -H "Content-Type: application/json" -d '{
    "subdomain": "www",
    "type": "CNAME",
    "target": "@"
    "zone": "",
    "record": "Y29tLm1haWx0YW5rZXIud3d3AUNOQU1FAXhhV1lnbnFaMA"

All record types have the following properties

Type specific options










Modify existing Resource Record

PUT /v1/zone/{zone}/records/{record}

$ curl -X PUT "" -H "Content-Type: application/json" -d '{
    "subdomain": "www",
    "type": "CNAME",
    "target": ""
    "zone": "",
    "record": "Y29tLm1haWx0YW5rZXIud3d3AUNOQU1FAXhhV1lnbnFaMA"

NB! resulting record ID might be different from the original ID

Delete Resource Record

DELETE /v1/zone/{zone}/records/{record}

$ curl -X DELETE ""
    "zone": "",
    "record": "Y29tLm1haWx0YW5rZXIBQQFjT2NWd0d6bE4",
    "deleted": true

Generate Certificate

This API endpoint requests a new certificate from Let's Encrypt or returns a previously generated one.

Certificates can only be requested for domains that:

  1. have at least one resource record set for their zone (not important which kind)
  2. have correctly pointed NS records to your PendingDNS servers
$ curl -X POST "" -H "Content-Type: application/json" -d '{
    "domains": [
    "dnsNames": ["*", ""],
    "key": "-----BEGIN RSA PRIVATE KEY-----\nMIIEpAIB...",
    "cert": "-----BEGIN CERTIFICATE-----\nMIIFaT...\n",
    "validFrom": "2020-06-03T18:50:52.000Z",
    "expires": "2020-09-01T18:50:52.000Z"