Documentation

Welcome to LuaDNS!

LuaDNS is a DNS hosting platform which allows easy DNS management (domains and records) and deployment through Git (optional).

Getting Started

In order to use this service you'll need a LuaDNS account, sign up for a free account here:

https://app.luadns.com/users/register

Git Integration

The git integration is a convenient way to manage your DNS settings, it allows you to keep all your zones and records in the repository and deploy changes automatically to our name servers when you are pushing the changes with git, see example repository.

After each git push our build system will pull DNS settings from your git repository. Your configuration files are parsed, validated and then DNS zones and records are distributed to our name servers. You'll receive an email with the build status.

To use git integration, you need to follow this steps:

  1. Set the repository URL in your the settings page.
  2. Configure your repository to grant read-only access when accessed with your build key, (this is optional if your git repository is public).
  3. Configure your repository to issue a POST request on each push to https://api.luadns.com/notifications/YOUR_API_KEY/push,
    you'll find your API key on API Keys page.

GitHub

  1. Access your settings page and set repository.
  2. Access GitHub -> Repository -> Settings -> Deploy keys and add your LuaDNS deploy key there.
  3. Access GitHub -> Repository -> Settings -> Webhooks and add a new webhook:

Bitbucket

  1. Access your settings page and set git repository.
  2. Bitbucket -> Repository -> Settings -> Access keys and add your LuaDNS deploy key there.
  3. Bitbucket -> Repository -> Settings -> Webhooks and add a new webhook:

Gitea/Gogs

  1. Access your settings page and set git repository.
  2. Access Gitea -> Repository -> Settings -> Deploy Keys and add your LuaDNS deploy key there.
  3. Access Gitea -> Repository -> Settings -> Webhooks and add a Gitea Webhook:

Example Repository

An example repository can be found here: https://github.com/luadns/dns

Troubleshooting

Use curl to trigger a manual rebuild of your zones:

$ curl -X POST https://api.luadns.com/notifications/YOUR_API_KEY/push

DNSSEC

You can improve domain security by enabling DNSSEC, this allows you to digitally sign your DNS records.

To start using DNSSEC you must enable it from the zone settings page. When DNSSEC is enabled, a pair of DNSKEY will be generated automatically: KSK (Key Signing Key) and ZSK (Zone Signing Key). The zone is signed and distributed to our name servers to be served right away.

The KSK is used to sign DNSKEY records and ZSK is used to sign other records. Using two keys together allows us to roll a new ZSK without updating the DS record in the parent zone.

Before enabling DNSSEC check that your registrar supports DS records with algorithm 13 (ECDSA Curve P-256 with SHA-256).

Some registries supports automated DNSSEC provisioning via CDS/CDNSKEY record signaling (RFC 7344). We support CDS & CDNSKEY records, they are generated automatically when DNSSEC is enabled.

Lua Zone File Format

Users have the option to store their configurations in a standard Bind format or to use more powerful Lua format.

Resource Records

LuaDNS supports most common Resource Records:

AAAA, ALIAS, A, CNAME, DS, FORWARD, HTTPS, MX, NS, PTR, REDIRECT, SOA, SPF, SRV, SSHFP, TLSA, TXT

A Record

A Record Syntax:

-- @name  = relative name
-- @ip    = IPv4 address
-- @ttl   = TTL (default: user default TTL)
a(name, ip, ttl)

Example:

a("mail", "1.2.3.4")

AAAA Record

AAAA Record Syntax:

-- @name  = relative name
-- @ip    = IPv6 address
-- @ttl   = TTL (default: user default TTL)
aaaa(name, ip, ttl)

Example:

aaaa("mail", "2001:4860:4860::8888")

ALIAS Record

ALIAS Record Syntax:

-- @name   = relative name
-- @target = target host (fqdn)
-- @ttl    = TTL (default: user default TTL)
alias(name, target, ttl)

This record is suited to solve the DNS restriction with CNAME on apex (root, naked) domains.

The system creates A and AAAA records for name with the IP addresses found while resolving target. The target is polled periodically and the A and AAAA records are updated when changes are detected.

