Photo by Joshua Aragon on Unsplash

Serving Nginx domain in DigitalOcean and running React app as a subdirectory

I found bits and pieces information here and there, and hence documenting the steps I followed as a future reference for me, and for anyone else in my shoes.

Nginx setup

I created a droplet from DigitalOceal ($5/month) and followed their tutorial on installing NginX server on Ubuntu 18.04, as well as securing it with certbot.

During the process, I registered a domain from GoDaddy and created A records attaching that domain name to my droplet from my DigitalOcean dashboard.

The product is that when I point to my domain, I see an https link displaying the default nginx page indicating that everything went on fine.

Here are a few points to note in this process.

Understanding nginx server block directives and context is very important. I am still struggling with that. (I am referring to whatever block and files you create under /etc/nginx/sites-available/ folder). Note that when you get your registered domain certified by the certbot, it add’s few directives in the file related to your domain (in my case it is

#this is file resided at /etc/nginx/sites-available/playquran.comserver {...
listen [::]:443 ssl ipv6only=on; # managed by Certbot
listen 443 ssl; # managed by Certbot
ssl_certificate /etc/letsencrypt/live/; # managed by Certbot
ssl_certificate_key /etc/letsencrypt/live/; # managed by Certbot
include /etc/letsencrypt/options-ssl-nginx.conf; # managed by Certbot
ssl_dhparam /etc/letsencrypt/ssl-dhparams.pem; # managed by Certbot

Also note that (if you followed the digitialOcean tutorial you will know that) the static contents are available in the directory: var/www/

Node js

Once you are done with serving static files, you may want to serve some nodejs contents listening over some port. For this digitalocean also has a good tutorial. Follow that tutorial and have the following node file serving at port (whatever, but in my case) 4003, as follows:

const http = require('http');const hostname = 'localhost';
const port = 4003;
const server = http.createServer((req, res) => {
res.statusCode = 200;
res.setHeader('Content-Type', 'text/plain');
res.end('Hello World!\n');
server.listen(port, hostname, () => {
console.log(`Server running at http://${hostname}:${port}/`);

The tutorial will tell you to have pm2 to keep your app running in the background.

Now, you need to adjust your nginx server block to reflect this content as a location context as follows:

server {...
location /nodejs {
proxy_pass http://localhost:4003;
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;

Test this modification syntax by sudo nginx -t and then reload the nginx by sudo systemctl restart nginx and then point to to see the Hello World! displaying.


I have the following express app as app.js:

onst express = require('express');
const app = express();
const PORT = process.env.PORT || 4001;app.listen(PORT, () => {
console.log(`Server is listening on port ${PORT}`);
app.get('/', (req,res,next)=>{
res.send('serinv your exprsso!');

and here is the location block:

location /express/ {
proxy_pass http://localhost:4001/;

I have struggled a lot, and it appears that others as well because of the absence of the trailing / at the end of /express/ and the uri as well. This link was very helpful in resolving that issue.


Now, let us turn our attention to a front-end react app. Let us assume you have your app available in a GitHub repo.

step 1. clone the app

step 2. cd to the directory

step 3. npm install

step 4. modify the package.json file to create an entry where you want the app to be available in my case it will be the ayaat subdirectory.

"homepage": "",

step 5. npm run build this will make npm follow the instruction in the package.json file and create static contents in the folder build

step 6. copy all files (and folders cp -r ) from the build folder into a folder (I will call it ayaat) inside your/var/www/ folder.

├── ayaat
│ ├── asset-manifest.json
│ ├── favicon.ico
│ ├── index.html
│ ├── manifest.json
│ ├── precache-manifest.85fa01ead59977e4e253ccd9aafda3ed.js
│ ├── service-worker.js
│ └── static
│ ├── css
│ │ ├── main.71e49a20.chunk.css
│ │ └──
│ ├── js
│ │ ├── 2.5dbd8ed4.chunk.js
│ │ ├──
│ │ ├── main.f41582ff.chunk.js
│ │ ├──
│ │ ├── runtime~main.7f5ee7e1.js
│ │ └──
│ └── media
│ └── logo.5d5d9eef.svg

After you are done with this, it remains only to add a location /ayaat context your nginx file /etc/nginx/sites-available/

server {root /var/www/;
location / {

location /ayaat/ {
try_files $uri /ayaat/index.html;

Note how we specified the root location under the server and used the try_files inside the location context.


In this tutorial, I guided you through three digitalocean tutorial links on how to provision your own server and serve static contents over an nginx server. Also, how to serve a nodejs app listening on a particular port. Also, gave you the solution how to serve an express app running on a port.

Finally, I showed you how to build a react front-end app and serve it through a subdirectory on your main domain.

Would you clap if this was helpful :)




We have certainly sent down to you a Book in which is your mention. Then will you not reason? [Quran 21:10]

Love podcasts or audiobooks? Learn on the go with our new app.

Recommended from Medium

How to Create Nested Routes with React Router and Hooks — An In Depth Project Summary

Building A Review App Using ReactJS, Elasticsearch, App Search and Grommet

15 Common JavaScript Questions

The first thing I do on any Typescript/Angular project

Design Patterns in JavaScript: Creational

How JavaScript is used for the back-end ft. Node.js?

The Power of the Composite Design Pattern in JavaScript

Apollo Client 3.0 — Reactive Variables in Local State

Get the Medium app

A button that says 'Download on the App Store', and if clicked it will lead you to the iOS App store
A button that says 'Get it on, Google Play', and if clicked it will lead you to the Google Play store


We have certainly sent down to you a Book in which is your mention. Then will you not reason? [Quran 21:10]

More from Medium

Develop Next JS AMP application

A Guide To Firebase Authentication In React (Initial Setup)

A React-Redux Form using JSX

Text Block Editor : Implement Editor.JS using React.JS and Node.JS