Driver FixRecommendedSound, Wi-Fi or graphics acting up? Check drivers firstFind missing or outdated drivers fast.Check DriversHalloween DealsAmazon USHalloween week deals: useful picks before month-endAmazon US: current deals, useful picks and tech finds.Check DealsPC HealthRecommendedCrashes, freezes, slowdowns? Check your PC nowSpot repairable issues before they interrupt work.Check PC×
Skip to content
VGSources
Blog

How to Deploy a Django and React App on an Ubuntu VPS

Deploy a Django API and React frontend on one Ubuntu VPS using PostgreSQL, Gunicorn, systemd and Nginx, with production settings, HTTPS, smoke tests and fixes for 502, missing CSS and broken SPA routes.
Length14 min Posted Quest giverVGSources Team
Special offer. See more information about Outbyte and uninstall instructions. Please review EULA and Privacy policy.

The dependable small-to-moderate deployment pattern is a single Ubuntu VPS running Nginx, Gunicorn, Django and PostgreSQL, with Nginx serving the React production build. Traffic flows from the browser to Nginx, then either to a React asset or through Gunicorn to Django and PostgreSQL. The production server must use a WSGI or ASGI server, not manage.py runserver.

Choose the production layout

Use this request path for a unified deployment:

Browser → Nginx (HTTP/HTTPS and React files) → Gunicorn (Django WSGI) → Django → PostgreSQL

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.

Nginx is the public boundary. It terminates TLS, serves immutable frontend assets, provides the single-page application fallback, and proxies API or other Django requests to an application process that is not exposed directly to the internet. Gunicorn supervises Django’s WSGI application; systemd keeps it running and starts it after reboots.

This arrangement keeps the React and Django applications on one host and one domain. It is straightforward for a small or moderate service, but it makes the VPS, its disk, upgrades and database part of the same failure domain. A larger service can separate these components later without changing Django’s basic production settings.

#1 Best Overall
Sale
Gaoye Blue Light Blocking Glasses
  • BLUE LIGHT BLOCKING GLASSES: Our blue light glasses for women boast UV400 protection, blocking harmful blue rays from computer screens. With these bluelight glasses women, you can enjoy gaming, reading, or watching TV with no worries of eye strain.
  • EYE RELIEF: Our blue light glasses are engineered to reduce blurry vision or strain caused by prolonged screen time. These womens blue light glasses aid in better sleep by preventing blue light from disrupting your natural sleep cycle, helping you fall asleep faster and enjoy a more restful night's sleep, making them the perfect christmas present.
  • COMFORTABLE: Crafted from durable material, our trendy blue light glasses for woman or blue light glasses men ensure long-lasting comfort. The high-transmittance lenses accessories, gamer gifts for men, help keep your eyes relaxed. Perfect stocking stuffers, gifts for gamers men, christmas gifts for men, halloween costumes.
  • LIGHTWEIGHT: These clear blue light glasses feature a lightweight frame, meaning they’ll stay comfy for long-term wear. Perfect as blue blockers glasses for women or mens blue light glasses, these non-prescription fake glasses for men can be worn throughout the day. The blue light blocking glasses women feature polycarbonate HD lenses, which are anti-reflective and restore true color.
  • WORRY-FREE PURCHASE: If you experience any issues, our support team is ready to assist you quickly. These are the perfect costume glasses for cosplay dressing up.

Decide which requests Django owns

  • Let Nginx serve the React build directory at the site root.
  • Route /api/ and any server-rendered Django paths to Gunicorn.
  • Serve Django’s collected static files from a dedicated STATIC_ROOT directory and user uploads from a controlled media directory.
  • Use try_files $uri $uri/ /index.html for client-side React routes so a browser refresh on a route such as /library still loads the SPA.

If your project uses a different API prefix, Django-rendered pages, or a separate frontend subdomain, adapt the Nginx locations rather than copying these paths literally.

