DEV Community

Joseph01
Joseph01

Posted on

Mastering VPS For Frontend Engineer - Part 2

In previous article we bought VPS, configured SSH and disabled the root access, which means our custom VPS authentication is ready to be used by us.

Now let's dive into adding more stuff to it

  1. Installing and configuring NGINX
  2. Setting up Node.js via NVM
  3. Deploying a Next.js frontend with NGINX and PM2
  4. Serving static React apps directly with NGINX
  5. Linking a custom domain and configuring DNS records
  6. Adding a subdomain for backend services
  7. Securing the server with a free SSL certificate from Let’s Encrypt

Why NGINX ?!

Now our VPS without NGINX can not serve our frontend and backend application, NGINX is responsible to handle large number of connection and its super fast and efficient.

One thing I like the most is Reverse Proxy before requests go to your backend application directly, it will go to NGINX first and direct them to correct service, you can simply say if users hits /api direct them to my python application.

Another thing is Load Balancing, imagine you've a lot of users and sometime lots of users uses your service at the same time, this add a lot more loads to your service and in result makes your app slow, what you can do you can have more than one running instance of your server, and NGINX will handle the traffic distribution and this will makes your service to be much faster.

There is much more about NGINX like SSL/TLS, Security and Concurrency, let's go and configure it.

Let's get started, install by running this on your server

sudo apt update
sudo apt install nginx
Enter fullscreen mode Exit fullscreen mode

Let's quickly get familiar with some of the most used files on NGINX, that you mostly interact with them.

  1. /etc/nginx/nginx.conf This is main global configuration, usually we create separate site configurations in other folder /sites-enabled then we'll just import it here so to be executable by nginx.

  2. /etc/nginx/sites-enabled/ this is where we put our nginx server block config files here, maybe you've portfolio or blog.portfolio, or using this file linked (symbolic linking) with sites-available specific files.

  3. /etc/nginx/sites-available As of best practices it is recommended to put our NGINX config files here and linking it with /sites-enabled directory, (cause nginx will only process files that is under /sites-enabled), technically we can skip the /sites-available directory if we want to but in that case we manually has to import and include the files from the nginx.conf.

  4. /var/www this is conventional location for web server content, means your source file it is not mandatory to put your projects directory here but its recomended to put your projects there, it is just standardized and secure location.

Deploying Frontend

Clone or upload your project source code under /var/www/frontend, here lets assume we've got NextJS Project.

and inside that build your app here for production by

npm run build
Enter fullscreen mode Exit fullscreen mode

this will create .next directory contains statics and server(for server side codes) this is crucial step and prepare our app to run efficiently.

Second create nginx config file under /etc/nginx/sites-available/frontend and add the config,
1- cd /etc/nginx/sites-available/
2- vi frontend
3-

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

    server_name (your_server_ip); # temp for now (we'll use real domain)

    location / {
        proxy_pass http://localhost:3000;
    }
}
Enter fullscreen mode Exit fullscreen mode

let's explain line by line
the server block is our virtual host, it contains a set of rules for single website or app, we can have more for other web apps.

listen 80 this tells nginx to listen for incoming connection on port 80 which is for HTTP traffic, when users types your server IP address they connect via this port. listen [::]:80 this is the same as 80 only it is for IPv6 the first one was for IPv4 addresses.

server_name this define the IP address or the domain name that this block is responding to, right now it is our server's public IP address, later we'll change to be real domain (e.g., example.com)

location / this define how to handle request when users hit the root address, like https://example.com/ this is root address.

lastly proxy_pass http://localhost:3000; will tell NGINX to forward the request from root to our internal port on 3000 which apparently our frontend app will be running on.

4- Now save and exit the file hit Esc from your keyboard and type wq then Enter

5- We should create a symbolic link so we'll create a symbolic file under /sites-enabled to let NGINX process our configuration, by running this command, make sure you're at /etc/nginx/ directory and run this command bellow

sudo ln -s /etc/nginx/sites-available/frontend /etc/nginx/sites-enabled/
Enter fullscreen mode Exit fullscreen mode

Now we'll test before restarting the NGINX server by

sudo nginx -t
Enter fullscreen mode Exit fullscreen mode

If you followed the steps you should be good to go.

Ok, the last step before restarting the NGINX and enable our web app, is to actually run our frontend app on port 3000, we built for production already now lets run it using pm2.

Why PM2

pm2 is a production process manager for Node.js apps, and since our app is NextJS and it may have SSR feature which is needs a node environment to run, otherwise if you only using pure ReactJS or VueJS they're purely static files no need for server side rendering so you'll just define the root in your server config.

So, if you using purely react just add or modify the location block of your NGINX config

    root /var/www/frontend/build;
    index index.html;

    location / {
        try_files $uri /index.html;
    }
Enter fullscreen mode Exit fullscreen mode

