Add SSL to EC2 Instance

You want https on your ec2 instance with nodejs? easy.

First thing is first. There are new rules. You can’t get an ssl certificate anymore that assignes to an IP address (More here). If you don’t know what this means, don’t worry about it. I’ll walk your through.

You’re going to need to set a few things up.

  1. First, set up a new instance on EC2 (make sure in your security group you open port 443  to “0.0.0.0/0”).
  2. Then associate an elastic IP address.
  3. Once you have this, go to your favorite registrar and buy a domain. If you already have one, that’s fine. Make sure you know what’s on your whois information. You’re going to need to apply for an ssl cert with the same contact information.
  4. Point the domain at your IP address:

Once you have your domain associate to the elastic IP address you can start applying for the ssl cert.

Now it’s time to grab openSSL and make a certificate request. To generate one, take a look at the documentation here: http://docs.aws.amazon.com/elasticbeanstalk/latest/dg/configuring-https.html#configuring-https-ssl-rsa.

  1. Download openSSL: https://www.openssl.org/source/ or type the following command in your terminal:
  2. which openssl

    * if you see a path to openssl then you already have it installed on your computer. For instance mine was installed automatically when I installed XAMPP.

  3. You need to first generate your private key:
  4. cd /path/to/directory/where/you/want/to/store/your/certs
    openssl genrsa 2048 > privatekey.pem
  5. Now you want to generate your certificate signing request. Make sure you follow the instructions linked to above:
  6. openssl req -new -key privatekey.pem -out csr.pem
  7. You will be prompted to fill in some contact information, make sure this is correct so they can verify it’s actually you. This information will be checked against the whois record for your domain, so make sure the information you put in here, matches the whois.
  8. * Also, for the common name (CA) make sure you use the domain name you pointed at your elastic IP, not the IP itself. You will get rejected otherwise. An example might be: “mydomain.com” not”54.204.243.234″ or “http://mydomain.com/”

  9. At this point you can buy an ssl cert. Make sure you buy a domain verification cert if you are looking for the cheapest route. Many will try to sell you extended verification certs. These can take a week to validate because they check your business out as well. Domain certs only take a couple of minutes, they verify that the whois matches and they can reach your server. Then they issue the cert.
  10. At this point you’re done. You can generate a temporary self signed cert if you want to test locally. Just enter your local information instead and do:
  11. openssl x509 -req -days 365 -in csr.pem -signkey privatekey.pem -out server.crt

Now that you have your cert (most like you received a zip folder with multiple certs) what do you do?

I’m running NodeJS and this is how I did it:

  1. put the certs in a folder that my nodeJS process can find.
  2. Add the following using express to my head:
  3. var express = require('express'),
        fs = require('fs'),
        https = require('https'),
        config = require('./config');
  4. Then this to my setup:
  5. var options = {
        key: fs.readFileSync(config.sslKeyPath),
        cert: fs.readFileSync(config.sslCertPath)
    };
    
    if(config.environment != 'local') {
        console.log('adding ca cert')
        options.ca = [fs.readFileSync(config.sslCaPath)];
    }
    
    var app = express();
    
    var server = https.createServer(options, app);
    
    server.listen(config.sslSocketPort, function() {
        console.log("Listening on " + config.sslSocketPort);
    });
    
    // if you are using ws or something like it, add the server
    var wss = new WebSocketServer({server: server});
  6. I have  a separate config file with the following structure:
  7. var config = {}
    
    // environmentals
    config.environment = process.env.DEVELOPMENT_ENVIRONMENT;
    
    if(config.environment == 'local') {
        config.sslSocketPort = 5053;
    
        config.sslKeyPath = '/Applications/XAMPP/xamppfiles/htdocs/path/to/privatekey.pem';
        config.sslCaPath = '/Applications/XAMPP/xamppfiles/htdocs/path/to/gd_bundle-g2-g1.crt';
        config.sslCertPath = '/Applications/XAMPP/xamppfiles/htdocs/path/to/server.crt';
    } else {
        config.sslSocketPort = 443;
    
        config.sslKeyPath = '/home/ubuntu/path/to/privatekey.pem';
        config.sslCaPath = '/home/ubuntu/path/to/gd_bundle-g2-g1.crt';
        config.sslCertPath = '/home/ubuntu/path/to/0a87sgdf087asdfg.crt';
    }
    
    module.exports = config;
  8. Then I set a .env file on my local and my remote server. The local has this in it:
  9. DEVELOPMENT_ENVIRONMENT=local
  10. The remote has:
  11. DEVELOPMENT_ENVIRONMENT=remote

This way the config file can tell whether I’m running locally or remotely.

That’s it! Basically all that config shit you can figure out on your own, just wanted to include so I don’t confuse people.

Leave a Reply

Your email address will not be published. Required fields are marked *