Skip to content

Serve multiple domains with TLS

One load balancer, one public address, port 443, several domains going to different places. Each name gets its own certificate, obtained and renewed for you.

A listener is a routing rule, not a socket. It carries a port and a hostname, so several listeners share a port:

PortHostnameTarget
443app.example.comKubernetes cluster, NodePort 30080
443s3.example.comstorage nodes
443api.example.orgservers 10.x.y.10:8080, 10.x.y.11:8080

Under the hood this is one HAProxy front end with three routing rules and three back ends. You never see that.

  • Each domain is in your account with DNS hosted here
  • A load balancer, public or internal

Ağ → Yük Dengeleyiciler, open the load balancer, Dinleyici Ekle (Add listener).

FieldValue
Port443
Alan adıapp.example.com
TLS burada sonlansınticked
Hedefcluster or servers

Same port, different hostname. The panel accepts it. Each one gets its own certificate record.

For each name, either create an A record pointing at the load balancer’s address, or use the LB control on the DNS records screen, which creates the listener and points the record in one step.

Each listener shows its own certificate status. Issuance takes minutes: the challenge record has to be published and seen by public resolvers before Let’s Encrypt is asked to check.

One protocol per port. All listeners on 443 are either all https or all tcp. The API refuses a mix, because HAProxy can only do it through a two-stage loop-back arrangement — technically possible, impossible to reason about from a panel.

A default is optional. A listener with an empty hostname is the fallback for that port. With no default, a request for an unknown name is rejected rather than silently served by whichever backend happens to be first. That is usually what you want.

tcp with a hostname routes by SNI. Nothing is decrypted, so only the TLS handshake’s server name is available. It works for TLS clients and only for them.

Reusing a hostname reuses its certificate. Putting the same name on a second listener does not request a duplicate — which also keeps you inside Let’s Encrypt’s limit of five identical certificates per week.

Turn on Proxy’li for any of these records if you want to hide your origin address. Nothing breaks:

  • The certificate keeps renewing, because the ACME challenge is a TXT record and TXT records are never proxied.
  • The panel never writes the proxy flag — when it points a record at a load balancer it reads your existing setting and writes it back unchanged.

Set Cloudflare’s SSL mode to Full (strict); your load balancer presents a valid certificate, so strict validation passes. See Using zone9 with Cloudflare.

“bu portta zaten bir dinleyici var”. You used the same port and the same hostname twice, or left the hostname empty on a port that already has a default.

“bir portun bütün dinleyicileri aynı protokolde olmalı”. You are adding an https listener to a port that already has a tcp one, or the reverse.

“alan adının DNS’i bizde değil”. The domain is in your account but its DNS is hosted elsewhere. Certificate issuance needs to write a challenge record.

The certificate keeps failing. Read the error on the listener. After fixing the cause use the explicit retry, which clears the exponential backoff — otherwise the next attempt may be hours away, by design.