Should we follow the old traefik port expose convention? #9

Open
opened 2026-08-13 13:50:22 +00:00 by decentral1se · 2 comments
Owner

This part here in this repository:

stalwart/compose.yml Lines 8 to 23 in 366993eadd
- target: 25
published: 25
protocol: tcp
mode: host
- target: 465
published: 465
protocol: tcp
mode: host
- target: 587
published: 587
protocol: tcp
mode: host
- target: 993
published: 993
protocol: tcp
mode: host

Is usually solved by exposing that via Traefik, e.g.

ports:
- target: 587
published: 587
protocol: tcp
mode: host

Shall I submit a PR to transfer that over? Or does it make sense now to keep that in the recipe repository now that our traefik recipe does host publishing by default in coop-cloud/traefik#88? I am not sure.

This part here in this repository: https://git.coopcloud.tech/coop-cloud/stalwart/src/commit/366993eadddb02ea23e2bb4336941ec5e6b1b353/compose.yml#L8-L23 Is usually solved by exposing that via Traefik, e.g. https://git.coopcloud.tech/coop-cloud/traefik/src/commit/063e6b4a5a05c1915aa86c61772f6de15b23f0d9/compose.smtp.yml#L8-L12 Shall I submit a PR to transfer that over? Or does it make sense now to keep that in the recipe repository now that our traefik recipe does host publishing by default in https://git.coopcloud.tech/coop-cloud/traefik/pulls/88? I am not sure.
Owner

Thanks for raising this! I'm aware of this convention, but there is also e.g. mailu recipe that publishes the same ports in host mode.

My thoughts:

  • You should only run one mail server on a public IP address anyway. It needs a valid DNS PTR record.
  • Ports 25 and 587 use STARTTLS, so Traefik can't route by SNI or terminate TLS here. Only blind forwarding is possible, so not adding much value. This also means Stalwart needs a cert for these two ports.
  • Ports 465 and 993 use implicit TLS. Traefik could technically terminate TLS here, but then the cert a client sees comes from Traefik, which complicates automated updating of TLSA records. Better to have Stalwart doing ACME for all mail ports, independently of Traefik's cert for 443. Alternatively, we could add a traefik-certs-dumper sidecar with a shared volume to copy Traefik's cert into Stalwart, with a post-action to reload on renewal. But that's a more complicated, error-prone path.
  • Publishing TLSA records for the mail ports is standardised in RFCs. With Let's Encrypt certs, that's only really practical with automated DNS updates, which Stalwart can do (also for auto-rotating DKIM keys). Another reason to have Stalwart manage certs for all non-443 ports itself.
  • Side note: while testing this, I found Stalwart's TLSA-record generator resolves a certificate per hostname independent of what's actually served on that port. For 443, it suggests TLSA data for the wrong cert, because it has no access to Traefik's cert store. This is still something that might need reporting upstream at Stalwart.

So I'm leaning towards keeping things as they are, but we could move all these ports to Traefik with TLS passthrough configured in labels if there's a reason to go that way.

Thanks for raising this! I'm aware of this convention, but there is also e.g. [mailu recipe](https://git.coopcloud.tech/coop-cloud/mailu/src/branch/main/compose.yml#L65) that publishes the same ports in host mode. My thoughts: - You should only run one mail server on a public IP address anyway. It needs a valid DNS PTR record. - Ports 25 and 587 use STARTTLS, so Traefik can't route by SNI or terminate TLS here. Only blind forwarding is possible, so not adding much value. This also means Stalwart needs a cert for these two ports. - Ports 465 and 993 use implicit TLS. Traefik could technically terminate TLS here, but then the cert a client sees comes from Traefik, which complicates automated updating of TLSA records. Better to have Stalwart doing ACME for all mail ports, independently of Traefik's cert for 443. Alternatively, we could add a traefik-certs-dumper sidecar with a shared volume to copy Traefik's cert into Stalwart, with a post-action to reload on renewal. But that's a more complicated, error-prone path. - Publishing TLSA records for the mail ports is standardised in RFCs. With Let's Encrypt certs, that's only really practical with automated DNS updates, which Stalwart can do (also for auto-rotating DKIM keys). Another reason to have Stalwart manage certs for all non-443 ports itself. - Side note: while testing this, I found Stalwart's TLSA-record generator resolves a certificate per hostname independent of what's actually served on that port. For 443, it suggests TLSA data for the wrong cert, because it has no access to Traefik's cert store. This is still something that might need reporting upstream at Stalwart. So I'm leaning towards keeping things as they are, but we could move all these ports to Traefik with TLS passthrough configured in labels if there's a reason to go that way.
Author
Owner

Very nice. Thanks for explaining that! I guess a line in that config file or something in the README.md to point to this issue will be enough for you not to receive another issue raised about this 😆

Very nice. Thanks for explaining that! I guess a line in that config file or something in the `README.md` to point to this issue will be enough for you not to receive another issue raised about this 😆
Sign in to join this conversation.
No labels
2 Participants
Notifications
Due Date
No due date set.
Dependencies

No dependencies set.

Reference: coop-cloud/stalwart#9