Skip to content

feat(dns): rework provider management and support all record types - #5150

Merged
Siumauricio merged 7 commits into
Dokploy:canaryfrom
logical-tech:feat/dns-records-management
Sep 1, 2026
Merged

feat(dns): rework provider management and support all record types#5150
Siumauricio merged 7 commits into
Dokploy:canaryfrom
logical-tech:feat/dns-records-management

Conversation

@logical-tech

@logical-tech logical-tech commented Aug 21, 2026

Copy link
Copy Markdown

What is this PR about?

DNS providers, domains and records each get their own page instead of a
stack of modals. Clicking a provider opens its domains. Clicking a domain
opens its records. Creating or editing a record happens in a panel that
slides in next to the table, so the record you are editing stays visible.

Two limits are lifted along the way. Record types were capped at A and
CNAME in the zod schema, and Cloudflare proxy status was not reachable at
all.

Provider list

Each provider is a row that opens its domains. The row carries three
actions with matching styling and tooltips: view domains, edit, delete.
Add Provider moved to the header, on the same line as the title.

Domain list

Domains render as cards. The record count on each card loads on its own
request, so the domain names appear as soon as the zone list arrives
instead of waiting for every count.

Record table

Records are a table with search, a type filter built from the types
present in that zone, a rows-per-page selector defaulting to 10, and
sortable columns. Record types are colour coded rather than uniform grey
badges.

Record editing

The create and edit form opens in a panel beside the table. Cloudflare
zones get a Proxied / DNS only control for A, AAAA and CNAME records,
with the proxy status also shown as a cloud icon in the table.

Record types

A, AAAA, CNAME, MX, TXT, NS, SRV, CAA and PTR are accepted now. The type
list lives in dnsRecordTypes in the schema, and both DnsRecordInput
and the Route53 client read from it.

MX needs a priority. Cloudflare takes it as a separate field, Route53
takes it inline in the value. The Cloudflare client splits the priority
out of the value on write and puts it back on read, so a single value
field behaves the same on both providers. A value with no leading number
falls back to priority 10.

Cloudflare proxy status

proxied was added to the record schema, DnsRecordInput and
DnsRecord. The Cloudflare client reads it in listRecords and sends it
on create and update, but only for the three proxiable types and only
when the caller sets the field. Sending proxied: false by default would
have turned the proxy off on any record updated through a path that does
not set it.

Proxied records force automatic TTL on Cloudflare, so the TTL input is
disabled while Proxied is selected and the request omits the TTL.

Testing

Tested locally against a real Cloudflare zone and a Route53 hosted zone.
Created, edited and deleted records of several types, switched the proxy
toggle both ways, and confirmed the changes landed in the provider
dashboard.

Automated coverage in apps/dokploy/__test__/dns/cloudflare.test.ts:

  • MX priority is inlined into the value when listing and split back out
    when writing, with a fallback to 10 when the value has no leading
    number
  • a value that starts with a number on a non-MX record is left alone
  • proxy status is sent for A, omitted for TXT, and absent entirely when
    the caller does not set it
  • proxy status comes back from listRecords

pnpm typecheck passes in apps/dokploy and packages/server, Biome is
clean, and the 40 tests in __test__/dns pass.

Notes for reviewers

Automated coverage in apps/dokploy/__test__/dns/cloudflare.test.ts:

  • MX priority is inlined into the value when listing and split back out
    when writing, with a fallback to 10 when the value has no leading
    number
  • a value that starts with a number on a non-MX record is left alone
  • proxy status is sent for A, omitted for TXT, and absent entirely when
    the caller does not set it
  • proxy status comes back from listRecords

pnpm typecheck passes in apps/dokploy and packages/server, Biome is
clean, and the 40 tests in __test__/dns pass.

Notes for reviewers

Route53 ignores proxied, since the concept does not exist there. The
Proxy column and the toggle are hidden for Route53 providers.

Checklist

