Micah Kamla

Houston, TX Web Developer

Setup Let's Encrypt on EC2 with Node.js

This writing assumes you have the following:

  • A Running Amazon Linux-flavored EC2 instance
  • SSH access
  • Your server is running Node.js (Express.js is shown, but not required)

To set up HTTPS on your Amazon Linux EC2 Instance with Express.js, SSH into your running instance:

ssh -i your-key.pem ec2-user@ec2-xx-xxx-xx-xxx.us-west-2.compute.amazonaws.com

Next, you'll need to utilize Certbot's (https://certbot.eff.org/lets-encrypt/pip-other)[alternative Unix installs. You can follow Certbot's example, or run the following commands:

wget https://dl.eff.org/certbot-auto
chmod a+x certbot-auto

Next, generate your certification. Before you proceed, ensure your web server is able to serve static files from hidden directories. The example, referrenced later, creates a directory named .well-known inside of /home/ec2-user/www/public/.

Setup Express to serve static files

Your Express.js static file declaration should look similar the following:

    var express = require('express');
    var app = express();
    //...
    app.use(express.static(__dirname+'/public',{dotfiles:'allow'}));

The command below generates certifications for example.com and www.example.com. Replace these with your own appropriate domain name.

Before running the following command, make sure you're server is running.

sudo /home/ec2-user/certbot-auto certonly --webroot -w /home/ec2-user/www/public -d example.com -d www.example.com

If you receive an error message in your shell that looks like the following: fatal: amazon linux support is very experimental at present...

Simply run the last command with the --debug flag enabled.

sudo /home/ec2-user/certbot-auto certonly --webroot -w /home/ec2-user/www/public -d example.com -d www.example.com --debug

Certbot will verify your ownership of the domain by accessing the files inside of the public/.well-known directory. If you've set everything up correctly, you should receive a console message detailing where your keys are stored. For this example, your keys should be stored in the following locations:

  • Key: /etc/letsencrypt/live/example.com/privkey.pem
  • Certificate: /etc/letsencrypt/live/example.com/cert.pem
  • Certificate Authority: /etc/letsencrypt/live/example.com/chain.pem

Now, setup your HTTPS server in Express.js and provide the necessary credentials:

var https = require('https');
var express = require('express');
var app = express();
//...
https.createServer({
    key: fs.readFileSync('/etc/letsencrypt/live/domain.com/privkey.pem','utf8'),
    cert: fs.readFileSync('/etc/letsencrypt/live/domain.com/cert.pem','utf8'),
    ca: fs.readFileSync('/etc/letsencrypt/live/domain.com/chain.pem','utf8')
},app).listen(8443,function(){
    console.log('Listening HTTPS');
});

Finally, you'll likely run into permission issues when trying to read the key files, so run your server command with privileges:

sudo node index.js