How to get around heroku’s pricey SSL

Heroku’s SSL add-ons are a great way to quickly and effortlessly add SSL to your apps.

… but If you’re running multiple sites on heroku, those fees add up quickly. Fortunately, they do provide a feature called “Piggyback SSL” free of charge, which allows you to visit your heroku app using it’s heroku domain name e.g. https://example.heroku.com.

That’s not a url you’d likely direct your clients to, but it does play a key role in this setup, as it ensures that traffic between our proxy server and heroku is secured, not just traffic between our proxy and the browser.

I chose Ubuntu 14.04 LTS for this setup because it includes v2.4 of apache and all the right openssl stuff by default, vs. AMI Linux (2015.03.1 as of this writing) which was still using v2.2, and wasn’t handling SNI for whatever reason.

We use AlphaSSL for our certs. They‘re inexpensive, have pretty decent documentation, and you can’t beat the turnaround time. Provided I have access to the DNS records and/or email account on the domain, I’ve gotten certs generated and signed within a 30 minute timeframe!

1 - Spin Up a New EC2


First, you’ll want to spin up an EC2 Ubuntu instance in AWS. I’ll leave you to the AWS Documentation if you have questions on how to do that.

Definitely set up an Elastic IP for this host, otherwise you’ll lose your public IP on a restart, and be forced to update your DNS records, which will take your sites offline in the process!


2 - Install Apache


Update the apt-get package manager, and install apache as follows:

# sudo apt-get update
# sudo apt-get install apache2 openssl


3 - Enable required modules


We need the following modules enabled:
rewrite to redirect users from the HTTP site to HTTPS
ssl to enable HTTPS (obviously)
proxy and proxy_http to forward requests for our EC2 instance to heroku

Enable them with:

# sudo a2enmod rewrite ssl proxy proxy_http


4 - Set Hostname Globally


This may not be required for apache to function, but I got tired of looking at the warning.

# sudo nano /etc/apache2/apache2.conf

add the following on a line by itself (I like to put this just below “Global configuration”)
ServerName localhost


5 - Restart Apache


Now would be a good time to restart apache so our newly enabled modules will load, and to make sure there are not config errors so far

# sudo service apache2 restart


6 - Set Up Your VirtualHost files


Create your virtualhost files inside /etc/apache2/sites-available/

Below is an example of a basic virtualhosts file with the simple function of redirecting visitors to the HTTPS version. Contents of the file are in red, and everything in blue should be replace with your own info. Be sure to save your files with a .conf extension.

Virtualhost example to redirect HTTP visitors to HTTPS:
<VirtualHost *:80>

ServerAdmin admin@example.com
ServerName example.com
ServerAlias www.example.com
RewriteEngine On
RewriteCond %{HTTPS} off
RewriteRule (.*) https://%{HTTP_HOST}%{REQUEST_URI}
</VirtualHost>


Virtualhost example for the HTTPS enabled proxy:
<IfModule mod_ssl.c>

<VirtualHost *:443>
ServerAdmin admin@example.com
ServerName example.com
ServerAlias www.example.com
SSLEngine on
SSLProxyEngine On
SSLProxyCheckPeerCN off
SSLProxyCheckPeerExpire on
SSLCertificateFile /etc/ssl/certs/example.crt
SSLCertificateKeyFile /etc/ssl/certs/example.pem
SSLCertificateChainFile /etc/ssl/certs/ssl-ca-bundle.crt
ProxyPass / https://example.herokuapp.com/
ProxyPassReverse / https://example.herokuapp.com/
</VirtualHost>
</IfModule>


7 - Install Your SSL Certificate files


Getting your SSL certificate files generated and signed is beyond the scope of this article, but make sure those files exist in the /etc/ssl/certs/ directory specified in (per the above virtualhosts file), and have the proper permissions.
8 - Enable Sites
Per Debian/Ubuntu convention, we need to enable the sites before apache will load them into it’s config

# sudo a2ensite example.conf
# sudo a2ensite example-ssl.conf
# sudo service apache2 restart


9 - Test your setup


A great way to test your SSL proxy before actually changing your DNS records is to set them in your own hosts file.

For Mac or Linux, you can simply add them to /etc/hosts. I recommend testing with several browsers to make sure they all like the SSL certs.

One common issue is that apache will serve up a single SSL cert for all of your sites, causing “Domain Name Mismatch” errors.


10 - Update DNS Records


Once you’re satisfied that everything looks good, it’s time to update your DNS records to the IP of your new proxy server.

Also, be sure to delete those records from your own /etc/hosts file now, since we now want to see the domains as the rest of the world does.


11 - Watch Your Domains Like a Hawk


Chances are that if you tested everything properly in step 9, all will be well after the DNS records propagate.

BUT… you’ll want to watch any domains you switched to this proxy very closely for a few hours, again making sure that the correct SSL certs are loaded for each site, that browsers aren’t complaining, etc… ‘cause you don’t want those nasty “someone might be trying to steal your info” warning freaking out your visitors.

A good way to know whether or not your records have propagated is to simply ping the domain from a terminal. The ping probably won't reply, but it will show you the IP that it resolved to, and if that IP matches the Elastic IP of your proxy, and your sites are still pulling up properly, you’re in business!

Jared
Sep. 15 2015