Introduction
In this article, we will deploy a nodejs express app to ec2. We will also add SSL and Nginx in the next article.
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
The -y
flag is to skip the questions and use the default values
⏭️ Install the following packages
npm install express dotenv
✅ Express is a web framework for nodejs
✅ Dotenv is a zero-dependency module that loads environment variables from a .env file into process.env.
⏭️ 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"
}
}
⏭️ Write your start script
In essence, you can run npm start
to start your server.
⏭️ 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
⏭️ Add the following to the .env file
PORT=2323
⏭️ 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
⏭️ Add the following to the .gitignore file
node_modules
.env
⏭️ 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}`);
});
⏭️ Start the server
Open your terminal and run the following command
npm start
⏭️ Curl the server
Open another terminal and run the following command
curl localhost:2323
⏭️ 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"
⏭️ Create a new repository on github
⏭️ I choose private because I don't want this code to be public
⏭️ Copy the code in the highlighted area and add to your terminal
⏭️ You should see the following
⏭️ Now lets setup our ec2 instance
Login to your aws account and go to ec2
⏭️ Choose EC2 from the list of services
⏭️ Choose Launch Instance
⏭️ Choose Ubuntu Server 20.04 LTS (HVM), SSD Volume Type
Name your instance and click next
⏭️ 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
⏭️ 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)
⏭️ Review and launch
⏭️ Success
We have successfully created our ec2 instance. Click on the instance highlighted in green to view the details
⏭️ Click on the instance Id to view the details
⏭️ 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
⏭️ Click the connect button
⏭️ 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.
⏭️ 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
⏭️ Activate nvm
We need to activate nvm so that we can use it in the current terminal session
. ~/.nvm/nvm.sh
Install node
Install the latest version of node using nvm
nvm install node
⏭️ Install git
Git is need to clone the repo we created earlier
sudo apt-get update -y
sudo apt-get install git -y
⚠️ You can omit the sudo since you are already root. So just run
apt-get update -y
apt-get install git -y
⏭️ Check if node is installed
We have the latest version of node installed
node -v
⏭️ Check if git is installed
git --version
⏭️ Clone the repo we created earlier using ssh
git clone git@github.com:drsimplegraffiti/ec2-deploy.git
You should get this error because you have not added your ssh key to github
⏭️ Connect github ssh key to ec2 instance
Generate a fingerprint for the ssh key
ssh-keygen -t ed25519 -C "your email"
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)"
⏭️ Add the ssh key to the ssh-agent
⏭️ Copy the ssh key to the clipboard
cat ~/.ssh/id_ed25519.pub
⏭️ 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
⏭️ Test the connection
Scan the ssh
ssh-keyscan github.com >> ~/.ssh/known_hosts
Let's test the connection to github in the ec2 instance terminal
ssh -T git@github.com
⏭️ 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
⏭️ List the files in the directory
ls -la
You should see the ec2-deploy folder
cd into the ec2-deploy
- cd - change directory
⏭️ See the files in the ec2-deploy folder
ls -la
⏭️ Install dependencies
cd ec2-deploy
npm install
⏭️ Start the server
npm start
We got port 3000 because we ignored the .env file in the .gitignore file
💡 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
⏭️ Start the server with pm2
pm2 start app.js
⏭️ Pick the ip address of the ec2 instance and curl it
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.
⏭️ 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
⏭️ Open your terminal and cd into the directory where you saved the key pair
cd Downloads
Run the ssh command
ssh -i "devtokey.pem" ubuntu@ec2-35-175-174-169.compute-1.amazonaws.com
⏭️ 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
⏭️ 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
⚙️ 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
⏭️ You should see the following
⏭️ Start the server
cd ec2-deploy
pm2 start app.js
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
or
pm2 stop 0 # 0 is the id of the script referencing app.js
⏭️ Start the server again
pm2 start app.js
⏭️ Check the ec2 ip by running
curl ifconfig.me
⏭️ Pick the ip address of the ec2 instance and curl it
⏭️ Open another terminal and curl the ip address
curl 35.175.174.169
🎉🎉🎉 We have connected to our ec2 instance using ssh from our local machine.
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.
Top comments (9)
Great article, thanks
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...
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?
You have to choose CUSTOM TCP instead of SSH, otherwise the default port value can not be changed apparently
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?
same here, have you found the solution?
Hello! I've shared a solution above regarding your issue. I hope it helps.