levelrail-cli dns, and the API lives under /api/v1/dns.
Nothing here is a DNS server of its own. Zones and records live at the provider; the control plane calls its API with the credentials stored under Domains, DNS provider.
Connect a provider
Zone management reuses the DNS-01 credentials from Domains and ingress. Zone level work needs a little more access than DNS-01 alone.- Cloudflare
- Route53
Create an API token (never the global API key) with:A new zone is created in the account the token’s existing zones belong to. When the token sees several accounts, pass
--account-id to dns zones create.--provider route53 (or ?provider=route53) picks the other one. Tokens are envelope encrypted at rest, never returned by any API, and never written to logs or audit rows.
Bring a domain onto a zone
The Add zone wizard has four steps, andlevelrail-cli dns zones ... does the same from a terminal.
- Domain. Enter the registrable domain (
example.com, notwww.example.com). The zone is created at the provider. - Name servers. The provider assigns name servers to the zone. Set exactly these at your registrar, replacing the current ones; a mix of old and new answers inconsistently.
- Import records. Before switching, copy what the domain serves today. Zone transfers (AXFR) are almost always refused, so the wizard looks up a list of common names (
@,www,mail,api, DKIM selectors,_dmarc, common SRV names and more) at the domain’s current name servers and shows what it found. Untick anything you do not want and add any other names you use. Only the sets you keep are imported. - Verify. The system resolver,
1.1.1.1and8.8.8.8are asked for the domain’s NS records and compared with the zone’s assigned servers.
A resolver that returns a subset of the assigned servers counts as a match: a registrar given two of Route53’s four servers still delegates correctly. Registries usually publish a name server change within an hour, but resolvers may keep the old answer for up to two days.
Records
The zone page lists record sets: all values of one name and type together. Search matches names, values and set identifiers. The type filter narrows results to one type. Lists longer than 50 sets are virtualized. Supported types are A, AAAA, CNAME, TXT, MX, CAA, SRV and NS (for delegating a subdomain; apex NS and SOA are provider managed and read only). Each type has its own fields in the record dialog, and every value is checked twice: in the browser for instant feedback and on the server, which parses each value withmiekg/dns before anything reaches the provider.
- A CNAME cannot share a name with any other record, in either direction.
- A CNAME at the apex is refused on Route53 (use an A record or a Route53 alias) and allowed with a warning on Cloudflare, which flattens it.
- A CNAME set holds exactly one value.
proxiedapplies to A, AAAA and CNAME on Cloudflare only. TTL1means automatic and is Cloudflare only.- TTL is otherwise between 30 seconds and 7 days. The default is
APP_DNS_DEFAULT_TTL, or 300 seconds. - TXT values are the raw text; splitting into 255 byte strings and quoting is handled for you.
Routing policies (Route53)
On Route53, a record set can use a routing policy. Several sets then share a name and type and are told apart by a set identifier.Import and export
Import accepts a BIND zone file or the JSON this page exports, as a file or pasted text. It always produces a plan first: what will be created, updated, deleted or left alone, with conflicts flagged. Nothing changes until you apply a plan without conflicts. By default an import never deletes anything, so records the file does not mention stay put. Replace deletes record sets missing from the file (never apex NS, SOA or alias sets) and requires typing the zone name.Templates
Templates add common setups as a plan you review before applying:
TXT values already at the same name are kept (verification tokens survive), except a second SPF or DMARC record, which would break mail authentication.
Health and propagation
The zone overview shows record counts by type, the delegation state, and the last change made through this control plane (who and which action), falling back to the provider’s own modified time. The Propagation tab, orlevelrail-cli dns check, asks one name and type of the system resolver, 1.1.1.1, 8.8.8.8, and, when the zone is known, each of the zone’s own name servers directly. Each answer shows its values and remaining TTL, whether all answers agree, and whether each matches what the zone holds. A resolver that still differs from the authoritative answer is waiting out its TTL.
APP_DNS_PUBLIC_RESOLVERS=off to ask only the system resolver, for example on a network that blocks outbound DNS.
Wildcard subdomains
An app can serve every name under a domain: add*.example.com (or *.apps.example.com) as one of its domains.
- Only a single leading
*.label is allowed.*.com,*.*.example.comanda.*.example.comare refused. - An exact domain always wins: if another app owns
api.example.com, requests for it go to that app, and every other name under*.example.comgoes to the wildcard app. A wildcard matches exactly one label, so*.example.comdoes not matcha.b.example.com. - The certificate must come from DNS-01, because HTTP-01 cannot issue wildcard certificates. Adding a wildcard domain is refused until Cloudflare or Route53 is connected; the error links to the Domains page and names the CLI command.
- When the provider manages the domain’s zone, a
*A record pointing at this server is created for you. An existing*record is never overwritten. - The domain check resolves a random name under the wildcard, so it tests the wildcard record rather than a cached exact name. The Domains table marks these domains Wildcard.
Permissions and audit
Reads (zones, records, delegation, checks, exports) need theread ability. Every write against the provider (zones, records, imports, templates, health checks) needs root, because it changes live infrastructure outside this server. Each write is audited with an action name (dns_zone.create, dns_zone.delete, dns_record.create, dns_record.update, dns_record.delete, dns_record.import, dns_record.template, dns_health_check.create, dns_health_check.delete); filter the audit log by dns_record or dns_zone.
Deleting a zone requires typing its name, and a zone that still has records beyond NS and SOA also needs force (--force). Export it first.
Limits
- Discovery before delegation is a best effort lookup of common names; names nobody guessed are not found. Add them in the wizard.
- Cloudflare zone listings do not include a record count; Route53 does.
- Route53 private hosted zones are listed but have no delegation to verify.
- Each change is applied as it is planned, one record set at a time; a provider error part way through an import stops it and reports how many changes landed.
Roadmap
How the Route53 feature set maps onto this page:
Also later: ownership TXT markers (as Kubernetes external-dns does) so imports can tell records this platform created from foreign ones, and Cloudflare load balancing pools.