Switch to HTTPS Now, For Free

published by Eric Mill on
Update, January 2016: This guide is seriously out of date. Don't use StartSSL anymore, and don't jump through all these hoops below.

Instead, check out either of three great options:

1) SSLMate issues single-domain certificates for $16/year. While it's more than $0, it's more than worth it to be able to run sslmate buy mywebsite.com and have it Just Work.

If you use SSLMate, this guide will still help you -- pick it up from Installing the certificates and Setup with other common hosts.

2) Let's Encrypt is here! They issue certificates entirely for free. Revocation is free, multi-domain certificates are free, and they are a bona fide non-profit. The downside is that currently their instructions and official command line client are a little rough, and certs need to be renewed every 90 days.

3) If you're using AWS, maybe AWS Certificate Manager (ACM). These certificates are free and issued directly by Amazon and last a little over a year. However, they currently require manual issuance through email validation, and do not support Certificate Transparency. Here's a good ACM guide for Jekyll.

I'm keeping the rest of the article intact below for historical purposes, but again: you should really go check out SSLMate and Let's Encrypt (or maybe AWS Certificate Manager) instead. I can't guarantee that the below steps will continue to work.

From now on, you should see a delightful lock next to https://konklone.com in your browser's URL bar, because I've switched this site to use HTTPS. I paid $0 for the trouble.

Why you should bother doing the same:

This post shows how to do your part in building a surveillance-resistant Internet by switching your site to HTTPS. Though it takes a bunch of steps, each one is very simple, and you should be able to finish this in under an hour.

A quick overview: to use HTTPS on the web today, you need to obtain a certificate file that's signed by a company that browsers trust. Once you have it, you tell your web server where it is, where your associated private key is, and open up port 443 for business. You don't necessarily have to be a professional software developer to do this, but you do need to be okay with the command line, and comfortable configuring a web server you control.

Most certificates cost money, but at Micah Lee's suggestion, I used StartSSL. They're who the EFF uses, and their basic certificates for individuals are free.

There are two things that could cost you money. One is that if your site is commercial in nature, they'll ask you to pay for a higher level certificate.

More importantly, if your certificate needs to be revoked someday, StartCom will charge you a $30 fee. While revocation has generally been rare, the Heartbleed exploit is an example where a huge portion of the Internet had to revoke their keys. For some people who had issued a large number of free certificates, this turned out to be expensive.

Still, StartCom makes getting started with SSL simple and inexpensive. Their website is difficult to use at first — especially if you're new to the concepts and terminology behind SSL certificates (like I was). Fortunately, it's not actually that hard; it's just a lot of small steps.

Below, we'll go step by step through signing up with StartSSL and creating your certificate. We'll also cover installing it via nginx, but you can use the certificate with whatever web server you want.

Final reminder: SSLMate is way easier than this. It's not too late!

Register with StartSSL

To get started, visit their signup page and enter your information.

They'll email you a verification code. They tell you to not close the tab or navigate away from it, so just keep it open until you get the code, and can paste it in.

You'll need to wait for certification, but it should only take a few minutes. Once you're approved, they'll email you a special link and a verification code to type in.

That'll bring you to a screen to generate a private key. They're generating you this private key inside your browser, using the "keygen" tag. However, this isn't the key you use to make your SSL certificate. They're using it to create a separate "authentication certificate" that you will use to log in to StartSSL's control panel going forward. You'll make a separate certificate for your website later.

Finally, they'll ask you to "Install" the certificate:

Which installs your authentication certificate directly into your browser.

If you're in Chrome, you should see this at the top of your browser window:

Again, this is just the certificate that identifies you by your email address and lets you log in to StartSSL going forward.

Now, we need to persuade StartSSL that we own the domain name we want to generate a new certificate for. From the control panel, click the "Validations Wizard" tab, and select "Domain Name Validation" from the dropdown.

Enter your domain name.

Next, you'll select an email address that StartSSL will use to verify you own the domain name.

As you can see, StartSSL will believe you own the domain if you control webmaster@, postmaster@, or hostmaster@ with the domain name, OR if you own the email address listed as part of the domain's registrant information (in my case, that's currently konklone@gmail.com). Choose an email address where you can receive mail.

They'll email you a validation code, which you can enter into the field to validate the domain.

Generating the certificate

Now that StartSSL knows who you are, and knows you own a domain, you can generate your certificate using a private key.

While StartSSL can generate a private key for you — and their FAQ assures you they use only the highest quality random numbers and don't hold onto the key afterwards — it's better to create your own, as StartSSL never sees your private key.

To create a new 2048-bit RSA key, open up your terminal and run:

openssl genrsa -aes256 -out my-private-encrypted.key 2048

You'll be asked to choose a pass phrase. Pick a good one, and remember it. This will generate an encrypted private key. If you ever need to transfer your key, via the network or anything else, use the encrypted version.

The next step is to decrypt it so that you can generate a "certificate signing request" with it. To decrypt your private key:

openssl rsa -in my-private-encrypted.key -out my-private-decrypted.key

Now, generate a certificate signing request. Don't worry about the details - all StartSSL cares about is the public key associated with the CSR.

openssl req -new -sha256 -key my-private-decrypted.key -out mydomain.com.csr

Go back to StartSSL's control panel and click the "Certificates Wizard" tab, and select "Web Server SSL/TLS Certificate" from the dropdown.

Since we generated our own private key, you can hit "Skip" here.