Example:

alias(_a, "myapp.herokuapp.com")

CAA Record

CAA Record Syntax:

-- @name    = relative name
-- @value   = value
-- @tag     = tag (issue, issuewild, iodef, default: issue)
-- @flag    = flag (default: 0)
-- @ttl     = TTL (default: user default TTL)
caa(name, value, tag, flag, ttl)

Example:

caa("", "letsencrypt.org", "issue")
caa("", "mailto:user@example.com", "iodef")

CNAME Record

CNAME Record Syntax:

-- @name    = relative name
-- @alias   = alias (fqdn)
-- @ttl     = TTL (default: user default TTL)
cname(name, alias, ttl)

Example:

cname("www", "example.com")

DS Record

DS Record Syntax:

-- @name        = relative name
-- @keytag      = key tag
-- @digest      = digest (hexadecimal characters)
-- @algorithm   = algorithm (default: 13)
-- @digest_type = digest type (default: 2)
-- @ttl         = TTL (default: user default TTL)
ds(name, keytag, digest, algorithm, digest_type, ttl)

Example:

-- Add a DS record for `us` subdomain using default values for
-- algorithm (13 = ECDSAP256SHA256) and digest type (2 = SHA256).
ds("us", 22021, "D657C7EE6B88F0F4163B69BE8B4DCBEAEC32DA3C3E8AA5B62F6E630D97A7DDEF")

FORWARD Record

The FORWARD pseudo record configures LuaDNS mail servers to accept and forward emails to an external email provider.

FORWARD Record Syntax:

-- @from    = mailbox name (without domain)
-- @to      = recipient (email address)
-- @ttl     = cache TTL (default: user default TTL)
forward(from, to, ttl)

Example:

-- File: example.com.lua
-- _a variable is set by the system to zone name
-- _a = "example.com"

-- Forward mailbox `joe@example.com` to `bob@mailinator.com`.
forward("bob", "bob@mailinator.com")

-- Catch-all forward.
-- Forward all unmatched mailboxes to alice@mailinator.com.
forward("*", "alice@mailinator.com")

HTTPS Record

HTTPS Record Syntax:

-- @name       = relative name
-- @target     = target (fqdn)
-- @svc_prio   = priority (default: 0)
-- @svc_params = params table (default: {})
-- @ttl        = TTL (default: user default TTL)
https(name, target, svc_prio, svc_params, ttl)

The svc_prio parameter specifies

  • when == 0 - alias mode
  • when != 0 - service mode

The svc_params is a list of key=value pairs. Supported keys:

  • alpn
  • ech
  • ipv4hint
  • ipv6hint
  • mandatory
  • no-default-alpn
  • port

Example:

-- File: example.com.lua
-- _a variable is set by the system to zone name
-- _a = "example.com"

-- Create an alias for apex/root domain.
https(_a, "lb.cdn-example.net")

-- Create a failover config (lower prio numbers have higher priority).
https("www", "svc1.example.net", 10, {alpn="http/1.1,h2"})
https("www", "svc2.example.net", 20, {alpn="http/1.1,h2"})

-- Configure Encrypted Client Hello (ECH).
https("app", "svc3.example.net", 1, {alpn="http/1.1,h2", ech="base64_public_key"})

MX Record

MX Record Syntax:

-- @name      = relative name
-- @exchanger = mail exchanger(fqdn)
-- @prio      = priority (default: 0)
-- @ttl       = TTL (default: user default TTL)
mx(name, exchanger, prio, ttl)

Example:

-- File: example.com.lua
-- _a variable is set by the system to zone name
-- _a = "example.com"
mx(_a, "aspmx.l.google.com", 10)

NS Record

NS Record Syntax:

-- @name    = relative name
-- @server  = name server (fqdn)
-- @ttl     = TTL (default: user default TTL)
ns(name, server, ttl)

Name servers are automatically added for each zone found in the repository, you don't have to specify them.

Example:

-- File: example.com.lua
-- delegate uk.example.com to uk-ns1.example.com, uk-ns2.example.com name servers
ns("uk", "uk-ns1.example.com")
ns("uk", "uk-ns2.example.com")

PTR Record

PTR Record Syntax:

-- @name  = relative name
-- @host  = host name (fqdn)
-- @ttl   = TTL (default: user default TTL)
ptr(name, host, ttl)

Example:

-- File: 1.168.192.in-addr.arpa.lua
ptr("1", "server.example.com")
-- File: 0.0.0.0.0.0.0.0.0.0.0.0.0.0.0.0.0.0.0.0.0.0.0.0.0.0.0.0.0.0.0.ip6.arpa.lua
ptr("1", "localhost.example.com")

REDIRECT Record

The REDIRECT pseudo record configures the DNS servers and HTTP redirection service to allow easy HTTP redirections.

REDIRECT Record Syntax:

-- @name   = relative name
-- @target = target url
-- @mode   = redirect mode (0=relative, 1=exact, 2=frame, default: 0)
-- @ttl    = cache TTL (default: user default TTL)
redirect(name, target, mode, ttl)

The mode parameter specifies how the name is going to be redirected to target:

  • 0 - relative mode, server appends the path and query string to target and issues a 301 redirect
  • 1 - exact mode, server issues a 301 redirect to target URL
  • 2 - frame mode, server returns a HTML page which loads the the target URL in a frame

Example:

-- File: example.com.lua
-- _a variable is set by the system to zone name
-- _a = "example.com"

-- Default mode (301 redirect)
-- Redirect http://example.com/* to http://www.example.com/*
--   http://example.com/foo => http://www.example.com/foo
--   http://example.com/foo?param=bar => http://www.example.com/foo?param=bar
redirect(_a, "http://www.example.com/")

-- Exact mode (301 redirect)
-- Redirect http://app.example.com/* to https://secure.example.com/home
--   http://app.example.com/foo => https://secure.example.com/home
--   http://app.example.com/foo?param=bar => https://secure.example.com/home
redirect("app", "https://secure.example.com/home", 1)

-- Frame mode
-- Returns a page which loads http://www.example.net/webmail in a frame
--   http://webmail.example.com/ => http://www.example.net/webmail
redirect("webmail", "http://www.example.net/webmail", 2)

SOA Record

SOA record it's created by automatically by the system, you don't have to specify one.

SPF Record

SPF Record Syntax:

-- @name    = relative name
-- @text    = text
-- @ttl     = TTL (default: user default TTL)
spf(name, text, ttl)

Example:

-- File: example.com.lua
-- _a variable is set by the system to zone name
-- _a = "example.com"
spf(_a, "v=spf1 a mx include:_spf.google.com ~all")

SRV Record

SRV Record Syntax:

-- @name    = relative name
-- @target  = host name(fqdn)
-- @port    = port number
-- @prio    = prio (default: 0)
-- @weight  = weight (default: 0)
-- @ttl     = TTL (default: user default TTL)
srv(name, target, port, prio, weight, ttl)

Example:

-- File: example.com
srv("_sip._tcp", "sipserver.example.com", 5060)

SSHFP Record

SSHFP Record Syntax:

-- @name        = relative name
-- @algorithm   = algorithm number (1=RSA, 2=DSA, 3=ECDSA, 4=Ed25519)
-- @fp_value    = fingerprint (presented in hex)
-- @fp_type     = fingerprint type (1=SHA-1, 2=SHA-256, default: 1)
-- @ttl         = TTL (default: user default TTL)
sshfp(name, algorithm, fp_value, fp_type, ttl)

Example:

-- File: example.com
-- Run ssh-keygen tool to print the SSHFP fingerprint resource record:
-- $ ssh-keygen -f /etc/ssh/ssh_host_rsa_key.pub -r myserver
-- myserver IN SSHFP 1 1 34b1436fa3d5cf235563efe42a9223ae1c6b486e
-- $ ssh-keygen -f /etc/ssh/ssh_host_dsa_key.pub -r myserver
-- myserver IN SSHFP 2 1 0392244baae593a996b354f473b350c4c2afe9f3
sshfp("myserver", 1, "34b1436fa3d5cf235563efe42a9223ae1c6b486e")
sshfp("myserver", 2, "0392244baae593a996b354f473b350c4c2afe9f3")

