DevOps & Deployment March 07, 2026 7 min read

How to Host Multiple Django Websites on a Single Server using Nginx and Gunicorn

Do I need to rent a separate virtual private server (VPS) for every single website I build? The short answer is: No, absolutely not.

A
azzani
3 views
How to Host Multiple Django Websites on a Single Server using Nginx and Gunicorn

Table of Contents

  • Loading table of contents...

How to Host Multiple Django Websites on a Single Server using Nginx and Gunicorn

If you are a web developer or a startup founder, managing infrastructure costs is often a top priority. When building web applications—particularly with Python and Django—a natural question arises: Do I need to rent a separate virtual private server (VPS) for every single website I build?

The short answer is: No, absolutely not.

Hosting multiple websites on a single server is not only cost-effective but also entirely professional and scalable when configured correctly. The secret lies in isolating your applications using virtual environments, managing their execution with dedicated Gunicorn service files, and intelligently routing incoming web traffic using Nginx Server Blocks (virtual hosts).

In this comprehensive, step-by-step guide, we will walk you through the exact architecture required to host multiple, completely independent websites on a single Ubuntu server without causing conflicts, downtime, or security breaches.


Understanding the Architecture

Before diving into the terminal commands, it is crucial to understand how multiple apps share the same physical server.

When a user types your domain name into their browser, the request hits your server. If you have five websites hosted there, the server needs a traffic cop to decide which application should handle that request.

  1. Nginx acts as that traffic cop. It listens on ports 80 (HTTP) and 443 (HTTPS), reads the domain name requested, and routes the traffic to the correct local socket.
  2. Gunicorn is your application server. Instead of running one giant Gunicorn instance for all your sites, we will create separate Gunicorn systemd services for each website. This ensures that if Website A crashes or experiences a memory leak, Website B remains completely unaffected.
  3. Virtual Environments (venv) ensure that your Python dependencies (like Django versions) do not conflict between projects.

Let's assume you want to host two applications: ProjectAlpha (alpha.com) and ProjectBeta (beta.com).


Step 1: Establishing the Directory Structure

Security and organization start at the file system level. Never mix project files. Create a dedicated directory structure for your web applications, typically inside /var/www/ or your user's home directory.

# Create directories for both projects
mkdir -p /var/www/project_alpha
mkdir -p /var/www/project_beta

Place your Django codebase inside these respective folders. For instance, /var/www/project_alpha/src/ would contain your manage.py file for Alpha, and /var/www/project_beta/src/ would contain the one for Beta.


Step 2: Isolating Python Dependencies with Virtual Environments

The most common mistake developers make when hosting multiple apps on one server is installing dependencies globally. If Alpha requires Django 4.2 and Beta requires Django 5.0, a global installation will break one of them.

Create a separate virtual environment for each project within its directory:

# Setup for Project Alpha
cd /var/www/project_alpha
python3 -m venv venv
source venv/bin/activate
pip install django gunicorn psycopg2-binary
deactivate

# Setup for Project Beta
cd /var/www/project_beta
python3 -m venv venv
source venv/bin/activate
pip install django gunicorn psycopg2-binary
deactivate

Now, both projects have totally isolated Python interpreters and package environments.


Step 3: Configuring Dedicated Gunicorn Services

This is the hardest but most crucial step for stability. We need to tell the operating system (systemd) how to run and manage Gunicorn for each project separately. We do this by creating two distinct Unix sockets and two service files.

1. Creating Systemd Sockets

Sockets allow Nginx to communicate with Gunicorn securely without using up TCP network ports.

Create the socket for Alpha: sudo nano /etc/systemd/system/gunicorn_alpha.socket

[Unit]
Description=gunicorn socket for Project Alpha

[Socket]
ListenStream=/run/gunicorn_alpha.sock

[Install]
WantedBy=sockets.target

Create the socket for Beta: sudo nano /etc/systemd/system/gunicorn_beta.socket

[Unit]
Description=gunicorn socket for Project Beta

[Socket]
ListenStream=/run/gunicorn_beta.sock

[Install]
WantedBy=sockets.target

2. Creating Systemd Services

Next, create the service files that define how Gunicorn boots up.

Create the service for Alpha: sudo nano /etc/systemd/system/gunicorn_alpha.service

[Unit]
Description=gunicorn daemon for Project Alpha
Requires=gunicorn_alpha.socket
After=network.target

[Service]
User=www-data
Group=www-data
WorkingDirectory=/var/www/project_alpha/src
ExecStart=/var/www/project_alpha/venv/bin/gunicorn \
          --access-logfile - \
          --workers 3 \
          --bind unix:/run/gunicorn_alpha.sock \
          alpha_config.wsgi:application

[Install]
WantedBy=multi-user.target

Create the service for Beta: sudo nano /etc/systemd/system/gunicorn_beta.service

[Unit]
Description=gunicorn daemon for Project Beta
Requires=gunicorn_beta.socket
After=network.target

