Report this

What is the reason for this report?

Deploy django app with subdomain

Posted on August 25, 2016

Hello! I am going to deploy a django app with nginx and gunicorn. The site (example.com) has language subdomains (fr.example etc), which is managed directly by my django app (it detects the subdomains and sets the proper language). So this gona be one app for several subdomains. So I have questions about settings:

  • What to write in Networking panel in DO?
  • How to configure Nginx?


This textbox defaults to using Markdown to format your answer.

You can type !ref in this text area to quickly search our full set of tutorials, documentation & marketplace offerings and insert the link!

These answers are provided by our Community. If you find them useful, show some love by clicking the heart. If you run into issues leave a comment, or add your own answer to help others.

The following solution will work as long as you are not hosting separate sites that also use a name.example.com subdomain on the same server and all requests for *.example.com that come to that server are expected to be served by your django app.

In the examples below 0.0.0.0 should be replaced with your IP address and example.com with your domain name

What to write in Networking panel in DO?

Create the following DNS records:

@   A  0.0.0.0
*  CNAME @

The first record points your domain (example.com) to your droplet’s IP address. This record handles any request for example.com without a subdomain. The second record says that any subdomain name should point to the same address as the domain without a subdomain. In our system this wildcard should be processed after any other defined subdomain records and act as a catch all. This means that existing records for things like mail.example.com can remain and should not pose a problem.

How to configure Nginx?

If this is the only site configured in nginx and has a default_server setting attached to it’s listen directive you wont have to make any changes at all since this will pass all requests on to your django application. If you have more than one site defined you’ll need to make a very minor configuration change. Open your site’s configuration file in /etc/nginx/sites-enabled/ and inside the server{} block you should see a server_name directive. Setting this to .example.com instead of example.com is all that is needed.

To deploy your Django app with Nginx and Gunicorn on DigitalOcean, with language-specific subdomains, you’ll need to set up the networking and configure Nginx appropriately. Here’s a step-by-step guide to answer your questions:

1. Networking Panel in DigitalOcean

  • Firewall: If you’re using a firewall in the DigitalOcean panel, make sure to allow the necessary ports for HTTP (80) and HTTPS (443). You may also want to open the port that Gunicorn will use (usually 8000, but this will be proxied by Nginx).

    • Open ports 80 and 443 for HTTP and HTTPS traffic.
    • Open the Gunicorn port (e.g., 8000) if you’re using it directly for testing purposes.
  • VPC (Optional): If you’re deploying multiple droplets (for example, separating your database and app), you can create a Virtual Private Cloud (VPC) to ensure private networking between droplets.

  • DNS Configuration: Ensure that your subdomains (fr.example.com, de.example.com, etc.) are pointing to your server’s IP address in the DigitalOcean DNS settings.

2. Nginx Configuration

Here’s how to configure Nginx to serve your Django app on multiple subdomains, while handling language detection and redirection.

a) Install Nginx

Make sure you have Nginx installed on your server:

sudo apt update
sudo apt install nginx

b) Nginx Configuration for Multiple Subdomains

Create a new configuration file for your Django app in /etc/nginx/sites-available and link it to /etc/nginx/sites-enabled.

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

c) Example Nginx Config

Here’s a basic example of how you can configure Nginx for your setup. We’ll assume Gunicorn is running on port 8000, and we will configure it for multiple subdomains.

server {
    listen 80;
    server_name example.com *.example.com;

    location / {
        proxy_pass http://127.0.0.1:8000;  # Gunicorn will serve the app on this port
        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;
    }

    # Static and media files
    location /static/ {
        alias /path/to/your/project/static/;
    }

    location /media/ {
        alias /path/to/your/project/media/;
    }

    # Additional configurations for HTTPS (optional)
    # Uncomment the following if you're using SSL
    # listen 443 ssl;
    # ssl_certificate /etc/ssl/certs/your_certificate.crt;
    # ssl_certificate_key /etc/ssl/private/your_certificate_key.key;

    # Redirect non-www to www (optional)
    # if ($host = 'example.com') {
    #     return 301 http://www.example.com$request_uri;
    # }
}

This configuration allows any subdomain (e.g., fr.example.com, de.example.com, etc.) to be routed to the same Django app. The Django app will handle the logic for setting the language based on the subdomain.

d) Enable the Nginx Config

Once your config is set up, you need to enable the Nginx site:

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

Then test your Nginx configuration to ensure there are no syntax errors:

nginx -t

If the test is successful, restart Nginx:

sudo systemctl restart nginx

3. Gunicorn Configuration

Now, configure Gunicorn to serve your Django app. Here’s an example command to run Gunicorn for your app:

gunicorn --workers 3 --bind 127.0.0.1:8000 example.wsgi:application

You can also create a Gunicorn service to run it automatically as a background process:

  1. Create a Gunicorn service file:
sudo nano /etc/systemd/system/gunicorn.service
  1. Add the following configuration:
[Unit]
Description=gunicorn daemon for Django project
After=network.target

[Service]
User=your-username
Group=your-group
WorkingDirectory=/path/to/your/project
ExecStart=/path/to/your/venv/bin/gunicorn --workers 3 --bind 127.0.0.1:8000 example.wsgi:application

[Install]
WantedBy=multi-user.target
  1. Start and enable Gunicorn to start on boot:
sudo systemctl start gunicorn
sudo systemctl enable gunicorn

4. Django Configuration for Subdomains

To handle subdomains for different languages, you can use the django-hosts package or manually detect the subdomain in your Django middleware. a) Install django-hosts (optional):

pip install django-hosts

b) Configure in settings.py:

Add the following settings for language and subdomain handling:

LANGUAGES = [
    ('en', 'English'),
    ('fr', 'French'),
    # Add more languages as needed
]

MIDDLEWARE = [
    'django_hosts.middleware.HostsRequestMiddleware',  # For django-hosts
    # Your other middleware here
]

ROOT_URLCONF = 'your_project.urls'

# If you're using django-hosts
HOSTS = {
    'example.com': 'your_project.urls',
    'fr.example.com': 'your_project.urls_fr',
    # Add more subdomains as needed
}

c) Configure Subdomain-based Views (if not using django-hosts)

If you aren’t using django-hosts, you can create custom middleware to set the language based on the subdomain.

from django.utils import translation
from django.http import HttpResponse

class SubdomainLanguageMiddleware:
    def __init__(self, get_response):
        self.get_response = get_response

    def __call__(self, request):
        host = request.get_host()
        subdomain = host.split('.')[0]  # Extract subdomain
        
        if subdomain == 'fr':
            translation.activate('fr')
        else:
            translation.activate('en')

        response = self.get_response(request)
        return response

Final Steps:

  • Static Files: Ensure that you have run python manage.py collectstatic to gather all static files into the correct directory.
  • Security: Don’t forget to configure HTTPS for your site using SSL certificates (you can use Let’s Encrypt).
  • Testing: Test your deployment by visiting your subdomains and ensuring the language is set correctly.

The developer cloud

Scale up as you grow — whether you're running one virtual machine or ten thousand.

Get started for free

Sign up and get $200 in credit for your first 60 days with DigitalOcean.*

*This promotional offer applies to new accounts only.