Deploying your React App can be a pain and here is a step by step guide to deploy and host your React application on Nginx server on Ubuntu.

Why Nginx?

When it comes to deploying a React or JavaScript web application, Nginx is the hot choice of most developers and architects. It is a high performance, highly scalable web server that has become very popular and is replacing the traditional Apache server. Nginx claims to serve at least 10x more (and often 100–1000x more) requests per server compared to Apache. Nginx is the preferred choice for hosting on Linux machines and utilizes the native power of Linux to provide top-notch performance. Companies like Airbnb, Box, Dropbox, Netflix, Tumblr are using Nginx due to its high scalability and performance.

Installing Nginx web server

Update your packages listing by running the apt update command to make sure your package list is updated. We can then install nginx simply by running the apt install command.

sudo apt update
sudo apt install nginx

This will install nginx and any other required dependencies on your system. Let's enable nginx to start automatically on system startup.

sudo systemctl enable nginx

Modify the firewall

The next step would be to add exceptions for nginx in the firewall. This can be done by using the ufw commands to allow http and https protocols for nginx.

sudo ufw allow 'Nginx HTTP'

Check the firewall rules status by running

sudo ufw status

This command returns the firewall rules modified by us

$ sudo ufw status
Status: active

To                         Action      From
--                         ------      ----
Nginx HTTP                 ALLOW       Anywhere                  
Nginx HTTP (v6)            ALLOW       Anywhere (v6) 

This command alters the firewall rules for both HTTP and HTTPS. Secure HTTP however requires setting up an SSL certificate which is out of scope of this post and can be discussed in another post, for now we will stick Screenshot from 2020-05-13 19-25-54to HTTP on port 80.

Start the server and test it

Start the nginx service by running

sudo systemctl start nginx

We can verify if the server came up successfully by running

sudo systemctl status nginx

This command should produce an output similar to

$ sudo systemctl status nginx
● nginx.service - A high performance web server and a reverse proxy server
     Loaded: loaded (/lib/systemd/system/nginx.service; enabled; vendor preset:>
     Active: active (running) since Wed 2020-05-13 19:16:16 UTC; 2s ago
       Docs: man:nginx(8)
    Process: 35380 ExecStartPre=/usr/sbin/nginx -t -q -g daemon on; master_proc>
    Process: 35391 ExecStart=/usr/sbin/nginx -g daemon on; master_process on; (>
   Main PID: 35392 (nginx)
      Tasks: 7 (limit: 19070)
     Memory: 8.6M
     CGroup: /system.slice/nginx.service
             ├─35392 nginx: master process /usr/sbin/nginx -g daemon on; master>
             ├─35393 nginx: worker process
             ├─35394 nginx: worker process
             ├─35395 nginx: worker process
             ├─35396 nginx: worker process
             ├─35397 nginx: worker process
             └─35398 nginx: worker process

If you see the above message it means that nginx started successfully.

Navigate to http://localhost or http://YOUR_SERVER_IP (in case you are installing on an Ubuntu server). You should be able to see the default nginx landing page.

Nginx welcome page

We have successfully installed nginx on our system and now it's time to deploy our React App.

Create and build the React App

If you do not have node js and npm installed on your system, install them with the below commands.

sudo apt-get install curl
curl -sL | sudo -E bash -
sudo apt-get install nodejs

This should install nodejs and npm on your system. Verify the installation and their versions by running

nodejs -v
npm --v

We also need the create react app library from npm that is used to generate a default ReactJS app skeleton.

sudo npm install create-react-app

Once the create react app library is installed we can generate the default react application. In your home directory, run

create-react-app demo-app

This is will generate the react application and all the boilerplate code for us. You should get the below message

Success! Created demo-app at /home/witcher/demo-app
Inside that directory, you can run several commands:

  npm start
    Starts the development server.

  npm run build
    Bundles the app into static files for production.

  npm test
    Starts the test runner.

  npm run eject
    Removes this tool and copies build dependencies, configuration files
    and scripts into the app directory. If you do this, you can’t go back!

We suggest that you begin by typing:

  cd demo-app
  npm start

Run the React app

cd demo-app
npm start
Standalone React app running on port 3000

Navigate to http://localhost:3000/ from your browser and verify that you see the React page. The application is running running on a standalone server right now on port 3000. However, our goal is to run it on Nginx and we would need do a production optimized build to run it on Nginx. Build the app by running

npm run build

You should see an output like this

$ npm run build

> demo-app@0.1.0 build /home/witcher/demo-app
> react-scripts build

Creating an optimized production build...
Compiled successfully.

File sizes after gzip:

  39.39 KB  build/static/js/2.c9cff612.chunk.js
  773 B     build/static/js/runtime-main.1602ad93.js
  646 B     build/static/js/main.6c4ed0e3.chunk.js
  547 B     build/static/css/main.5f361e03.chunk.css

The project was built assuming it is hosted at /.
You can control this with the homepage field in your package.json.

The build folder is ready to be deployed.
You may serve it with a static server:

  npm install -g serve
  serve -s build

Find out more about deployment here:

Notice the build files generated in the build/ directory of your app. This is the deployable package folder that we will reference through Nginx.

Deploy the App on Nginx server

Create the nginx configuration file for the demo app. You can also use vim, gedit or any other code editor of your choice.

sudo nano /etc/nginx/sites-available/demo-app

Copy and paste the below code in nano(Ctrl + Shift + V). Replace server_name by your IP address/domain name or localhost. Also make sure to replace the root by your own demo app's build directory.

server {
  listen 80;
  root /home/witcher/demo-app/build;
  index index.html;
  access_log /var/log/nginx/demo-app.access.log;
  error_log /var/log/nginx/demo-app.error.log;
  location / {
    try_files $uri /index.html =404;

Save the configuration file and quit the text editor.

Nginx created the sites-available and sites-enabled directory in /etc/nginx. We need to place our configuration file in both the directories for our application to work. One way to achieve this would be to copy and paste the demo-app file we just created in the sites-enabled. However, that would add an unnecessary task to our list every time we edit the configuration file. A better solution is to use a file link that will automatically create an update a  replica of the file in sites-enabled directory.

sudo ln -s /etc/nginx/sites-available/demo-app /etc/nginx/sites-enabled

Since we have chose port 80 for our app, we also need to remove the default Nginx welcome page that is pre-configured to be served on port 80.

sudo rm -f /etc/nginx/sites-available/default
sudo rm -f /etc/nginx/sites-enabled/default

Make sure that the default configuration file and it's link are deleted before proceeding, otherwise the server will not come up.

Verify that nginx didn't throw any errors by running

sudo nginx -t

We now need to restart the nginx server and that would be it.

sudo systemctl restart nginx

Navigate to http://localhost/ or http://YOUR_SERVER_IP (in case you are installing on an Ubuntu server) and you will be able to view the demo app deployed on nginx.

React App running on Nginx on HTTP port 80

Please note that port 80 is the default HTTP port and we do not need to specify it in the URL.

This is how we deploy any React or Nodejs application on Nginx for production use.