Skip to content
Six pink braided cables fan in from different angles and converge on a single compact module glowing indigo on dark slate
Security & SSL

One VIP, Many Domains: HTTPS Multi-Tenancy with SNI

There was a time when every HTTPS site needed its own IP address. The certificate had to be chosen before the client said which site it wanted, so the only way to know was to give each site somewhere different to connect to. Hosting forty customer domains meant forty public addresses, and a conversation with your provider about the next block.

Server Name Indication ended that, and it did so long enough ago that most people now take it for granted. Which is fine, right up until the afternoon a customer points their DNS at your VIP a day early, every visitor gets a full-page certificate warning bearing your hostname, and their marketing director rings.

This is how SNI works on Tula, how to structure certificates when you are serving many domains from one address, and the handful of things that only bite in a multi-tenant setup.

What SNI actually does

TLS has a chicken-and-egg problem: the server has to present a certificate before the encrypted session exists, but which certificate depends on which hostname the client wants — and the hostname is in the HTTP request, which does not exist yet.

SNI solves it by having the client state the hostname it is looking for in the ClientHello, the very first message of the handshake, before encryption begins. The server reads it, picks the matching certificate, and the handshake proceeds normally.

On Tula this is the mechanism that lets multiple HTTPS sites share a single VIP and IP address: HAProxy matches the incoming SNI hostname to the appropriate certificate. You assign a certificate for each domain under Load Balancing > L7 Virtual IPs, along with one certificate that has a special job.

Two consequences of the design are worth holding onto, because both come up later.

The hostname travels in the clear. The ClientHello is unencrypted by definition, so the name of the site being requested is visible to anything on the path. TLS still protects the content; it does not conceal which site you visited. For most hosting this is unremarkable — the DNS query was in the clear too — but if you serve anything where the identity of the site is sensitive, SNI is not the place to hide it.

The client has to send it. Every browser in current use does. Some older embedded clients, some monitoring probes, and some scripts written against ancient libraries do not, and those clients are what the default certificate exists for.

The default certificate, and why it deserves more thought than it gets

Tula requires a default certificate on the VIP. It is used when the client does not send an SNI header, or when it sends one that matches nothing you have configured.

That second clause is the one that matters, and it is easy to read past. A hostname you have not configured does not produce a clean, obvious error. It produces your default certificate, served confidently to a client that asked for something else — which the client then rejects, because the name does not match, with a full-page browser interstitial naming whatever hostname your default certificate carries.

So the default certificate is not a fallback in the sense of “something sensible happens”. It is the thing every misdirected request in the world will be answered with, and its name is the one that appears in the warning.

Choose it deliberately:

  • Use a hostname you own and control, on infrastructure you are happy to have named in an error message.
  • Do not use a customer’s certificate, however tempting it is to pick the first one in the list. One customer’s domain appearing in another customer’s browser warning is a conversation nobody wants.
  • Monitor its expiry like any other, remembering that it serves the least-visible traffic on the VIP — which means its expiry will be noticed last, by whoever is least equipped to diagnose it.

The failure nobody rehearses: DNS arriving before the certificate

Here is the multi-tenant failure that catches people, and it needs no mistake on your part at all.

You agree to onboard a customer on Thursday. On Tuesday, keen and helpful, they repoint their DNS to your VIP.

Traffic arrives. There is no certificate for their hostname yet, so no SNI match, so the default certificate is served. Every visitor to their site — customers, their own staff, Google — receives a browser security warning naming your infrastructure. From the outside this looks exactly like your platform breaking their site, on a day you had not agreed to do anything.

It is entirely avoidable, and the fix is sequencing:

  1. Issue the certificate before the DNS moves. With DNS-01 validation you can obtain a certificate for a hostname that does not yet point at you — which is precisely what the challenge is for.
  2. Configure the SNI certificate on the VIP and confirm it is being served, by connecting to the VIP directly with the hostname overridden.
  3. Only then tell the customer to repoint.

Get that order right and the cutover is invisible. Get it wrong and it is visible to everyone except you, because your monitoring is watching hostnames you know about.

Wildcards, SAN certificates, and one certificate per domain

Three ways to cover many names, with genuinely different trade-offs.

One certificate per domain. Each hostname gets its own certificate, its own renewal, its own expiry. Most work to set up, least coupling: a failure affects exactly one tenant.

A wildcard certificate. .example.com matches any subdomain, which makes onboarding new subdomains free — no issuance at all, just a routing rule. Two caveats: a wildcard matches one label only, so .example.com covers a.example.com but not a.b.example.com; and a wildcard requires DNS-01 validation, so it comes with the DNS credential considerations that entails.

A SAN certificate carrying many names on one certificate. Fewer objects to manage — and, in a multi-tenant context, a mistake.

