DEV Community

Cover image for From Code to the Cloud: A Step-by-Step Guide to Deploying Your Node.js App on AWS EC2
Abayomi Ogunnusi
Abayomi Ogunnusi

Posted on • Updated on

From Code to the Cloud: A Step-by-Step Guide to Deploying Your Node.js App on AWS EC2

Introduction

In this article, we will deploy a nodejs express app to ec2. We will also add SSL and Nginx in the next article.

Let's dive in imh

 

Prerequisites

🎯 AWS account
🎯 Github account
🎯 Nodejs installed on your local machine
🎯 Git installed on your local machine
🎯 Basic knowledge of nodejs and express
🎯 Basic knowledge of git
🎯 Basic knowledge of ssh
🎯 Basic knowledge of linux commands

 

⏭️ Create a Nodejs express app

Run the following commands in your terminal



mkdir ec2
cd ec2
npm init -y


Enter fullscreen mode Exit fullscreen mode

Image description

The -y flag is to skip the questions and use the default values

⏭️ Install the following packages


npm install express dotenv


Enter fullscreen mode Exit fullscreen mode

✅ Express is a web framework for nodejs
✅ Dotenv is a zero-dependency module that loads environment variables from a .env file into process.env.

Image description

⏭️ Confirm the installed packages in the package.json file

package.json is the heart💖 of npm. It holds metadata relevant to the project and it is used to give information to npm that allows it to identify the project as well as handle the project's dependencies.



{
  "name": "ec2",
  "version": "1.0.0",
  "description": "",
  "main": "index.js",
  "scripts": {
    "test": "echo \"Error: no test specified\" && exit 1"
  },
  "keywords": [],
  "author": "",
  "license": "ISC",
  "dependencies": {
    "dotenv": "^16.3.1",
    "express": "^4.18.2"
  }
}


Enter fullscreen mode Exit fullscreen mode
⏭️ Write your start script

In essence, you can run npm start to start your server.
Image description

⏭️ Create a .env file

This is where we will store our environment variables. The environment variables are accessible through process.env object. We will use the dotenv package to load the environment variables from the .env file into process.env object.



touch .env


Enter fullscreen mode Exit fullscreen mode
⏭️ Add the following to the .env file


PORT=2323


Enter fullscreen mode Exit fullscreen mode
⏭️ Create a .gitignore file

This is where we will add the files we don't want to push to github. Preventing the .env file from being pushed to github is very important because it contains sensitive information like your database credentials, api keys, etc.



touch .gitignore


Enter fullscreen mode Exit fullscreen mode
⏭️ Add the following to the .gitignore file


node_modules
.env


Enter fullscreen mode Exit fullscreen mode
⏭️ Create app.js


require('dotenv').config(); // load environment variables from .env file
const express = require('express');
const app = express();
const port = process.env.PORT || 3000; // default port is 3000

app.get('/', (req, res) => {
    return res.status(200).json({
        message: 'Hello World'
    });
});

app.listen(port, () => {
    console.log(`Server running on port ${port}`);
});


Enter fullscreen mode Exit fullscreen mode
⏭️ Start the server

Open your terminal and run the following command



npm start


Enter fullscreen mode Exit fullscreen mode

Image description

⏭️ Curl the server

Open another terminal and run the following command



curl localhost:2323


Enter fullscreen mode Exit fullscreen mode

You should see the following
Image description

 

⏭️ Create a git repository

Now that we have our app running, let's create a git repository and push our code to github. Run the following commands in your terminal



git init
git add .
git commit -m "Initial commit"



Enter fullscreen mode Exit fullscreen mode

Image description

⏭️ Create a new repository on github

Image description

⏭️ I choose private because I don't want this code to be public

Image description

⏭️ Copy the code in the highlighted area and add to your terminal

Image description

⏭️ You should see the following

Image description


⏭️ Now lets setup our ec2 instance

Login to your aws account and go to ec2

Image description

⏭️ Choose EC2 from the list of services

Image description

⏭️ Choose Launch Instance

Image description

⏭️ Choose Ubuntu Server 20.04 LTS (HVM), SSD Volume Type

Name your instance and click next

Image description

⏭️ Create a new key pair

A key pair consists of a public key that AWS stores and a private key file that you store. Together, they allow you to connect to your instance securely.
⚠️ Ensure you note the location of the key pair

Image description

⏭️ Network setting

Tick the the three boxes and click next

  • Allow ssh traffic: This allows you to connect to the instance using ssh
  • Allow http traffic from internet: This allows you to access the instance from the browser over http (unsecure)
  • Allow https traffic from internet: This allows you to access the instance from the browser over https (secure)

Image description

⏭️ Review and launch

Image description

⏭️ Success

We have successfully created our ec2 instance. Click on the instance highlighted in green to view the details
Image description

⏭️ Click on the instance Id to view the details

Image description

⏭️ Connecting to the ec2 instance using ssh

There are two ways to connect to the ec2 instance using ssh. You can either use the browser or use the terminal.

Method 1: Using the browser
Click on connect and follow the instructions

Image description

⏭️ Click the connect button

Image description

⏭️ Change to root user
  • Sudo: Super User Do; allows a user with proper permissions to execute a command as another user, such as the superuser.
  • su: Switch User; allows you to switch to another user account without logging out of your current terminal session.

  • the - flag is used to preserve the environment variables
    Image description

⏭️ Install nvm

nvm is a version manager for nodejs. It allows you to install multiple versions of nodejs and switch between them easily.



curl -o- https://raw.githubusercontent.com/nvm-sh/nvm/v0.34.0/install.sh | bash


Enter fullscreen mode Exit fullscreen mode
⏭️ Activate nvm

We need to activate nvm so that we can use it in the current terminal session



. ~/.nvm/nvm.sh


Enter fullscreen mode Exit fullscreen mode
Install node

Install the latest version of node using nvm



nvm install node


Enter fullscreen mode Exit fullscreen mode

Image description

⏭️ Install git

Git is need to clone the repo we created earlier



sudo apt-get update -y
sudo apt-get install git -y


Enter fullscreen mode Exit fullscreen mode

⚠️ You can omit the sudo since you are already root. So just run



apt-get update -y
apt-get install git -y


Enter fullscreen mode Exit fullscreen mode
⏭️ Check if node is installed

We have the latest version of node installed



node -v


Enter fullscreen mode Exit fullscreen mode

Image description

⏭️ Check if git is installed


git --version


Enter fullscreen mode Exit fullscreen mode

Image description

⏭️ Clone the repo we created earlier using ssh


git clone git@github.com:drsimplegraffiti/ec2-deploy.git


Enter fullscreen mode Exit fullscreen mode

You should get this error because you have not added your ssh key to github

Image description

⏭️ Connect github ssh key to ec2 instance

Generate a fingerprint for the ssh key



ssh-keygen -t ed25519 -C "your email"


Enter fullscreen mode Exit fullscreen mode

Image description

Click enter thrice and leave the passphrase empty as default. You can add a passphrase if you want to add an extra layer of security.

⏭️ eval the ssh-agent

eval is used to evaluate the ssh-agent in the current terminal session. The ssh-agent is a program that runs in the background and stores your ssh keys. The ssh-agent is used to authenticate you to the remote server without having to type your password every time.



eval "$(ssh-agent -s)"


Enter fullscreen mode Exit fullscreen mode

Image description

⏭️ Add the ssh key to the ssh-agent

Image description

⏭️ Copy the ssh key to the clipboard


cat ~/.ssh/id_ed25519.pub


Enter fullscreen mode Exit fullscreen mode

Image description

⏭️ Paste the ssh key to github

Go to github settings -> SSH and GPG keys -> New SSH key
Paste the key and save. Auhenticate with your github password or Github mobile app

Image description

Image description

⏭️ Test the connection

Scan the ssh



ssh-keyscan github.com >> ~/.ssh/known_hosts


Enter fullscreen mode Exit fullscreen mode

Let's test the connection to github in the ec2 instance terminal



ssh -T git@github.com


Enter fullscreen mode Exit fullscreen mode

Image description

⏭️ Clone the repo again

This time, we should be able to clone the repo without any error



git clone git@github.com:drsimplegraffiti/ec2-deploy.git


Enter fullscreen mode Exit fullscreen mode

Image description

⏭️ List the files in the directory


ls -la


Enter fullscreen mode Exit fullscreen mode

You should see the ec2-deploy folder

Image description

cd into the ec2-deploy

  • cd - change directory
⏭️ See the files in the ec2-deploy folder


ls -la


Enter fullscreen mode Exit fullscreen mode

Image description

⏭️ Install dependencies


cd ec2-deploy
npm install


Enter fullscreen mode Exit fullscreen mode

Image description

⏭️ Start the server


npm start


Enter fullscreen mode Exit fullscreen mode

We got port 3000 because we ignored the .env file in the .gitignore file

Image description

💡 You can also use pm2 to start the server if you want to keep the server running even after you close the terminal
Install pm2 globally



npm install pm2 -g