This way you don't need to use pm2 because your app is simply a static, one crucial thing here is the location block that tell NGINX to let the React's routing mechanism to handle the routing, cause if you did miss this part a user will hit /about NGINX will look for it under your /frontend/build/about/ and it is not there but if you add the location block it will let reactJS's Javascript-driven routing handles it, now simply restart NGINX with sudo systemctl restart nginx you should see your static files. Tadaa!!

But if you're using NextJS lets install pm2 and run the app with it.

Install pm2

sudo npm install -g pm2
Enter fullscreen mode Exit fullscreen mode

PM2 will let us manage multiple apps, like running, restarting, stopping and generate logs and monitor performance, it is super nice.

Now let's go to the frontend directory where we've our built file and we've got package.json file where there is a script for running that build production file for us.

package.json make sure you've this

  "scripts": {
    "build": "next build",
    "start": "next start",
  },
Enter fullscreen mode Exit fullscreen mode

Now run the PM2 with this and name your running process on pm2

pm2 start npm --name "frontend-app" -- run start
Enter fullscreen mode Exit fullscreen mode

now restart nginx and go to your server's IP address, and you'll see your web app live on VPS, Tada!!!

Add Domain

Of course you'll not share the server's public IP Address! lets add the domain I'll go with namecheap, go ahead and pick a cheap domain in their homepage.

Once you purchased a domain, one easy step left, and it is basically you’ll point your domain’s DNS records (managed at Namecheap) to DigitalOcean’s nameservers.

Let's update the DNS record from the namecheap step by step

  1. Go to Domain List → Manage next to your domain.
  2. Under Nameservers, choose Custom DNS.
  3. Enter these DigitalOcean nameservers:
ns1.digitalocean.com
ns2.digitalocean.com
ns3.digitalocean.com
Enter fullscreen mode Exit fullscreen mode
  1. Save changes (may take up to 24–48 hours globally, but often faster).

  2. Now going back to digitalocean dashboard click on
    Networking → Domains.

  3. Add your domain name (e.g., example.com).

  4. Lastly we need to add two records, @ record for root and CNAME record for www so our domain will be available by www.example.com

  • Click your domain you just added it
  • You can see a button Create Record
  • Choose A Record with its value @
  • Choose CNAME Record with value of www

Now after saving these settings we should wait for propagation process to take in place it may take a few minute or a few hours, just wait patiently if exceeded 48hrs contact the support team to get help.

Finally go ahead and replace the IP Address of our server from the NGINX config to be pointing to our new domain.

etc/nginx/sites-available/frontend

server {
    listen 80;
    server_name example.com www.example.com;   # or your_server_IP
    ...
}
Enter fullscreen mode Exit fullscreen mode

Then restart the NGINX

sudo systemctl restart nginx
Enter fullscreen mode Exit fullscreen mode

Note/ there is one thing, I face it to when I was experimenting with, for my domain I've choose .dev which is managed and owned by google and it requires me to have and active SSL Certificate and from this point I didn't had it so I couldn't access my website, but no worries once we add the certificate our web app will be active and online, just bare in mind that if your domain was not reachable at this point check your domain extension if accessible without SSL or you can check if the propagation has ended by visiting this website DNS Checker

Adding SSL Certificate

So, here we are this is by far one of the most amazing steps, in this step your step you officially marked as a secure site (HTTPS) and google will rank it better (SEO rank HTTPS over HTTP), and all this comes from Let's Encrypt organization and its all free, we can simply by simple commands enable it and make an auto renew when expired, sometime companies or providers will sell these if you're using shared hosting.

  1. Download certbot on Ubuntu/Dabian
sudo apt install certbot python3-certbot-nginx -y
Enter fullscreen mode Exit fullscreen mode

And apply for your domain for both A Record and CNAME Record we just added previously.

sudo certbot --nginx -d yourdomain.com -d www.yourdomain.com
Enter fullscreen mode Exit fullscreen mode

Lastly we'll enable auto renew, cause lets encrypt's certificates will expire in 90 days

sudo certbot renew --dry-run
Enter fullscreen mode Exit fullscreen mode

Now you've officially got your website up and running on VPS, whether it is static web application like ReactJS or it has SSR feature like NextJS.

Note/ if you've got a backend as well do exact same thing we just did it for Nextjs, in summary you'll need these steps

  1. Clone your backend project under /var/www/backend/
  2. Build for production and run it with PM2
  3. Add the NGINX configuration under /etc/nginx/sites-available/backend
  4. Create symbolic link for sites-enabled so NGINX will process it
  5. Add A Record for your sub domain (e.g. api.yourdomain.com)
  6. Restart and Test NGINX configuration
  7. Add SSL Certificate with certbot and enable auto renew

At this stage, our VPS can serve production apps securely with HTTPS. In Part 3, we’ll improve security, add CI/CD, Load balancer and explore containerization.

Top comments (0)