That last point deserves stating plainly, because it is not obvious and it is not reversible. Every certificate issued by a public CA is published to Certificate Transparency logs, permanently and publicly. Put forty customer domains as Subject Alternative Names on one certificate and you have published, in a single searchable record, a list of exactly who your customers are — to your customers, to your competitors, and to anyone who watches CT logs for a living. It is a customer list, and you have filed it.

There is an operational argument too: every renewal of a SAN certificate revalidates every name on it, so one customer’s DNS mistake can fail the renewal for all forty. But the disclosure is the reason not to do it.

Approach Use when Watch out for
One certificate per domain Multi-tenant hosting, unrelated customer domains More objects; automate issuance or it will not scale
Wildcard Many subdomains of a domain you own Matches one label only; needs DNS-01
SAN (multiple names) A handful of names you own that belong together CT logs publish the whole list; one bad name fails every renewal

Chains: the classic “works in my browser” failure

Tula requires the complete chain — the server certificate plus any intermediates — and this is where a certificate that looks fine can still be broken.

Browsers are forgiving. If an intermediate is missing, many will fetch it themselves or use one they cached from another site, and the padlock appears anyway. curl, older Java clients, mobile SDKs, payment gateways and monitoring probes are not forgiving. They fail, and they fail for a subset of clients, and the subset does not include the developer’s laptop.

That asymmetry is why “I checked in Chrome” is not a test. Verify the chain the way an unforgiving client sees it:

openssl s_client -connect <vip>:443 -servername app.example.com -showcerts </dev/null 2>/dev/null \
  | grep -E 's:|i:'

You should see a chain that walks from your certificate up through the intermediate. If it stops at your certificate, the chain is incomplete regardless of what your browser says.

Cipher and protocol policy in a shared world

TLS versions and cipher suites are configured through the VIP’s SSL settings, and the recommendation is straightforward: disable TLS 1.0 and 1.1 and the weak cipher suites.

In multi-tenancy, “straightforward” acquires a tenant dimension. The policy applies to the VIP, and the VIP is shared. If one customer has an integration partner stuck on an obsolete client, the choice is not theirs alone — it is whether the whole VIP relaxes for everybody.

Three options, in descending order of preference:

  1. Hold the line. The partner updates. This is the right answer and sometimes it is even achievable.
  2. Separate VIP. Move the tenant with the legacy requirement onto their own VIP with its own policy, so their compromise is theirs alone. This costs an address and is the honest way to say yes.
  3. Relax the shared VIP. Every other tenant now runs with weakened settings because of somebody else’s supplier, and they have not been asked. Avoid.

Deciding this once, in advance, is much easier than deciding it while a customer’s biggest client is escalating.

A worked example: onboarding forty customers

Numbers make the certificate strategy concrete. Suppose you are bringing forty customer sites onto one VIP.

If each customer brings their own domain — acme-tools.co.uk, bright-widgets.com and so on — then each is a separate registered domain as far as the CA is concerned. Let’s Encrypt’s limit of 50 certificates per registered domain per week applies to each independently, so forty separate customers is forty separate allowances. You could onboard all forty in an afternoon and touch nothing.

If instead you host them as subdomains of your own domain — acme.hosting.example.com and so on — every one of them draws on the same weekly allowance for example.com. Forty is fine; the fifty-first that week is not. Onboard sixty over a weekend and you will stop at fifty with no way to hurry it.

That is the entire argument for a wildcard in the second case: *.hosting.example.com is one certificate, issued once, that covers every subdomain you will ever add, with no per-customer issuance and no allowance to exhaust.

So the strategy follows from whose domain it is:

  • Customers’ own domains → one certificate each, automated. Rate limits are irrelevant.
  • Subdomains of yours → a wildcard. Onboarding becomes a routing rule.
  • A mix → both, on the same VIP. Nothing prevents it.

What sharing an address actually costs

SNI removes the need for one address per site. It does not remove the consequences of tenants sharing one, and those consequences are worth naming before a customer discovers them for you.

Shared reputation. The VIP’s address is the address every tenant appears to send from. If one tenant’s site is compromised and starts serving something unpleasant, blocklists and reputation services do not list the hostname — they list the IP. Every other tenant on that address inherits the listing, and none of them did anything.

Shared blocking. The same asymmetry applies whenever anyone blocks you. A corporate firewall, a national filter or an irritated network administrator blocking one tenant’s site blocks the address, and takes the other thirty-nine with it. Those tenants have no visibility into why, and neither will your first line of support.

Shared attack surface. A volumetric attack aimed at one tenant arrives at an address serving all of them. Mitigation that would be proportionate for one site — rate limits, geographic restrictions, challenge pages — now applies to everybody, or to nobody.

Shared policy. As above with TLS versions and ciphers: the settings belong to the VIP, and the VIP is shared.

