I like to run my sites without a www. You’re looking at this site like that i.e. https://bash-prompt.net.
Some traffic always arrives at https://www.bash-prompt.net which sometimes breaks things, especially with dynamic sites.
This problem can be solved using the Apache module mod_rewrite. But I’ve had problems with that and it’s an overcomplicated way to do things.
The problem is more easily solved using Apache’s Redirect
directive supplied by mod_alias.
What we’re going to do is to:
- Generate an SSL certificate for both WWW and non-WWW hostnames.
- Create a new
VirtualHost
for the undesired hostname (www or non-www) that redirects the visitor.
Generate a multi-hostname SSL certificate
This is required because traffic arriving at the WWW hostname e.g. https://www.example.com first has to complete the HTTPS interaction before it can receive the redirect response from Apache.
You can get a wildcard SSL from Let’s Encrypt but it’s more work than getting a multi-hostname certificate.
You can read my guide on doing that here or use the following command (for example.com and www.example.com hostnames):
# certbot certonly --expand -d example.com -d www.example.com
You can now use this certificate and key in the WWW and non-WWW VirtualHost
files.
Step 2 - Preparation
First, make sure that the mod_alias
module is enabled and reload Apache:
# a2enmod alias
# systemctl reload apache2
Next, remove the undesired hostname (usually it’s a ServerAlias) from the existing VirtualHost
file. In the following I want to redirect all traffic from https://www.example.com to https://example.com.
This would be the relevant section of the VirtualHost
file for this site:
<VirtualHost 1.2.3.4:443>
DocumentRoot /var/www/example-com
ServerName example.com
ServerAlias www.example.com
</VirtualHost>
This becomes:
<VirtualHost 1.2.3.4:443>
DocumentRoot /var/www/example-com
ServerName example.com
</VirtualHost>
Step 3 - Create the new, redirecting HTTPS WWW VirtaulHost
Create a new VirtualHost
file for https://www.example.com which will include the Redirect
instruction and the certificate you just generated:
<VirtualHost 1.2.3.4:443>
DocumentRoot /var/www/example-com
ServerName www.example.com
Redirect permanent / https://example.com
SSLCertificateFile /etc/letsencrypt/live/example.com/fullchain.pem
SSLCertificateKeyFile /etc/letsencrypt/live/example.com/privkey.pem
Include /etc/letsencrypt/options-ssl-apache.conf
</VirtualHost>
Reload Apache again to get the new config live.
Apache will now reply with an instruction to the requesting client that the requested URL/page/file etc has a new location with a 301 Permanent Move response.
Here’s the curl output for requesting https://www.bash-prompt.net:
# curl -Ia http://www.bash-prompt.net/guides/openssl-benchmark/index.html
HTTP/1.1 301 Moved Permanently
Date: Mon, 31 Jul 2023 07:47:59 GMT
Server: Apache/2.4.57 (Debian)
Location: https://bash-prompt.net/guides/openssl-benchmark/index.html
Cache-Control: max-age=172800
Expires: Wed, 02 Aug 2023 07:47:59 GMT
Content-Type: text/html; charset=iso-8859-1
Everything after the hostname i.e. /guides/openssl-benchmark/index.html is preserved in the redirect response.