Deploying Express Server to EC2 using Github Actions

Fardeen Khan
Code Panthers
5 min readApr 17, 2022

--

In this article, we are going to create a simple Express server in Node.js and deploy it to an EC2 machine using Github Actions. That's the Gist of it.

Prerequisites

  • Have a Github account (seriously you need one anyhow)
  • An AWS account with root access

AWS Architecture

For this tutorial we are going to need an EC2 instance setup with a Security Group which allows HTTP/s Incoming traffic and SSH connection (for debugging). Also, attaching an Elastic IP will be a good idea to have a static IP attached to the Instance.

The Express server will run on NGINX

All our resources will be created through a CloudFormation Stack. Below is the template for the Stack.

Permissions

To create all the required resources and manage deployment we will create a new IAM user and assign the following policy permissions

Managed Policies

Inline Policy

That's all for IAM permissions

Creating CloudFromation Stack

Before we actually create the stack we need to create a KeyPair for the EC2 instance. This is something we have to do manually as CloudFormation doesn’t support creating one. If you already have one just replace the KeyPair name in the Template. Otherwise, follow here

  • EC2 Console > Network & Security > Key Pairs > Create Key Pair

Create and Download and KeyPair, and make sure to keep it safe.

Head over to the CloudFormation Console. Select your Region of choice (for me that's ap-south-1) and Create a new Stack.

  • Upload the Template file (which will be stored in an S3 bucket). If you already have a template stored in S3, just paste the Object URL
  • Enter Stack name and skip the rest of the options

Once the Stack is created you will see the following resources being created in EC2

  • EC2 Instance (t2.micro, Amazon Linux 2, 8GB EBS)
  • Elastic IP
  • Security Group (Incoming — 22, 80, 443)

Setup NGINX

  • SSH into the Instance using the KeyPair we download
ssh -i "node-ec2-github-actions-key.pem" ec2-user@<instance-dns>.ap-south-1.compute.amazonaws.com
  • Install and start NGINX
// Install updates and NGINX
sudo yum update -y
sudo amazon-linux-extras install nginx
// Start NGINX
sudo service nginx start
// Enable service startupo at Boot
sudo chkconfig nginx on
// Checck the service status
sudo service nginx status

If all went well you will be greeted by the following screen on the Instance Public IP/DNS

  • Add a new configuration under /etc/nginx/conf.d for your domain of choice and add the below nginx blocks
  • Edit /etc/nginx/nginx.conf and remove the default server block listening on PORT 80
  • Add an A record in your Domain Registrar to point to the Instance’s IP address.

Install Tools and Dependencies

Install the following tools to get the project running on the instance

  • Good old Git
sudo yum install 
  • Node.js through nvm
// Install NVM (Node Version Manager)
curl https://raw.githubusercontent.com/creationix/nvm/master/install.sh | bash
source ~/.bashrc
// Install LTS version of Node.js (am using v16.14.2)
nvm install --lts
nvm use --lts

For a deeper insight into NVM have a look at another article I wrote

  • Process Manager (pm2), we will use this tool to manage our server process like keep it running, autostart on boot, etc.
npm install pm2 -g

Project Setup

We will be using a simple Express server for the task. You can find the started code for the project right here

And [Github] Action….

The gist of the process

  1. SSH into the EC2 Instance
  2. Stop already running the process
  3. Clone the repo if it’s not there, otherwise check out the changes
  4. Run a new Process with pm2

Adding Secrets

To remotely connect with the EC2 Instance we will need the private key pair, the system Hostname, and username. We will keep this information in the Secret Repository on Github and access the same in the Action Pipeline

Github Repo > Settings > Security > Secrets > Actions > New Repository Secret.

Add the following Secrets

  • EC2_PRIVATE_KEY (Contents of the pem file)
  • HOSTNAME (Full DNS address of Instance)
  • USER (ec2-user for Amazon Linux AMI)

Adding the Action

We start by adding the YAML script for the actions which act as the Pipeline.

Add .github/workflows/main.yml

Now as you push the changes to the master branch, the action should be executed and the server should go live

In Conclusion…

So that was all about deploying a Node.js application to AWS EC2 using Github actions. Here’s the final repo link

Although we were able to achieve this goal, remotely connecting to the instance and pulling some commands doesn’t always fair well, so in the next article, we will be exploring a better approach to do so and use other AWS services to reinforce the process.

Till then, thanks and See you around !!

Buy me a coffee

--

--