[Service]
User=www-data
Group=www-data
WorkingDirectory=/var/www/project_beta/src
ExecStart=/var/www/project_beta/venv/bin/gunicorn \
          --access-logfile - \
          --workers 3 \
          --bind unix:/run/gunicorn_beta.sock \
          beta_config.wsgi:application

[Install]
WantedBy=multi-user.target

Notice how everything is explicitly separated: different virtual environments (ExecStart), different working directories, and different binding sockets.


Step 4: Activating the Gunicorn Services

With the configuration files written, you must now start and enable both sockets so they automatically boot if the server reboots.

# Reload system daemon to register the new files
sudo systemctl daemon-reload

# Start and enable Alpha
sudo systemctl start gunicorn_alpha.socket
sudo systemctl enable gunicorn_alpha.socket
sudo systemctl start gunicorn_alpha.service
sudo systemctl enable gunicorn_alpha.service

# Start and enable Beta
sudo systemctl start gunicorn_beta.socket
sudo systemctl enable gunicorn_beta.socket
sudo systemctl start gunicorn_beta.service
sudo systemctl enable gunicorn_beta.service

If you check /run/, you should now see two separate socket files: gunicorn_alpha.sock and gunicorn_beta.sock.


Step 5: Configuring Nginx Server Blocks

Gunicorn is now running your applications flawlessly in the background, but the outside world cannot reach them. We use Nginx to listen for internet traffic and proxy it to the correct socket based on the domain name.

1. Nginx Config for Alpha

Create a new file: sudo nano /etc/nginx/sites-available/alpha

server {
    listen 80;
    server_name alpha.com www.alpha.com;

    location = /favicon.ico { access_log off; log_not_found off; }
    
    location /static/ {
        root /var/www/project_alpha/src;
    }

    location /media/ {
        root /var/www/project_alpha/src;
    }

    location / {
        include proxy_params;
        proxy_pass http://unix:/run/gunicorn_alpha.sock;
    }
}

2. Nginx Config for Beta

Create a new file: sudo nano /etc/nginx/sites-available/beta

server {
    listen 80;
    server_name beta.com www.beta.com;

    location = /favicon.ico { access_log off; log_not_found off; }
    
    location /static/ {
        root /var/www/project_beta/src;
    }

    location /media/ {
        root /var/www/project_beta/src;
    }

    location / {
        include proxy_params;
        proxy_pass http://unix:/run/gunicorn_beta.sock;
    }
}

3. Enable the Sites

To enable these configurations, create a symbolic link from sites-available to sites-enabled.

sudo ln -s /etc/nginx/sites-available/alpha /etc/nginx/sites-enabled
sudo ln -s /etc/nginx/sites-available/beta /etc/nginx/sites-enabled

Test your Nginx configuration for syntax errors and restart the service:

sudo nginx -t
sudo systemctl restart nginx

Step 6: Securing with SSL (Certbot)

A modern website must serve traffic over HTTPS. Hosting multiple sites makes no difference to Let's Encrypt; it will happily generate free SSL certificates for both domains.

Simply run Certbot for each domain independently:

sudo certbot --nginx -d alpha.com -d www.alpha.com
sudo certbot --nginx -d beta.com -d www.beta.com

Certbot will automatically modify your Nginx server blocks to include the SSL certificates and redirect all HTTP traffic to HTTPS.


Best Practices for Multi-App Hosting

Now that you have multiple websites thriving on a single server, you must adopt a proactive mindset regarding resource management.

  1. Monitor RAM Usage: Every Gunicorn worker consumes RAM. If you have 3 workers per site and 5 sites, that’s 15 workers running concurrently. If you have a 2GB RAM server, you may suffer from Out-Of-Memory (OOM) crashes. Adjust your --workers count in the gunicorn.service files based on your server capacity. A good baseline formula is (2 * CPU Cores) + 1 total workers across the entire server.
  2. Database Segregation: Do not share the same PostgreSQL database for multiple projects. Create a unique Database and a unique Database User for every single website. This ensures database-level security isolation.
  3. Use .env files: Never hardcode your SECRET_KEY, database passwords, or debug flags. Use python-dotenv and keep a strict .env file in each project directory.
  4. Log Management: By default, logs can pile up and fill your disk space. Ensure that you have log rotation configured for your Nginx and systemd logs.

Conclusion

Hosting multiple Django websites on a single server is a rite of passage for robust web developers. It allows you to maximize your cloud infrastructure investment while maintaining strict, professional isolation between client projects.

By meticulously applying virtual environments, writing dedicated Gunicorn systemd configurations, and leveraging the routing intelligence of Nginx, you have built a scalable environment. If one website goes viral, you can easily migrate just its database and code folder to a new server without breaking the others, making this architectural pattern both cost-effective for today and scalable for tomorrow.

And Finally after deploying your sites, test their security and performance useing our open-source scanners and one of the top scanners open-source on internet.

Security Scanner

Performance Scanner

 

Related Articles

Discussion 0

No comments yet. Be the first to start the discussion!

Leave a Comment