What changed in Apache 2.4
The old NameVirtualHost directive is gone. Any IP/port pair you Listen on can host name-based virtual hosts; Apache selects a <VirtualHost> using the request’s IP/port tuple and the HTTP Host header (or TLS SNI during handshake for HTTPS). Misunderstanding default-vhost ordering is still one of the most common causes of “wrong site” bugs after migrations.
How Apache picks a vhost
- Find all
<VirtualHost addr:port>blocks matching the local socket endpoint (for example*:443or203.0.113.5:443). - If the request is TLS, use SNI server name to choose among TLS vhosts on that endpoint.
- For HTTP/1.1, compare
Hostagainst each candidate’sServerNameandServerAlias(wildcard patterns allowed). - If no name matches, Apache uses the first listed vhost for that IP/port as the default—make that behavior intentional (catch-all, maintenance page, or 444-style close).
Minimal TLS and plain-HTTP pair
<VirtualHost *:80>
ServerName www.example.com
ServerAlias example.com
Redirect permanent / https://www.example.com/
</VirtualHost>
<VirtualHost *:443>
ServerName www.example.com
DocumentRoot /var/www/example/html
SSLEngine on
SSLCertificateFile /etc/letsencrypt/live/www.example.com/fullchain.pem
SSLCertificateKeyFile /etc/letsencrypt/live/www.example.com/privkey.pem
Include /etc/letsencrypt/options-ssl-apache.conf
</VirtualHost>Certificate SANs must cover every name in ServerAlias served on that socket. Details: Apache SSL configuration.
ServerName, ServerAlias, and useCanonicalName
ServerName sets the canonical hostname for redirects the server generates itself (for example mod_dir trailing-slash redirects). ServerAlias accepts space-separated names, IP literals on rare layouts, and *.example.com-style wildcards where supported. UseCanonicalName On makes self-referential URLs prefer ServerName—useful behind stable public names; mis-set values behind split-horizon DNS can generate links clients cannot resolve.
| Directive | Role |
|---|---|
ServerName | Primary vhost identity; should match public DNS and TLS CN/SAN |
ServerAlias | Alternate Host headers accepted in this block |
ServerAdmin | Email or URL in auto-generated error pages—avoid personal inboxes in production |
IP-based vs name-based vhosts
Name-based vhosts share an address; differentiation depends on Host/SNI. IP-based layouts bind different addresses per site (<VirtualHost 203.0.113.10:443>)—still need valid certs unless clients use legacy non-SNI TLS (rare). Mixed wildcard and specific vhosts require careful ordering; when in doubt, test with curl -v --resolve and OpenSSL s_client -servername.
IPv6 and dual stack
Typical dual-stack listens:
Listen 80
Listen [::]:80
Listen 443
Listen [::]:443Match <VirtualHost *:443> with distro guidance—some sites use explicit <VirtualHost [::]:443> blocks when separating v6-only policy. Link-local clients need zone indices in URLs outside Apache, but vhost matching still keys on global addresses on the wire.
Protocol and HTTP/2
Declare ALPN protocols inside the TLS vhost:
Protocols h2 http/1.1Compatibility with MPM and module set is distribution-specific—validate after upgrades. Background: Apache configuration fundamentals and performance tuning.
Enterprise layout
One file per site under sites-available/, enabled via symlink, owned by root and deployed through CI. Pair vhost changes with apachectl configtest and a graceful reload. Document which vhost is default per socket for on-call. SELinux: label DocumentRoot trees with httpd_sys_content_t; separate writable upload trees with a more restrictive type where policy allows.
False positives
Clients without SNI (very old libraries) may always see the default TLS vhost—if logs show mysterious cert name mismatches, capture TLS ClientHello features before blaming application code.
Related: .htaccess, common Apache errors.