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:
- An AWS LightSail Account
- Domain Name
- SSH / FTP Client
- Code Editor
- A budget of $5
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.
I made a Step by step YouTube video as well.
The Client and Server Code I used: View GitHub Repo
Table of contents
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“.
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.
Pick instance image and APP + OS
- Select Linux/Unix.
- Under the Apps + OS select MEAN.
Instance Plan
Choose whatever you think fits your requirements. In this example, I will use the $5 option.
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:
- The Official MEAN Documentation link can be found here: MEAN Documentation
Project Setup
In this section we are going to set up the following:
- Static IP
- Snapshots
- Server Configuration
- Client Project (ReactJs)
- Server Project (NodeJs, Express)
- Domain Name (SSL)
- MongoDB Database
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:
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:
- Server IP
- Username: bitnami
- SSH Key / PEM Key
- Filezilla
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“.
Once you have everything and you are ready to connect to your server, let’s do the following:
- Open Filezilla.
- Go to Edit -> Settings
- Under Connection -> FTP -> SFTP, add your SSH key file.
- Press Okay
Now let’s add a new Site to our Site Manager
- Click File
- New Site
- Focus on the General Tab
- Protocol: Select SFTP
- Host: add your AWS MERN host IP.
- Leave Port blank. It should be 22 as the default
- User: bitnami
- Password: You can get your password via the Terminal. Use the command below.
- Click Connect.
cat bitnami_application_password
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:
- AWS Instance IP
- Port: 22
- SSH Key / Pem Key / Private Key
- Terminal or PuTTY – PuTTYgen
Tunnel via SSH
Option 1 – Using PuTTY / PuTTYgen Windows
Download your SSH Key from your MERN instance.
- Open PuTTYgen and Load your SSH Key. Click Generate and save your newly created private key.
- Open PuTTY
Add the following settings:
- Host Name – xxx.xx.xxx.xx.
- Port: 22
- Saved Session: Project Name
- Under Connection -> SSH -> Auth -> Load your Private Key.
- Under Connection -> SSH -> Tunnels add: Source Port 27017, Destination: localhost:27017
- Under Connection -> Data -> Add Auto-login username: bitnami
- 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 [email protected] <- IP HERE
On Windows, you might have permissions issues. Follow the instructions shown in the Terminal.
Windows Permissions
- Find your account name
You can go under Control Panel\User Accounts\User Accounts and get your Username from there.
Locate your Pem key.
- Right Click -> Properties
- Select Security Tab -> Click Advanced
- Click Disable inheritance -> Remove all inherited permissions from this object
- Select Add -> Select a principal -> Enter your Computer Name + Username
- Permission Entry -> Grant Read permissions and select OK.
- Apply, Okay everything…
Try again:
ssh -i ~/LightsailDefaultKey-eu-west-2.pem -N -f -L 8000:127.0.0.1:27017 [email protected] <- 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 [email protected] <- IP HERE
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.