Deploy Node.js to EC2

konstantinstanmeyer

Konstantin Stanmeyer

Posted on February 10, 2023

Deploy Node.js to EC2

Setting up an environment to use for both development and production on a cloud server can especially useful for remote teams and testing purposes.

This blog will explain how to initialize an Ubuntu instance within an EC2 virtual machine, with an end goal of creating somewhat of a "sandbox" to clone Github repositories. It will also allow us to open endpoints to this server and utilize running api's or applications.

First, here is some basic code for a test application to run within the deployed EC2 instance:

// ./app.js

import express from 'express';

const app = express();

app.get('/', (req, res) => res.json({ message: "App works!" }));

app.listen(3000, () => console.log("Server is running!"));
Enter fullscreen mode Exit fullscreen mode

Now, with a working application, ensure that it is pushed to a Github repository, like so:

git init
git add .
git commit -m "first commit"
git remote add origin https://github.com/githubusername/example.git
git push -u origin main
Enter fullscreen mode Exit fullscreen mode

Our next stop is to set up our EC2 instance. Assuming you have an AWS account set up, navigate to the EC2 dashboard.

IMPORTANT: Make sure you remember which region you are set within. For example, I set mine up to be hosted in Ohio so the small menu in the top-right of my page looks like so:

region

Here, the EC2 dashboard should display a menu like so:

ec2 menu

Below that menu, select the "Launch Instance" button, which will bring you to a separate launch page.

Provide a name for your instance and select "Ubuntu" as the OS Image.

launch setup

The outlined area shows the free tier option if you would like to run the server with no charges, but depending on your application you may prefer a different image.

Next, the security fields must be set up to SSH into our machine. Just below the tier options, create a new key-pair with the following options:

launch security fields

This will save a .pem file (or potentially .cer), which should be saved in an easy-to-remember folder within your computer. We will later navigate to the folder where this key resides to to SSH.

For simplicity I've allowed SSH traffic from any IP address, but this can allow specified access. The "Network Settings" section should look like so:

launch network settings

Keep the "Configure Storage" section as default, and select "Launch instance":

launch instance button

Navigate back to the EC2 dashboard, and select the instances option. Now, you should see your new Ubuntu machine running:

running ec2 process

Select the instance's checkbox, and select the "Connect" option near the top right of the dashboard:

Image description

Make sure you're on the SSH tab, we will follow the steps listed:

Image description

Navigate to the folder where the access key was placed on our local computer. Within that folder, using a terminal, we must make sure our key is not "publically viewable" and run this command, from the third step(key is placed within my desktop folder for this example):

cd Desktop
chmod 400 example-ec2.pem
Enter fullscreen mode Exit fullscreen mode

Which will return nothing, but we will then run the example SSH command:

Image description

Image description

Type "yes", and you will now be within your instance:

Image description

To allow us to run a Node application, we have to set up and install a few things. First, cURL will let us to download external packages and data:

sudo apt-get install curl
Enter fullscreen mode Exit fullscreen mode

Node will be the next step, using setup code made from this open-source repository (can also choose a different version of Node/npm):

curl -sL https://deb.nodesource.com/setup_16.x | sudo -E bash -
Enter fullscreen mode Exit fullscreen mode

Which will prompt us for a further command:

Image description

sudo apt-get install nodejs
Enter fullscreen mode Exit fullscreen mode

One last package must be installed, being PM2, which will allow us to execute a command that keeps a defined process running, even after closing out of the SSH terminal. You can also use other tools like Screen if you'd prefer to avoid further downloads, built into Lunix.

sudo npm install -g pm2@latest
Enter fullscreen mode Exit fullscreen mode

Clone your Github repository now:

git clone https://github.com/githubusername/example.git
Enter fullscreen mode Exit fullscreen mode

Then run a pm2 command to start the process:

pm2 start example
Enter fullscreen mode Exit fullscreen mode

It should be running within the machine now! You can monitor current processes within pm2 by typing:

pm2 list
Enter fullscreen mode Exit fullscreen mode

With the application running, we need to allow our EC2 instance to expose the port the application is running on. We can navigate to the EC2 instance dashboard, and select the box for our current application. Below, now, we can see the security options like so:

Image description

Select the option below "Security Groups", bringing you to the group's page, and click the "Edit inbound rules" button:

Image description

There should be the existing rule for SSH traffic, but select "Add rule", and fill out a new rule for Custom TCP traffic, within a port range you set in your application (this example used port 3000), along with allowing all IPs to access the ports:

Image description

Now, with your server still running, you should be able to visit your public IP, which you can find in the your running instance's menu:

Image description

Put the port your application is currently on, and it should be fully functional, returning all the data and handling all the requests you need!

The processes can be monitored by SSH'ing into the EC2 instance, and running pm2 list to check what's still running. You can stop these applications by typing pm2 stop <application name>.

.env Variables

To create an env file, cd into your project while SSH'ed into your instance, then run:

sudo touch .env
Enter fullscreen mode Exit fullscreen mode

Editing the file can be done by running:

sudo nano .env
Enter fullscreen mode Exit fullscreen mode

Save your edited content with control + S and exit with control + x.

NGINX

When using a domain/IP, we'd like to avoid having to request the exact port the process is running on. NGINX gives us the ability to reverse-proxy requests to a process on port 3000, while requesting from PORT 80(HTTP-traffic).

From the root of your instance, enter this command to create and edit a configuration file:

sudo nano /etc/nginx/conf.d/my-app.conf
Enter fullscreen mode Exit fullscreen mode

Then, within that file, we can define the port in which our application is running, as well as where we'd like our NGINX server to listen from.

server {
    listen 80;
    server_name 242.19.227.100;
    # w/ domain it would be www.example.com

    location / {
        proxy_pass http://127.0.0.1:3000/;
    }
}
Enter fullscreen mode Exit fullscreen mode

control + S + control + x

Restart the service with our updated configuration:

sudo service nginx restart
Enter fullscreen mode Exit fullscreen mode

Now, the address you sending requests to has a domain like this:

// before

242.19.227.100:3000/

// after 

242.19.227.100/
Enter fullscreen mode Exit fullscreen mode

This setup allows you to push further changes to your Github repository, then update your running server with a simple SSH into it and pull command.

Thanks for reading!

💖 💪 🙅 🚩
konstantinstanmeyer
Konstantin Stanmeyer

Posted on February 10, 2023

Join Our Newsletter. No Spam, Only the good stuff.

Sign up to receive the latest update from our blog.

Related