Apache virtual host redirection with ssl

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.