Skip to main content

Command Palette

Search for a command to run...

How to deploy - AWS / VM (Simplified)

Let's deploy your React.js, Node.js and Static files

Updated
7 min read

Prequests

  • Any Debain based linux machine E.g. Ubuntu, Amazon Linux.

  • A domain name (Optional but required for making connection HTTPS).

  • Make sure to enable HTTP and HTTPS in the firewall (for aws its called security groups).

Step 1 - installations

Before getting into any thing lets first update your system.

sudo apt update -y && sudo apt upgrade -y # This will update all packages installed by apt

Next we need to install node.js

curl -o- https://raw.githubusercontent.com/nvm-sh/nvm/v0.40.0/install.sh | bash
source ~/.bashrc
nvm install --lts
nvm use --lts

Verify installations by running node -v and npm -v.

Now you should be able to run node and see REPL of Node.js. Try to run some file with node index.js

Now lets install PM2, a process manager used to keep Node.js running even after closing the terminal (running Node.js in background).

npm install -g pm2

Verify installations by running pm2 -v

Now you should be able to run pm2 start index.js, this will create a new process in pm2.

Here are some commands that come in handy

  1. pm2 startup make pm2 automatically start when the system turn’s on (very helpful). make sure to turn this on so that you don’t need to worry about mannually restarting every time.

  2. pm2 list list all processes.

  3. pm2 monit monitor a process.

  4. pm2 save save current process list.

  5. pm2 logs show logs of all running process.

Now let’s install one more team member Nginx, a powerfull webserver and reverse proxy (Very helpful).

sudo apt install -y nginx

Verify installations by running nginx -v

Here are some commands that come in handy

  1. sudo systemctl start nginx starts nginx.

  2. sudo systemctl enable nginx make nginx automatically start when the system turns on. Make sure to run this. so that you don’t need to worry about mannally starting nginx every time.

  3. sudo systemctl status nginx view current status on nginx service.

If you have a public ip address and if the firewall is enabled you should be able to see nignx welcome page while entring your public ip http://<your public ip>.

Step 2 - Deployment.

before running any commands lets first understand what we are going to do.

We are goning to use nginx as a proxy (distributor of requests to our projects) and a static file server (for serving react).

We have 3 services.

  1. Node.js backend (running using pm2) in port 3000. for /api

  2. React.js admin pannel (serving bulid using pm2) in port 5173. for /admin

  3. React.js main website (build files serving using nginx) for requests to /,

Nginx will listen in the port 80 (HTTP default port) and 443 (HTTPS default port). and redirect/serve requests according to the requests’ path.

So if :

  1. Request is coming to / then nginx will look at the reacts’ build for for main website and serve static files according to the requests.
    E.g.. urls http://12.12.12.12/ or https://example.com/ (when ever path is or starts with /).

  2. Request is coming to /api then nginx will redirect/forward that request to Node.js listening on 3000 and running on pm2.
    E.g.. urls http://12.12.12.12/api/ or https://example.com/api/ (when ever path is or starts with /api).

  3. Request is coming to /admin then nginx will redirect/forward that request to React serving using pm2 on port 5173.
    E.g.. urls http://12.12.12.12/admin/ or https://example.com/admin/ (when ever path is or starts with /admin).

Now lets get into implimentaion

First lets start our backend, Clone you code or just create a new js file in the server.

cd /backend # Open you folder with node.js code

For now i am creating a index.js file in /backend folder

nano index.js # This will create a new file and open in nano editor
const http = require('http');

const hostname = 'localhost';
const port = 3000;

const server = http.createServer((req, res) => {
  res.statusCode = 200;
  res.setHeader('Content-Type', 'text/plain');
  res.end('Hello World!\n');
});

server.listen(port, hostname, () => {
  console.log(`Server running at http://${hostname}:${port}/`);
});

Use ctrl + o to save the changes and ctrl + x to exit the nano editor.

pm2 start index.js --name test-server # Change index.js to you entry poient

