DriversRecommendedOutdated drivers can make a good PC feel brokenScan driver issues before chasing fixes manually.Scan NowHalloween DealsAmazon USHalloween week deals: useful picks before month-endAmazon US: current deals, useful picks and tech finds.Check DealsWindows FixRecommendedWindows errors stealing your time? Find the fix fastScan stability, cleanup and performance issues.Fix Now×
Skip to content
World desk12 min

How to Deploy a React App with Nginx on Ubuntu

A practical guide to deploying static React builds with Nginx on Ubuntu, including build directories, server blocks, SPA routing, HTTPS, verification, and troubleshooting.
Special offer. See more information about Outbyte and uninstall instructions. Please review EULA and Privacy policy.

To deploy a client-rendered React app on Ubuntu, create its production build, copy the complete output directory into an Nginx document root, and configure an Ubuntu server block with try_files $uri $uri/ /index.html;. That fallback lets React Router resolve deep links instead of returning Nginx’s 404 page. Test the configuration with sudo nginx -t, reload Nginx, then verify both the home page and a direct deep-route request from the public domain or IP.

This guide covers static React builds produced by tools such as Create React App and Vite. A server-side-rendered React application is different: Nginx should proxy requests to its running application process rather than serve only static files.

As an Amazon Associate I earn from qualifying purchases.

Special offer. See more information about Outbyte and uninstall instructions. Please review EULA and Privacy policy.

What Nginx is doing in a React deployment

A production React build is a collection of static files: an index.html entry point, JavaScript bundles, CSS, images, fonts, and other generated assets. Nginx reads those files from the directory specified by its root directive and returns them over HTTP.

The browser then runs the JavaScript application. For a single-page application (SPA), navigation often happens in the browser without requesting a new HTML document. A visitor who opens / receives index.html; a visitor who later moves to /settings may see the same document while React Router changes the view.

#1 Best Overall
Sale
TOZO A1 Wireless Earbuds Bluetooth 5.3 Light Weight in Ear Headphones | IPX5 Waterproof,2 Mics for AI Calls,Immersive Premium Sound Bass Headset with Charging Case,32 EQ via App Black
  • [Ultra-Lightweight Ear Buds Designed for Small Ears] Each earbud weighs only 3.7g and features a compact, ergonomic in-ear design made especially for small ears. Secure, low-profile, and comfortable for workouts, all-day wear or overnight sleeping.The ultra-slim profile sits flush in your ear with no hard edges poking or rubbing, so you can even sleep on your side without discomfort.
  • [Immersive Stereo Sound with TOZO OrigX Technology] TOZO OrigX tuning delivers clear vocals, balanced mids, and natural stereo sound for music, podcasts, and videos.
  • [Long Battery Life for Daily Use] Get up to 7 hours of playtime on a single charge, with up to 32 hours total using the charging case—ideal for workdays, commuting, and extended listening sessions.
  • [Bluetooth 5.3 & Stable Connection] Bluetooth 5.3 provides fast pairing, stable wireless performance, and reduced dropouts as you move around home or office.
  • [Deep Bass with Clear Vocals] High-performance drivers produce punchy bass while keeping vocals clean and detailed for everyday listening.

The important edge case is a direct request. If someone pastes https://example.com/settings into a new browser tab or refreshes that URL, Nginx receives a request for a filesystem path named settings. Because that file normally does not exist, an ordinary static configuration returns 404. The SPA configuration instead tries the requested path and then falls back to /index.html, allowing the client router to resolve the route.

React’s current documentation says, “If you want to build a new app or website with React, we recommend starting with a framework.” That advice matters when your project uses server-side rendering or another runtime. The instructions below apply when your chosen project setup produces a static client build that can be served directly by Nginx.

What’s actually slowing this PC down?

Pick the symptom - the matching free tool is one click away.

Special offer. See more information about Outbyte and uninstall instructions. Please review EULA and Privacy policy.

Prerequisites and decisions

