Skip to content

Instantly share code, notes, and snippets.

@sjosephrw
Last active March 23, 2024 05:13
Show Gist options
  • Star 38 You must be signed in to star a gist
  • Fork 16 You must be signed in to fork a gist
  • Save sjosephrw/5bc7efbf4c332070165c61dba253288d to your computer and use it in GitHub Desktop.
Save sjosephrw/5bc7efbf4c332070165c61dba253288d to your computer and use it in GitHub Desktop.
Deploy Multiple MERN apps to a single digital ocean ubuntu droplet with nginx and SSL

Deploy Multiple MERN apps to digital ocean

This tutorial will guide you through the process of deploying multiple MERN apps to a single digital ocean ubuntu VPS droplet Reference

1. Sign up for Digital Ocean

DigitalOcean

2. Create a droplet and Login via SSH

YouTube

3. Install NodeJS and npm

$ sudo apt update
$ sudo apt install nodejs
$ nodejs -v
$ npm -v

4. Create a folder for the project on the Droplet

In your droplets home directory create a folder called apps

$ mkdir apps
$ cd apps

5.Clone your project from Github

$ git clone yourproject.git

6. Install dependencies and test app

cd yourproject
npm install
npm start (or whatever your start command)
# stop app
ctrl+C

7. Setup PM2 process manager to keep your app running

sudo npm i pm2 -g
# Make sure you are in the root folder of your app then run
pm2 start app (or whatever your file name)

# Other pm2 commands
pm2 show app
pm2 status
pm2 restart app
pm2 stop app
pm2 logs (Show log stream)
pm2 flush (Clear logs)

# To make sure app starts when reboot
pm2 startup ubuntu

8. Setup UFW Firewall

sudo ufw enable
sudo ufw status
# (Port 22)
sudo ufw allow ssh
#(Port 80)
sudo ufw allow http 
#(Port 443)
sudo ufw allow https 

9. Install NGINX and configure

sudo apt install nginx

10. Move the REACT front end into /var/www/html/ folder

I am assuming that the react front end is contained in a folder called "build" in your projects root directory

#From within your project ROOT directory
cp -Rv build /var/www/html

11. Rename the build folder to a name that will reflect the domain name of your app

mv build mydomain.com 

12. Change permissions of the "mydomain.com" folder

Reference 1 Reference 2

chown -R www-data:www-data /var/www/html/mydomain.com

13. Configure NGINX

sudo nano /etc/nginx/sites-available/mydomain.com.conf

I assume that the backend is running on port 5000 as denoted in the config block below -> "proxy_pass http://localhost:5000;"

and that the front end accesses the backend like this https://www/mydomain.com/backend/your-api-endpoints

Copy paste this into the file that opens in NANO

server {
    listen 80;
    listen [::]:80;

    #Path to the React front end
    root /var/www/html/mydomain.com;
    
    #the main html file
    index index.html;
    
    #Enter the IP address of your droplet
    server_name <ENTER THE IP ADDRESS OF YOUR DROPLET>;

     #STORE the nginx access logs for this app here
     access_log /var/log/nginx/mydomain.com.access.log;
     #Store the error logs for this app here
     error_log /var/log/nginx/mydomain.com.error.log;

    
    location / {
        # Without this line routing in your Single Page APP will not work  
        try_files $uri $uri/ /index.html =404;
    }
    
    #REST API BACKEND CONFIG
    location /backend {
        proxy_set_header X-Real-IP $remote_addr;
        proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;
        proxy_set_header X-NginX-Proxy true;
        proxy_pass http://localhost:5000;
        proxy_ssl_session_reuse off;
        proxy_set_header Host $http_host;
        proxy_cache_bypass $http_upgrade;
        proxy_redirect off;
    }    
    

Save and close the config file

Ctrl + O
Ctrl + X

14. Enable the new server block file by creating a symbolic link from the file to the sites-enabled directory

sudo ln -s /etc/nginx/sites-available/mydomain.com.conf /etc/nginx/sites-enabled/

15. Test the Nginx configuration for correct syntax

sudo nginx -t

If there are no errors, the output will look like this:

nginx: the configuration file /etc/nginx/nginx.conf syntax is ok
nginx: configuration file /etc/nginx/nginx.conf test is successful

16. Restart the Nginx service for the changes to take effect

sudo systemctl restart nginx

17. Install Python NGINX certbot to generate a SSL Certificate

DigitalOcean Documentation

sudo add-apt-repository ppa:certbot/certbot
sudo apt-get update
sudo apt-get install python-certbot-nginx
sudo certbot --nginx -d mydomain.com -d www.mydomain.com

To renew the certificate

sudo certbot renew --dry-run

If you ever need to make changes to /etc/nginx/sites-available/mydomain.com.conf

Reference

#FIRST DELETE THE CONF FILE FROM SITES-ENABLED AND NOT SITES-AVAILABLE
#ONCE AGAIN DELETE THE CONF FILE IN SITES-ENABLED

cd /etc/nginx/sites-enabled

rm mydomain.com.conf

#and then after you have finished modifying the conf file in SITES-AVAILABLE run this once again
sudo ln -s /etc/nginx/sites-available/mydomain.com.conf /etc/nginx/sites-enabled/

For multiple MERN apps repeat from STEP 10 and replace mydomain.com with anotherdomain.com and make sure the backend is running on a different port, also update the port for the backend in your sites-available conf file proxy_pass http://localhost:differen-port;

@benlhachemi
Copy link

Good tutorial
Thanks a lot, it's very helpful :)

@mizan126721
Copy link

How to setup ci cd now.

@sjosephrw
Copy link
Author

Good tutorial Thanks a lot, it's very helpful :)

You 're welcome

@sjosephrw
Copy link
Author

How to setup ci cd now.

I will try to cover that in another post if time permits.

@AbdukahharS
Copy link

What about MongoDB?

@AbdukahharS
Copy link

Can I install MongoDB on digitalocean ubuntu droplet?

@sjosephrw
Copy link
Author

sjosephrw commented Dec 19, 2021

You can install mongo on the ubuntu droplet but I would advise you to go for the fully managed Mongo Cloud Database as a solution.

@korbonya
Copy link

thanks a lot !!

@sjosephrw
Copy link
Author

thanks a lot !!

You 're welcome.

@sjosephrw
Copy link
Author

sjosephrw commented May 17, 2022

Did you follow step 14, the symbolic link may not have been created, try running the step 14 command again, also check this folder "/etc/nginx/sites-enabled/" for the .conf file

@Apolloniann
Copy link

My app's root is also operational, as is the navbar's page. However, if I go to any other route, such as /login or /product, or if I refresh the URL of that page, they do not load my page and give me this error. Error: ENOENT: no such file or directory, stat '/root/IBN/src/build/index.html'

@Apolloniann
Copy link

issue resolved actually i write the wrong address in server/index.js file

@sjosephrw
Copy link
Author

sjosephrw commented Jun 26, 2022

Hi Zeeshan I am glad you were able to resolve the problem you were facing.

@puzaan
Copy link

puzaan commented Aug 16, 2022

after deploying in digitalocean
my api doesn't take or read authorization api key

@raja-muhammad-asher
Copy link

Thank you @sjosephrw for writing this concise and to the point guide. There is a missing closing brace in step 13 for server. Kindly add } at the end so that who copies it and use it does not face error. Thank you once again for saving us hours of research to achieve this.

@Sahil-widski
Copy link

Sahil-widski commented Mar 28, 2023

Hey how can I deal with this error?
[This request has been blocked; the content must be served over HTTPS] @sjosephrw @sjosephrw
While making requests from my frontend to backend but my frontend on HTTPS after certbot steps and server is on host ip

@Jimfarrugia
Copy link

Thank you for this. I was having lots of trouble figuring this stuff out. Your guide is the best one I've seen so far and it got me up and running.

@sjosephrw
Copy link
Author

Thank you @sjosephrw for writing this concise and to the point guide. There is a missing closing brace in step 13 for server. Kindly add } at the end so that who copies it and use it does not face error. Thank you once again for saving us hours of research to achieve this.

Thank you for this. I was having lots of trouble figuring this stuff out. Your guide is the best one I've seen so far and it got me up and running.

You're welcome and Sorry for the delay in replying .

@Satyam1Dev
Copy link

Very Helpful Tutorial Thanks

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment