When migrating WordPress sites to self-managed servers, many developers encounter this specific Apache warning:
[Error] Hostname example.com provided via SNI and hostname www.example.com provided via HTTP are different
This occurs when the Server Name Indication (SNI) in the TLS handshake doesn't match the HTTP Host
header. In your case, clients are requesting example.com
via SNI but the browser ultimately sends requests for www.example.com
.
Your current Apache configuration likely has these characteristics:
<VirtualHost *:443>
ServerName www.example.com
ServerAlias example.com
SSLEngine on
SSLStrictSNIVHostCheck off
# SSL certificate paths...
</VirtualHost>
The performance degradation stems from Apache performing additional verification steps when SNI and HTTP hostnames mismatch. While SSLStrictSNIVHostCheck off
prevents outright rejection, it doesn't eliminate the overhead.
Option 1: Canonical Hostname Enforcement
Force all traffic to use either www or non-www version consistently:
<VirtualHost *:80>
ServerName example.com
ServerAlias www.example.com
RewriteEngine On
RewriteCond %{HTTP_HOST} ^example\.com [NC]
RewriteRule ^(.*)$ https://www.example.com$1 [L,R=301]
</VirtualHost>
<VirtualHost *:443>
ServerName www.example.com
SSLEngine on
# Ensure certificate covers both variants
SSLCertificateFile /path/to/cert.pem
SSLCertificateKeyFile /path/to/key.pem
</VirtualHost>
Option 2: Dual SSL VirtualHosts
Create separate virtual hosts for each hostname variant:
<VirtualHost *:443>
ServerName www.example.com
SSLEngine on
# SSL configuration for www
</VirtualHost>
<VirtualHost *:443>
ServerName example.com
SSLEngine on
# SSL configuration for non-www
</VirtualHost>
Option 3: Wildcard Certificate Implementation
For maximum flexibility with subdomains:
<VirtualHost *:443>
ServerName example.com
ServerAlias *.example.com
SSLEngine on
SSLCertificateFile /path/to/wildcard.crt
SSLCertificateKeyFile /path/to/wildcard.key
</VirtualHost>
After implementing the solution, test SSL handshake times:
openssl s_time -connect example.com:443 -www / -new -servername example.com
openssl s_time -connect www.example.com:443 -www / -new -servername www.example.com
Compare results before and after the fix to quantify performance improvements.
Ensure these settings in wp-config.php
match your SSL configuration:
define('WP_HOME','https://www.example.com');
define('WP_SITEURL','https://www.example.com');
And update the siteurl and home options in the WordPress database:
UPDATE wp_options SET option_value = 'https://www.example.com' WHERE option_name IN ('siteurl', 'home');
When you see the error [Error] Hostname example.com provided via SNI and hostname www.example.com provided via HTTP are different
, this indicates a fundamental mismatch between how your server identifies itself during different phases of the HTTPS handshake process.
# Typical error pattern in Apache logs
[ssl:error] [pid 12345] Hostname example.com provided via SNI
and hostname www.example.com provided via HTTP are different
The performance degradation occurs because Apache has to perform extra validation steps when it encounters this mismatch. Each TLS handshake becomes more computationally expensive as the server tries to reconcile the conflicting host information.
Your current setup likely has these characteristics:
# Port 80 VirtualHost
<VirtualHost 192.0.2.1:80>
ServerName www.example.com
ServerAlias example.com
# ... other config
</VirtualHost>
# Port 443 VirtualHost
<VirtualHost 192.0.2.1:443>
ServerName www.example.com
ServerAlias example.com
SSLEngine on
SSLStrictSNIVHostCheck off
# ... SSL certificate paths
</VirtualHost>
The issue stems from how modern browsers handle SNI (Server Name Indication) versus traditional HTTP host header processing. When a client connects:
- During TLS handshake: Provides example.com via SNI
- After encryption: Sends www.example.com in HTTP Host header
Implement one of these approaches:
Option 1: Standardize Hostnames
# Force canonical hostname in both vhosts
<VirtualHost *:80>
ServerName www.example.com
ServerAlias example.com
RewriteEngine On
RewriteCond %{HTTP_HOST} ^example\.com$ [NC]
RewriteRule ^(.*)$ https://www.example.com$1 [L,R=301]
</VirtualHost>
Option 2: Match SNI Exactly
# Modify your SSL vhost to prioritize the non-www version
<VirtualHost *:443>
ServerName example.com
ServerAlias www.example.com
SSLEngine on
# Certificate files should cover both variants
SSLCertificateFile /path/to/cert.pem
SSLCertificateKeyFile /path/to/key.pem
SSLCertificateChainFile /path/to/chain.pem
</VirtualHost>
Option 3: Upgrade Configuration
For Apache 2.4+, consider using:
SSLStrictSNIVHostCheck on
ServerName example.com
ServerAlias www.example.com
After implementing the fix, test with:
ab -n 100 -c 10 https://www.example.com/
openssl s_client -connect example.com:443 -servername example.com
- Ensure your SSL certificate covers both example.com and www.example.com
- Check for mixed content warnings in browser developer tools
- Verify DNS records have proper CNAME/ALIAS configurations