Skip to content

Instantly share code, notes, and snippets.

@conaticus
Last active September 24, 2023 14:37
Show Gist options
  • Save conaticus/ea47a52c70eb3c16674a2f06f0625442 to your computer and use it in GitHub Desktop.
Save conaticus/ea47a52c70eb3c16674a2f06f0625442 to your computer and use it in GitHub Desktop.
A guide for using NGINX Web Server with React and Express with a domain and SSL certificate (Ubuntu)

Using NGINX Web Server with React and Express with a domain and SSL certificate (Ubuntu)

Introduction

For this to work, we are going serve React's static files for the client, and are going to proxy our Express server to /api.

Disclaimer - Ensure you are the root user, otherwise some of these commands may not work. The Express app also needs to server under a seperate route from the client (e.g /api), so all backend routes will look like this: /api/signup.

Steps

Installation

  • apt-get update # update packages
  • apt-get install nginx # install nginx package
  • nginx # start nginx server

Check the server is online

  • Go to http://localhost if on a local machine
  • Go to http://[PUBLIC IPv4 Address] if remote to machine
  • curl localhost # see if it is running locally

Setup React App

  • Ensure npm run build or yarn build has been executed
  • Go inside the build directory
  • cp -r * /var/www/html # move all build files to the html folder
  • cd /etc/nginx # go to nginx directory
  • rm nginx.conf # there is a default config file, we are going to overwrite it
  • vim nginx.conf # edit nginx.conf, use any text editor you wish Add the following to the file:
http {
        server {
                # Root of static files
                root /var/www/html;

                # Serve static files correctly
                include /etc/nginx/mime.types;

                location / {
                        # Forward all requests to index.html (get react router working)
                        try_files $uri /index.html;
                }
events {}
  • Save and exit the file (Esc then :wq)
  • nginx -s reload # restart the nginx server
  • Your React app should now be working

Setup Express App

  • Go inside your app's directory
  • Ensure npm i has been executed
  • npm i pm2 -g # pm2 is a CLI that allows us to run node applications for production
  • pm2 start (entry point).js # run the express app with pm2
  • pm2 startup ubuntu # will run the app every time the system boots
  • cd /etc/nginx
  • vim nginx.conf
  • Add a proxy to the server's port in the server block
http {
        server {
                # Proxy the backend to /api, this can vary depending on what extenion Express adds to the route
                location /api {
                        # Dependent on the Express server's port
                        proxy_pass http://localhost:5000; 
         }
}

events {}
  • nginx -s reload
  • The Express App should now be working

Setup Domain

  • Ensure your server is hooked up to your domain
  • Add the server name to the server block:
        server {
                # Domain Name
                server_name example.com www.example.com;
}
  • nginx -s reload
  • The domain should now be ready, bare in mind this can take up to 48 hours (though it doesn't usually) to take effect

Setup SSL

  • add-apt-repository ppa:certbot/certbot # add the certbot repository
  • apt-get update
  • apt-get install python3-certbot-nginx # install certbot for nginx
  • certbot --nginx -d example.com -d www.example.com
  • crontab -e # open the cronjobs file
  • Add this: 0 12 * * * /usr/bin/certbot renew --quiet - auto renews the SSL certificate
  • Close the file
  • You should now have SSL

Switch to HTTP 2.0

  • Append http2 to this line: listen 443 ssl http2; # managed by Certbot

Security

  • Change the http block to look like this:
http {
        server {
                # Root of static files
                root /var/www/html;

                # Serve static files correctly
                include /etc/nginx/mime.types;

                # Domain Name
                server_name example.com www.example.com;

                location / {
                        # Only allow these HTTP methods
                        limit_except GET { deny all; }

                        # Forward all requests to index.html (get react router working)
                        try_files $uri /index.html;
                }

                # Proxy the backend to /api
                location /api {
                        # Only allow these HTTP methods
                        limit_except GET POST PUT DELETE { deny all; }
                        # Dependent on the Express server's port
                        proxy_pass http://localhost:5000; 
                }

        # Security settings

        # Stop sending information about the NGINX server
        server_tokens off;

        # Prevents DoS attacks
        client_body_buffer_size 1k;

        # Prevents clickjacking
        add_header X-Frame-Options "SAMEORIGIN";

        # Only allow HTTPS requests
        add_header Strict-Transport-Security "max-age=31536000; includeSubdomains; preload";

        # XSS protection
        add_header Content-Security-Policy "default-src 'self' http: https: data: blob: 'unsafe-inline'" always;
        add_header X-XSS-Protection "1; mode=block";

    # Below is kept the same
    listen 443 ssl http2; # managed by Certbot
    ssl_certificate /etc/letsencrypt/live/example.net/fullchain.pem; # managed by Certbot
    ssl_certificate_key /etc/letsencrypt/live/exple.net/privkey.pem; # managed by Certbot
    include /etc/letsencrypt/options-ssl-nginx.conf; # managed by Certbot
    ssl_dhparam /etc/letsencrypt/ssl-dhparams.pem; # managed by Certbot
}

We should now have a working React + ExpressJS site!

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