Setting up an SSL on AWS EC2 with Amazon Linux 2 — [A.N.T.S]
A.N.T.S — A Note To Self; with the intention that it maybe helpful to at least 1 other person that reads this.
So you want to get an SSL Certificate setup on an Amazon EC2 instance, sweet! Lets get cracking.
Assumptions
- You know how to create a vanilla Amazon EC2 Instance, using Amazon Linux 2, if you don’t, there are plenty of tutorials. (Guide link).
- Your security group protocol allows inbound traffic at port 22, 80 & 443; SSH: Port 22, HTTP: Port 80 and HTTPS: Port 443 (Guide Link)
- You can SSH into your instance via a command line (Guide Link).
- You own a domain (E.g. https://www.jacksonjacob.me , I own that)
- You can change the domain DNS settings to point to the new VM
1. Setting Up Apache
I will be pulling code from official Amazon Resources which will be linked below.
The Web Server is needed to host the files on the VM, think MAMP but on the cloud so everyone can access it. Once you have SSH’ed in, lets go:
sudo yum update -y
sudo amazon-linux-extras install lamp-mariadb10.2-php7.2
sudo yum install -y httpd php mariadb-server php-mysqlnd
sudo systemctl start httpd
sudo systemctl enable httpd
sudo systemctl is-enabled httpd
At this point, if you insert your IPv4 Public IP Address into your browser, it take you to a page like this.
(You can find this in the EC2-Management Console once you clicked on the VM, bottom right.)
2. Website, build files
There is where your build files for a web application goes so that it is hosted on the cloud. This part talks you through the process of enabling access to it.
2.1 Permissions, Permissions, Permissions
sudo usermod -a -G apache ec2-user
At this point you need to logout for the change to take affect, you can do this using:
exit
SSH back into your instance.
sudo chown -R ec2-user:apache /var/www
sudo chmod 2775 /var/www && find /var/www -type d -exec sudo chmod 2775 {} \;
sudo chmod 2775 /var/www && find /var/www -type d -exec sudo chmod 2775 {} \;
And your done, any member of the apache group can add, delete and edit files in the Apache document root.
2.2 Navigation Tips
- Access to the build file directory
cd /var/www
2. Return to ec2-user directory or “safe space” as I like to call it
cd ~
3. LetsEncrypt and SSL
You need to ensure your instance accepts incoming connection on Ports 22, 80 and 443 as per the assumptions!
In order to get Certbot onto the VM we need to configure a few things.
On a side note, I noticed I am in the “/var” directory. This does not matter, just “cd ~“ and continue; for anyone overthinking it right now.
3.1 Pre-Certbot Configuration
sudo wget -r --no-parent -A 'epel-release-*.rpm' http://dl.fedoraproject.org/pub/epel/7/x86_64/Packages/e/
sudo rpm -Uvh dl.fedoraproject.org/pub/epel/7/x86_64/Packages/e/epel-release-*.rpm
sudo yum-config-manager --enable epel*
Now we need to amend a specific file on the VM, specifically the /etc/httpd/conf/httpd.conf file; apache configuration I believe.
You may need to use the sudo command to overwrite the files, I’ve added it in just incase.
cd /etc/httpd/conf
ls
sudo nano httpd.conf
At this point you need to insert 5 lines of code into the configuration, replace jacksonjacob.me with your own domain name which you have bought and paste it in.
<VirtualHost *:80>
DocumentRoot "/var/www/html"
ServerName "jacksonjacob.me"
ServerAlias "www.jacksonjacob.me"
</VirtualHost>
sudo systemctl restart httpd
And the configuration is done, we can now crack on with installing Certbot and generating an SSL
3.2 Installing Certbot and generating an SSL
Additionally, you will need to change the DNS settings on the domain to point to your VM instance.
So, whenever someone goes to jacksonjacob.me or www.jacksonjacob.me, they get re-routed to my VM’s IPv4 address of 35.178.57.230 (In my case), this is set on the DNS settings for the domain, refer to whoever you bought your domain off’s documentation for this part.
DO THIS NOW OR THE FOLLOWING STEPS WILL NOT WORK!
sudo yum install -y certbot python2-certbot-apache
sudo certbot
At this point you have to enter your Email, T/C’s (Y or N) and EFF Mailing List authorisation (Y or N). I’ve already done this part so it skips ahead.
3.2.1- DNS error that you may counter…
If you haven’t changed your DNS settings on your domain to point to the VM (EC2 Instance), you’ll likely see an error similar to this.
You need to do this and start step 3.2 again.
3.2 Continued…
Congratulations, you have created SSL’s for your domain!
4. Done
Hopefully you have successfully followed the guide and created an SSL certificates for a domain.
But there’s one more thing you may need to do. The following directory owners need to be changed in order for applications to have read access to them. I believe the fullchain.pem and privkey.pem are symbolic links to those in the archive folder therefore BOTH directories ownership needs to change for access.
sudo chown -R ec2-user:ec2-user /etc/letsencrypt/live
sudo chown -R ec2-user:ec2-user /etc/letsencrypt/archive
This allows you to use the SSL certificates to make HTTPS calls, for example in a Node API:
'use strict'// 1.0 Get packages
const fs = require('fs')
const http = require('http')
const https = require('https')
const express = require('express')
const bodyParse = require('body-parser')// 1.1 Read SSL details on server
const privateKey = fs.readFileSync('/etc/letsencrypt/live/<YOUR_DOMAIN>/privkey.pem', 'utf8')
const certificate = fs.readFileSync('/etc/letsencrypt/live/<YOUR_DOMAIN>/fullchain.pem', 'utf8')// 1.2 Create SSL object to feed https
const credentials = {
key: privateKey,
cert: certificate
}// 2.0 Create server
const app = express()// 2.1 Configure body parse
app.use(bodyParse.urlencoded({extended: true}))
app.use(bodyParse.json())// 3.0 Set server information and create the server
const httpPort = 8080
const httpsPort = 8443// Create https server
https.createServer(credentials, app).listen(httpsPort, () => {
console.log('API listening on HTTPS port ' + httpsPort + '.')// HTTP request will redirect to HTTPS
const redirectApp = express()// Get all requests from HTTP and redirect to HTTPS
redirectApp.get('*', (req, res) => res.redirect('https://' + req.hostname + req.url))
http.createServer(redirectApp).listen(httpPort, () => {
console.log('API-redirect listening on HTTP port ' + httpPort + '.')})})
Otherwise you are likely to run into permission issues when the API attempts to read the SSL Certificates.
Hope this helps!
Resources: