←- Back

Deploy Your MERN Stack App on AWS Lightsail in Minutes! or Hours.

In this comprehensive guide, I will walk through the process of deploying a fully functional application using Node.js, MongoDB, and a front-end library of your preference. Regardless of whether you choose React, Vue, or Angular, this tutorial will ensure seamless deployment for all.

Requirements:

Although there are many generous platforms available, some have inactivity time limits and limited storage space. This means that I need to use 3-4 different platforms to build a simple website. At the same time, those platforms like Remder, Cyclic, and Heroku do make the process a lot easier.

deploy mern app on aws lightsail

I made a Step by step YouTube video as well.

The Client and Server Code I used: View GitHub Repo

Create AWS MEAN Instance

The AWS Lightsail instance that we are going to use today is called MEAN, but as mentioned previously, you can use whatever front-end library you wish. In this example, I will be using NodeJs, Express, MongoDB and ReactJs.

Create Instance

Navigate to AWS LightSail and click on the orange button “Create instance“.

aws mean instance

Pick instance location

You can either choose the nearest data centre closest to you or maybe where your app is going to be mainly used.

location

Pick instance image and APP + OS

  1. Select Linux/Unix.
  2. Under the Apps + OS select MEAN.
aws mean instance os

Instance Plan

Choose whatever you think fits your requirements. In this example, I will use the $5 option.

aws mean price

Name your instance

Give your instance a name and then click on Create instance to create your project. It could take a minute to process.

Done!

Read more:

Project Setup

In this section we are going to set up the following:

Static IP

To set up a Static IP, navigate to your AWS LightSail Dashboard and click on Networking. From there you can create a Static IP. Click on “Create static IP” and give it a name.

Static IP can be helpful for multiple reasons. The main reason I use it is so that if I even need to create a new instance, I can always de-attach the Static IP from the old virtual server and attach it to another one. This way you don’t have to keep re-configuring your domain name records.

Note that Static IPs are free as long as they are used. If you create one and don’t attach it to a server you will be charged slightly.

Snapshot

Snapshot is a backup of your instance. It costs pennies and it’s totally worth having. Navigate to your AWS LightSail Project and click on Snapshots. Make sure that Automatic snapshots are enabled and you are good to go.

Server Configuration

To better organise our project, we should split it into two parts: the Front-end (client) and Back-end (server). We can achieve this by creating two separate folders and uploading the project files accordingly. Additionally, we need to configure our server to allow access to these projects using two different domains/subdomains. As a result, we can use the following URLs to access our project:

Client: raddy.dev – Server: server.raddy.dev

Domain Name Records

We need to create three A records. One for the main domain (raddy.dev) and two for the subdomains( www and server.).

Go to your domain registrar and update the DNS to match the IP of your AWS MERN instance. You can use the Static IP that we created.

Example of Google Domains:

aws mern domain

Update your records and we can move on…

Connect to our Server via FTP using FileZilla

For this part, we’ll need to get the following:

To get your SSH Key, go to AWS LightSail, click on your newly created MERN instance and under the Connect tab at the bottom of the page you’ll see “Download default key“.

mern pem key

Once you have everything and you are ready to connect to your server, let’s do the following:

  1. Open Filezilla.
  2. Go to Edit -> Settings
  3. Under Connection -> FTP -> SFTP, add your SSH key file.
  4. Press Okay

Now let’s add a new Site to our Site Manager

  1. Click File
  2. New Site
  3. Focus on the General Tab
  4. Protocol: Select SFTP
  5. Host: add your AWS MERN host IP.
  6. Leave Port blank. It should be 22 as the default
  7. User: bitnami
  8. Password: You can get your password via the Terminal. Use the command below.
  9. Click Connect.
cat bitnami_application_password
ftp

Server

Next, inside the folder “/home/bitnami/” create a folder called “client” and a folder called “server”. Note that the “htdocs” folder is where your front-end build code will live.

Let’s start with the Sever. Upload your Server project files in the “server” folder. Everything excusing the “node_modules” folder.

Open the Terminal, and navigate to the “server” folder that we just created using the “cd” command. You can use “ls” to see your current directory files.

cd server

Now install the Node dependencies.

npm install

Client

Do the same for the client.

Open the Terminal, and navigate to the “client” folder that we just created using the “cd” command.

cd client

Drop your files inside the folder and then install the node dependencies.

npm install

Build your project.

npm run build

This normally creates a folder called “dist” if you are using Vite. This is the compiled version of your project. You can also do this locally.

Move the files from the “dist” folder to the “htdocs” folder located in “opt/bitnami/apache/htdocs”.

Create Virtual hosts for Client & Server

Using FileZilla or Terminal navigate to “/opt/bitnami/apache/conf/” and add a file “vhost.conf” with the following code below, replacing the domain name “raddy.dev” with yours.

<VirtualHost *:80>
    ServerName raddy.dev
    # Other directives here
</VirtualHost>

<VirtualHost *:80>
    ServerName server.raddy.dev
    ProxyPass / http://localhost:8000/
    ProxyPassReverse / http://localhost:8000/
    # Other directives here
</VirtualHost>

Now restart Apache

sudo /opt/bitnami/ctlscript.sh restart apache

SSL

To generate an SSL certificate for our website, we need to first ensure that our domain is pointing to the server. We have already done this earlier in this tutorial. Now, we can use the Bitnami Bncert Tool to generate the SSL certificate.

To do this, open a terminal window and navigate to the directory where you installed the Bitnami Bncert Tool. Then, run the following command:

sudo /opt/bitnami/bncert-tool

The setup will ask you for your domain names. Enter them with space in between and follow the rest of the instructions.

This will generate an SSL certificate for your website. The certificate will be stored in the /opt/bitnami/apache/conf directory.

Once you are done with the SSL setup, you should be able to go under “/opt/bitnami/apache/conf/” and see the “crt” and “key” in there. We need to add them to our vhost.conf file.

Replace the “<add_cert…” with the name of your website certificates.

<VirtualHost *:443>
    ServerName raddy.dev
    SSLEngine on
    SSLCertificateFile "/opt/bitnami/apache/conf/<add_cert_name>.crt"
    SSLCertificateKeyFile "/opt/bitnami/apache/conf/<add_key_name>.key"
    # Other directives here
</VirtualHost>

<VirtualHost *:443>
    ServerName server.raddy.dev
    ProxyPass / http://localhost:8000/
    ProxyPassReverse / http://localhost:8000/
    SSLEngine on
    SSLCertificateFile "/opt/bitnami/apache/conf/<add_cert_name>.crt"
    SSLCertificateKeyFile "/opt/bitnami/apache/conf/<add_key_name>.key"
    # Other directives here
</VirtualHost>

Restart Apache

sudo /opt/bitnami/ctlscript.sh restart apache

You can also test your configuration by using the command below.

apachectl configtest

Start NodeJS Project

To kick off your NodeJs project and ensure its continuous operation, you have several alternatives at your disposal. Today, however, we’ll focus on a particularly powerful tool, known as “PM2”.

PM2 is not just a process manager, but a daemon one, designed to help you effectively manage your application and keep it running smoothly without interruption. Adopting PM2 is a breeze. It comes with a simple and intuitive Command Line Interface (CLI), and can be conveniently installed through the Node Package Manager (NPM). This makes it a straightforward solution for your application’s management needs.

sudo npm install pm2@latest -g

Using the Terminal, “cd” to your “server” folder and run your application by doing the following.

 pm2 start index.js

To stop the “index.js” process you can use the following command listed below.

 pm2 stop index.js

If you wish to watch for changes you can add:

 pm2 start index.js --watch

You can also explore the following options:

 pm2 [list|ls|status]

If you make changes to your .env file, please use:

 pm2 --update-env

And here is something super cool

 pm2 monit

Here is the full usage guide: https://pm2.keymetrics.io/docs/usage/quick-start/

Test your application

Go into your browser and test your URLs: In my case: raddy.dev and server.raddy.dev.

ReactJS 404 Error on Page Reload

In the event that you stumble upon a 404 error when either manually refreshing the page or navigating to a specific URL such as “/about,” don’t worry. This guide outlines steps you can take to remedy the situation. This problem typically emerges due to the fact that our index.html file is tasked with serving the entirety of the application. When the web server can’t find a file matching the given name, it results in a 404 error, which is a standard response in such scenarios.

To rectify this issue, what you’ll need to do is redirect all incoming requests to the index.html file. While there are multiple ways to approach this, for the scope of this guide, we will particularly focus on providing solutions tailored for Apache users.

The first step is to allow the use of HTACCESS. Using SSH or FTP Client, navigate to and change the following file:

Look for <Directory "/opt/bitnami/apache/htdocs">
  
CHANGE:
AllowOverride None
  
TO:
AllowOverride All

Save the changes.

Now navigate to “/opt/bitnami/apache/htdocs/” and add the following code in the “.htaccess” file.

<IfModule mod_rewrite.c>
  RewriteEngine On
  RewriteBase /
  RewriteRule ^index\.html$ - [L]
  RewriteCond %{REQUEST_FILENAME} !-f
  RewriteCond %{REQUEST_FILENAME} !-d
  RewriteCond %{REQUEST_FILENAME} !-l
  RewriteRule . /index.html [L]
</IfModule>

Save the changes.

Go back to the AWS Terminal and Restart Apache.

sudo /opt/bitnami/ctlscript.sh restart apache

Your SPA should now work as intended.

Configure Mongo DB Username, Database & Access

To gain access to our MongoDB Database, a few crucial steps must be executed. Initially, you must procure the AWS Instance password. Following that, you’ll need to log in with administrative privileges. Once logged in, your next task is to create a new database. Lastly, establish an Administrator Username and Password to ensure secure and authorised access. This systematic approach will pave the way for smooth and secure database operations.

Get MongoDB Password:

To get the root password open the terminal and type the following command:

cat bitnami_application_password

This should return your password. Make a copy of it and keep it safe.

Access Mongosh as Administrator

Now we need to access Mongo DB using Mongosh. To do that type the following command:

mongosh admin --username root -p

It will ask you for your password. Paste your password.

Create / Select Database and add User Permissions

Select a database of your choice to which you would like to give user permissions. In my case, I will select a database called “database”.

Select the database:

use "database"

Create a username and password permissions:

db.createUser({ user: "raddy", pwd: "strong password here", roles:["dbOwner"] })

To see the available Users:

show users

See the available Databases:

show dbs

Connect Project To Local MongoDB Database

In order to access our MongoDB locally on our computer we need to tunnel via SSH.

We need:

  1. AWS Instance IP
  2. Port: 22
  3. SSH Key / Pem Key / Private Key
  4. Terminal or PuTTY – PuTTYgen

Tunnel via SSH

Option 1 – Using PuTTY / PuTTYgen Windows

Download PuTTY + PuTTYgen

Download your SSH Key from your MERN instance.

mern pem key
  1. Open PuTTYgen and Load your SSH Key. Click Generate and save your newly created private key.
  2. Open PuTTY

Add the following settings:

  1. Host Name – xxx.xx.xxx.xx.
  2. Port: 22
  3. Saved Session: Project Name
  4. Under Connection -> SSH -> Auth -> Load your Private Key.
  5. Under Connection -> SSH -> Tunnels add: Source Port 27017, Destination: localhost:27017
  6. Under Connection -> Data -> Add Auto-login username: bitnami
  7. Go back to Session and Save!

Once you are ready, click Open. This should SSH tunnel to your project and now you can use programs like MongoDB Compass to manage your Database locally. You need to have the window Open.

Option 2 – Windows / Mac / Linux

Locate your Lightsail pem key file and use it to SSH.

ssh -i ~/LightsailDefaultKey-eu-west-2.pem -N -f -L 8000:127.0.0.1:27017 bitnami@xx.xx.xx.xx <- IP HERE

On Windows, you might have permissions issues. Follow the instructions shown in the Terminal.

Windows Permissions

  1. Find your account name

You can go under Control Panel\User Accounts\User Accounts and get your Username from there.

Locate your Pem key.

  1. Right Click -> Properties
  2. Select Security Tab -> Click Advanced
  3. Click Disable inheritance -> Remove all inherited permissions from this object
  4. Select Add -> Select a principal -> Enter your Computer Name + Username
  5. Permission Entry -> Grant Read permissions and select OK.
  6. Apply, Okay everything…

Try again:

ssh -i ~/LightsailDefaultKey-eu-west-2.pem -N -f -L 8000:127.0.0.1:27017 bitnami@xx.xx.xx.xx <- IP HERE

Add this connection string in MongoDB Compass:

mongodb://root:<your password>@127.0.0.1:8000

Linux / Fedora Permissions Fix

chmod 400 LightsailDefaultKey-eu-west-2.pem
ssh -i ~/LightsailDefaultKey-eu-west-2.pem -N -f -L 8000:127.0.0.1:27017 bitnami@xx.xx.xx.xx <- IP HERE
private key permissions
mongodb://root:<your instance password>@127.0.0.1:8000

Connect using MongoDB Compass

To connect to your database you need to have your SSH Tunnel / PuTTY connection window open. You can Download MonogDB Compass from here.

Open MongoDB Compass and use the following string:

mongodb://root:<your instance password>@localhost:27017

OR

mongodb://<user_you_created>:<password_of_the_user>@localhost:27017/database <-db name here

Click “Connect” and you should be in.

You can use the MongoDB string in your project to connect to your database.

That’s all. I hope that you found the article useful.