Have these items ready before changing the server:

  • An Ubuntu server or cloud VM with SSH access and an account that can use sudo.
  • Your React project and its documented production build command.
  • Node.js and the package manager required by that project on the machine where you build, or on the server if you build there.
  • The hostname you intend to use, if you are deploying a domain rather than testing with a public IP or DNS name.
  • Knowledge of the build output directory. Create React App normally writes to build/; Vite commonly writes to dist/. Confirm the actual directory instead of assuming every React project uses build/.

Decide whether this server will host one site or several. Ubuntu’s standard layout places each site’s configuration in /etc/nginx/sites-available/ and enables it with a symbolic link in /etc/nginx/sites-enabled/. A dedicated directory and server block are easier to maintain than putting a new application into the default site.

1. Create a production React build

Use the project’s documented command

From the project directory, install the locked dependencies and run the production script defined by the project:

npm ci
npm run build

If the project documents a different package manager or build command, use that command. The result should be a production output directory containing index.html and generated asset directories. Do not copy the development source tree as a substitute; Nginx needs the generated output.

Confirm the output before configuring Nginx

Inspect the result locally or on the build machine:

Free tools Windows power users keep installed

One-click scans. No signup required.

Special offer. See more information about Outbyte and uninstall instructions. Please review EULA and Privacy policy.
ls -la build
ls -la dist

Only one of those directories may exist. Open the directory you actually produced and check that it contains index.html. If your toolchain emits a differently named directory, use that directory consistently in the copy command and in the Nginx root path.

Transfer the complete output

You can build locally and upload the output over SSH. This example uses a dedicated document root; replace the hostname and local directory with your values:

sudo mkdir -p /var/www/example.com/html
sudo rsync -av --delete build/ /var/www/example.com/html/

When the build was created on another machine, run the transfer from that machine instead:

rsync -av --delete dist/ [email protected]:/tmp/react-dist/
ssh [email protected] 'sudo mkdir -p /var/www/example.com/html && sudo rsync -av --delete /tmp/react-dist/ /var/www/example.com/html/'

The trailing slash on the source directory means that its contents, including index.html, are copied directly into the document root. Copying the parent directory instead can leave you with a path such as /var/www/example.com/html/dist/index.html, which does not match a root expecting /var/www/example.com/html/index.html.

Special offer. See more information about Outbyte and uninstall instructions. Please review EULA and Privacy policy.
Rank #2
Sale
Smart Watch for Men Women Compatible with iPhone Samsung Android Phone 1.69 inch Full Touch Screen IP68 Waterproof Bluetooh Fitness Tracker Heart Rate/Sleep Monitor (Black)
  • 【IP68 Waterproof Multifunctinal Smart Watch】Torjalph fitness activity tracker smart watch is IP68 waterproof technology ,you can wear it when swimming,handwashing,it's rain-proof which means that you perform multiple exercise modes outside without worrying about sweat or rain corroding your fitness smart watch,and this watch equipped with a 230 mAh large capacity battery magnetic charging ,and this sports activity tracker watch can be used 5-7 days If fully charged.
  • 【Larger 1.83'' Full Screen Watch & Multi-dial Selection】1.83 inch full HD color touch screen smart watch for men / women provides excellent 240*284 resolution image quality ,This Bluetooth smart watch offers a better touch experience and remarkable immersion and ,more than 200 watch faces for you to choose from App"Da Fit ", you can change the dial style according to your mood to wear keeping the world on your wrist
  • 【Accurate Activity Tracker Smart Watch 】sports watch activity tracker uses sweat and dust resistant breathable silicone strap, our Fitness Tracker Smart Watch for Android iOS Phones supports 12 sports modes,walking,running,bicycle,swimming,badminton,basketball,football,rope skipping. This bluetooth calls smart watch for men women is lightweight and stylish, bringing more convenient and relaxing sports experience while also providing more protection.
  • 【Your 24 Hour Personal Daily Health Monitor】Fitness watch for women men full touch screen IP67 waterproof bluetooth smartwatch for Android iOS Phones with heart rate blood pressure monitor multifunction Andriod smart watch with steps counter sleep monitor sports fitness watch, monitoring blood oxygen saturation allows you to understand your physical condition in real time to track fitness progress ,to know your health status in time.
  • 【More Functions Bluetooth Call Smart Watch】This fitness activity smart watch full screen for iPhone and Android phones includes a bunch of new features including:The bluetooth smart watch can hang up the phone, receive and display WhatsAPP /Text /Facebook /Twitter /Messenger reminder.Support sedentary reminder, alarm clock, stopwatch, timer,weather information,music control, remote camera control compatible with Android 5.0 and above or iOS 9.0 and above smartphones.

2. Install and start Nginx on Ubuntu

On the Ubuntu server, install the package and start it as a service:

sudo apt update
sudo apt install nginx
sudo systemctl enable --now nginx
sudo systemctl status nginx

The status command should show an active running service. If it is not running, inspect the service output before editing site files:

sudo systemctl status nginx --no-pager
sudo journalctl -u nginx --no-pager -n  fifty

If your shell rejects the second command because of the written number, use the numeric form:

sudo journalctl -u nginx --no-pager -n 50

Ubuntu’s default site serves /var/www/html. You can use that site for a single test, but a named server block with its own root avoids collisions and makes later multi-site deployments clearer.

Special offer. See more information about Outbyte and uninstall instructions. Please review EULA and Privacy policy.

3. Prepare the document root and permissions

The Nginx root directive must point to the directory that directly contains index.html. A typical layout is:

/var/www/example.com/html/
├── index.html
├── assets/
├── static/
└── ...generated files...

Ensure Nginx can traverse the parent directories and read the generated files. One straightforward ownership arrangement is to keep deployment ownership with your administrative user and grant the web service read access through normal directory permissions:

sudo chown -R $USER:$USER /var/www/example.com/html
sudo find /var/www/example.com/html -type d -exec chmod 755 {} ;
sudo find /var/www/example.com/html -type f -exec chmod 644 {} ;

If your server uses a different deployment account or a restricted permissions policy, preserve that policy as long as the Nginx worker can read the files. Avoid making the entire web root world-writable.

4. Create an Nginx server block for the SPA

Minimal configuration

Create a site file:

sudo nano /etc/nginx/sites-available/example.com

Use this configuration for a static React application:

