How one server hosts multiple domains
Imagine you are running a VPS with a single public IP like 203.0.113.10. On this machine, you want to host two separate web sites:
- orion.example.net
- atlas.example.com
When a user types either domain, DNS points both of them to the same IP address. So how does the server know which project to serve?
HTTP Host Header
In a plain HTTP request, the browser identifies the target using the Host header. Even though the TCP connection is made to an IP address, the browser still explicitly tells the server which domain it wants:
GET / HTTP/1.1
Host: orion.example.net
Then the web server, such as Nginx, uses configuration blocks to match that hostname. For example:
server {
listen 80;
server_name orion.example.net;
root /var/www/orion;
}
server {
listen 80;
server_name atlas.example.com;
root /var/www/atlas;
}
If the request contains Host: orion.example.net, Nginx serves files from /var/www/orion. It is basically straightforward string matching at the HTTP layer.
HTTPS and SNI
With HTTPS, there is a problem. The server must present a TLS certificate before the encrypted connection is established. But the Host header is part of the HTTP request, and that request is only sent inside the encrypted tunnel, after the TLS handshake is completed.
This is what Server Name Indication (SNI) solves. SNI is a TLS extension that allows the client to include the target hostname in the Client Hello, early in the TLS handshake, before the HTTP request can be sent. This lets the server choose the correct certificate and continue the handshake, even when multiple HTTPS sites share the same IP address.
The downside is that in traditional TLS this hostname is sent in plaintext, so intermediaries such as ISPs or network administrators can often still see which domain you are connecting to, even though the HTTP content itself remains encrypted. Newer mechanisms such as Encrypted Client Hello (ECH) aim to fix this by encrypting the sensitive parts of the handshake, including the real hostname.
The Request Lifecycle
The full HTTPS flow looks like this:
-
DNS:
orion.example.netresolves to203.0.113.10 -
TCP connection: the client connects to
203.0.113.10:443 -
TLS Client Hello: the client sends
SNI = orion.example.net -
Certificate selection: the server selects the matching certificate
-
TLS handshake completes: the encrypted tunnel is established
-
HTTP request: inside that tunnel, the client sends:
GET / HTTP/1.1 Host: orion.example.net -
Routing: the web server routes the request to the correct site
TL;DR
A single server can host multiple domains on the same IP address because the client tells it which hostname it wants. In plain HTTP, this is done with the Host header. In HTTPS, the server needs that information earlier so it can choose the correct certificate, which is why TLS uses SNI. The downside is that traditional SNI exposes the hostname in plaintext, which is why newer mechanisms such as ECH were introduced.