Enabling HTTPS on an AWS EC2 Instance with Node.js and Nginx on an Ubuntu Server
I have an AWS EC2 instance running Node.js and Nginx on an Ubuntu 16.04 server. In this tutorial, I will show you how to switch your website from HTTP to HTTPS using Let’s Encrypt. HTTPS prevents unauthorized tampering with the communication between your website and your users’ browsers. It encrypts this communication using Transport Layer Security (TLS) Certification. Let’s Encrypt is a certificate authority that provides free X.509 certificates.
Firstly, SSH into your EC2 instance:
ssh -i <keyfile.pem> ubuntu@<public-ip-address>
Next, clone the Let’s Encrypt repository into the /opt/letsencrypt
path:
sudo git clone https://github.com/letsencrypt/letsencrypt /opt/letsencrypt
Then, check if any application is listening on port 80 by running:
netstat -na | grep ':80.*LISTEN'
If any processes are returned, terminate them. For example, if you already have an Nginx server running on port 80, you may need to stop it as follows:
sudo systemctl stop nginx
After that, navigate to your repository with cd /opt/letsencrypt
and run the following command to obtain the certificates:
./letsencrypt-auto certonly --standalone --email <your@email.com> -d <domain.com> -d <subdomain.domain.com>
If you encounter an error like this:
OSError: Command /opt/eff.org/certbot/venv/bin/python2.7 - setuptools pkg_resources pip wheel failed with error code 1
Then set the following environment variables before you rerun the script:
export LC_ALL="en_US.UTF-8"
export LC_CTYPE="en_US.UTF-8"
Follow the on-screen instructions, and you should receive your certificates at the path /etc/letsencrypt/live/<domain.com>
.
Next, configure the Nginx settings to redirect your HTTP traffic to HTTPS. Edit the file using:
sudo vi /etc/nginx/sites-available/default
The content should look like this (remember to replace <YourDomain.com>
and the root path for your website):
server {
listen 443 ssl;
server_name <YourDomain.com>;
ssl_certificate /etc/letsencrypt/live/<YourDomain.com>/fullchain.pem;
ssl_certificate_key /etc/letsencrypt/live/<YourDomain.com>/privkey.pem;
ssl_protocols TLSv1 TLSv1.1 TLSv1.2;
ssl_prefer_server_ciphers on;
ssl_ciphers 'EECDH+AESGCM:EDH+AESGCM:AES256+EECDH:AES256+EDH';
root /var/www/yourPath;
index index.html index.htm;
location / {
proxy_pass http://localhost:3000/;
proxy_http_version 1.1;
proxy_set_header Upgrade $http_upgrade;
proxy_set_header Connection "upgrade";
proxy_set_header Host $http_host;
proxy_set_header X-Real-IP $remote_addr;
proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;
proxy_set_header X-Forwarded-Proto http;
proxy_set_header X-Nginx-Proxy true;
proxy_redirect off;
}
}
server {
listen 80;
server_name <domain.com>;
return 301 https://$host$request_uri;
}
To test your configuration for any errors, run:
sudo nginx -t
If everything is okay, restart Nginx:
sudo service nginx stop
sudo service nginx start
Last but not least, go to the AWS console and make sure your security group has port 443 open for HTTPS.
Done! Navigate to the HTTPS version of your domain to verify that it’s working. If you encounter issues like a 502 Bad Gateway error, ensure that your Node.js application is running correctly. I use PM2 to keep it running. Let’s make the internet more secure! 🙂