Virtual hosts
Put host blocks inside a binding to dispatch by the
Host header on a single shared socket. Each host block matches one or more
host patterns and has its own routes; a request whose host matches
no block falls back to the binding's direct routes — the default vhost.
binding ":443" {
tls cert="./cert.pem" key="./key.pem"
host "app.example.com" {
route "/*" {
proxy {
upstream "http://127.0.0.1:9000"
}
}
}
host "*.static.example.com" {
route "/*" {
files root="./public"
}
}
// default vhost: unmatched hosts (and Host-less requests)
route "/*" {
redirect "https://example.com" status=308
}
}
Host patterns
A host block takes one or more patterns as arguments. Matching is
case-insensitive and ignores any port in the Host header.
| Pattern | Matches |
|---|---|
example.com | exactly that host |
*.example.com | any single-or-multi-label subdomain |
* | any host |
A block can list several:
host "example.com" "www.example.com" {
route "/*" {
files root="./public"
}
}
The default vhost
The binding's direct route blocks (those not inside any host) serve as the
fallback for any request whose Host matches no block. This also catches
requests with no Host header — for example HTTP/1.0 clients. A binding
with no host blocks is just a plain set of routes (the behavior described in
Routing).
This works uniformly across HTTP/1.1, HTTP/2, and HTTP/3: the gateway resolves
the host from the Host header or, for h2/h3, the :authority pseudo-header.
Per-host TLS (SNI)
A host block can carry its own tls certificate, selected by the TLS
ClientHello's SNI on the shared socket. The binding-level tls (if present) is
the fallback for unmatched SNI.
binding ":443" {
// fallback certificate for unmatched SNI
tls cert="./default.pem" key="./default-key.pem"
host "a.example.com" {
tls cert="./a.pem" key="./a-key.pem"
route "/*" {
files root="./site-a"
}
}
host "b.example.com" {
tls cert="./b.pem" key="./b-key.pem"
route "/*" {
files root="./site-b"
}
}
}
The same certificate resolver feeds both the rustls acceptor and (with the h3
feature) the QUIC/HTTP/3 listener, so per-host certificate selection works
identically on HTTP/1.1, HTTP/2, and HTTP/3.
SNI selects the certificate during the TLS handshake; the Host header (or
:authority) selects the routes after the connection is established. They
usually name the same host, but they're resolved separately — a binding-level
fallback certificate can still terminate TLS for a request that then falls
through to the default vhost.