What you need before connecting to the VPS

  • An Ubuntu VPS with administrative access and a public IP address.
  • A domain whose DNS record points to that IP before requesting an HTTPS certificate. Add an IPv6 record only when the VPS is correctly configured for IPv6.
  • The application repository, its pinned Python requirements, its frontend lockfile and the build command documented in package.json.
  • SSH key authentication. Create a non-root deployment account and reserve root for initial administration.
  • Production values for the Django secret key, database credentials, allowed hosts, CSRF trusted origins, email settings and any third-party credentials. Keep these outside Git.
  • A decision about database placement: PostgreSQL on this VPS, or a managed PostgreSQL service reachable over a restricted network.
  • A backup and rollback plan covering both the previous application revision and database migrations.

Do not size the server from a generic traffic number: the supplied deployment guidance publishes no universal CPU, memory, storage or cost figure. Measure your own workload and leave capacity for PostgreSQL, build artifacts, logs and backups.

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

Prepare Ubuntu securely

  1. Create the deploy account. Log in with the initial administrative account, create a dedicated user, grant only the administrative elevation it needs, and install your public SSH key for that account. Test a second SSH session before disabling root or password login.
  2. Update the operating system. Apply Ubuntu updates and reboot when the kernel or a critical service requires it. Record the Ubuntu release and the update date so future troubleshooting has a baseline.
  3. Install the runtime and services. Install Python, the Python virtual-environment and build prerequisites, Git, Nginx and PostgreSQL when the database is self-hosted. Install Node.js and npm using the version policy required by the repository; do not silently substitute a different major version.
  4. Set DNS. Point the domain’s DNS record at the VPS and wait for it to resolve publicly. Certificate issuance will fail if the hostname does not reach this server.
  5. Restrict network exposure. Permit SSH administration and public HTTP/HTTPS at the firewall. Gunicorn should listen on a Unix socket or loopback address, not a public interface.

Ubuntu’s Nginx documentation describes Nginx as a web server commonly used as a reverse proxy or HTTP cache. In this design it is the only process that needs to accept public web traffic.

Deploy the Django project

Use a controlled application directory

Clone the repository into a directory owned by the deploy account, for example /srv/myapp. Keep releases reproducible: record the Git commit, Python version, lockfile or pinned requirements and the environment-file revision. Never commit a production .env file, private key or database password.

Create the virtual environment and install dependencies

  1. Change to the backend directory and create a virtual environment with the server’s supported Python interpreter: python3 -m venv .venv.
  2. Activate it for installation: source .venv/bin/activate.
  3. Upgrade packaging tools only when that change is intentional, then install the pinned requirements, for example pip install -r requirements.txt.
  4. Confirm that the virtual environment contains the exact Gunicorn executable that systemd will run: .venv/bin/gunicorn --version.

Keep configuration out of source control

Provide environment variables through a root-readable or service-readable environment file with restrictive permissions. At minimum, define the Django SECRET_KEY, DEBUG=False, database name, user, password, host and port, allowed hostnames, CSRF trusted origins, email configuration and any storage credentials. Make the settings module read these values and fail clearly when a required production value is absent.

Rank #2
Windex Gaming Cleaning Wipes, Pre-Moistened Wipes to Instantly Clean all Gaming Gear and Electronics, Resealable Packaging for a Freshness Lock, 25 count (Pack of 1)
  • WINDEX GAMING WIPES: effortlessly clean all your gaming gear and gaming electronics in one easy step with our new Windex Gaming Wipes
  • AMMONIA FREE: our ammonia-free formula is safe to use on all of your favorite gaming equipment like consoles, headsets, controllers, screens, keyboards, and more
  • PRE-MOISTENED WIPES: each wipe instantly removes dust, dirt, and stubborn smudges and fingerprints leaving a streak-free shine
  • ANTI-STATIC: great for cleaning and wiping down your gaming gear and electronics leaving behind no visible residue
  • COMPACT RESEALABLE PACKAGE: store your pack of Windex Gaming Wipes anywhere in your home for whenever a quick and easy wipedown is needed

Apply production Django settings

  • Set DEBUG = False.
  • Set ALLOWED_HOSTS to the exact domain names and, only if needed, the server address.
  • Configure CSRF trusted origins with the HTTPS scheme and exact hostnames used by the frontend.
  • Enable secure, HTTP-only cookies as appropriate for your authentication design, and set the secure proxy options consistently with Nginx’s forwarded HTTPS header.
  • Define STATIC_ROOT as a directory Nginx can read and configure media storage separately from collected static assets.
  • Configure production logging so application errors reach the system journal or another protected log destination without exposing secrets.

Before exposing the site, run python manage.py check --deploy inside the virtual environment and resolve every relevant warning. Django’s deployment checklist is the authority for production-specific settings; the development server is not a substitute for it.

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

Create PostgreSQL data and run release tasks

Create a least-privilege database account

When PostgreSQL is on the VPS, create a database and an application role with a strong password. Grant the application only the permissions it needs for its database. Do not use the PostgreSQL superuser in Django’s production settings. If the database is managed elsewhere, create the equivalent restricted role there and allow connections only from the application host or private network.

Run migrations as an explicit release step

With the environment file loaded and the virtual environment active, run:

python manage.py migrate

Inspect migration output and errors rather than treating a non-zero exit as harmless. Take a database backup or verify the managed provider’s restore point before migrations that alter or remove data. Keep the previous application commit and a migration compatibility plan until smoke tests pass.

Collect Django static files

python manage.py collectstatic --noinput

This copies files from installed apps into STATIC_ROOT, which Nginx will serve. It does not build the React application and it does not upload user media. Run it after installing the exact backend dependencies for the release.

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.
Rank #3
Sale
LISEN Cell Phone Stand Phone Holder for Desk, Office Decor Gadgets for Men
  • Ergonomic & Adjustable Design: Fight "text neck" and improve your posture. Designed for comfort, it offers an adjustable height (7.1in-8.5in) (1.4in adjustable range) and angle (5°-85°) Please note: cell phone stand is only 9 inches tall—the length of a standard pencil
  • Without blocking subtitles Perfect for office desk Tiktok Face Time Zoom video—this is the ultimate kitchen desk essential for phones! Perfect viewing experience while reducing neck back strain, A must-have for gamers streamers desk, and anyone who values both style and support!
  • Sleek & Stable Design fits Otterbox Case: Say goodbye to bent cables, tangles, and tip-overs! LISEN’s stylish adjustable desk phone holder features a built-in charging hole and smart cable management, keeping your phone secure and your workspace clutter-free cool gadgets for men
  • ANTI-SLIP DESIGN free hands: The under 10.00 items easy gadgets back and the bottom of this kitchen essentials for women are fully covered by anti-skid silicone, which LISEN stand up desk decor can provide maximum protection device from any scratches and slides
  • Your Perfect Viewing Companion:If your product arrives damaged or breaks within 365 days, reach out to LISEN for a quick and hassle-free solution. Struggling with assembly, like tightening the screw? We’ve got your back! Your experience matters to us. (Product including: phone Holder stand*1, screw*1, hexagon screwdriver*1, specification*1)

Build the React frontend

  1. Change to the frontend directory.
  2. Install the locked JavaScript dependencies using the repository’s prescribed command, such as npm ci when a compatible lockfile is present.
  3. Inspect package.json and the project’s environment files to identify the production API base URL. It must point to the public HTTPS API path, not localhost or a development port.
  4. Run the repository’s build script, commonly npm run build. npm invokes a package script through npm run-script build; the project’s script determines the actual bundler and output.
  5. Record the generated directory. Toolchains differ: some produce build/, others dist/ or a configured path. Use the directory actually produced by this project when setting Nginx’s root.

