Greetings DNS fans!
This release needs extra testing
WARNING: This release may be a little unstable. Test carefully before putting into production especially if you use IDN (Unicode in domain names) or Cloudflare redirects (CF_REDIRECT, CF_TEMP_REDIRECT, CF_SINGLE_REDIRECT), or the BIND "filenameformat" feature.
We're using the Github feature to mark this as a "pre-release". It will be labeled as non-production ready. It will be marked as production ready in a few weeks, or we may just skip to a .1 release if bugs are found.
Volunteer changes:
- We're sad to announce @Deraen and @philhug are stepping down as maintainers of the DIGITALOCEAN and OPENSRS respectively. We’re grateful for their past contributions and wish them well in their future endeavors.
- Applause all around to @chicks-net for stepping up to be the new maintainer of DIGITALOCEAN! We look forward to great things!
- We need a new maintainer for OPENSRS. If you are interested or have questions, please contact our official Liaison To Maintainers, @fm by opening an issue.
Monthly video call is Mon, Dec 15, 2025
Our next "Monthly DNSControl Community Video Conference Call" is on Monday, Dec 15. Join in whether you are a new user with questions or an experienced developer that wants to discuss DNSControl internals. More details at #3840. All are invited!
There's so much new in this release!
-
New Providers!
-
IDN support for domain names! c11a523 (#3879) (@tlimoncelli)
- Internationalized domain name (IDN) support has been extended to include domain names! Previously Unicode was supported in labels but not domains. It now works everywhere (we hope). This code is very new. Please test before putting it into production. Please file bug reports with problems or suggestions. I don't use IDN myself so your feedback is extra important!
- Thanks to everyone that offered suggestions about how to go about adding IDN support. There was a lively discussion in
#2874 (shout out to @KaiSchwarz-cnic for explaining the conventions that other SDKs use). I haven't implemented all the IDN-related features discussed, but this is a good start. - It's impossible for me to test this with all providers, so please tread carefully, test before going into production, and submit bug reports!
-
DNSControl now plays well with K8s's "external-dns" service! f1b30a1 (#3869) (@tridion)
- Do you use K8s and find that DNSControl wants to remove DNS records created by the external-dns service? Sure, you can add IGNORE() statements ahead of time, but unless you are a time-traveler it's difficult to know what parameters to use. Plus, manual work? Yuck!
- The new IGNORE_EXTERNAL_DNS() domain modifier automatically works around (ignores) DNS records created by the external-dns service.
- Check out #3869 and the documentation for details.
- Thanks to @tridion for taking the intiative to work out all the details of how the TXT registry works and extending DNSControl to utilize the protocol.
-
AKAMAIEDGEDNS now supports ALIAS and AKAMAITLC records! 97209bc (#3836) (@gvengel)
-
CLOUDFLAREAPI now supports LOC records ec9a9e2 (#3857) (@kevinji)
-
GANDI_V5 and BIND now support the RP record. This is the first record type to use the new "RecordConfig v2" system (see below).
-
INWX fixed to support their unexpected data-type breaking-change! 9aad292 (#3855) (@patschi)
-
The output of
--reportnow includes details about what changed! 9d4cb30 (#3835) (@kevinneufeld)
And not to forget...
- It is no longer an error if
creds.jsonis zero length. (#3844) (@tlimoncelli) - @das7pad found that many providers may have a bug when used concurrently and has reached out to them with code fixes. This release includes improvements for CLOUDNS, DESEC, and ROUTE53. Thanks for taking the initiative to do this, @das7pad!
- @gvengel discovered the shoutrrr module we were using was no longer supported and took the initiative to find its replacement! Thanks, @gvengel!
- And much, much, more!
Thanks to all contributors involved in this release! This is a community project and we couldn't do it without all of your contributions!
Cloudflare's Page Rules are gone.
POTENTIAL BREAKING CHANGE:
Cloudflare is removing support for Page Rules and converting them to "Single Redirects". Earlier this year DNSControl added a mechanism where Page Rules were optionally transpiled into Single Redirect regular expressions.
This translation is no longer optional. All code for Page Rules has been removed. CF_TEMP_REDIRECT and CF_REDIRECT simply generate CF_SINGLE_REDIRECT records.
The first time you run "push" with the new release, DNSControl will change the "name" field (removing the "001,", "002,", .... prefix). Also, the order of the rules may change. The order can be managed in Cloudflare's dashboard, DNSControl will not affect the order. (Though, in the future we'd like for DNSControl to enforce ordering too.)
Please "preview" and verify the changes before running "push".
BIND "filenameformat" changes
POTENTIAL BREAKING CHANGE:
Implementing the IDN changes meant some potential breaking changes to the "filenameformat" string used in the BIND provider. I think (I hope!) that the only configurations that will break are ones with uppercase Unicode runes. That said, please review the "filenameformat" section of the BIND documentation for details.
RecordConfig v2 (big news!)
DNSControl stores each DNS Record in a structure called a "RecordConfig". The format of this record was showing its age. It consumes more memory as more record types are supported, it isn't flexible, it isn't very OO, and adding new record types is very difficult. In fact, the instructions for adding new types is many pages long. Worst of all, code for each record type is splattered all over the code base instead of being centralized to one place.
About a year ago I started working on prototypes that would fix these problems. There were many challenges. How could we make adding new record types super easy? How could we migrate a lot of the work done in JavaScript to the main Go code (which would make it easier to write unit tests and use more advanced debugging tools)? How could we do all that and not break old code?
The first 2 attempts were failures but I learned a lot. In particular I learned that it wasn't feasible to convert all the existing record types immediately and instead I could make the old and new system coexist. Converting older types could come later.
I'm excited to announce "RecordConfig v2"!
- It's easier to add new DNS types.
- DNSControl's main code does almost all the work; the code for a specific type is minimized.
- It consolidates almost all code for a record type to a single file (and paves a path to fix the remaining exceptions)
- You only need to know Go, instead of also needing to know JavaScript.
- New record types and "builders" can leverage Go's testing framework, which will make brittle features like LOC and SPF_BUILDER more stable in the future.
- It works side-by-side the old RecordConfig.
- Older types require no code changes, new types use the new system.
- There's an obvious path to migrate existing types to use the new system eventually.
- All normalization and validation happens earlier.
- No longer does code have to worry whether a RecordConfig has been normalized or validated because all that happens right away. Code that accesses a RecordConfig is shorter as a result.
- IDN handling is done properly, not as an after-thought
- It creates a path towards automatic code generation.
- Imagine DNSControl supporting any newly standardized record types automatically!
In this release RP and CF_SINGLE_REDIRECT are the only record types that use v2. One is entirely new to DNSControl, the other is an old type that's been migrated. That proves the concept works. Converting existing types will happen over the next year.
The original RecordConfig was designed in 2014. We're 11+ years smarter both about how to best use Go and what is important (and not important) to DNSControl users.
All of this is below the surface. It doesn't affect the user's experience or the format of dnsconfig.js. However in the future users will appreciate new record types and "builders" being added more rapidly and with better stability.
This change was low risk in that not many users use RP or CF_SINGLE_REDIRECT. However the change did affect many areas of the code base so please test carefully before putting v4.28.0 into production.
Feedback is appreciated!
P.S. If you are interested in converting existing types to the new system, please ping me!
Changelog
Major features:
- c11a523: FEATURE: Fixing IDN support for domains (#3879) (@tlimoncelli)
- 4d29c2c: NEW FEATURE: Empty creds.json should not be an error (#3844) (@tlimoncelli)
Provider-specific changes:
- 97209bc: AKAMAIEDGEDNS: Add ALIAS and AKAMAITLC support to the Akamai Edge DNS provider (#3836) (@gvengel)
- bcef7f5: ALIDNS: Implement ALIDNS Provider (#3878) (@bytemain)
- ec9a9e2: CLOUDFLARE: Add LOC support (#3857) (@kevinji)
- b992ae3: CLOUDFLAREAPI: Skip read-only records inserted by provider (#3850) (#3852) (@SukkaW)
- d1765b6: CLOUDNS: populate zone cache when creating zone (#3331) (@das7pad)
- ee47032: DESEC: populate zone cache after creating zone (#3332) (@das7pad)
- c073f2e: HETZNER: gracefully handle FQDN labels when listing records (#3859) (@das7pad)
- 1e67585: HETZNER_V2: Add provider for Hetzner DNS API (#3837) (@das7pad)
- 6e42ccf: INWX: Enable concurrency support (#3856) (@patschi)
- 9aad292: INWX: Fix INWX provider after their unexpected data-type breaking-change (#3855) (@patschi)
- 7b81878: ROUTE53: make caching of zones thread-safe (#3328) (@das7pad)
- 6153e3b: VERCEL: Fix some bugs (#3887) (@SukkaW)
- daf5a7a: VERCEL: Implement Vercel DNS Provider (#3379) (#3542) (@SukkaW)
Documentation:
CI/CD:
- 2a7ac6f: Build(deps): Bump actions/checkout from 5 to 6 (#3851) (@dependabot[bot])
- 539fe5c: Build(deps): Bump glob from 11.0.1 to 11.1.0 (#3846) (@dependabot[bot])
- 6340756: Build(deps): Bump golang.org/x/crypto from 0.43.0 to 0.45.0 (#3848) (@dependabot[bot])
- fa24aa8: Build(deps): Bump js-yaml from 4.1.0 to 4.1.1 (#3847) (@dependabot[bot])
Dependencies:
- 0c5d4ea: CHORE: Update dependencies (#3868) (@tlimoncelli)
- 9353554: CHORE: Update dependencies (#3871) (@tlimoncelli)
- bdf8bef: DEPS: Switch to maintained fork of shoutrrr (#3838) (@gvengel)
- abe96b1: DEPS: Upgrade shoutrrr dependency and remove Go toolchain pinning (#3858) (@das7pad)
Other changes and improvements:
- 1b2f5d4: BUGFIX: IDN support is broken for domain names (#3845) (@tlimoncelli)
- b8f2167: BUGFIX: Reverse order of domain ascii/unicode displayed (#3872) (@tlimoncelli)
- 7dc81bb: CHORE: FIx lint in diff2 (#3885) (@tlimoncelli)
- f306472: CHORE: Maintainer changes for OPENSRS and DIGITALOCEAN (#3849) (@tlimoncelli)
- e87f03a: CHORE: fmt (#3882) (@tlimoncelli)
- 11e9fd1: CHORE: generate-all.sh (#3892) (@tlimoncelli)
- 4d77744: CICD(golangci) Disable errcheck (#3873) (@tlimoncelli)
- efa2e1e: DEV: Add tool to reset js/parse_tests data (#3874) (@tlimoncelli)
- 7030841: REFACTOR: BIND/GANDI_V5 add "RP" record type, rewrite CLOUDFLAREAPI CF_* and more (#3886) (@tlimoncelli)
- 3bf0c5a: Remove unused --depopulate flag (#3843) (@das7pad)
- 9d4cb30: feat(report): --report output now includes detailed list of changes (#3835) (@kevinneufeld)
- f1b30a1: feat: Add IGNORE_EXTERNAL_DNS() for Kubernetes external-dns coexistence (#3869)s (@tridion)
Deprecation warnings
Warning
- REV() will switch from RFC2317 to RFC4183 in v5.0. This is a breaking change. Warnings are output if your configuration is affected. No date has been announced for v5.0. See https://docs.dnscontrol.org/language-reference/top-level-functions/revcompat
- OPENSRS, NAMEDOTCOM and SOFTLAYER need maintainers! These providers have no maintainer. Maintainers respond to PRs and fix bugs in a timely manner, and try to stay on top of protocol changes.
Install
macOS and Linux
Install with Homebrew (recommended)
brew install dnscontrolUsing with Docker
You can use the Docker image from Docker hub or GitHub Container Registry.
docker run --rm -it -v "$(pwd):/dns" ghcr.io/stackexchange/dnscontrol previewAnywhere else
Alternatively, you can install the latest binary (or the apt/rpm/deb/archlinux package) from this page.
Or, if you have Go installed, you can install the latest version of DNSControl with the following command:
go install github.com/StackExchange/dnscontrol/v4@mainUpdate
Update to the latest version depends on how you choose to install dnscontrol on your machine.
Update with Homebrew
brew upgrade dnscontrolAlternatively, you can grab the latest binary (or the apt/rpm/deb package) from this page.