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.
Antihost offers Linux VPS plans with full root access, unlimited traffic on a 1 Gbps port and a 14-day free trial.
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.
Quick wins for a faster PC:
Repair Windows errors before they cause bigger problemsFix Now →Fix the driver behind crashes, sound loss and screen glitchesFind Drivers →Clear out junk files and repair common Windows errorsFree Scan →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
- [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.
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 todist/. Confirm the actual directory instead of assuming every React project usesbuild/.
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.
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.
Recommended Free Tools
Rank #2
- 【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.
Windows Errors? Fix Them Before They Spread
Repair common Windows errors and clear accumulated junk for a smoother, more stable PC - no reinstall needed.Free scan · no reinstallCrashes, No Sound, or Screen Glitches?
Random freezes, missing sound and display glitches usually trace back to one bad driver. Find and replace yours safely.Free scan · under a minute3. 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:
The Tool Desk
Outbyte PC Repair FREERepair Windows errors before they cause bigger problemsFix Now →Outbyte Driver Updater FREEScan for outdated or missing drivers - takes under a minuteDriver Scan →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
- [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:
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:
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:
Do these 3 things before closing this tab:
1Scan for outdated or missing drivers - takes under a minute2Repair Windows errors before they cause bigger problems3Fix the driver behind crashes, sound loss and screen glitchesRank #4
- 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.
- Paste the complete route into a new browser tab.
- Refresh the page while that route is displayed.
- 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:
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.
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.
| 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:
Best Value
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.
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.
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.
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.
Quick Recap
Deployment checklist
- Run the project’s documented production build command.
- Confirm whether the output is
build/,dist/, or another documented directory. - Copy the complete output so
index.htmlsits directly inside the Nginx root. - Install and start Nginx, then verify its service status.
- Create a server block in
/etc/nginx/sites-available/with the correctserver_nameandroot. - Use
try_files $uri $uri/ /index.html;for history-based client routing. - Enable the site, run
sudo nginx -t, and reload. - Test the home page, a direct deep route, and asset requests from the public endpoint.
- Add a certificate, an HTTPS server block, and an HTTP-to-HTTPS redirect for production.
- 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.