Shared fate during maintenance. Anything that takes the VIP out takes every tenant out. This is exactly what the HA pair is for, and it is also why “we’ll just move this VIP to the other node quickly” is a bigger decision in a multi-tenant setting than a single-tenant one.

None of this is an argument against SNI — the alternative is forty public addresses, which solves none of the operational problems and creates several of its own. It is an argument for knowing which risks you have pooled, and for being able to say so when a customer asks why their site was unreachable from one particular office.

When a tenant genuinely needs their own address

Occasionally the answer to “can we have a dedicated IP?” is yes, and it helps to know in advance which reasons are real.

Reason given Real?
“Our integration partner allowlists by IP” Yes — a shared address means allowlisting your whole platform, and a change affects everyone on it
“We need TLS 1.0 for a legacy client” Yes, if you are not relaxing the shared VIP — a separate VIP is the honest way to say yes
“Some of our clients’ devices don’t support SNI” Yes — those clients will always receive the default certificate
“We want to be isolated from other customers’ reputation” Yes, and increasingly the most common real reason
“We need our own IP for SEO” No — search engines have not cared for many years
“Dedicated IP is more secure” No, not by itself — the TLS is identical either way
“We need it for a dedicated SSL certificate” No — that is precisely what SNI removed the need for

The first four are worth honouring, and worth pricing. The last three come up constantly and are worth answering patiently once, in writing, so your support team can point at it.

A note on the hostname being visible

It is worth being straight with customers who ask about this, because the honest answer is more reassuring than a vague one.

The hostname in the ClientHello is unencrypted, so an observer on the network path can see which site a client connected to, though not what was sent or received. That has been true of every TLS connection since SNI became universal, and the same observer could already see the DNS lookup that preceded it. It is not a weakness introduced by sharing a VIP — a single-tenant address leaks the same information more directly, since the address itself identifies the site.

Encrypted Client Hello exists to close that gap and is gradually appearing in clients and infrastructure. Until it is widespread, the accurate statement to a customer is: the content of their traffic is protected, the fact that a visit happened is not, and moving them to a dedicated address would make that more visible rather than less.

Symptoms and causes

Symptom Likely cause
Browser warning naming your hostname on a customer’s site No certificate for that hostname; the default certificate is being served
Works in a browser, fails from curl or a Java client Incomplete chain — the browser is filling in the intermediate
One old client cannot connect at all, everything else fine Client without SNI support, hitting the default certificate
A customer’s subdomain-of-a-subdomain fails Wildcard matches one label only
Renewal failing for forty domains at once SAN certificate; one name on it no longer validates
Certificate correct, still warned about Name mismatch — check the SNI name actually sent, not the URL typed
Cannot issue any more certificates this week Rate limit against one registered domain — the subdomain case above
Everything fine until an obscure integration breaks TLS version or cipher policy tightened on a shared VIP

Test it properly

Testing HTTPS multi-tenancy means testing by hostname, not by URL, and testing the paths nobody visits.

1. Confirm each hostname gets its own certificate. Connect to the VIP directly and override the name, so you are testing the VIP rather than whatever DNS currently says:

openssl s_client -connect <vip>:443 -servername app.example.com </dev/null 2>/dev/null \
  | openssl x509 -noout -subject -dates

Repeat for every tenant. This is the check that catches a certificate configured against the wrong VIP.

2. Confirm the default certificate is what you intended. Connect with no SNI at all and see what comes back:

openssl s_client -connect <vip>:443 </dev/null 2>/dev/null | openssl x509 -noout -subject

If that returns a customer’s name, fix it today.

3. Confirm an unknown hostname behaves as you expect. Request a name you have not configured, and confirm you get the default certificate rather than something surprising — this is the onboarding failure above, rehearsed deliberately.

4. Verify the chain from a clean trust store, not a browser.

5. Check expiry across every certificate on the VIP, including the default one. The default is the one that will be forgotten.

6. Test the oldest client you actually support. If a customer integration runs on something ancient, find out now whether it sends SNI, rather than during their peak trading week.

In short

SNI turns “one IP per HTTPS site” into “one VIP, as many domains as you like”, and on Tula that is a matter of assigning certificates and letting HAProxy match. The parts that need judgement are all about multi-tenancy rather than TLS: choose a default certificate you own and monitor it, issue certificates before customers move their DNS, keep customer domains on separate certificates so Certificate Transparency does not publish your client list, and decide your protocol policy before a tenant’s supplier decides it for you.

Get those right and adding the forty-first domain is a five-minute job.

Further reading: certificate management, the Let’s Encrypt guide for automating issuance, and SSL termination best practices.

CategoriesSecurity & SSL
Avatar photo

Alison Ivers

Leave a comment