subDimension

flask, mod_wsgi, ssl, oh my!

I wanted to be able to access my instruments control panel via https:// as well as http://.

First, I started off by getting an SSL certificate. I used StartSSL which offers a free-tier SSL certificate. Following all of their steps carefully, I ended up with 2 files:

  • a private .key file (unencrypted),
  • my certificate file* (I had to wait for it to be approved and copied it from the Retrieve Certificate section of the Tool Box).

* I run instruments on a sub-domain of subdimension.co.uk, the certificate I created was tied to this sub-domain. The paid-tier StartSSL offers allows you to create a wildcard certificate that would work for the whole domain, but I don’t need to spend £40 on that.

I also needed a third file from the StartSSL Tool Box page; in the StartCom CA Certificates section, download a copy of the Class 1 Intermediate Server CA file.

I uploaded these files onto my server, into a non-web-accessible directory.

I use Apache, with mod_wsgi to run my flask applications currently. Instruments was already running with the following configuration file:

<VirtualHost *:80>
    ServerName instruments.example.com

    WSGIDaemonProcess instruments_t user=user group=www-data umask=0002 threads=5 home=/path/to/instruments
    WSGIScriptAlias / /path/to/instruments.wsgi

    <Directory /path/to/instruments>
        WSGIProcessGroup instruments_t
        WSGIApplicationGroup %{GLOBAL}
        WSGIScriptReloading On
        Order deny,allow
        Allow from all
    </Directory>
</VirtualHost>

I wasn’t sure quite how to go about the next step - I could have just repeated the same thing again, but with <VirtualHost *:443> instead, but I suspected that would create 2 identical applications running at the same time. I wanted 1 application that was accessed via both ports.

A blog post from the creator of mod_wsgi helped me out. Although he is talking about web2py, the problem and solution were the same. Simply dropping the WSGIDaemonProcess line and making sure I referenced the same WSGIProcessGroup seemed to be enough.

My Apache config file became this:

<VirtualHost *:80>
    ServerName instruments.example.com

    WSGIDaemonProcess instruments_t user=user group=www-data umask=0002 threads=5 home=/path/to/instruments
    WSGIScriptAlias / /path/to/instruments.wsgi

    <Directory /path/to/instruments>
        WSGIProcessGroup instruments_t
        WSGIApplicationGroup %{GLOBAL}
        WSGIScriptReloading On
        Order deny,allow
        Allow from all
    </Directory>
</VirtualHost>

<VirtualHost *:443>
    ServerName instruments.example.com

    WSGIScriptAlias / /path/to/instruments.wsgi

    SSLEngine On
    SSLCertificateFile /path/to/instruments.example.com.cer
    SSLCertificateKeyFile /path/to/unencrypted_private.key
    SSLCertificateChainFile /path/to/sub.class1.server.ca.pem

    <Directory /path/to/instruments>
        WSGIProcessGroup instruments_t
        WSGIApplicationGroup %{GLOBAL}
        WSGIScriptReloading On
        Order deny,allow
        Allow from all
    </Directory>
</VirtualHost>

According to Graham in the post above, this works as long as the ServerName is the same for both, and because mod_wsgi treats the ports :80 and :443 as a special pair.

Before I could enable the site (and disable the old config file), the SSL module needed to be enabled:

$ sudo a2enmod ssl

disable the old app:

$ sudo a2dissite instruments

enable the new one:

$ sudo a2ensite instruments-ssl

because of the enabling of mod_ssl, apache needs to be restarted, rather than just reloaded:

$ sudo /etc/init.d/apache2 restart

a quick browser point to https://instruments.example.com and everything appeared to be working! My next task is to rework the instruments app to make sure that it always redirects to the https:// site which I’ll likely write about separately later.

Additionally, the main reason I wanted this was so that I could get subMarks able to bookmark websites that are only accessible via https://. I’ll probably write a bit about that too.