After building, inspect the generated HTML and asset URLs. A build that contains a development API endpoint, an incorrect base path or absolute asset URLs for another hostname will appear healthy locally but fail behind Nginx.

Run Django with Gunicorn and systemd

Choose the WSGI callable

Gunicorn needs the import path to your Django WSGI application, typically myproject.wsgi:application. Replace myproject with the package that contains wsgi.py. Test the import from the application directory before creating the service.

Create a systemd unit

Create a unit such as /etc/systemd/system/myapp.service. The important values are the service user, the exact WorkingDirectory, the environment file, the virtual environment’s Gunicorn binary and a private bind address:

[Unit]
Description=Gunicorn service for Django
After=network.target

[Service]
User=deploy
Group=www-data
WorkingDirectory=/srv/myapp/backend
EnvironmentFile=/etc/myapp/myapp.env
ExecStart=/srv/myapp/backend/.venv/bin/gunicorn --workers 3 --bind unix:/run/myapp.sock myproject.wsgi:application
Restart=on-failure

[Install]
WantedBy=multi-user.target

The worker count in this example is illustrative, not a universal capacity recommendation. Choose it from application behavior and measured resource use. Ensure the runtime user can read the code, virtual environment and environment file, and that Nginx can access the socket. A systemd-managed socket in /run avoids exposing Gunicorn on a public port.

Special offer. See more information about Outbyte and uninstall instructions. Please review EULA and Privacy policy.
  1. Reload unit definitions: sudo systemctl daemon-reload.
  2. Enable startup on boot: sudo systemctl enable myapp.
  3. Start the service: sudo systemctl start myapp.
  4. Check it immediately: sudo systemctl status myapp.
  5. Read application failures: sudo journalctl -u myapp -n 100 --no-pager.

Do not place Gunicorn directly on the public interface when Nginx is the reverse proxy. Nginx should be able to reach the socket while outside clients cannot bypass TLS, request limits and routing rules.

Rank #4
Ledagic IC+RGBW USB Powered Led Light Bar with App & Remote Control, 2 Pack
  • Easy Installation: Our gaming lights have been designed to enhance your entertainment experience. Simply position the led light bar next to your TV or game console to create a game room environment with ease. They come with USB power and a 60 inch cord for direct mounting and mobility
  • Audio Syncing & Extensive Mode: The built-in high-sensitivity music sensor allows you to sync the TV led lights to your favorite music. Lights react and move to the beat of music, film and game audio, creating an incredible immersive sound and light experience – and all without the need for an additional hub. You can choose from 64+ patterns, including strobe, illusion, jump, energy, gradient, running, chasing, fluttering mode etc. Each mode can be applied to different scenes
  • 64+ Chasing IC+RGB & W Effect: The independent control design of IC+RGB and white all-in-one multifunctional rgbw led bar lights monitor backlight allows you to easily switch the led lights for desk between IC+RGB and white to enjoy a variety of lighting effects, you can choose white lighting mode with high brightness for better illumination when working, etc. Choose IC+RGB lighting mode when you need to create an entertaining atmosphere for the light show, 16 million colours of Color changing rgb light bar let you dance to the beat and create a dynamic party atmosphere
  • Dynamic and Dimmable Lights: 1%-full brightness free brightness adjustment gives you the flexibility to adjust dimmable led light bar for room decorations or a variety of occasions
  • USB Powered: USB light bars for room can be powered by powernank, usb charger, TV, Monitor, laptop PC mainframe, making behind TV led lighting bar easy to install in any location.TV led lights are powered by the TV usb interface / PC mainframe, can be turned on/off synchronously with TV / PC

Configure Nginx for React, Django and media

Write a server block

Create a site configuration with the React build directory as root. The following is a pattern; replace paths, hostnames and the socket with your values:

