Use one public Nginx instance and one isolated Gunicorn service for each Django site. Point every domain to the server, let Nginx choose a server block from the Host header, serve that site’s static and media files, and proxy dynamic requests to that site’s private Unix socket (or loopback TCP port). Give each project its own directory, virtual environment, settings, secrets, database credentials, logs, service name and socket. This keeps deployments, restarts and failures from spreading across sites.
Antihost offers Linux VPS plans with full root access, unlimited traffic on a 1 Gbps port and a 14-day free trial.
The examples below use two domains, site1.example and site2.example, with projects in /srv/site1 and /srv/site2. Replace those example values, users and paths after reviewing permissions, distribution-specific paths and your Django settings.
As an Amazon Associate I earn from qualifying purchases.
Architecture and request flow
Only Nginx should be exposed publicly. Gunicorn processes listen on private Unix sockets or on loopback addresses, so clients cannot bypass Nginx and reach an application directly.
- DNS A or AAAA records for each domain point to the server’s public address.
- Nginx receives the request on port 80 or 443 and matches the
Hostheader to an explicitserver_name. - The selected server block serves files from that site’s
STATIC_ROOTand media directory. - Requests that are not static or media are proxied to the matching Gunicorn socket or loopback port.
- That Gunicorn service loads only its own WSGI module, virtual environment and environment file, then returns the response through Nginx.
Never use a single catch-all upstream for all projects. A separate upstream path for every hostname prevents a configuration mistake from sending one site’s request to another site’s application.
#1 Best Overall
- Read Before You Buy — No Video Output: These adapters support charging and USB 2.0 data transfer, but cannot transmit video signals. Except for standard USB webcams (which use USB data only), they are not compatible with HDMI/DisplayPort cables, video-capable USB-C hubs, or docking stations with video output.
- Convert USB-A Ports to USB-C: Designed to connect USB-C earphones, cables, flash drives, card readers, and other USB-C accessories to standard USB-A ports. Plug-and-play with no drivers or software required.
- Aluminum Alloy Housing: Built with a sturdy aluminum alloy shell that aids in heat dissipation and protects against daily wear and scratches. Designed to maintain a stable and secure connection.
- Compact & Travel-Friendly: The ultra-compact design allows the adapter to stay plugged into your device without blocking adjacent ports or adding bulk, reducing wear and tear on your original USB ports.
- 12-Month Warranty: Backed by a 12-month manufacturer warranty for peace of mind. Designed to meet strict quality control standards for reliable everyday performance.
Plan isolation before installing anything
Separate services cost a little more operational work, but they sharply reduce the blast radius of a bad release, memory leak or restart. Record an owner, service name, socket path, project directory, database and log location for every site.
| Concern | Site 1 example | Site 2 example |
|---|---|---|
| Domain | site1.example |
site2.example |
| Linux identity | site1 |
site2 |
| Project root | /srv/site1 |
/srv/site2 |
| Virtual environment | /srv/site1/.venv |
/srv/site2/.venv |
| Environment file | /etc/site1/site1.env |
/etc/site2/site2.env |
| Gunicorn unit | site1-gunicorn.service |
site2-gunicorn.service |
| Private socket | /run/site1/site1.sock |
/run/site2/site2.sock |
| WSGI module | site1.wsgi:application |
site2.wsgi:application |
Use distinct databases, database users, cache namespaces and log files as well. A shared database account or shared writable directory can defeat the isolation that separate processes provide.
Free tools Windows power users keep installed
One-click scans. No signup required.
Prepare the host, DNS and service identities
Provision the common components
- A supported Linux server with enough memory for Nginx, every Gunicorn worker, the databases and background jobs.
- Nginx, Python, your database server or database client, and systemd.
- A firewall allowing public TCP ports 80 and 443, while blocking public access to Gunicorn ports and sockets.
- DNS records for every hostname, including any IPv6 record you intend to use.
- Separate Unix users or service identities such as
site1andsite2.
Do not copy a worker count, memory limit or directory ownership from an example without measuring your workload. There is no universal Gunicorn worker formula that is correct for every collection of Django sites.
Create directories and identities
Create each project root, configuration directory and runtime directory with ownership that lets the service read its code and secrets but does not make the application tree writable by Nginx. The exact commands vary by distribution; the important result is that site1 cannot modify site2‘s files.
Keep environment files outside source control. They should contain the production SECRET_KEY, database credentials, email credentials and any third-party tokens, with permissions readable only by the corresponding service user (and root).
Install and configure each Django project
Create an isolated virtual environment
- Place the first project in
/srv/site1and create its environment withpython3 -m venv /srv/site1/.venv. - Install the project’s pinned dependencies with
/srv/site1/.venv/bin/pip install -r /srv/site1/requirements.txt. - Repeat in
/srv/site2using/srv/site2/.venvand its own dependency lock file.
Pin compatible versions and deploy the same dependency set that was tested for each project. Never let one site’s package upgrade silently alter another site’s runtime.
Crashes, 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 minutePC Slower Than It Used to Be?
A free scan shows the junk files, broken settings and background clutter dragging Windows down - then fixes them in one click.Free scan · Windows 10 & 11Rank #2
- 5-in-1 USB-C Hub: Experience comprehensive connectivity featuring a Power Delivery input, two USB-A 2.0 ports, a USB-A 3.0 port, and an HDMI port. (Note: The USB-C power delivery input port is only for connecting an external wall charger to power your laptop and cannot power peripheral devices.)
- 90W Pass-Through Charging: Achieve optimal charging with 90W pass-through power to your laptop, supported by a total input of 100W, with the hub reserving 10W for operational efficiency. (Note: Wall charger not included.)
- Quick Data Transfers: Accelerate your productivity with rapid data transfers using a high-speed 5Gbps USB 3.0 port and two 480Mbps USB 2.0 ports.
- 4K HDMI Display: Enhance your visual experience with a hub capable of delivering 4K resolution at 30Hz in both mirror and extend modes. Please note that this hub is compatible with MacBook (macOS 12 and newer), Windows 10 and 11, ChromeOS, and laptops equipped with DP Alt Mode and Power Delivery. Note: This device is not compatible with Linux.
- What You Get: Anker USB-C Hub (5-in-1, 4K HDMI), welcome guide, 18-month warranty, and our friendly customer service.
Use production settings and environment variables
For each project, set DEBUG = False, a unique secret key, production database and cache settings, and the correct logging and email backends. Add every public hostname, including alternate names that actually resolve to the site, to that site’s ALLOWED_HOSTS. Django requires ALLOWED_HOSTS when DEBUG is false; it also helps prevent Host-header and related CSRF attacks.
Keep the production settings module explicit in the service and deployment commands. For example, a site might use site1.settings.production while another uses site2.settings.production. Do not assume both projects have the same module layout.
Run migrations, collect static files and validate
- From
/srv/site1, run/srv/site1/.venv/bin/python manage.py migrate --settings=site1.settings.production. Run the equivalent command in/srv/site2. - Set a site-specific
STATIC_ROOT, such as/srv/site1/staticfiles, and runcollectstaticwith that site’s settings. - Choose a media directory such as
/srv/site1/media; user-uploaded media must be writable by the application where required, but only readable by Nginx for delivery. - Run
/srv/site1/.venv/bin/python manage.py check --deploy --settings=site1.settings.production, then run the corresponding command for site 2.
The deployment check is a release gate, not a substitute for reviewing database, cache, email, logging, backup and cookie settings. Fix its warnings before exposing a site.
Choose a Gunicorn isolation model
One service per site (recommended)
Create site1-gunicorn.service and site2-gunicorn.service. Each unit sets its own working directory, virtual-environment executable, WSGI module, environment file, restart policy and socket. A failed restart of site 1 then leaves site 2 running, and each deployment can be rolled back independently.
Unix sockets versus loopback TCP
| Criterion | Unix socket | Loopback TCP port |
|---|---|---|
| Permission management | Requires correct socket user, group and mode; a mismatch commonly causes 502 errors. | Uses bind and firewall rules; local port access is usually simpler to inspect. |
| Observability | Socket existence and filesystem ownership are direct checks. | Listening ports are easy to inspect with standard network tools. |
| Portability | Convenient when Nginx and Gunicorn share one host. | Works when a proxy and application are separated onto different hosts. |
| Cross-host support | Not usable across machines. | Suitable for a networked proxy, with strict firewalling and trusted-proxy controls. |
| Failure diagnosis | Check file creation, parent-directory traversal and Nginx group access. | Check bind address, port ownership, local connectivity and firewall rules. |
For a single host, a private Unix socket is a sensible default. A loopback port is equally valid when your tooling, container layout or future split-host design makes TCP easier.
Example systemd service units
The following pattern uses a separate runtime directory and a socket owned so the Nginx worker can connect. Adjust the user, group, worker count and settings module after reviewing the project.
Rank #3
- Sleek 7-in-1 USB-C Hub: Features an HDMI port, two USB-A 3.0 ports, and a USB-C data port, each providing 5Gbps transfer speeds. It also includes a USB-C PD input port for charging up to 100W and dual SD and TF card slots, all in a compact design.
- Flawless 4K@60Hz Video with HDMI: Delivers exceptional clarity and smoothness with its 4K@60Hz HDMI port, making it ideal for high-definition presentations and entertainment. (Note: Only the HDMI port supports video projection; the USB-C port is for data transfer only.)
- Double Up on Efficiency: The two USB-A 3.0 ports and a USB-C port support a fast 5Gbps data rate, significantly boosting your transfer speeds and improving productivity.
- Fast and Reliable 85W Charging: Offers high-capacity, speedy charging for laptops up to 85W, so you spend less time tethered to an outlet and more time being productive.
- What You Get: Anker USB-C Hub (7-in-1), welcome guide, 18-month warranty, and our friendly customer service.
[Unit]
Description=Gunicorn for site1
After=network.target
[Service]
User=site1
Group=www-data
WorkingDirectory=/srv/site1
RuntimeDirectory=site1
EnvironmentFile=/etc/site1/site1.env
ExecStart=/srv/site1/.venv/bin/gunicorn --workers 3 --umask 007 --bind unix:/run/site1/site1.sock site1.wsgi:application
Restart=on-failure
[Install]
WantedBy=multi-user.target
Save the second unit with the site 2 values, including RuntimeDirectory=site2, /run/site2/site2.sock and site2.wsgi:application. If your project uses a production settings module, set it in the environment file or add the appropriate Gunicorn option rather than assuming the default settings module.
After placing the units in the systemd unit directory, reload systemd and enable both services:
Quick wins for a faster PC:
Fix the driver behind crashes, sound loss and screen glitchesFind Drivers →Clear out junk files and repair common Windows errorsFree Scan →Scan for outdated or missing drivers - takes under a minuteDriver Scan →sudo systemctl daemon-reload
sudo systemctl enable --now site1-gunicorn.service
sudo systemctl enable --now site2-gunicorn.service
sudo systemctl status site1-gunicorn.service site2-gunicorn.service
Confirm that each socket exists and that the service logs show the intended WSGI application. Test locally before changing DNS or enabling public traffic.
Optional socket activation
Gunicorn also supports systemd socket activation. In that design, create a matching site1-gunicorn.socket and service rather than having Gunicorn create the listening socket itself. A socket unit needs a unique ListenStream, plus SocketUser, SocketGroup and SocketMode that permit Nginx access:
[Unit]
Description=Socket for site1 Gunicorn
[Socket]
ListenStream=/run/site1/site1.sock
SocketUser=site1
SocketGroup=www-data
SocketMode=0660
[Install]
WantedBy=sockets.target
Use the activation-specific Gunicorn command and unit arrangement documented for your Gunicorn version. Do not configure both a socket-activation listener and a normal --bind listener for the same path; only one component should own the socket.
Configure Nginx server blocks
Reject unknown hostnames
Define a default server that does not route arbitrary Host headers to a real project. Returning status 444 is a common Nginx choice for an unknown host:
Recommended Free Tools
Rank #4
- Dual Converters, Infinite Potential:Includes 2× USB C male to USB A female adapters and 2× USB A male to USB C female adapters. Perfect for a wide range of uses—tablets with Bluetooth keyboards, expand USB ports on macbook, and more. Two different converters for all your daily needs
- Next-Level 10Gbps & 3A Charging: No more slow 480Mbps, this usb to usb c adapter has a transfer speed of up to 10Gbps, allowing you to do more transferring in less time. This usb adapter fits both USB A and USB C charger, supporting up to 3A fast charging
- Upgraded Exquisite Craftsmanship: With an aluminum alloy housing and metal connector, the usbc to usb adapter is extremely durable and sturdy. Rigorously tested to withstand more than 10,000 times of plugging and unplugging, ensuring long-lasting performance
- Broad Compatible: The usb c to usb adapter widely supports all USB C/ USB A devices like laptops, tablets, cellphones, car chargers, and phone chargers. Such as compatible with MacBook Pro/Air 2023/2022, Thunderbolt 4/3 Devices,Apple MagSafe Watch 9/8/7/SE/Ultra, iPad Pro 2022/2021, Samsung Galaxy S23/S20/S10, and iPhone 17/16/15 Pro. Plug and play
- Please Note: To reach 10Gbps speed, keep the cable under 3.3 ft. For USB A Male to USB C adapters, try flipping the USB C connector. USB C Male to USB A adapters support bidirectional 10Gbps transfer within 3.3 ft
server {
listen 80 default_server;
listen [::]:80 default_server;
server_name _;
return 444;
}
Add an equivalent default for the TLS listener if your Nginx layout has a shared HTTPS default. This prevents an accidental first-listed site from becoming the response for an unrelated hostname.
Route site 1
server {
listen 80;
listen [::]:80;
server_name site1.example www.site1.example;
location /static/ {
alias /srv/site1/staticfiles/;
}
location /media/ {
alias /srv/site1/media/;
}
location / {
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/site1/site1.sock:;
proxy_buffering on;
}
}
Route site 2
server {
listen 80;
listen [::]:80;
server_name site2.example www.site2.example;
location /static/ {
alias /srv/site2/staticfiles/;
}
location /media/ {
alias /srv/site2/media/;
}
location / {
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/site2/site2.sock:;
proxy_buffering on;
}
}
For loopback TCP, replace the socket target with a unique address such as http://127.0.0.1:8011 for site 1 and another unused port for site 2. Bind Gunicorn to loopback, not to a public interface.
The trailing slash on each alias matters: it maps /static/ to the directory whose files were produced by collectstatic. Verify that the Nginx worker can traverse every parent directory and read the files, while the application user retains the access needed to write uploads.
Add HTTPS and Django proxy settings
Obtain a certificate covering every public hostname, then create HTTPS server blocks for each domain. Redirect each site’s HTTP block to its own HTTPS URL rather than redirecting all unknown hosts to a real site.
The Tool Desk
Outbyte Driver Updater FREEScan for outdated or missing drivers - takes under a minuteDriver Scan →Outbyte PC Repair FREERepair Windows errors before they cause bigger problemsFix Now →Because TLS terminates at Nginx, preserve the original protocol with X-Forwarded-Proto. Configure Django’s trusted proxy and secure-cookie settings consistently with that header and your Django version. Enable site-wide HTTPS for any project that accepts logins: credentials, session cookies and password-reset tokens are access tokens and must not cross the network in cleartext.
Use secure cookies, an appropriate HSTS policy after confirming every subdomain is HTTPS-ready, and CSRF trusted origins that match the exact schemes and hostnames used by the site. Do not enable a blanket setting on all projects without checking whether an individual site has a separate administrative hostname.
Best Value
- 5-in-1 Connectivity: Equipped with a 4K HDMI port, a 5 Gbps USB-C data port, two 5 Gbps USB-A ports, and a USB C 100W PD-IN port. Note: The USB C 100W PD-IN port supports only charging and does not support data transfer devices such as headphones or speakers.
- Powerful Pass-Through Charging: Supports up to 85W pass-through charging so you can power up your laptop while you use the hub. Note: Pass-through charging requires a charger (not included). Note: To achieve full power for iPad, we recommend using a 45W wall charger.
- Transfer Files in Seconds: Move files to and from your laptop at speeds of up to 5 Gbps via the USB-C and USB-A data ports. Note: The USB C 5Gbps Data port does not support video output.
- HD Display: Connect to the HDMI port to stream or mirror content to an external monitor in resolutions of up to 4K@30Hz. Note: The USB-C ports do not support video output.
- What You Get: Anker 332 USB-C Hub (5-in-1), welcome guide, our worry-free 18-month warranty, and friendly customer service.
Deploy in a repeatable order
- Provision the host, firewall, DNS records and per-site users or service identities.
- Create each project directory and virtual environment; install pinned dependencies.
- Write production settings and secret files outside source control.
- Run migrations,
collectstaticand the deployment check for each project. - Install and validate every Gunicorn unit or socket. Confirm unique paths, users and WSGI modules.
- Enable the Gunicorn services at boot and test each socket or local port from the Nginx account.
- Add the Nginx default server and one explicit server block per domain.
- Run
nginx -t. Only after it succeeds, perform a controlled reload withsudo systemctl reload nginx. - Obtain certificates, enable HTTPS redirects and test every hostname over both HTTP and HTTPS.
- Inspect application, Gunicorn and Nginx logs, then repeat the deployment check after the first production release.
A useful pre-DNS test is to send a request with an explicit Host header to the server’s address, or to use a temporary hosts-file entry. This verifies Nginx selection without waiting for DNS caches.
Test each layer before declaring success
Application and socket checks
- Run
systemctl is-active site1-gunicorn.serviceand the equivalent for site 2. - Check that
/run/site1/site1.sockand/run/site2/site2.sockexist with the expected group and mode. - From the Nginx service account, make a Unix-socket request to each socket, supplying the correct Host header. A response from the wrong project indicates an upstream or WSGI mapping error.
- For TCP listeners, test each loopback port locally before opening any firewall rule.
Nginx and browser checks
- Run
nginx -tbefore every reload. - Request a known static file and a dynamic URL for each domain.
- Submit a form or login flow on a staging account to confirm CSRF, secure cookies and forwarded protocol handling.
- Confirm that an unknown hostname receives the default rejection instead of site 1.
- Check certificate names, HTTP-to-HTTPS redirects and canonical host redirects separately for every domain.
Troubleshooting common failures
| Symptom | Likely causes | Recovery steps |
|---|---|---|
| 502 Bad Gateway | Gunicorn stopped, wrong socket or port, inaccessible socket, or WSGI startup failure. | Inspect systemctl status and journal logs; confirm the target exists; test it locally; verify Nginx group access; run the WSGI command from the site’s virtual environment. |
| Wrong site served | DNS points elsewhere, server_name is incomplete, the default server catches the request, or the upstream path belongs to another project. |
Check the Host header and DNS answer, list enabled Nginx configurations, inspect the default server, and compare each domain’s proxy target with its Gunicorn unit. |
| Static files return 404 | collectstatic was not run, STATIC_ROOT differs from the Nginx alias, or filesystem traversal is denied. |
Run collectstatic with the production settings, compare the generated path to the alias, and test read and execute permissions as the Nginx user. |
| Permission denied on socket | Socket user, group or mode does not include the Nginx worker; a parent runtime directory is inaccessible. | Align SocketUser, SocketGroup, mode and directory permissions; restart the service so the socket is recreated, then test as Nginx. |
| Redirect loop or insecure URLs | X-Forwarded-Proto is missing or Django’s proxy-SSL setting disagrees with the TLS termination layer. |
Pass the forwarded protocol once, configure Django’s trusted proxy behavior, and ensure only the intended HTTPS layer performs redirects. |
| One site’s restart affects another | A shared Gunicorn unit, shared virtual environment or shared runtime directory remains in use. | Move the project to its own service, environment, socket and logs; verify Nginx points to the new unique target before disabling the shared unit. |
Operate and scale without losing isolation
Independent services versus a shared Gunicorn service
| Factor | Separate service per site | One shared service |
|---|---|---|
| Isolation | Each process has its own code, environment and settings. | Projects can share process settings and dependencies. |
| Deployments | Release or roll back one domain independently. | A restart or package change can affect every domain. |
| Blast radius | A crash is normally limited to one site. | A crash or bad configuration can remove all sites. |
| Resource accounting | Per-site worker counts, logs and service metrics are clear. | Memory and CPU usage are harder to attribute. |
| Operational overhead | More unit files, health checks and upgrades to maintain. | Fewer units, but tighter coupling and more complicated deployment logic. |
Separate services are usually the safer default for unrelated sites. A shared process can be reasonable for tightly controlled applications with identical dependencies, but it should be a deliberate trade-off rather than an accidental shortcut.
What’s actually slowing this PC down?
Pick the symptom - the matching free tool is one click away.
Choose worker counts from measurements
Start conservatively, observe memory and response latency under representative concurrency, and increase workers only when the host has headroom. A worker count that is safe for one small site can exhaust a host when multiplied across several sites. Account for background workers, management commands and database connections in addition to Gunicorn processes.
Keep logs and restart procedures site-specific
Send each unit’s standard output and error to a clearly identified journal or log destination. Monitor Nginx 4xx and 5xx rates, Gunicorn restarts, socket availability, disk space and certificate expiry per domain. Document a rollback that stops only the affected service, restores its previous release and leaves the other sites untouched.
Production security gates
- Use
DEBUG = Falseand a complete, site-specificALLOWED_HOSTS. - Keep secret keys and database credentials out of Git and out of Nginx configuration files.
- Restrict databases, caches and Gunicorn listeners to the addresses that actually need them.
- Use HTTPS for every login-capable site and configure secure session and CSRF cookies.
- Pass and validate forwarded headers only through trusted proxy layers.
- Run
check --deployfor every settings module on every release. - Back up each database and media directory independently, and test restoration.
- Review Nginx configuration after adding a domain so its static aliases and upstream cannot cross project boundaries.
With Nginx as the public router, one correctly mapped server block per hostname, and one privately bound Gunicorn service per project, multiple Django sites can share a host while retaining independent deployments, credentials, logs and failure domains.
Quick Recap
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.
Do these 3 things before closing this tab:
1Scan for outdated or missing drivers - takes under a minute2Clear out junk files and repair common Windows errors3Fix the driver behind crashes, sound loss and screen glitches