TLSA Record

TLSA Record Syntax:

-- @name          = relative name
-- @usage         = usage (0 - PKIX-TA, 1 - PKIX-EE, 2 - DANE-TA, 3 - DANE-EE)
-- @certificate   = certificate association data (hex)
-- @selector      = selector (0 - Cert, 1 - SPKI, default: 1)
-- @matching_type = matching type (1=SHA-256, 2=SHA-512, default: 1)
-- @ttl           = TTL (default: user default TTL)
tlsa(name, usage, certificate, selector, matching_type, ttl)

Example:

-- File: example.com
tlsa("_25._tcp.mail", 3, "0c72ac70b745ac19998811b131d662c9ac69dbdbe7cb23e5b514b56664c5d3d6")

TXT Record

TXT Record Syntax:

-- @name    = relative name
-- @text    = text
-- @ttl     = TTL (default: user default TTL)
txt(name, text, ttl)

Example:

-- File: example.com.lua
-- _a variable is set by the system to zone name
-- _a = "example.com"
txt(_a, "google-site-verification=vEj1ZcGtXeM_UEjnCqQEhxPSqkS9IQ4PBFuh48FP8o4")

Wildcard Record

Wildcard records are supported, example usage:

-- File: example.com.lua
-- Variable _a is replaced with zone name by LuaDNS
-- _a = "example.com"

-- *.example.com resolves to 1.2.3.4
a("*", "1.2.3.4")

-- Email for *.uk.example.com is handled by mx-eu.example.com
a("*.uk", concat("mx-eu", _a))

User default TTL

In a Resource Records definition user default TTL (default: 3600 seconds) is used when TTL is not specified, you can change your default TTL from the account settings page.

System Functions

  • concat(str1, str2) - Concatenates two names using dot, used usually to construct host names.
    Example usage: mx(_a, concat("mail", _a))
  • slave(name, ip, ttl) - defines a slave for the current zone, ip is an IPv4 address used to configure ACLs and to send NOTIFY messages. Required A and NS records are added automatically. To add multiple servers invoke function multiple times. Please, configure your ACLs on slave servers to use axfr.luadns.net or IP 108.61.179.251.
    Example: slave("ns1", "1.1.1.1") or slave("ns1.third-party-ns.com", "2.2.2.2")

System Variables

  • _a - variable is set by compiler to zone name (extracted from file name).
    Example: _a = "example.com" for configuration file example.com.lua.

Comments

Comments are simple Lua comments:

A comment starts with a double hyphen (--) anywhere outside a string. If the text immediately after -- is not an opening long bracket, the comment is a short comment, which runs until the end of the line. Otherwise, it is a long comment, which runs until the corresponding closing long bracket. Long comments are frequently used to disable code temporarily.

Templates

Templates are simulated through Lua functions. Global functions/templates should be grouped in templates.lua file in your repository. Functions defined here are available to each zone.

Example (templates.lua):

function google_app(domain)
  -- Configure Google Apps mail exchangers
  mx(domain, "aspmx.l.google.com", 5)
  mx(domain, "alt1.aspmx.l.google.com", 10)
  mx(domain, "alt2.aspmx.l.google.com", 10)
  mx(domain, "aspmx2.googlemail.com", 20)
  mx(domain, "aspmx3.googlemail.com", 20)

  -- Additional Google Apps records
  cname(concat("calendar", domain), "ghs.google.com")
  cname(concat("docs", domain), "ghs.google.com")
  cname(concat("mail", domain), "ghs.google.com")
  cname(concat("sites", domain), "ghs.google.com")

  -- Configure SPF
  txt(domain, "v=spf1 a mx include:_spf.google.com ~all")
end

Domain aliases

When dealing with multiple domains sharing the same configuration to avoid cluttering the repository with zone files, LuaDNS allows domain aliases to be specified in .clones files:

Example:

