Today I learned more about Apache virtual hosting and redirection. I decided to change my server host to Digital Ocean a few months ago. There was nothing wrong with my then host, it was a shared web host, which I mainly used to access and manage with cPanel.
During my day job I have been administering a CentOS based virtual server hosted by Rackspace and have become more comfortable with using a SSH to manage it. Comfortable, but still with lots of Googling and Stack Overflowing.
So I thought I would challenge myself a bit and make the jump to Digital Ocean and take more control of my own server. I wanted to be able to make any sites I run use SSL via Let’s Encrypt. This was not possible with my old host, as they had a more traditional “buy a certificate” business model and I could not administer the server to install Certbot.
After setting this new server up and getting neilmagee.com served on port 80, I used Let’s Encrypt to generate some certs for the www
and non-www
versions of the sites (Why? See notes at end of article). This worked well, and I could now access https://neilmagee.com and https://www.neilmagee.com. My goal was to redirect all traffic (http{s} and www) to my canonical domain, https://neilmagee.com.
I chose to avoid doing the domain configuration in .htaccess
files and wanted to do it all in Apache .conf files. On this server, which is running Ubuntu, they are located in /etc/apache2/sites-enabled
. To get those config files to be included by Apache, I added this line to the bottom of my apache2.conf
located in /etc/apache2
:
# Include the virtual host configurations:
IncludeOptional sites-enabled/*.conf
My config for neilmagee.com now consisted of three seperate files - neilmagee.com.conf
for port 80, neilmagee.com-le-ssl.conf
on port 443 and www.neilmagee.com-le-ssl.conf
on port 443. The 443 configs were generated by Let’s Encrypt during the certificate request process.
After spending a lot of time changing and adding different rewrite rules to neilmagee.com.conf
I was almost getting what I wanted. http
and https non www
were redirecting correctly, http www
was redirecting to https non www
but https www
was not redirecting at all. It took me a while before I realised that I was not adding the redirect in the right .conf
file. I believed the www.neilmagee.com-le-ssl.conf
was just handling my certs and ssl, but I overlooked it was the virtual host for www on https. I added the redirect scripts to www.neilmagee.com-le-ssl.conf
and restarted apache. I cleared the cache of my browser and used another browser to double check. Https www is now redirecting to https non www. I have truncated the scripts below to focus on the config that works for me. I have left the redirects as code 302
, temporary redirects, which will become 301
when I am 100% sure everything is working as expected.
neilmagee.com.conf
<VirtualHost *:80>
# Other config omitted
<Directory /absolute/path>
RewriteEngine On
# match any URL with www and rewrite it to https without the www #
RewriteCond %{HTTP_HOST} ^(www\.)(.*) [NC]
RewriteRule (.*) https://%2%{REQUEST_URI} [L,R=302]
# match urls that are non https (without the www) #
RewriteCond %{HTTPS} off
RewriteCond %{HTTP_HOST} !^(www\.)(.*) [NC]
RewriteRule (.*) https://%{HTTP_HOST}%{REQUEST_URI} [L,R=302]
</Directory>
</VirtualHost>
www.neilmagee.com-le-ssl.conf
<IfModule mod_ssl.c>
<VirtualHost *:443>
# Other config omitted
<Directory /absolute/path>
RewriteEngine On
# match any URL with www and rewrite it to https without the www
RewriteCond %{HTTP_HOST} ^(www\.)(.*) [NC]
RewriteRule (.*) https://%2%{REQUEST_URI} [L,R=302]
</Directory>
# Other config emitted
</VirtualHost>
</IfModule>
Notes
The reason I requested www
and non-www
is to avoid certificate warnings from browsers such as Edge and Firefox. In my experience if you only have one certificate (non-www
), and then use mod_rewrite
to redirect www
to non-www
, Edge and Firefox will show warnings and the padlock will not be green. Chrome has decided to subdue warnings and just handle the redirection automatically. This was a problem I faced in my day job and as I use Chrome a lot, it took me a while to diagnose it. After I figured it out, I always request both certs.
Final Note
The conclusions I have made here are the results of lots of trial and error, lots of Googling and reading smarter people than me explain things. Whilst in isolation, this config is quite simple, it is very hard to find one clear example of what to do that matches your own requirements. If you take anything away from this, I am glad.