Ok now backend is ready. To accessing the backend directly enable 3000 port in firewall (security groups if you are in AWS) and request to your servers public ip address or if you are in same LAN with the server use its ip address.
E.g.. link http://12.12.12.12:3000/

Now lets serve React.js admin dashboard usign pm2.

First clone the repo and get the code to the server. and open that.

cd admin-page # Open your admin page directory with react project
npm run build # Build the project and create static files

To serve this using PM2’s static file server

pm2 serve --name admin-pannel ./dist 5173

Ok now admin page is ready. To accessing the admin page directly enable 5173 port in firewall (security groups if you are in AWS) and request to your servers public ip address or if you are in same LAN with the server use its ip address.
E.g.. link http://12.12.12.12:5173/

Now lets serve main react page using Nginx

Note : You can use pm2 to serve this one also, but for learning purpouse I am serving using Nginx.

To service someting using nginx we need to create a config file.

The default folder for nginx config in Ubuntu is /etc/nginx/sites-available and /etc/nginx/sites-enabled

What we generally do is we create a config file in /etc/nginx/sites-available and create a soft link of that file to /etc/nginx/sites-enabled. what ever files/configs is on the sites-enabled folder will get exicuted by Nginx.

So lets create our config file for Nginx.

sudo nano /etc/nginx/sites-available/deploy # here i am using depoy as file name

insdie that file we need to add config for Nginx.

server {
   # this will match all request, if you have a domain name replace _ with your domain name.
   server_name _; 

    # This is the folder where nginx look for you react dist folder.
    # Make sure to give the correct path or copy dist output to the below folder
    root /var/www/my-react-app; 

    # Configuring default file to serve.
    index index.html; 

    # this will serve static files according to url else index.html
    location / {
       try_files $uri $uri/ /index.html; 
    }

    # Forward all request to Node.js running on PM2 at 3000
    location /api {
       proxy_pass http://localhost:3000;
       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;
    }

    # Forward all request to React.js serving from PM2 at 5173
    location /admin {    
       proxy_pass http://localhost:5173;
       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;
    }

    # Optional: gzip compression for better performance
    gzip on;
    gzip_types text/plain text/css application/javascript application/json image/svg+xml;
    gzip_min_length 256;
}

Use ctrl + o to save the changes and ctrl + x to exit the nano editor.

Now link the file to sites-enabled folder

sudo ln -s /etc/nginx/sites-available/deploy /etc/nginx/sites-enabled/

It's a good practice to remove old non used nginx configs from sites-enabled folder

sudo rm /etc/nginx/sites-enabled/default

before starting nginx test your config files for errors

sudo nginx -t
sudo systemctl restart nginx # Start if not running otherwise restart nginx.

Hurray, Now you should be able to see your deployment by opening you public ip address in you browser.

E.g.. link

  • http://12.12.12.12:5173/ for your main react app.

  • http://12.12.12.12:5173/admin/ for your react admin app.

  • http://12.12.12.12:5173/api/ for your node.js backend.

Step 3 - Adding SSL certificates - HTTP to HTTPS

Let’s Encrypt is a Certificate Authority (CA) that provides an easy way to obtain and install free TLS/SSL certificates, thereby enabling encrypted HTTPS on web servers. It simplifies the process by providing a software client, Certbot, that attempts to automate most (if not all) of the required steps. Currently, the entire process of obtaining and installing a certificate is fully automated on both Apache and Nginx.

Let's install certbot along with its nginx plugin

sudo apt install certbot python3-certbot-nginx

Certbot will find correct server_name directive that matches the domain name you mentioned on the command and automatically add certificates. It will update our Nginx Confing file that we have created with 443 port binding (for listening to HTTPS requests).

Ok lets run certbot

sudo certbot --nginx -d your_domain_name # Replace your_domain_name with your actucal domain name

So select your choice and hit ENTER. The configuration will be updated, and Nginx will reload to pic up the new settings.

Your certificates are downloaded, installed, and loaded. Try reloading your website using https:// and notice your browser’s security indicator. It should indicate that the site is properly secured, usually with a lock icon. If you test your server using the SSL Labs Server Test, it will get an A grade.

Happy coding :)