$ ls -al example.com.*
-rw-r--r-- 1 vitalie vitalie  25 2012-04-18 00:31 example.com.clones
-rw-r--r-- 1 vitalie vitalie 266 2012-03-01 12:46 example.com.lua

$ cat example.com.clones
example.org
example.info

The system will generate the same set of records for example.org, example.info mirroring records from example.com.

Zone transfers (AXFR)

LuaDNS can be configured to function together with external slave servers. To configure a slave server use slave function. Example:

-- File: example.com.lua
-- Zone: example.com

-- Add two slave servers (ns1.example.com, ns2.example.com)
-- required A and NS records are created automatically
slave("ns1", "1.1.1.1")
slave("ns2", "1.1.1.2")

-- Add two external slave servers
-- required NS records are created automatically
slave("ns1.third-party-ns.com", "2.2.2.1")
slave("ns1.third-party-ns.com", "2.2.2.2")

-- Please, configure your ACLs on slave servers
-- to use axfr.luadns.net or IP 108.61.179.251.

Examples

Basic Example

-- File: example.com.lua
-- Variable _a is replaced with zone name by LuaDNS
-- _a = "example.com"

-- A Records
a(_a, "1.2.3.4")

-- CNAME Records
cname("www", _a)

-- MX Records
mx(_a, _a)

Advanced Example

-- File: example.com.lua
-- Zone: example.com
-- Variable _a is replaced with zone name by LuaDNS
-- _a = "example.com"

-- A records
a(_a, "1.2.3.4")

-- CNAME records
cname("www", _a)
cname("ftp", _a)

-- Templates
google_app(_a)

-- Add 2 slave servers (ns1.example.com, ns2.example.com)
-- required A and NS records are created automatically
slave("ns1", "1.1.1.1")
slave("ns2", "1.1.1.2")

Bind Zone File Format

LuaDNS has native support for Bind zone files, add Bind files to your git repository (use .bind extension) and push modifications with git (git push origin master).

Your configuration files will be parsed, validated and deployed to our name servers, shortly you'll receive from us an email with status of the deployment.

Examples:

Information on Bind zone file format is available here: https://www.zytrax.com/books/dns/ch8

Supported directives

  • $TTL
  • $ORIGIN

Supported Records

  • A
  • AAAA
  • CNAME
  • MX
  • NS
  • PTR
  • SOA
  • SPF
  • SRV
  • SSHFP
  • TXT

Vanity Name Servers

There are many situations when you need to use your vanity name servers with your domains, example:

  • ns1.yourcompany.com
  • ns2.yourcompany.com

To configure your account to use vanity name servers follow this steps:

  1. Create ns1-2.yourcompany.com name servers (A & AAAA records) in yourcompany.com zone
  2. Add glue records (A & AAAA) for ns1-2.yourcompany.com servers at your registrar
  3. Add ns1-2.yourcompany.com to Vanity Servers in the settings page

Create Vanity Name Servers

Edit yourcompany.com zone and create A & AAAA records for each name server pointing to our IP addresses:

  # A records
  ns1.yourcompany.com -> 185.142.218.1
  ns2.yourcompany.com -> 185.142.218.2

  # AAAA records
  ns1.yourcompany.com -> 2001:67c:25a0::1
  ns2.yourcompany.com -> 2001:67c:25a0::2

If you have more than 4 name servers you can reuse one of the IPv4 & IPv6 addresses.

Add Glue Records for Vanity Name Servers

If you intend to use your vanity name servers ns1-2.yourcompany.com for yourcompany.com domain, you'll have to add glue records (same A & AAAA records) for each vanity name server at your registrar.

Use Your Vanity Servers

To use your vanity name servers instead of defaults, edit your account and add your name servers (one name server per line) in the "Vanity Servers" textarea.

Example:

ns1.yourcompany.com
ns2.yourcompany.com

Next time when you'll create/update a zone via web GUI or git, your name servers will be injected automatically instead of the default ones (ns1-4.luadns.net).

Dynamic DNS Update

We support dyndns2 protocol, check the Dynamic DNS Update page for more details.