TLSA record creation fails using Spaceship DNS provider

Issue Description

When enabling automatic DNS management and explicitly enabling TLSA records under Record Types, the Perform DNS management for a domain fails, giving an API error.

Expected Behavior

Stalwart should create the relevant TLSA records, as it does with the rest of the DNS records when set to automatically manage them.

Actual Behavior

TLSA records and any DNS records that are queued afterwards within the same task do not get created, updated, etc. Thus, this breaks all auto DNS management.

Reproduction Steps

  1. Acquire a Spaceship domain name.
  2. Under Management → Domains → , enable Automatic DNS management.
  3. Set it to use the Spaceship API and explicitly enable TLSA records under Record Types.
  4. Save the settings, causing the task to automatically start.
  5. Observe the task fail.

Relevant Log Output

Failed to set DNS RRSet for _995._tcp.mail.example.com./TLSA: Failed to set DNS RRSet: API error: HTTP 422: {"detail":"Request validation error.","data":[{"details":"Port should be equal asterisk or must start with an underscore and have a number between 1 and 65535","field":"items[0].port"},{"details":"Port should be equal asterisk or must start with an underscore and have a number between 1 and 65535","field":"items[1].port"},{"details":"Port should be equal asterisk or must start with an underscore and have a number between 1 and 65535","field":"items[2].port"},{"details":"Port should be equal asterisk or must start with an underscore and have a number between 1 and 65535","field":"items[3].port"}]}; Failed to set DNS RRSet for _443._tcp.mta-sts.example.com./TLSA: Failed to set DNS RRSet: API error: HTTP 422: {"detail":"Request validation error.","data":[{"details":"Port should be equal asterisk or must start with an underscore and have a number between 1 and 65535","field":"items[0].port"},{"details":"Port should be equal asterisk or must start with an underscore and have a number between 1 and 65535","field":"items[1].port"},{"details":"Port should be equal asterisk or must start with an underscore and have a number between 1 and 65535","field":"items[2].port"},{"details":"Port should be equal asterisk or must start with an underscore and have a number between 1 and 65535","field":"items[3].port"}]}; Failed to set DNS RRSet for _25._tcp.mail.example.com./TLSA: Failed to set DNS RRSet: API error: HTTP 422: {"detail":"Request validation error.","data":[{"details":"Port should be equal asterisk or must start with an underscore and have a number between 1 and 65535","field":"items[0].port"},{"details":"Port should be equal asterisk or must start with an underscore and have a number between 1 and 65535","field":"items[1].port"},{"details":"Port should be equal asterisk or must start with an underscore and have a number between 1 and 65535","field":"items[2].port"},{"details":"Port should be equal asterisk or must start with an underscore and have a number between 1 and 65535","field":"items[3].port"}]}; Failed to set DNS RRSet for _443._tcp.mail.example.com./TLSA: Failed to set DNS RRSet: API error: HTTP 422: {"detail":"Request validation error.","data":[{"details":"Port should be equal asterisk or must start with an underscore and have a number between 1 and 65535","field":"items[0].port"},{"details":"Port should be equal asterisk or must start with an underscore and have a number between 1 and 65535","field":"items[1].port"},{"details":"Port should be equal asterisk or must start with an underscore and have a number between 1 and 65535","field":"items[2].port"},{"details":"Port should be equal asterisk or must start with an underscore and have a number between 1 and 65535","field":"items[3].port"}]}; Failed to set DNS RRSet for _443._tcp.autodiscover.example.com./TLSA: Failed to set DNS RRSet: API error: HTTP 422: {"detail":"Request validation error.","data":[{"details":"Port should be equal asterisk or must start with an underscore and have a number between 1 and 65535","field":"items[0].port"},{"details":"Port should be equal asterisk or must start with an underscore and have a number between 1 and 65535","field":"items[1].port"},{"details":"Port should be equal asterisk or must start with an underscore and have a number between 1 and 65535","field":"items[2].port"},{"details":"Port should be equal asterisk or must start with an underscore and have a number between 1 and 65535","field":"items[3].port"}]}; Failed to set DNS RRSet for _443._tcp.ua-auto-config.example.com./TLSA: Failed to set DNS RRSet: API error: HTTP 422: {"detail":"Request validation error.","data":[{"details":"Port should be equal asterisk or must start with an underscore and have a number between 1 and 65535","field":"items[0].port"},{"details":"Port should be equal asterisk or must start with an underscore and have a number between 1 and 65535","field":"items[1].port"},{"details":"Port should be equal asterisk or must start with an underscore and have a number between 1 and 65535","field":"items[2].port"},{"details":"Port should be equal asterisk or must start with an underscore and have a number between 1 and 65535","field":"items[3].port"}]}; Failed to set DNS RRSet for _443._tcp.autoconfig.example.com./TLSA: Failed to set DNS RRSet: API error: HTTP 422: {"detail":"Request validation error.","data":[{"details":"Port should be equal asterisk or must start with an underscore and have a number between 1 and 65535","field":"items[0].port"},{"details":"Port should be equal asterisk or must start with an underscore and have a number between 1 and 65535","field":"items[1].port"},{"details":"Port should be equal asterisk or must start with an underscore and have a number between 1 and 65535","field":"items[2].port"},{"details":"Port should be equal asterisk or must start with an underscore and have a number between 1 and 65535","field":"items[3].port"}]}; Failed to set DNS RRSet for _465._tcp.mail.example.com./TLSA: Failed to set DNS RRSet: API error: HTTP 422: {"detail":"Request validation error.","data":[{"details":"Port should be equal asterisk or must start with an underscore and have a number between 1 and 65535","field":"items[0].port"},{"details":"Port should be equal asterisk or must start with an underscore and have a number between 1 and 65535","field":"items[1].port"},{"details":"Port should be equal asterisk or must start with an underscore and have a number between 1 and 65535","field":"items[2].port"},{"details":"Port should be equal asterisk or must start with an underscore and have a number between 1 and 65535","field":"items[3].port"}]}; Failed to set DNS RRSet for _993._tcp.mail.example.com./TLSA: Failed to set DNS RRSet: API error: HTTP 422: {"detail":"Request validation error.","data":[{"details":"Port should be equal asterisk or must start with an underscore and have a number between 1 and 65535","field":"items[0].port"},{"details":"Port should be equal asterisk or must start with an underscore and have a number between 1 and 65535","field":"items[1].port"},{"details":"Port should be equal asterisk or must start with an underscore and have a number between 1 and 65535","field":"items[2].port"},{"details":"Port should be equal asterisk or must start with an underscore and have a number between 1 and 65535","field":"items[3].port"}]}