server {
    listen 80;
    server_name example.com www.example.com;
    root /srv/myapp/frontend/dist;

    location /static/ {
        alias /srv/myapp/backend/static/;
    }

    location /media/ {
        alias /srv/myapp/backend/media/;
    }

    location /api/ {
        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;
        proxy_pass http://unix:/run/myapp.sock;
    }

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

Use the exact syntax supported by the Nginx package on the VPS, especially for Unix-socket proxying. If Django owns additional paths outside /api/, add explicit locations before the SPA fallback. The alias directories must match the paths used by STATIC_ROOT and media storage, and their trailing slashes must be consistent with the location mapping.

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

Enable and test the site

  1. Enable the site configuration and remove or disable the default site if it would win the hostname match.
  2. Run sudo nginx -t. This tests the configuration; it does not start or reload Nginx.
  3. Only after a successful test, run sudo systemctl reload nginx.
  4. Inspect Nginx errors with sudo journalctl -u nginx -n 100 --no-pager and the configured access and error logs.

A successful configuration test proves syntax, not application health. A wrong root, missing socket permission or incorrect upstream path can still produce a broken page after reload.

Enable HTTPS and align proxy settings

First make the domain resolve to the VPS and serve the HTTP server block on port 80. Use a supported ACME client such as Certbot to obtain a trusted certificate, then configure a port-443 server block and redirect HTTP requests to HTTPS. Ubuntu’s Nginx guidance uses separate SSL handling on port 443 and an HTTP-to-HTTPS redirect.

After TLS is active, set Django’s proxy and secure-cookie settings to agree with Nginx’s X-Forwarded-Proto header. Ensure the CSRF trusted origins use https://, and test both the canonical hostname and any redirect from the alternate hostname. Confirm certificate renewal is enabled and perform a renewal test according to the ACME client’s documentation.

Best Value
Sale
HUANUO FlowLift™ Dual Monitor Stand, Fully Adjustable Gaming Monitor Desk Mount for 13–32″ Computer Screens, Full Motion VESA 75x75/100x100 with C-Clamp & Grommet Base, Each Arm Holds 4.4 to 19.8 lbs
  • Compatible with Wide Screens - To ensure compatibility with the dual monitor mount, your each monitor must meet three conditions at the same time: First, computer screens size range: 13 to 32 inches. Second, screen weight range: 4.4 to 19.8 lbs. Third, the back of the monitor screen must have VESA mounting holes with a pitch of 75x75mm or 100x100mm.
  • Regarding the compatibility with desks - Your desk must meet three conditions at the same time: First, desk material: Only wooden desks are recommended, plastic or glass desks cannot be used. Second, desk thickness range: 0.59" - 3.54". Third, the bottom of the desk should not have any cross beams or panels, as this will interfere with installation. We recommend carefully checking that your desk and monitors meets all above conditions before purchasing.
  • Dual C-Clamp Hold - Worried your dual monitors might wobble or slip? Our upgraded base uses a larger platform plus a dual C-clamp structure to lock the dual monitor arm firmly to your desk. Each arm safely keeps your screens steady while you type, click and game—no shaking, no sliding, just a clean and secure setup you can trust every day. It also provides Grommet Mounting installation choice, both options ensure stable and secure fixation for your 0.59" - 3.54" desk.
  • Full-Motion Adjustment For Comfortable View - Pull the screen closer when you’re deep in a spreadsheet, push it back to watch videos, or rotate to portrait for coding — moving everything smoothly with just one hand. The monitor stand offers +85°/-50° tilt, ±90° swivel and 360° rotation. Raise your monitor up to 15.75″ to support a healthy sitting posture. Whether you’re working from home, gaming through the night, or switching between video calls and documents, getting the screens to your natural line of sight helps relieve neck, shoulder and back strain so you can stay focused longer with less fatigue.
  • Keep Your Desk Organized: By lifting both screens off the desktop, this dual monitor stand opens up valuable space for your keyboard, notebook, docking station or a simple, clutter-free work area. Built-in cable management guides wires along the arms, keeping cords out of sight and out of the way. Enjoy a tidy, modern workstation that looks as good as it feels to use.
Independent reader supportYour contribution helps us test, update, and keep practical guides available for everyone.Support on Ko-Fi

Verify the deployment end to end

  1. Check services: inspect systemctl status for both Nginx and the Gunicorn unit.
  2. Check the upstream locally: use curl against the local socket or loopback endpoint, or request a lightweight Django health route. A local failure isolates the problem from DNS and TLS.
  3. Check the public URL: request the HTTPS homepage and an API endpoint with curl -I or an authenticated test request where appropriate.
  4. Test authentication: log in, refresh the session and make an API request. Look for CSRF, cookie-domain and mixed-content errors.
  5. Test deep React routes: paste a nested route into a new browser tab and refresh it. Nginx should return index.html for a client-side route that is not a real file.
  6. Test assets and media: verify that a Django static URL, a React JavaScript file, a stylesheet and an allowed media file return the expected content type and status.
  7. Inspect browser diagnostics: review the Network and Console panels for 404s, blocked mixed content, failed API origins, MIME errors and JavaScript exceptions.
  8. Review logs: correlate the browser request time with Nginx access/error logs and the Gunicorn journal.

Diagnose common failures

Symptom Likely causes Checks and fixes
502 Bad Gateway Gunicorn stopped, wrong socket path, socket permissions, incorrect WSGI import or Nginx upstream syntax. Run systemctl status myapp and journalctl -u myapp; verify the socket exists; compare the Nginx upstream with ExecStart; test nginx -t; ensure the Nginx user can connect to the socket.
React page loads but refreshing a nested route returns 404 The SPA fallback is absent or the request is being routed to a filesystem path. Put try_files $uri $uri/ /index.html in the frontend location and reload Nginx after a successful configuration test.
Missing CSS or JavaScript React output directory is wrong, asset base path is wrong, files were not built, or Nginx is returning HTML for an asset URL. Check the build output and browser Network panel; verify Nginx root; inspect the response body and content type for the asset; rebuild with the correct production environment.
Django static files return 404 collectstatic was skipped, STATIC_ROOT differs from Nginx’s alias, or permissions prevent reads. Run python manage.py collectstatic --noinput; compare the setting and alias paths; verify the file exists and is readable by Nginx.
API requests hit the wrong host or return CORS errors The React build contains a development API URL, the API prefix does not match Nginx, or a split-origin deployment lacks deliberate CORS and CSRF configuration. Inspect the built JavaScript and environment values; use the same-origin /api/ path where possible; configure trusted origins and CORS only for the actual frontend origins.
400 Bad Request or CSRF failure ALLOWED_HOSTS, CSRF trusted origins, cookie security or forwarded-protocol settings do not match the HTTPS hostname. Check the exact hostname and scheme in Django settings, confirm Nginx forwards X-Forwarded-Proto, restart Gunicorn after environment changes and retry over HTTPS.
502 or timeout during a long request Application work exceeds proxy or worker timeouts, or all workers are blocked. Read Gunicorn and Nginx logs, identify slow database or external calls, and change timeouts only after understanding the workload. Move durable background work to a suitable job system rather than tying up web workers.

Release and rollback safely

Treat each deployment as a release, not as an ad hoc file copy. Keep the previous known-good Git commit, dependency set and database backup or compatible migration plan until smoke tests pass.

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.
  1. Fetch and check out the new commit in a controlled release directory.
  2. Install its pinned backend and frontend dependencies without deleting the known-good release.
  3. Review migrations and take or verify a restorable database backup.
  4. Run manage.py check --deploy, migrations and collectstatic.
  5. Build the React assets and confirm the configured output path.
  6. Update the service’s release path or environment, restart Gunicorn, and reload Nginx only after nginx -t succeeds.
  7. Run the public smoke tests, including login, API calls, deep routes and static/media requests.

If the release fails, restore the previous code and dependency set, apply the compatible database migration plan, restart Gunicorn and reload Nginx. Do not blindly reverse a destructive migration; restore from the verified backup when the schema or data cannot safely move backward.

Compare alternatives before the VPS becomes a constraint

Decision Single-VPS default When the alternative is justified
Frontend and API placement Nginx serves React and proxies Django on one host. Split hosting isolates frontend deploys or lets the API scale independently, but introduces cross-origin, DNS and deployment coordination.
Static asset delivery Nginx serves the build and Django collected static files from local disk. Object storage plus a CDN is useful for geographic distribution, high asset volume or independent cache invalidation.
Django protocol server Gunicorn with WSGI for conventional request/response Django. Use an ASGI deployment when the application genuinely needs asynchronous views, WebSockets or other realtime workloads; verify every dependency supports that model.
PostgreSQL Self-host PostgreSQL when operational ownership and backups are acceptable. A managed database reduces patching and backup operations and can live outside the VPS failure domain.
Gunicorn binding Unix socket between Nginx and Gunicorn. Loopback TCP can simplify container boundaries or multi-host layouts; never bind an unprotected application server publicly.
Release process Manual, documented releases with health checks. CI/CD is worthwhile when tests, approvals, secrets management and rollback automation are mature.
TLS operations ACME client on the VPS with renewal monitoring. Managed TLS can centralize certificates when a platform or load balancer already terminates HTTPS.

Deployment completion checklist

  • DNS resolves the intended hostname to the VPS.
  • SSH key access works for the non-root deploy account.
  • Production secrets are outside Git and have restricted permissions.
  • DEBUG is false, hosts and CSRF origins are exact, and check --deploy is clean.
  • PostgreSQL credentials use a restricted role, migrations completed, and a restorable backup exists.
  • collectstatic completed and Nginx aliases point to readable directories.
  • The React build uses the production API base URL and the actual generated output directory.
  • Gunicorn runs under systemd, uses the intended virtual environment and is reachable only through its private socket or loopback.
  • Nginx passes nginx -t, serves the SPA fallback, proxies Django paths and redirects HTTP to HTTPS.
  • Certificate renewal is enabled and monitored.
  • Login, API calls, static files, media, deep links and browser console output have been tested publicly.
  • The previous release and rollback procedure remain available until the new release is proven.

Frequently Asked Questions

Can I deploy Django with manage.py runserver on the VPS?

No. runserver is for development. Use Gunicorn for a WSGI deployment (or an appropriate ASGI server for an asynchronous workload), supervise it with systemd and place Nginx in front.

Why does the React app work at the homepage but fail when I refresh another route?

Client-side routes need Nginx’s try_files $uri $uri/ /index.html fallback. Without it, Nginx looks for a physical file such as /library and returns 404.

What is the fastest way to investigate a 502?

Check the Gunicorn unit and journal first, then verify that the socket path in Nginx exactly matches ExecStart, exists, and is accessible to Nginx. Finally run sudo nginx -t and inspect the Nginx error log.

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

Should React and Django use separate domains?

They can, but a same-origin Nginx setup avoids much CORS and CSRF complexity. Separate origins require deliberate API base URLs, CORS policy, CSRF trusted origins, cookie settings, DNS and certificate configuration.

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 quests from Patch Notes

  1. How to Set Up a RedM (RDR2) Server in 2026: License Key, txAdmin and server.cfg, Step by StepBlog11min
  2. Best RedM (RDR2) Server Hosting in 2026: Comparing Four Hosts on Slots, Memory and PriceBlog10min
  3. How to Host a Mindustry Server in 2026: server-release.jar, Port 6567 and the Commands That MatterBlog7min
Recommended PC Tool
Recommended PC Tool
Outdated Drivers Are Slowing You DownFree scan - exact matches
Windows Errors? Fix Them Before They SpreadFree repair 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.