Watch on YouTube:

Free, Automatic SSL Certificates

Starting sometime in the summer of 2015 Mozilla will be giving everyone the cheap-o ($7-$40) basic SSL certificates for free. They'll be short term, but they'll automatically renew all on their own (via the appropriate npm, gem, egg, etc).

See Let's Encrypt for details.

If you want the double green bar platinum all-star (but still not actually verified) certificates for $300, you'll still have to pay for those.

Inexpensive SSL from

Until Let's Encrypt is up and running, you'll still need to buy a basic certificate from an SSL provider.

1. Create a 2048-bit RSA Private Key for SSL

If you're on Windows, you're gonna need to get on a real computer for a few minutes to run commands.

For everyone else, just open up Terminal and copy/paste the following:

mkdir -p certs/server
openssl genrsa \
  -out certs/server/my-server.key.pem \

2. Create a CSR with your Domain Info

There are two ways to go about this:

  1. Run the command bare and type answers to a lot of questions
  2. Run the command with the questions already filled out

I prefer the latter because, well, I'm lazy and it's a lot faster.

mkdir -p certs/tmp
openssl req -new \
  -sha256 \
  -key certs/server/my-server.key.pem \
  -out certs/tmp/my-server.csr.pem \
  -subj "/C=US/ST=Utah/L=Provo/O=ACME App Client/"

A quick rundown of the options.

Note: These all apply in the context of the business or person requesting the certificate. So if your domain is, but you live in Georgia and operate your business in South Carolina... it's one of the latter two, not Florida.

ThingyWhat it meansWhat it really means
CCountryThe country (or Indian Reservation?) in which you reside
ST*StateState, Province, Region - whatever your country calls a state
LLocalityCity, Locality, District - whatever your country calls a city
OOrganizationThe business or organization name - i.e. ACME, Inc
OUOrganizational Unit(optional) i.e. ACME Sales Dept
CN*Cananical Nameeither (assumes bare domain also) or

Special Notes:

  • C should be the TWO DIGIT country code
  • ST must be ALL SPELLED OUT: Utah, not UT
  • CN GET IT RIGHT. If you put the wrong domain you'll have to contact customer support and stuff to get it cancelled and fixed
    • WWW. vs BARE DOMAIN requires a subdomain, but using www will also validates your cert for the bare domain.
    • (P.S. don't let anyone tell you different, www. looks retarded. If you have cookie issues, get a second domain for your CDN, usercontent, or whatever)


Also, sometimes you'll see in the instructions to not use a passphrase, but it doesn't really matter whether you do or you don't.

If you do, you'll end up hard-coding the passphrase into your server - and if someone can gain access to the directory where you're storing your certs, they can almost certainly also gain access to the file that has the passphrase hard-coded into it.

Passphrases are more useful for Trusted Peer SSL or other situations where you might have a device that prompts the user for their passphrase.

Even in that case you're just as well to use the biometric (fingerprint) scanner or device passcode to AES-256 encrypt the private key... wait... that's what the passphrase is doing.

Yeah, so doesn't much matter, might as well not.

3. Test Run before you Spend $$

If you followed my steps above then you have a directory that looks like this:

├── server
│   └── my-server.key.pem
└── tmp
    └── my-server.csr.pem

    2 directories, 2 files

I have a test repository (nodejs-ssl-example) so that you can

  1. copy your certs into the directory
  2. sign your CSR with my bogus Root CA
  3. fire up the webserver and make sure the darn thing works
git clone

rsync -av certs/ nodejs-ssl-example/certs/

pushd nodejs-ssl-example/

bash bin/

npm install
node ./server.js

Open your browser to

You will see an error message in your browser informing you that:

  • Your connection is not private
  • The Server's certificate does not match the URL.
  • The Server's certificate is not trusted.

That's okay for this example. Click on your browsers SSL icon (normally a lock or key of some sort) and verify that your domain name is represented correctly. If that looks good, make sure you can get through to your site.

If your domain is correct (i.e. and not, then you're good to proceed to the next step.

If you get a different kind of error such as when starting the server (i.e. node ./serve.js) or the connection error that won't allow you to view the test page in the example repo, then you may need to hone your copy and paste skills a little and try again after you've worked on that.

4. Go exchange your dollars for SSL

Head over to and pick the cheapest (or pay extra money to get the same certificate with a special directive in the comment field that tells the browser to give you the double extra platinum green-lock ultra icon, if that's your thing).

You'll need to copy and paste the contents of your CSR into their form and off you go.

cat certs/tmp/my-server.csr.pem

5. Hunt down the Intermediate Root CA

You may notice that when you only pay $10 ~ $30 for a certificate, you'll be told that you need to download an intermediate certificate.

Intermediate certificates are like... one of the 6 degrees of friends between you and Kevin Bacon.

See, the certificate you were issued is untrusted, because it was signed by an untrusted intermediate certificate that generally expires in 1-3 years (at least as long as the one you purchased). However, that cert is signed by a trusted Root CA (that generally won't expire for several years later) - but the browser won't know that unless you bundle them both together (or it's just a really really old browser or device that hasn't gotten any security updates in the past few years).

Take a look at the code of serve.js for an example of how to add a intermediate root-ca. It's a one-liner. No biggie.

6. If io.js / node.js, use root-ssl-cas

Unfortunately the method for adding a Root CA in io.js / node.js exclusively causes the installed certificates to be ignored. I wasn't sure how to reach the right ears to solve this problem but, fortunately, it's another one-line fix.


Many people won't experience any SSL problems if you choose not to use ssl-root-cas, because your app doesn't connect to 3rd party services, but if you're using request or oauth (facebook connect, etc), or s3, then it very likely that you will get cert errors and that ssl-root-cas will make them disappear.


Some sites require the -sha256 option to be used during the CSR generation. I don't think that any sites will fail to work without it, but if you do happen to get an error about your CSR you could try running the command without that option specified.

By AJ ONeal

If you loved this and want more like it, sign up!

Did I make your day?
Buy me a coffeeBuy me a coffee  

(you can learn about the bigger picture I'm working towards on my patreon page )