Enter fullscreen mode Exit fullscreen mode

Image description

⏭️ Start the server with pm2


pm2 start app.js


Enter fullscreen mode Exit fullscreen mode

Image description

⏭️ Pick the ip address of the ec2 instance and curl it

Image description

YAAY! We have our server running on ec2 mapped to this ip address 🎉🎉🎉. However it is not secure because it is running on http. We will add SSL and Nginx in the next article.
Image description

⏭️ Method 2: Connecting to the ec2 instance using ssh from your local machine

Click connect from your instance -> connect -> ssh client -> copy the ssh command

Image description

⏭️ Open your terminal and cd into the directory where you saved the key pair


cd Downloads


Enter fullscreen mode Exit fullscreen mode
Run the ssh command


ssh -i "devtokey.pem" ubuntu@ec2-35-175-174-169.compute-1.amazonaws.com


Enter fullscreen mode Exit fullscreen mode
⏭️ You will get this warning

This warning is related to permissions. We need to change the permissions of the key pair. We will do that in the next step

Image description

⏭️ Chmod the key pair

Chmod is a command in Linux and other Unix-like operating systems that allows to change the permissions (or access mode) of a file or directory.



chmod 400 devtokey.pem


Enter fullscreen mode Exit fullscreen mode

⚙️ 400 - read only by owner
⚙️ 600 - read and write by owner

⏭️ Run the ssh command again


ssh -i "devtokey.pem" ubuntu@ec2-35-175-174-169.compute-1.amazonaws.com


Enter fullscreen mode Exit fullscreen mode
⏭️ You should see the following

Image description

⏭️ Start the server


cd ec2-deploy
pm2 start app.js


Enter fullscreen mode Exit fullscreen mode

Image description

You should get script already running because we already started the server on the ec2 instance earlier in the browser. Stop the ec2 on the browser by running



pm2 stop app.js


Enter fullscreen mode Exit fullscreen mode

or



pm2 stop 0 # 0 is the id of the script referencing app.js


Enter fullscreen mode Exit fullscreen mode

Image description

⏭️ Start the server again


pm2 start app.js


Enter fullscreen mode Exit fullscreen mode

Image description

⏭️ Check the ec2 ip by running


curl ifconfig.me


Enter fullscreen mode Exit fullscreen mode
⏭️ Pick the ip address of the ec2 instance and curl it

Image description

⏭️ Open another terminal and curl the ip address


curl 35.175.174.169


Enter fullscreen mode Exit fullscreen mode

🎉🎉🎉 We have connected to our ec2 instance using ssh from our local machine.

Image description

 

Conclusion

We have successfully deployed our nodejs express app to ec2. We will add SSL and Nginx in the next article. Thanks for reading. Please leave a comment if you have any questions or suggestions.
lol

Top comments (9)

Collapse
 
samuel_kelv profile image
Samuel Kelv

Great article, thanks

Collapse
 
some_dev profile image
some_dev

If you cannot access your application from the global IP or experience timeouts, the solution is provided here.

In its simplest explanation, the port on which your JavaScript app is listening does not match the AWS EC2 Cloud port.

Navigate to EC2 > Security Groups, select your launch wizard, and click on the security group ID. At the bottom of the page, you will find the 'inbound rules' section, including https, ssh, and http. Take note of the 'Port range' value for the protocol you use to access the server. Replace this port range value with the listening port in your JavaScript application and start your application. From now on, you can connect to the global IP address without specifying any custom port values.

NOTE: I solved the problem I encountered in this way. Below is a screenshot I obtained from another guide related to what I explained. I hope it helps.

miro.medium.com/v2/resize:fit:1400...

Collapse
 
sapinder_dev profile image
Sapinder Singh • Edited

Hi, I could not change the Port Range as it is disabled for me. I tried doing it with the root AWS account as well, but with no success. Could you help me figure it out?

Image description

Collapse
 
pythonuserux profile image
Andrea Virgillito

You have to choose CUSTOM TCP instead of SSH, otherwise the default port value can not be changed apparently

Collapse
 
lester016 profile image
Lester016

How are you able to access or curl the IP address without adding port number in the URL? It shows in one of the screenshot that it defaulted to 3000.

I'm trying to replicate the article and able to access my express app in EC2 instance but the only thing that confuses me is it doesn't work without the port number. Maybe you missed out some part in the tutorial?

Collapse
 
arifirfan06 profile image
Irfan Arif

same here, have you found the solution?

Collapse
 
some_dev profile image
some_dev

Hello! I've shared a solution above regarding your issue. I hope it helps.