Skip to content

Zone management

Ignore rules

Use DNS ignore rules to leave externally managed records unchanged. Match names or targets, preserve selected records, and preview shared ownership safely.

5 min read

On this page

Ignore rules preserve selected live provider records even when those records are absent from your saved draft, while NO_PURGE preserves all otherwise-unmanaged record sets. The key point is that matching happens against fresh provider data during preview and push; the counts in Settings only show draft records that would conflict with each rule.

Add an ignore rule#

Open Zones, choose a zone, then open Settings → Ignore rules. The form has three match dimensions:

UI fieldSaved IGNORE argumentMeaning
Name patternlabelSpecRelative owner name, such as @, _acme-challenge, or *.dev.
TypestypeSpecOne type or a comma-separated list such as A,MX. Matching is case-insensitive because values are normalized to uppercase.
Target patterntargetSpecThe record's target field or logical TXT/SPF value.

Blank fields are saved as *, which matches anything in that dimension. Select Add rule, review its Matches n draft records badge, then select Save changes. Removing a rule also edits only the browser draft until you save.

The generic and shorthand dnsconfig.js forms are equivalent:

dnsconfig.js
D("example.com", REG_NONE, DnsProvider(DSP),
  IGNORE("_acme-challenge", "TXT", "*"),
  IGNORE_NAME("legacy", "A,AAAA"),
  IGNORE_TARGET("**.acm-validations.aws.", "CNAME"),
)

IGNORE_NAME(name, types) is IGNORE(name, types, "*"). IGNORE_TARGET(target, type) is IGNORE("*", type, target). All omitted arguments default to *.

Understand what is matched#

Rules are applied per value, not only per record set. Suppose the provider has:

text
www  300  IN  A  192.0.2.10
www  300  IN  A  192.0.2.11

and the saved draft has www A 198.51.100.10. This rule preserves only the first live value:

dnsconfig.js
IGNORE("www", "A", "192.0.2.10")

The planned set becomes the managed value plus the ignored value. DNS can store only one TTL for a record set, so the managed draft TTL wins when the values differ. The core planner records that adjustment as a warning, but the release managed-zone service does not include planner warnings in Changes.

A target is selected as follows:

  • TXT and SPF match their entire logical text, including spaces but without zone-file quotes.
  • Alias metadata matches its DNS target, or its resource ID when it has no DNS target.
  • Every other type is tokenized with quote and backslash handling, and the last token is matched. For MX that is the exchange, not the priority; for SRV it is the hostname; for CAA it is the value.

Owner names and canonical hostname targets are lowercased before matching. TXT text and other raw values retain case. Glob matching itself is case-sensitive, so write TXT target patterns with the case you expect.

Use the implemented glob syntax#

Name and target patterns are anchored: the whole label or target must match. The implementation supports:

PatternMeaningExample match
*Zero or more characters*.dev matches api.dev and one.api.dev.
**Zero or more characters_acme-challenge.** matches nested challenge labels.
?Exactly one character?oo matches foo.
[abc], [a-c]One listed character or range[a-c]oo matches boo.
[!abc]One character not listed[!a-c]oo matches zoo.
{one,two}One alternative; alternatives can contain other pattern forms{mail,smtp} matches either label.
\Escape the next character\*.dev matches the literal wildcard owner *.dev.

Malformed trailing escapes, unclosed braces/classes, and backwards ranges are rejected before Add rule succeeds.

Resolve the safety check#

It is unsafe for a saved record value to match a rule that promises another system owns it. By default, planning for an affected provider stops with a message like:

text
1 record(s) are both IGNORE*()'d and defined in the config: myhost.example.com. TXT mytext.
Unsafe to continue. Add DISABLE_IGNORE_SAFETY_CHECK to override.

The UI warns Some records you manage here also match an ignore rule whenever its draft match count is nonzero. The safest fixes are to remove the value from the draft, narrow the name/type/target pattern, or remove the rule.

Turn off the ignore safety check maps to:

dnsconfig.js
D("example.com", REG_NONE, DnsProvider(DSP),
  DISABLE_IGNORE_SAFETY_CHECK,
  TXT("myhost", "mytext"),
  IGNORE("myhost", "TXT"),
)

With this override, planning continues instead of turning the conflict into a provider error. The core planner records a warning, but the release Changes payload does not expose planner warnings. The override does not define which writer wins during concurrent changes, so use it only when ownership is coordinated. The old per-record IGNORE_NAME_DISABLE_SAFETY_CHECK form is rejected by the browser importer.

Leave external-dns records alone#

Select Leave Kubernetes external-dns records alone to enable IGNORE_EXTERNAL_DNS. During planning, DNSMigrator finds live TXT ownership values containing heritage=external-dns, preserves those TXT records, and infers the record sets they own.

It recognizes ownership labels beginning with a., a-, aaaa., aaaa-, cname., cname-, ns., ns-, mx., mx-, srv., srv-, txt., or txt-. For example, a-myapp owns the A set at myapp. An ownership label without a recognized type preserves A, AAAA, CNAME, NS, MX, and SRV at the corresponding name, in addition to its ownership TXT.

The settings form enables the default naming behavior. A custom external-dns TXT prefix is available through Config as code:

dnsconfig.js
D("example.com", REG_NONE, DnsProvider(DSP),
  IGNORE_EXTERNAL_DNS("extdns-"),
)

With that prefix, extdns-cname-api owns the CNAME set at api, and extdns-a represents the apex A set. If the draft defines a set inferred as external-dns-owned, DNSMigrator does not preserve the external copy. The core records a conflict warning, but the release Changes payload does not display it.

Choose between targeted ignores and NO_PURGE#

Under Settings → Record defaults, Never delete records at the provider sets purge to false. Its dnsconfig.js equivalent is:

dnsconfig.js
D("example.com", REG_NONE, DnsProvider(DSP),
  NO_PURGE,
  A("www", "192.0.2.10"),
)

With normal PURGE behavior, a provider record set absent from the effective desired zone is planned for deletion. With NO_PURGE, planning merges the draft into live state: it adds missing sets and updates matching managed sets, but leaves unrelated live sets in place. PURGE is the default and can be written explicitly in an imported config.

NO_PURGE is broad. Prefer a narrow ignore rule when you know which names or targets another controller owns, because a stale unknown record will otherwise remain indefinitely. An explicit ENSURE_ABSENT_REC() loaded from dnsconfig.js is still allowed to remove its named value under NO_PURGE; the web settings form does not create those absent markers.

Preview shared ownership#

After saving, select Preview changes and inspect every provider under Changes. Confirm that ignored values do not appear under Delete or Change. Because shared-TTL and external-dns planner warnings are not included in the release payload, verify those ownership choices from the saved rules and live records before pushing. For provider capability issues, see Record types.