Stalwart Version

v0.16.x

Installation Method

Docker

Database Backend

RocksDB

Blob Storage

RocksDB

Search Engine

Internal

Directory Backend

Internal

I have reviewed the documentation and FAQ and confirm that my issue is NOT addressed there.

on

I have searched this support forum (open and closed topics) and confirm this is not a duplicate.

on

I understand that topics in this category are triaged by a bot first but a human reply will follow up. If I’d prefer a human-only reply, I’ll add the no-ai tag to my topic.

on

This looks like a bug in the underlying dns-update crate’s Spaceship provider integration, not a configuration mistake on your end. Looking at Stalwart’s DNS record builder (crates/common/src/network/dns/records.rs), TLSA records are generated as owner names like _<port>._tcp.<hostname>. with a numeric port (e.g. _995._tcp.mail...), which is the standard RFC 6698 TLSA naming convention. The error is coming back from Spaceship’s own API validation (“Port should be equal asterisk or must start with an underscore and have a number between 1 and 65535”), which suggests the dns-update crate is submitting the port field to Spaceship’s API in a format Spaceship’s validator doesn’t accept (it appears to want the underscore-prefixed value, e.g. _995, rather than a bare 995, in the port field it sends to Spaceship, separate from the record name).

Since the record-building logic in Stalwart itself looks correct, the fix would need to happen in the dns-update crate’s Spaceship provider implementation (the piece that translates Stalwart’s TLSA record into Spaceship’s API request body). This isn’t something you can work around from the WebUI/config side; disabling TLSA in “Record Types” for that domain is the only current workaround while this gets fixed upstream.

A human or staff member will follow up on this report since it appears to be a genuine provider-integration bug rather than a documented behavior.

This is an automated reply from the Stalwart Help Bot. Other community members may follow up if this answer is incomplete or wrong.

Seems to be correct. Spaceship expects the following schema for TLSA records:
Fields: usage, selector,matching (each 0–255); port* or _<1–65535>; protocol (e.g. _tcp); associationData — certificate hash or data. (from their docs). This seems to suggest it expects ports as strings with a prefixed underscore, like _995 or _25.

Created an issue on the dns-update crate: TLSA record creation on Spaceship fails: ports should be underscore-prefixed · Issue #81 · stalwartlabs/dns-update · GitHub .

Would appreciate if someone involved in Stalwart could back this up :slight_smile: