Brought to you by EsC (AKA Ryan Smith)

How To Deploy MERN (Mongo Express React Node) Stack App on AWS EC2— THE RIGHT WAY!

Ryan Smith
9 min readAug 26, 2018

***********Video Walk Through HERE!***********

This tutorial is how to deploy your MERN stack app on a Ubuntu 16.04 Amazon Web Services (AWS) EC2 instance. This can also be done with other services like Digital Ocean or Linode because they offer Ubuntu 16.04 instances.

— — — — — -

My small rant: I must say, when I first was learning React.js, and utilizing it as a full stack with Mongo DB, Node.js and Express.js, and it came time to deploy.. It was literal HELL!! AWS EC2, as alot of me and my buddies say can be a “black hole of confusion!” At least at first… Anyways, I have deployed a good amount of apps for practice, but NEVER for a MERN stack, and due to all the separate moving parts, and the fact that you have to worry about a front and and the back end, it was a constant trail and error adventure! Not to mention, the only very rare tutorials I found online, and I mean, after hours of extensive search, none of them worked…Especially that lil bastard who basically had us fork someone else’s boiler plate, oh god, you know who I mean if you been searching for this type of a tutorial… GOD AWFUL! Anyways, None of what I could find worked, At least not for my project… After searching and searching, I finally realized I’d have to just figure it out. And when I did figure it out I swore to make the best tutorial on it EVER! The kind of tutorial that Grandpa will tell to his grand kids around a fire while drinking whiskey!! Well geeks and nerds alike! Today is that day! Here is the full stack MERN Deployment tutorial! Thank you for putting up with my obnoxious venting… IT HAD TO BE SAID!! ;)

— — — — — —

  • NOTE* MAKE SURE YOU HAVE THIS ADDED IN YOUR SERVER.JS!:

const path = require(“path”);
app.use(express.static(path.join(__dirname, “client/build”)))

— — — — — -

  • ALSO be sure to go into your main folder APPNAME, and add a .gitignore file:
  • Open Gitbash(windows) Terminal(mac) and type
  • CD Into your app directory
touch .gitignore

Add the following to .gitignore :

/node_modules
package-lock.json

— — — — —

Now,