Before submitting this PR, please make sure that:

  • You created a dedicated branch based on the canary branch.
  • You have read the suggestions in the CONTRIBUTING.md file https://github.com/Dokploy/dokploy/blob/canary/CONTRIBUTING.md#pull-request
  • You have tested this PR in your local instance. If you have not tested it yet, please do so before submitting. This helps avoid wasting maintainers' time reviewing code that has not been verified by you.

Screenshots (if applicable)

new-record-form domains-list dns-records-list dns-providers-list

Greptile Summary

The PR reorganizes DNS provider management into dedicated provider, domain, and record pages while expanding record-type support and Cloudflare proxy controls.

  • Adds searchable, sortable, paginated record management with an adjacent editing panel.
  • Adds provider-neutral support for A, AAAA, CNAME, MX, TXT, NS, SRV, CAA, and PTR records.
  • Preserves Route53 multi-value record sets during editing and serializes Cloudflare SRV/CAA writes as structured data.
  • Resets pagination when search or record-type filters change.

Confidence Score: 5/5

The PR appears safe to merge.

No blocking failure remains.

Reviews (3): Last reviewed commit: "fix(dns): preserve every value of a Rout..." | Re-trigger Greptile

Context used:

Providers, domains and records now each have their own page instead of
a stack of modals. A provider opens its domains as cards, with the
record count loading separately so the domains appear right away. A
domain opens its records as a table with search, type filter and
pagination. Creating or editing a record happens in a panel that
slides in next to the table.

The type list was capped at A and CNAME in the zod schema, so widening
the dropdown alone would not have worked. AAAA, MX, TXT, NS, SRV, CAA
and PTR work now. MX carries a priority that Cloudflare takes as a
separate field and Route53 takes inline in the value, so the
Cloudflare client splits it out on write and puts it back on read.
The form keeps one value field for both providers.

Cloudflare proxy status is now editable and visible. A, AAAA and CNAME
records get a Proxied / DNS only toggle in the form and a cloud icon
in the table. The proxy field only goes to the API when the caller
sets it, so an update from another path cannot silently disable the
proxy.

Tests cover the MX priority round trip and the proxy rules in the
Cloudflare client.
@dosubot dosubot Bot added the size:XXL This PR changes 1000+ lines, ignoring generated files. label Aug 21, 2026
Comment thread packages/server/src/utils/dns/cloudflare.ts
Comment thread apps/dokploy/components/dashboard/settings/dns/show-dns-records.tsx
logical-tech and others added 6 commits August 21, 2026 11:47
Cloudflare treats content as read-only for SRV and CAA and expects a
data object instead, so both types were rejected on write. The client
now parses the inline value into the fields Cloudflare wants, and
builds the payload before the lookup request so a malformed value
fails without spending an API call.

The form rejects a malformed SRV or CAA value up front and shows the
expected shape, so the error lands on the field instead of coming
back from the provider.
Filtering from a later page left pageIndex past the end of the
filtered set, so the table said no records matched while the counter
above it reported matches. The page index is clamped to the available
page count, and changing the search or the type filter goes back to
the first page.
Route53 returns a record set as a list of values, but listing joined them
into one string and writing sent that string back as a single
ResourceRecord. Editing a multi-value NS, MX or TXT set therefore either
failed validation or collapsed the set into one bogus value, and creating
a record for a name that already had values replaced them silently.

Values are now newline separated end to end: listing joins with a
newline, writing splits back into one ResourceRecord per line, and
creating merges into the existing set instead of replacing it. Unquoted
TXT values get the quotes Route53 requires. The record panel shows a
textarea for Route53 and validates every line.
@Siumauricio
Siumauricio merged commit 78fe5e3 into Dokploy:canary Sep 1, 2026
3 of 4 checks passed
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

size:XXL This PR changes 1000+ lines, ignoring generated files.

Projects

None yet

Development

Successfully merging this pull request may close these issues.

2 participants