Special offer. See more information about Outbyte and uninstall instructions. Please review EULA and Privacy policy.
server {
    listen 80;
    listen [::]:80;
    server_name example.com www.example.com;

    root /var/www/example.com/html;
    index index.html;

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

Replace example.com with the hostname clients will use. If you are testing only by IP, you can use the server’s address or a suitable catch-all during testing, but a real domain should be listed explicitly before production use.

Why each directive matters

Directive Purpose
listen 80 and listen [::]:80 Accept HTTP connections over IPv4 and IPv6.
server_name Select this server block when the request hostname matches.
root Tell Nginx where index.html and generated assets live.
index index.html Use the React entry document for a directory request.
try_files $uri $uri/ /index.html Serve an existing file or directory; otherwise return the React entry document for client-side routing.

The try_files line is the key SPA behavior. It preserves direct access to real assets such as JavaScript and CSS while routing unknown application paths to React. Without it, a history-based React Router URL commonly works when clicked inside the app but fails when opened or refreshed directly.

Rank #3
New Bee Guitar Cable 10ft Electric Instrument Bass AMP Cord
  • [Low Noise High Fidelity] New bee guitar cord with 22AWG oxygen-free-copper center conductors provides enhanced signal transfer, the PVC insulation material and the high-density stranded copper double shield provide noise rejection for quiet operation
  • [Ideal for Choice] New bee 1/4 straight and right angle metal connectors, ensures a secure connection in any instrument, pedal, or amp jack. L shape great fro on stage guitar stands
  • [Wide Compatible] Suitable for mixer, power amplifier, microphone, effector, decoder, equalizer, electoronic organ, electric guitar, electric bass and other electronic equipments. Widely used in the installation of smart home, karaoke speaker, professional stage audio, etc
  • [Easy Disassemble] Making incidental repairs quick and easy! Very nice, flexible cable
  • [Dont Hesite to Order] 24 hours customer services and professional technology team are standing by

Enable the site

Create the symbolic link Ubuntu expects, then test the complete Nginx configuration:

sudo ln -s /etc/nginx/sites-available/example.com /etc/nginx/sites-enabled/example.com
sudo nginx -t

Proceed only when the test reports that the syntax is successful. If the default site catches requests intended for your domain, disable its link after confirming your new server block is correct:

Special offer. See more information about Outbyte and uninstall instructions. Please review EULA and Privacy policy.
sudo rm /etc/nginx/sites-enabled/default
sudo nginx -t
sudo systemctl reload nginx

Removing the default link is optional; do not delete the file in sites-available if you may need it for reference or another test.

5. Reload safely and inspect failures

After a successful syntax test, reload rather than stop and start the service:

sudo systemctl reload nginx

A reload applies the new workers without unnecessarily interrupting existing connections. If the reload fails, check the configuration test output and the service journal:

sudo nginx -t
sudo systemctl status nginx --no-pager
sudo journalctl -u nginx --no-pager -n 50

Nginx’s access and error logs usually provide the next clue:

Special offer. See more information about Outbyte and uninstall instructions. Please review EULA and Privacy policy.
sudo tail -f /var/log/nginx/access.log /var/log/nginx/error.log

Keep a second terminal open while making a request so you can see which server block is receiving it and whether the requested file is being found.

6. Verify the deployment from the public endpoint

Test the home page

Open the configured domain in a browser, or use the server’s public IP or DNS name while DNS is being set up. You should receive the React application rather than Nginx’s welcome page. From a shell, inspect the response headers:

curl -I http://example.com/

A successful static response normally includes an HTTP success status and a content type for HTML. The exact headers depend on your Nginx and distribution configuration.

Test a deep route directly

Choose a route that exists in the application, such as /dashboard, and perform all three tests:

Special offer. See more information about Outbyte and uninstall instructions. Please review EULA and Privacy policy.
Rank #4
BSIMB 15.6" Digital Family Calendar & Chore Chart, No Subscription Fees
  • Digital Family Calendar: BSIMB digital calendar wall touch screen puts an end to your chaotic life. Designed for busy families, the digital calendar keeps you organised and in step with your family. Assign different colours and tasks to each family member to make family scheduling easier and more intuitive.
  • Easy Setup and Auto-Sync: Plug in, connect to WLAN and auto-syn your electric calendar in minutes. Digital wall calendar compatible with Google calendar, iCloud calendar, Outlook calendar, Cozi calendar and Yahoo calendar. Add events directly on the device or through the ecalendar app. Electronic calendar stays current whether you're at work or traveling—no manual updates needed.
  • All-In-One Home Assistant: Smart calendar builds habits and encourage independence with personalised chores. Display daily meal plan to reduce the daily ‘What's for dinner?’ stress. To-do lists keep track of everything you want. Turning chores into valuable achievements with stars and rewards, making life easier and more enjoyable.
  • Manage Anytime Anywhere: BSIMB electronic calendar for family stay connected with the powerful ecalendar app. Access and manage your digital wall calendar anytime, anywhere with free features like stars & rewards, photo screensaver, chore charts, meals plans, to-do lists etc. Electronic planner paid features like Magic Import tailor advanced tools for users with special needs.
  • Stay in Touch with Loved Ones: Share photos or videos from your phone to electronic wall calendar with app, instantly update your life moment, and keep in touch with your family, especially those who are far away; you can also surprise your smart calendar digital wall by sending him a wish card; it's also great for keeping tech-illiterate elders in touch with the youngsters.
  1. Paste the complete route into a new browser tab.
  2. Refresh the page while that route is displayed.
  3. Open the browser’s network panel and check that the JavaScript and CSS requests return successfully.

The first two tests exercise the Nginx fallback. The network panel distinguishes a routing problem from an asset-path problem: the HTML may load while a bundle request still points to the wrong URL.

Check DNS and hostname matching

If the public IP works but the domain does not, verify that the domain’s DNS record points to this server and that the browser is reaching the expected address. If the domain reaches a different server block, confirm the spelling of server_name, the enabled symbolic link, and whether another configuration is listening on the same address.

7. Add HTTPS for production

HTTP deployment and TLS deployment are separate steps. Obtain a certificate from a certificate authority such as Let’s Encrypt, then configure an HTTPS server block with the certificate and private-key paths supplied by your certificate process.

A TLS-enabled block follows this pattern, with paths replaced by the files installed on your server:

Special offer. See more information about Outbyte and uninstall instructions. Please review EULA and Privacy policy.
server {
    listen 443 ssl;
    listen [::]:443 ssl;
    server_name example.com www.example.com;

    root /var/www/example.com/html;
    index index.html;

    ssl_certificate /path/to/fullchain.pem;
    ssl_certificate_key /path/to/privkey.pem;

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

server {
    listen 80;
    listen [::]:80;
    server_name example.com www.example.com;
    return 301 https://$host$request_uri;
}

Run sudo nginx -t after adding the certificate configuration and reload only after the test passes. The port-80 block redirects HTTP requests; the port-443 block serves the application and retains the SPA fallback. Certificate renewal must be handled by the certificate-management method you selected.

Independent reader supportYour contribution helps us test, update, and keep practical guides available for everyone.Support on Ko-Fi

Static serving versus runtime proxying

Choose the deployment model from what your React project produces, not from the fact that it uses React.

Model What runs on Ubuntu Nginx’s role Typical configuration
Static client build Only generated HTML, JavaScript, CSS, images, and fonts Reads files directly from root try_files $uri $uri/ /index.html
Server-side-rendered React A Node.js or framework runtime process Terminates HTTP/TLS and proxies requests to that process proxy_pass location plus process supervision
Static frontend with API Static files plus a separate API process Serves the frontend and proxies a path such as /api/ Static root and a dedicated API location

If the project requires server-side rendering, request-time data loading, or another runtime, do not point Nginx at a source directory and expect it to execute the application. Follow that framework’s server deployment instructions and proxy the running service. The static procedure in this article is for a build that is complete before the request arrives.

Hosting one site or several

A single site can use one server block and one document root. Multiple sites should have separate roots and separate files in sites-available, each enabled with its own link. Keep the hostnames distinct so Nginx can select the intended block.

Special offer. See more information about Outbyte and uninstall instructions. Please review EULA and Privacy policy.
Choice Advantages What to watch
One site Few moving parts; easy to understand while learning. The default site or a broad catch-all can mask hostname mistakes.
Multiple server blocks Independent deployments, roots, logs, and TLS names. Every block needs a unique hostname mapping and a successful configuration test.

For either arrangement, keep generated files inside the root named by that site’s root directive. A successful upload to the wrong directory is indistinguishable from a missing deployment when Nginx is looking elsewhere.

Optional production improvements

Get the basic static site and deep-route behavior working before adding optimization. The deployment guidance commonly adds these improvements after the initial configuration:

Compression

Enable gzip for text-based responses when appropriate for your Nginx package and traffic profile. Compression is an optimization, not a fix for an incorrect root or route fallback. Confirm that compressed responses still have correct content types and that the change is applied only after nginx -t succeeds.

Cache headers for generated assets

Many build tools place content hashes in JavaScript and CSS filenames. Those immutable-looking files can usually receive long-lived cache headers, while index.html should be revalidated more frequently so a new deployment points browsers at the newest bundles. Match the cache policy to the naming strategy your build actually uses; do not assign an effectively permanent cache to filenames that are overwritten without changing names.

Special offer. See more information about Outbyte and uninstall instructions. Please review EULA and Privacy policy.

Security headers

Add security headers deliberately and test the application after each change. A restrictive policy can block scripts, fonts, images, or API calls that the application legitimately needs. Headers should support the resources your build and backend use rather than being copied blindly from an unrelated site.

Proxy an API path

If the frontend calls an API process on the same server, add a separate /api/ location that proxies to that process. Keep it separate from the SPA fallback: API errors should be handled by the API service, not converted into index.html responses.

location /api/ {
    proxy_pass http://127.0.0.1:3000/;
    proxy_set_header Host $host;
    proxy_set_header X-Real-IP $remote_addr;
    proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;
    proxy_set_header X-Forwarded-Proto $scheme;
}

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

Use the upstream address and port exposed by your API process. Test API requests separately from browser navigation so a backend failure does not get mistaken for a React routing failure.

Common failures and targeted fixes

A deep URL returns Nginx 404

Confirm that the active server block’s location / contains try_files $uri $uri/ /index.html;, then run sudo nginx -t and reload. Verify that you edited the file linked into sites-enabled, not an unused file in sites-available.

Special offer. See more information about Outbyte and uninstall instructions. Please review EULA and Privacy policy.

The home page loads, but JavaScript or CSS is missing

Look at the failed asset URL in the browser network panel. Check that the generated asset directories were copied alongside index.html and that the build’s public base path matches the URL at which the app is hosted. A site deployed below a subdirectory may require a project-specific base-path setting; do not solve that by changing the Nginx root to a directory that omits the entry document.

Nginx shows its welcome page

The request is probably reaching the default server block or a different machine. Check DNS, the requested hostname, the enabled links in /etc/nginx/sites-enabled/, and the server_name value. Reload after correcting the selection.

The browser reports 403 Forbidden

Check that the root contains an index.html, that directory permissions allow traversal, and that files are readable by the Nginx worker. Inspect /var/log/nginx/error.log for the exact path and permission error.

Nginx will not reload

Run sudo nginx -t first. A missing semicolon, duplicate listen declaration, invalid certificate path, or malformed server block will be reported there. Fix the first reported error, test again, and only then reload.

Special offer. See more information about Outbyte and uninstall instructions. Please review EULA and Privacy policy.

The domain does not open at all

Check that Nginx is active, that DNS points to the server’s public address, and that the request is reaching ports 80 or 443. Service status, access logs, and error logs separate an application problem from a network or hostname problem.

Deployment checklist

  1. Run the project’s documented production build command.
  2. Confirm whether the output is build/, dist/, or another documented directory.
  3. Copy the complete output so index.html sits directly inside the Nginx root.
  4. Install and start Nginx, then verify its service status.
  5. Create a server block in /etc/nginx/sites-available/ with the correct server_name and root.
  6. Use try_files $uri $uri/ /index.html; for history-based client routing.
  7. Enable the site, run sudo nginx -t, and reload.
  8. Test the home page, a direct deep route, and asset requests from the public endpoint.
  9. Add a certificate, an HTTPS server block, and an HTTP-to-HTTPS redirect for production.
  10. Add compression, cache rules, security headers, or API proxying only after the basic deployment works.

Product prices and availability are accurate as of the date/time indicated and are subject to change. Any price and availability information displayed on Amazon at the time of purchase will apply.

Leave a Reply

Your email address will not be published. Required fields are marked *

Special offer. See more information about Outbyte and uninstall instructions. Please review EULA and Privacy policy.

More from the Wire

  1. World desk4 min
    How to Spot an AI Voice Scam Before Sending MoneyDon’t rely on how a caller sounds. Pause, call back through a known number, and verify the emergency with another trusted person before sending money.
  2. Mountain View desk4 min
    Google’s SynthID Detector: How to Check AI-Generated Images, Video and AudioGoogle’s SynthID Detector looks for an embedded watermark in supported images, video and audio. Here is what its results do—and do not—show.
  3. Redmond desk20 min
    How to create a link to File or Folder in Windows 11Windows 11 gives you several ways to point to a file or folder without moving or duplicating it. You can create a desktop shortcut,…
Recommended PC Tool
Recommended PC Tool
PC Slower Than It Used to Be?Free scan - under a minute
Crashes, No Sound, or Screen Glitches?Free driver scan

Two free Windows tools

One Free Minute Could Fix That PC

Before you go - each of these free tools takes about a minute and tackles what quietly slows a Windows PC down.

Special offer. View Outbyte info, uninstall instructions, EULA, and Privacy Policy.