Deploying a NodeJS Application on AWS EC2 with Nginx and SSL
Welcome to a comprehensive guide on deploying a Node.js application to an AWS EC2 instance. This tutorial aims to equip you with the knowledge to deploy your application efficiently and securely.
This tutorial is centered on deploying a Node.js application on an EC2 instance running Ubuntu. However, the methods outlined are applicable to deploying any Node.js application or framework.
Prerequisites
- An AWS Account
- A domain name
- An EC2 instance 📎Link
Getting started
Begin by connecting to your EC2 instance. Once connected, execute the following commands to refresh your package listings
sudo apt update && sudo apt upgrade && sudo apt dist-upgrade
Installing Git
To proceed, we must clone the application into our instance, requiring Git installation. Execute the following to install Git
sudo apt install git
To verify the successful installation of Git
git --version
Installing Node.js
To run a Node.js application, setting up a Node.js environment is crucial. Here, I have added two methods for installing Node.js; please use either one to install Node.
Installing through NodeSource
Here’s a step-by-step guide on how to install Node.js using NodeSource. This will install Node.js and npm (Node package manager):
- Retrieve the installation script:
curl -fsSL https://deb.nodesource.com/setup_18.x -o nodesource_setup.sh
(Change 16.x
to whatever version line you prefer, like 14.x
or 18.x
.)
Run the script:
sudo bash nodesource_setup.sh
Install Node.js:
sudo apt-get install -y nodejs
2. Installing through NVM
For this purpose, we’re installing NVM (Node Version Manager), which facilitates the management of multiple Node.js versions, allowing for easy switching between them.
curl -o- https://raw.githubusercontent.com/nvm-sh/nvm/v0.39.3/install.sh
curl -o- https://raw.githubusercontent.com/nvm-sh/nvm/v0.39.3/install.sh | bash
source ~/.bashrc
To install a specific Node.js version
nvm install <node-version>
To switch among various Node.js versions
nvm use <node-version>
Cloning the Repository
To successfully clone and launch the application, follow this checklist.
- Clone the application.
git clone <https-repo-url>
- Checkout to the updated branch.
git checkout <branch-name>
- Add .env file.
sudo nano .env
- Install npm dependency.
npm ci
- Build the application.
npm run build
- Execute the application once to ensure it functions correctly (Opt.).
npm start
After cloning the application and ensuring it’s running correctly, proceed to use PM2 to launch it. This approach guarantees that the application remains operational even after closing the terminal.
Installing PM2
PM2 is a tool for managing Node.js applications. It ensures your apps run continuously, restarts them if they crash, and can manage multiple instances for better performance.
Use it by installing with npm
npm i -g pm2
To launch an application with PM2, first move to the application’s root directory using the cd
command. Then execute the following command to start the application with PM2.
pm2 start npm --name "appname" -- run "command"
Following are some of the helpful pm2 commands
// List all the applications
pm2 list
// Log a specific application
pm2 log <id>
// Start, stop, or restart instances
pm2 start <id>
pm2 stop <id>
pm2 restart <id>
// Examples of passing IDs
pm2 log 1 // Logs application with ID 1
pm2 log all // Logs all applications
pm2 log 1 2 3 // Logs applications with IDs 1, 2, and 3
Having successfully launched the application with PM2, we now need to ensure it’s accessible externally. For this, we’ll utilize Nginx, a web server that serves as a proxy layer, enabling external access to the application.
Installing Nginx
Execute the following command to install Nginx
sudo apt install nginx
It is recommended that you enable the most restrictive profile that will still allow the traffic you’ve configured. Right now, we will only need to allow traffic on port 80.
sudo ufw allow 'Nginx HTTP'
To confirm Nginx has been correctly installed, use the following command.
sudo systemctl status nginx
After successfully installing Nginx, it’s time to configure it. This involves editing Nginx’s configuration files to define how it serves your application to external requests.
navigate to sites-available
inside the nginx folder.
cd /etc/nginx/sites-available/
Create a new file named app1.conf
and input the following configurations into it. This file will specify how Nginx directs traffic to your application, setting up the necessary proxy settings for external access.
server {
listen 80;
server_name example.com www.example.com; # change the doamin name
root /var/www/html;
index index.html index.htm;
location / {
proxy_pass http://127.0.0.1:3000; # change the port
proxy_read_timeout 60;
proxy_connect_timeout 60;
proxy_redirect off;
# Allow the use of websockets
proxy_http_version 1.1;
proxy_set_header Upgrade $http_upgrade;
proxy_set_header Connection 'upgrade';
proxy_set_header Host $host;
proxy_cache_bypass $http_upgrade;
}
}
Now, Create a symbolic link (symlink) in sites-enabled
that points to your configuration file in sites-available
. This step is crucial for enabling the new settings you've added for your application.
To create the symbolic link, execute the following command:
sudo ln -s /etc/nginx/sites-available/app1.conf /etc/nginx/sites-enabled/
Likewise, you can create multiple .conf
files if you're managing multiple applications. Just ensure to modify the server_name
and proxy_pass
accordingly.
We can test the nginx config by running the following command.
sudo nginx -t
After completing the configuration, restart Nginx to apply the changes by executing the following command.
sudo systemctl restart nginx.service
Configuring the domain name
To configure your domain, log into your DNS service provider’s website and navigate to the DNS settings. Select type as A record.
for a subdomain, enter its name, or use @
to point to your main domain under the name field. In the value field, input the public IP address of your EC2 instance. This step directs traffic from your domain to your application hosted on AWS EC2.
Example:
Type | Name | Value |
---|---|---|
A | dev | xx.xx.xx |
A | www.dev | xx.xx.xx |
Enabling SSL certificate
After configuring your domain, the next step is to secure your application with an SSL certificate, enabling HTTPS. This is crucial for establishing a secure connection, protecting data exchange between users and your application.
To install Certbot, which is used for obtaining SSL certificates from Let’s Encrypt for your application’s domains, follow these commands
Update your package list to ensure you can install the latest version of Certbot
sudo apt-get update
Install Certbot and its Nginx plugin:
sudo apt install python3-certbot-nginx -y
To obtain an SSL certificate for your domain using Certbot and Let’s Encrypt, execute the following command:
sudo certbot --nginx -d yourdomain.com -d www.yourdomain.com
Automating SSL renew
The generated SSL certificate will be valid for 90 days. To ensure the SSL certificate renews automatically every 90 days, we’ll set up a cron job. A cron job is a scheduled task that runs at predetermined times. This automatic renewal process is vital for keeping your SSL certificate up to date, ensuring your website remains secure without manual intervention.
Start by installing cron
sudo apt install cron
After installing cron, it can be activated using the following command
sudo systemctl enable cron
Create a file on the instance to input the renewal commands.
sudo nano ssl_auto_renew.sh
Insert the following commands into the file we created.
echo "Cron job ran on $(date)"
sudo certbot renew
Grant execution permissions to the file we created.
sudo chmod +x ./ssl_auto_renew.sh
To set up Cron, use the following command.
sudo crontab -e
This command will ask you to select a text editor. Choose nano
as the editor by selecting option 1
.
Insert the provided code into the opened file, save it by pressing ctrl + S
, and exit by pressing ctrl + X
.
0 0 * * * /home/ubuntu/ssl_auto_renew.sh >> /home/ubuntu/cron.log 2>&1
Note:/home/ubuntu
is specific for ubuntu if you are using different Linux distribution usepwd
to find out the current directory
0 0 * * *
specifies that it will execute daily at 12 AM
The path /home/ubuntu/ssl_auto_renew.sh
indicates the location of the script to be run.
The segment >> /home/ubuntu/cron.log 2>&1
directs the output to a file named cron.log
, with 2>&1
ensuring that both standard output and error logs are captured.
We can check if the cron is executed by examining the cron.log
file, which stores the logs.
Conclusion
We’ve come to the end, and I hope your application is up and running. Thank you for visiting my blog.