Skip to main content

DNSRecord

Beta

Being rolled out. The interface described here is the one of the next release: it may still change, and may not be enabled on your tenant yet.

apiVersiondns.stackngo.io/v1alpha1
kindDNSRecord
Applied bysng apply (manifest) or sng dns record set
Related commandssng dns record list · describe · delete, sng template gen DNSRecord

What it is for​

A DNSRecord publishes a name in a zone you own: your default zone <tenant>.dev.stackngo.app, or a domain you bring with a DNSZone. The name is relative to the zone, at any depth. The platform checks that the zone is yours, that the name is not reserved, and that it is not already published elsewhere, then sends it to the DNS provider. status.fqdn gives the full name.

Minimal example​

www.yml
apiVersion: dns.stackngo.io/v1alpha1
kind: DNSRecord
metadata:
name: www
spec:
name: www # → www.<tenant>.dev.stackngo.app
type: A
targets: ["203.0.113.10"]
sng apply www.yml
sng dns record describe www

Equivalent without a manifest: sng dns record set www --type A --target 203.0.113.10 (object named www-a-<empreinte>).

Complete annotated example​

dns.yml
apiVersion: dns.stackngo.io/v1alpha1
kind: DNSRecord
metadata:
name: mail # free-form object name; used as the id for sng dns record describe|delete
spec:
zone: exemple.fr # domain of a DNSZone in your tenant; absent = default zone
name: "@" # relative to the zone: "@" (apex), "www", "a.b", "*.preview", "_dmarc"
type: MX # A, AAAA, CNAME, TXT, or MX
ttl: 3600 # 60 to 86400 seconds; 300 by default
targets: # 1 to 16 targets, no duplicates
- "10 mx1.mail.ovh.net." # MX: "<priority> <host>", trailing dot tolerated
- "20 mx2.mail.ovh.net."
---
apiVersion: dns.stackngo.io/v1alpha1
kind: DNSRecord
metadata:
name: dmarc
spec:
zone: exemple.fr
name: _dmarc
type: TXT
targets: ["v=DMARC1; p=quarantine; rua=mailto:dmarc@exemple.fr"] # at most 255 ASCII characters
---
apiVersion: dns.stackngo.io/v1alpha1
kind: DNSRecord
metadata:
name: preview-api
spec:
name: api.preview # default zone: api.preview.<tenant>.dev.stackngo.app
type: CNAME
targets: ["my-api.netlify.app"] # CNAME: a single target, never at the apex

Fields​

Cross-field validation rules​

The schema rejects, as early as sng apply:

  • a CNAME with several targets, or at the apex: un CNAME a une seule cible et n'est jamais à l'apex;
  • a name outside the pattern (lowercase, digits, -, _, * only at the start), a ttl outside 60–86,400, more than 16 targets, or a target longer than 255 characters.

