Skip to content

fix(tailscale): select HTTPS listeners by TLS provider - #519

Open
clwsgruk wants to merge 2 commits into
almeidapaulopt:mainfrom
clwsgruk:fix/custom-domain-https-listener
Open

clwsgruk wants to merge 2 commits into
almeidapaulopt:mainfrom
clwsgruk:fix/custom-domain-https-listener

Conversation

@clwsgruk

Copy link
Copy Markdown

This pull request was prepared and submitted by an AI assistant acting on behalf of @jnsgruk.

Summary

Fix per-proxy custom-domain HTTPS when using an external TLS provider such as ACME.

  • Propagate the resolved TLS provider to traffic exposure.
  • Use a raw tsnet listener only when external TLS termination is required.
  • Preserve ListenTLS and Funnel behavior for Tailscale-managed TLS.
  • Reject the unsupported combination of external custom TLS and Funnel.
  • Add regression coverage for defaults, aliases, fallback behavior, errors and cleanup.

Problem

Per-proxy HTTPS listeners are currently always created with tsnet.Server.ListenTLS(). For a custom domain using ACME, the proxy manager instead needs the underlying raw listener so it can terminate TLS with the custom-domain certificate.

The mismatch causes domain setup to fail with:

get raw tcp listener: proxy port not found

Listener selection now uses the resolved TLS provider rather than simply checking whether a domain is configured.

Example setup

Cloudflare provides DNS only; traffic remains inside the tailnet.

 Cloudflare DNS (DNS-only)
 quartz.jnsgr.dev ---- CNAME ----> quartz.<tailnet>.ts.net
 notes.jnsgr.dev  ---- CNAME ----> notes.<tailnet>.ts.net
                                      |
 Tailnet client                       | HTTPS via Tailscale
      |                               |
      +-------------------------------+
                                      v
 +----------------------- Docker host -----------------------+
 |                                                           |
 |  +------------------- TSDProxy container ---------------+ |
 |  | Per-proxy tsnet nodes                                | |
 |  |   quartz     notes      tsdproxy      matrix         | |
 |  |      |         |           |             |           | |
 |  +------|---------|-----------|-------------|-----------+ |
 |         |         |           |             |             |
 |  +------v---+ +---v------+ +--v------+ +----v---------+  |
 |  | quartz-  | | notes-   | | TSDProxy| | matrix-proxy |  |
 |  | web      | | web      | | :8080   | +-------+-------+  |
 |  +----------+ +----------+ +---------+         |          |
 |                                      +---------v--------+ |
 |                                      | Continuwuity     | |
 |                                      +------------------+ |
 +-----------------------------------------------------------+

For the custom domains, TSDProxy accepts a raw tsnet connection and terminates TLS using the ACME certificate. Matrix continues to use Tailscale-managed TLS through ListenTLS.

Testing

  • go test -race -count=1 ./...
  • go vet ./...
  • golangci-lint on the changed packages
  • Live per-proxy deployment with Docker, Tailscale, Cloudflare DNS and ACME

Full-repository golangci-lint currently reports five pre-existing issues on the base commit; the changed packages report zero issues.

@clwsgruk
clwsgruk force-pushed the fix/custom-domain-https-listener branch from ff4053c to be7e8e1 Compare September 14, 2026 20:36
@almeidapaulopt

Copy link
Copy Markdown
Owner

@clwsgruk Could you rebase this onto current main? The GitHub build workflow has never run on this PR (first-contribution workflow approval gating), and a rebase would re-trigger CI so the merge decision has a fresh build behind it. The change itself reviewed well — just want the green check on record before merging.

@clwsgruk
clwsgruk force-pushed the fix/custom-domain-https-listener branch from be7e8e1 to 0fa7770 Compare October 14, 2026 09:18
@jnsgruk

jnsgruk commented Oct 14, 2026

Copy link
Copy Markdown

@almeidapaulopt done!

This branch has not been deployed

No deployments
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

3 participants