Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
27 changes: 27 additions & 0 deletions documentation/provider/dnscale.md
Original file line number Diff line number Diff line change
Expand Up @@ -64,6 +64,33 @@ DNScale supports the following record types:
- TLSA
- TXT

## Nameservers and apex NS records

DNScale automatically assigns nameservers (e.g. `ns1.dnscale.eu`, `ns2.dnscale.eu`) when a zone is created. These system-managed NS records at the zone apex are invisible to DNSControl — they cannot be modified or deleted.

Third-party NS records at the apex **are** supported for multi-provider DNS setups. For example, if you use DNScale alongside another provider, you can add their nameservers as NS records and DNSControl will manage them normally.

### Multi-provider DNS setup

Because DNScale assigns nameservers server-side, `GetNameservers` returns an empty list. This means DNScale's nameservers are not automatically included in registrar delegation. For multi-provider setups, you must explicitly declare them using `NAMESERVER()`:

{% code title="dnsconfig.js" %}
```javascript
var REG_NAMECHEAP = NewRegistrar("namecheap");
var DSP_DNSCALE = NewDnsProvider("dnscale");
var DSP_CLOUDFLARE = NewDnsProvider("cloudflare");

D("example.com", REG_NAMECHEAP,
DnsProvider(DSP_DNSCALE),
DnsProvider(DSP_CLOUDFLARE),
NAMESERVER("ns1.dnscale.eu"),
NAMESERVER("ns2.dnscale.eu"),
A("@", "192.0.2.1"),
A("www", "192.0.2.1"),
END);
```
{% endcode %}

## New domains

If a domain does not exist in your DNScale account, DNSControl will automatically create it when you run `dnscontrol push`.
Expand Down
3 changes: 0 additions & 3 deletions providers/dnscale/auditrecords.go
Original file line number Diff line number Diff line change
Expand Up @@ -11,9 +11,6 @@ import (
func AuditRecords(records []*models.RecordConfig) []error {
a := rejectif.Auditor{}

// DNScale automatically manages apex NS records - they cannot be modified via API
a.Add("NS", rejectif.NsAtApex)

a.Add("MX", rejectif.MxNull) // MX records must have a target

a.Add("TXT", rejectif.TxtHasDoubleQuotes) // TXT records shouldn't contain unescaped double quotes
Expand Down
25 changes: 20 additions & 5 deletions providers/dnscale/dnscaleProvider.go
Original file line number Diff line number Diff line change
Expand Up @@ -146,9 +146,13 @@ func (p *dnscaleProvider) GetZoneRecords(dc *models.DomainConfig) (models.Record

curRecords := make(models.Records, 0, len(records))
for _, rec := range records {
// Skip NS records at apex - these are managed by DNScale
// Skip DNScale's own NS records at apex - these are system-managed.
// Third-party NS records at apex are kept for multi-provider DNS setups.
if rec.Type == "NS" && (rec.Name == domain+"." || rec.Name == "@") {
continue
content := strings.TrimSuffix(rec.Content, ".")
if strings.HasSuffix(content, ".dnscale.eu") || strings.HasSuffix(content, ".dnscale.com") {
continue
}
}
// Skip SOA records
if rec.Type == "SOA" {
Expand Down Expand Up @@ -217,9 +221,20 @@ func (p *dnscaleProvider) GetZoneRecordsCorrections(dc *models.DomainConfig, cur
return corrections, actualChangeCount, nil
}

// GetNameservers returns an empty array.
// DNScale manages apex NS records automatically - they cannot be modified via API.
// Returning empty prevents DNSControl from trying to create NS records at apex.
// GetNameservers returns an empty array because DNScale assigns nameservers
// server-side when a zone is created. Returning empty means dnscontrol won't
// auto-generate NS records for DNScale at the apex.
//
// For multi-provider DNS setups, you must explicitly declare DNScale's
// nameservers so they are included in registrar delegation:
//
// D("example.com", REG_NAMECHEAP,
// DnsProvider(DSP_DNSCALE),
// DnsProvider(DSP_CLOUDFLARE),
// NAMESERVER("ns1.dnscale.eu"),
// NAMESERVER("ns2.dnscale.eu"),
// // ...
// )
func (p *dnscaleProvider) GetNameservers(domain string) ([]*models.Nameserver, error) {
return []*models.Nameserver{}, nil
}
Expand Down