Create aws/ec2 instance:

  • Enter AWS, and click launch new instance.
  • Select Ubuntu 16.04 LTS
  • Select t2.micro
  • Set security settings:
  • add http and https set them to:
  • ssh 0.0.0.0, (Anywhere or myIP)
  • http 0.0.0.0 (Anywhere)
  • https 0.0.0.0 (Anywhere, or don't set it)
  • Download a .pem key from AWS or use an existing key

NOTE* This pem key is access to your deployed ubuntu server on aws. Put it in a safe place, separate from your app directory and don’t EVER push it to github.

  • Move the .pem file to an appropriate folder on your system
  • create instance

Images:

*NOTE* DO NOT “REVIEW AND LAUNCH”! CLICK “NEXT: CONFIGURE INSTANCE DETAILS” !

— — — — — — — — — — — — — — — — — — — — — —

Head back to your aws instances,

  • *Right click * your newly created instance and click “connect”
  • open git bash(windows) or terminal(mac) and cd into the directory you saved the particular pemkey for that instance,
  • Follow the steps on window that pops up after clicking connect

Type into terminal:


chmod 400 {{PemKeyName.pem}}

ssh into your ubuntu server:
*Note* copy the ssh - link right under example:

ssh -i “PemKeyName.pem” ubuntu@ec2–18–222–194–136.us-east-2.compute.amazonaws.com

Once SSHed in, then from here its mostly copy and paste! There will be a few parts where you have to input some info, but most of this is copy and paste from here.

Type in terminal/gitbash:

yessudo apt-get updatesudo apt-get install -y build-essential openssl libssl-dev pkg-config

— — — — — — — — — — — -

Node.js Setup:

sudo apt-get install -y build-essential openssl libssl-dev pkg-configsudo apt-get install -y nodejs nodejs-legacy sudo apt-get install npm -ysudo npm cache clean -fsudo npm install -g nsudo n stablesudo apt-get install nginx git -y

When cloning repo to ubuntu Server:

  • *Note* Git/Github: I will not showing you how to push/create repos from your git/github… But I will show you where to snag the repository link for cloning:

— — If you want to see tutorial on how to make and push your repositories consult here:

Copy from here:


cd /var/www
sudo git clone {{your project file path on github/git}}

NOTE- Don’t npm install just yet! — more on this later!— For now move on to the next steps

SetUp Nginx:

sudo apt-get install -y build-essential openssl libssl-dev pkg-configcd /etc/nginx/sites-availablesudo vim {{your cloned repo’s name}}

— Note This will open an empty file, but when you enter the info below and save it, the file will be created with the information you input.
— Note vim is a terminal-based text editor. For more info see: vim-adventures.com/ or other vim learning tools. The key commands for us are —

vim commands:
i = which allows us to type, or insert text
esc = which turns off insert
:wq = which we use to write (also known as save) and quit

Add the following code to the file you just made by using vim. Enter insert mode by clicking i. Change the two placeholders inside of double curly brackets {{ }} to match your specifications.

server {
listen 80;
location / {
proxy_pass http://{{PRIVATE IP FROM EC2 INSTANCE}}:{{NODE-PROJECT-PORT}};
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;
}
}

Proper Format Below:

Hit ESC Key and Type in terminal:

hit: esc
type: :wq
hit: enter key

Remove the default from nginx’s sites-available directory:

sudo rm default

Create a symbolic link from sites-enabled to sites-available:


sudo ln -s /etc/nginx/sites-available/{{repo name}} /etc/nginx/sites-enabled/{{repo name}}

Remove the default from nginx’s sites-enabled diretory:

sudo rm /etc/nginx/sites-enabled/default
Installing pm2 and updating project dependencies:sudo npm install pm2 -gcd /var/www/sudo chown -R ubuntu {{AppName}}cd {{AppName}}sudo npm install

then,

cd clientsudo npm install  
  • NOTE* Only run build IF you didn’t push your build folder to your github! If it doesn't work, you most likely already have it! move on!

sudo npm run build

— For mongo database information:
Main:
MONGO WEBSITE

Type into terminal: *NOTE* This below is ONE LINE! Copy all of it and paste it!:

sudo apt-key adv --keyserver hkp://keyserver.ubuntu.com:80 --recv 9DA31620334BD75D9DCB49F368818C72E52529D4
echo "deb [ arch=amd64,arm64 ] https://repo.mongodb.org/apt/ubuntu xenial/mongodb-org/4.0 multiverse" | sudo tee /etc/apt/sources.list.d/mongodb-org-4.0.list

then,

sudo apt install udosudo apt-get updatesudo apt-get install -y mongodb-org
  • NOTE * If it gives your an unauthenticated issue, Then type this instead:
sudo apt-get install -y mongodb-org --allow-unauthenticated

Then create data/bd:

sudo mkdir /datasudo mkdir /data/dbsudo service mongod start

Check the status of your service. Use ctrl C when you are done:


sudo service mongod status

Now we want to automatically start Mongo when the system starts:


sudo systemctl enable mongod && sudo systemctl start mongod
cd /var/www/{{repo name}}

Start your pm2 project:


pm2 start server.js

Restart nginx:


sudo service nginx stop && sudo service nginx start

NOTE- DONT DO THIS, just FYI incase you want to stop pm2:

pm2 stop

At this point, you should be able to navigate to your AWS public IP and see your live project!

Go back to your EC2 Instance, at the bottom window of information for said selected instance, copy the PUBLIC IP ADDRESS, and paste it into your browser!

  • NOTE* If your deployment didn’t work, then I promise you, you did something wrong within the process or it’s an issue with your app itself. I have personally tested this method with multiple MERN stack apps with a 100% success rate. Hope this helped!

Use pm2 logs to see the logs of your different pm2 instances. This will give you details of that instance:

pm2 show {{ pm2 instance id }}

ADDING CUSTOM DOMAIN INFO BELOW!

*NOTE* IF YOU USED REDUX!! *

ONLY PEOPLE WHO HAVE REDUX DEV TOOLS EXTENSION ON CHROME WILL BE ABLE TO SEE YOUR DEPLOYED APP… PEOPLE WHO HAVE THE EXTENSION, (SUCH AS YOURSELF) WILL SEE IT, BUT OTHERS WITHOUT IT, WONT. UNFORTUNATELY, I HATE TO SAY I AM CURRENTLY LOOKING INTO IT, AND HAVE BOILED IT DOWN THE THE STORE.JS FILE WITHIN YOUR REACT APP. THE SOLUTION LIES SOMEWHERE WITH:

composeWithDevTools() from the redux-devtools-extension package.

AS SOON AS I FIGURE THIS OUT, I WILL UPDATE IT HERE. FOR THE MOST PART THESE INSTRUCTIONS SHOULD GIVE YOU A SUCCESSFUL DEPLOYED APP.

Adding your custom domain name to your deployed server!:

Depending on where you got your domain name from, this may vary.. However these steps in these instructions will usually be very similar to most domain services. If not, your domain name service should be able to provide you with such instructions as to how to utilize your DNS for your own deployment.

In our case here, we will be using my favorite, godaddy.com -

GO DADDY INSRUCTIONS BELOW:

Basically, log into your domain service, and add your ip address from your EC2 instance into your domain path.

  • Log in to your GoDaddy account.
  • Go to Manage your domain > DNS zone file.
  • Change the @ record’s IP address to EC2’s public IP address and save the changes.
  • It may take couple of minutes for GoDaddy to update your IP address.

That should be it! It’ll take a few minutes, but now when anyone types in that said domain, it’ll pull your deployed sever from the inputted IP address.

Please like and share if this helped you! If you want to support, or have any questions or constructive criticism, please visit me at RyanKenSmith.com.

--

--