The API also rejects (and a manifest that got past it stays Invalid):

  • a target that does not match the type: A = IPv4, AAAA = IPv6, CNAME = lowercase hostname, TXT = printable ASCII text, MX = "<priorité 0-65535> <hôte>";
  • a non-public address: private, shared (100.64.0.0/10), loopback, link-local, multicast, unspecified;
  • a duplicate target;
  • a reserved name: any _acme-challenge, _stackngo-verify, or extdns-* label, and in the default zone status and everything below it;
  • in a manifest, a zone equal to your default zone: zone "acme.dev.stackngo.app" : zone par défaut, laisser zone vide;
  • an intrinsically invalid zone (subdomain, platform domain, another customer's default zone) (400); a brought zone that is not declared yet is accepted: the record stays ZoneNotOwned then is published on its own once the DNSZone is proven; without zone, the record targets your default zone;
  • the same zone + name + type combination already declared by another object in your tenant, across all contexts (409).

sng apply and sng dns record set apply exactly the same checks: the DNSZone can be declared before or after its records.

DNSRecord​

DNSRecord : enregistrement DNS de votre tenant, publié par la plateforme après contrôle de la zone.

ChampDescriptionDéfautValidation
apiVersion stringdns.stackngo.io/v1alpha1
kind stringDNSRecord
metadata ObjectMetaSeul metadata.name est à renseigner (nom de la ressource dans votre tenant).
spec DNSRecordSpec
status DNSRecordStatus

DNSRecordSpec​

DNSRecordSpec : un enregistrement DNS dans une zone que possède votre tenant.

ChampDescriptionDéfautValidation
zone stringZone : domaine apporté par votre tenant (spec.domain d'une de vos DNSZone).
Vide = zone par défaut de votre tenant, <tenant>.<domaine de base de la plateforme>.
MaxLength: 253
Pattern: ^([a-z0-9]([-a-z0-9]\{0,61\}[a-z0-9])?\.)+[a-z]([-a-z0-9]\{0,61\}[a-z0-9])?$
Optional: {}
name stringName relatif à la zone, à toute profondeur : "@" (apex), "www", "a.b", "*.preview", "_dmarc".MaxLength: 200
MinLength: 1
Pattern: ^(@|\*|(\*\.)?[a-z0-9_]([-a-z0-9_]\{0,61\}[a-z0-9])?(\.[a-z0-9_]([-a-z0-9_]\{0,61\}[a-z0-9])?)*)$
type stringType : A, AAAA, CNAME, TXT ou MX.Enum: [A AAAA CNAME TXT MX]
ttl integerTTL en secondes.300Maximum: 86400
Minimum: 60
Optional: {}
targets string arrayTargets : IP (A, AAAA), nom d'hôte (CNAME), texte (TXT), "<priorité> <hôte>" (MX).MaxItems: 16
MinItems: 1
items:MaxLength: 255

DNSRecordStatus​

DNSRecordStatus : état de publication.

ChampDescriptionDéfautValidation
fqdn stringFQDN publié (ou qui le serait).Optional: {}
observedGeneration integerDernière version du manifeste prise en compte par la plateforme.Optional: {}
conditions Condition arrayConditions de l'enregistrement (Ready…), avec leur reason et un message lisible.Optional: {}

Status and conditions​

A single condition, Ready. status.fqdn is filled in as soon as the zone is known, even if the name is not published.

reasonReadyExplanationAction
PublishedTruethe record is sent to the DNS provider—
ConflictFalsethe name is already held by another source: same type, or a CNAME on one side; the message names the holder; retried every minutedelete the other source, or choose another name
ReservedFalsename reserved for the platformchoose another name
ZoneNotOwnedFalsela zone … n'appartient pas au tenant … : déclarer un DNSZone et prouver la propriétéwaiting state: the record is kept and published on its own (Published) as soon as the zone is proven; create the DNSZone, or fix zone
ZoneNotReadyFalseDNSZone … en phase Pending (or Verified)finish verifying the domain
InvalidFalsetarget, name, or length refused (full name longer than 253 characters)fix, sng apply

A Conflict record keeps its place in the queue: it is published as soon as the name is freed. All other refusals remove the record from the DNS if it was there.

What happens when you apply​

Creation. The record is published within a few minutes. In a domain you bring, it is written as soon as the zone is Provisioned, even before the delegation: prepare your records before changing the name servers.

Update. sng apply or sng dns record set (same zone, name, and type) replaces the targets and TTL. A change in the zone's phase, or its deletion, re-evaluates all of the tenant's records.

What happens when you delete​

sng dns record delete <id> or sng kind delete DNSRecord <nom>: the record is removed from the DNS, within 10 minutes at most. No deletionPolicy.

Common errors​

SymptomCauseFix
un CNAME a une seule cible et n'est jamais à l'apexCNAME on @at the apex, use A/AAAA, or expose the App at the apex (Domains on an App)
targets[0] : 192.168.1.10 n'est pas une adresse publiqueprivate addressuse the service's public address
targets[0] : "mail.exemple.fr" : forme "<priorité> <hôte>" attendueMX without a priority"10 mail.exemple.fr"
Conflict: shop.acme.dev.stackngo.app A déjà publié par ingress/…an App already exposes this namedo not duplicate an App with a record
Conflict between two TXTs with the same nametwo objects for the same name and typea single object, all values in targets
ZoneNotOwnedthe zone is not (yet) declared and proven, was removed afterwards, or zone is misspelledsng dns zone list; declare the DNSZone (published automatically afterwards), or fix zone
ZoneNotReadydomain you bring not verified yetBring a domain
status.acme.dev.stackngo.app : réservé aux status pages de la plateformereserved namechoose another name

See also​