Then, paste in the contents of the .csr file we generated earlier.

If all goes well, it should say it received your certificate signing request.

Now, choose the domain you validated earlier which you plan to use with the certificate.

It requires you to add a subdomain. I added "www" for mine.

It will ask you to confirm. If it looks right, hit "Continue".

Note: It's possible you'll get hit with a "Additional Check Required!" step here, where you wait for approval by email. It didn't happen to me the first time, but did the second time, and my approval arrived in ~30 minutes. Upon approval, you'll need to visit the "Tool Box" tab and visit "Retrieve Certificate" to get your cert.

That should do it — your certificate will appear in a text field for you to copy and paste into a file. Call it whatever you want, but the rest of the guide will refer to it as mydomain.com.crt.

Creating the full certificate chain

(If you used SSLMate, you can skip this step.)

Next, we're going to create the "certificate chain" that your web server will use. It contains your certificate, and StartSSL's intermediary certificate. (Including StartSSL's root cert is not necessary, because browsers ship with it already.) Download the intermediate certificate from StartSSL:

wget https://www.startssl.com/certs/class1/sha2/pem/sub.class1.server.sha2.ca.pem

Then concatenate your certificate with theirs:

cat mydomain.com.crt sub.class1.server.sha2.ca.pem > unified.crt

Installing the certificates

If you have direct access to your web server and its nginx configuration, here's how to install your certificate. If you don't, check out setup options for other common hosts or for Apache.

First, make sure port 443 is open on your web server. Many web hosts automatically keep this port open for you. If you're using Amazon Web Services, you'll need to make sure your instance's security group has port 443 open.

Also, take a look at David Zvenyach's nginx-ssl, a simple script to bootstrap the nginx/HTTPS process.

Finally, tell your web server about your unified certificate, and your decrypted private key. I use nginx — below is the bare minimum nginx configuration you need. It redirects all HTTP requests to HTTPS requests using a 301 permanent redirect, and points the server to the certificate and key.

You can also check out a more complete HTTPS nginx configuration that turns on SPDY, HSTS, SSL session resumption, OCSP stapling, and enables Forward Secrecy.

Qualys' SSL Labs offers an excellent SSL testing tool you can use to see how you're doing.

Now, ensure your nginx configuration is okay (this also verifies that the key and certificate are in working order):

sudo nginx -t

Then restart nginx:

sudo service nginx restart

Cross your fingers and try it out in your browser! If all goes well, the will be yours.

Important: the StartSSL free Class 1 certificate is good for just 1 year. Don't forget to renew it before then! Set a calendar reminder or something!

Setup with other common hosts

Many common hosts don't give you direct access to install a certificate yourself. In that case, you'll probably have to pay $$ for HTTPS, if it's possible at all.

If you use:

  • Heroku, you'll need to pay $20/month for their SSL add-on, and then use it to set up an SSL endpoint. Check out Moncef Belyamani's SSLMate + Heroku tutorial for some straightforward assistance.
  • Amazon S3, as of March 2014 they support free SSL for custom domains via CloudFront. Bear in mind this requires SNI, which won't work for users running Internet Explorer on Windows XP or Android 2.x's default browser. It's also unsupported by Python 2.x. If that's a dealbreaker, then you'll have to pay an insane $600/month for a dedicated IP.
  • Apache, check out kang's blog post on making an Apache config that gets the A rating from Qualys.
  • Bytemark and other servers using Symbiosis for Debian support simple SSL hosting as standard. Use the key generation guide above and name it ssl.key, following the Symbiosis documentation. Likewise, the certificate when generated should be ssl.crt. You'll also need StartSSL intermediate certificate that's mentioned above: sub.class1.server.sha2.ca.pem. Rename this to ssl.bundle.
  • Github Pages, they offer undocumented HTTPS support for *.github.io domains. However, they offer no HTTPS support at all for custom domains, so for that you'll have to look elsewhere (see below).
  • Webfaction, they provide HTTPS support at no extra charge. Go Webfaction!

If you need to look elsewhere because your host makes it too expensive or impossible to set up HTTPS, another option is to sign up for CloudFlare. You don't need to leave your current host to use them — they sit "in front" of your website and can speed it up in various ways.

CloudFlare offers HTTPS to anyone for free, but there are two big catches:

  • The free plan doesn't support clients using Windows XP or Python 2. To support older clients, you need a paid plan (which start at $20/month).
  • All CloudFlare plans can only encrypt between the visitor and CloudFlare. To ensure that the connection is encrypted all the way from the visitor to your website, you'll need to install your own certificate on your own web server anyway and tell CloudFlare to use and validate that certificate.

The tradeoffs are yours to choose, and yours alone!

Mixed Content Warnings

If your site is running on HTTPS, it's important to make sure all linked resources — images, stylesheets, JavaScript, etc. — are HTTPS too. If they're not, users' browsers will complain about mixed content.

Fortunately, pretty much every major service with an embed code has an HTTPS version, and most (including Google Analytics and Typekit) handle it automatically. For others, you'll need to figure it out on a case by case basis.

Back up your keys and certificates

Don't forget to back up your SSL certificate, and its encrypted private key. I put them in a private git repository, and included a brief text file describing every other file, and the process or command that created it. Make sure to record when your certificate expires, and set a calendar alarm for that date!

You should also back up your authentication certificate that you use to log in to StartSSL. StartSSL's FAQ has instructions — it's a .p12 file containing a cert + key that you export from your browser.