You have 2 or more Django applications. You wish to hook each to a separate domain. Behind the scenes, they’re two or more separate gunicorn instances. How do you proxy to the gunicorn instances via Nginx? Here’s how it works.
A few assumptions
- Our domains are
one.example.comandtwo.example.com - We’re using Gunicorn
- We’re using Nginx
- It’s a Django Project we’re handling.
- This won’t teach you how to setup your Django
- This assumes you know your stuff around your VPS.
- We’re using
virtualenvwrapper - Django project One is in the folder,
/home/yourUsername/One - Django project Two is in the folder,
/home/yourUsername/Two
SystemD, baby
Previously, it used to be Upstart. Nowadays, it is SystemD. In case you don’t know the difference, just assume SystemD is better.
SystemD will be responsible to start our applications whenever the system is restarted. Now, open your eyes.
/etc/systemd/system/one.example.service
[Unit] Description=gunicorn daemon After=network.target [Service] User=yourUsername Group=www-data WorkingDirectory=/home/yourUsername/One ExecStart=/home/yourUsername/.virtualenvs/one/bin/gunicorn --workers 3 --bind unix:/home/yourUsername/One/one.sock One.wsgi:application [Install] WantedBy=multi-user.target
Don’t worry, here are what the above means:
yourUsernameis your username. That’s the logged in user.oneis where the root project of the Django application is. In this case, where themanage.pyis as well- We’re using
virtualenvwrapperthus our virtual environments for pip are within the~/.virtualenvsYou could put it literally anywhere you want. Just point to it. - We’re using
unix:sockapproach here. You can read about what that is. - If you created your Django project using the command,
django-admin.py startproject One, theOne.wsgi:applicationwould be found within theOne/One/wsgi.pyfile. Notice we’re pointing to the file without the extension. In thewsgi.pyfile, there’s theapplicationfunction - The virtual environment for the
oneabove was created using the command,mkvirtualenv one
The rest of the file is just straightforward.
Create the above file too for the Django project two. Just change the parts to point to the Django Project Two directory instead.
‘Boosu Keena’, Nginx
Don’t worry what the ‘Boosu Keena’ means. The focus is on Nginx.
Here will be our Nginx configuration that will proxy the requests to Gunicorn internally. Now since we’re using unix socks instead of HTTP (used for proxying to NodeJS-like run apps), there’s no need to define our upstream server block.
‘Unix socks’? What a lovely term!
So, here we go:
server {
listen 443 ssl http2;
root /home/yourUsername/One;
index index.html index.htm;
server_name one.example.com;
include /etc/nginx/ssl/ssl-params.conf;
include /etc/nginx/ssl/one.example.ssl;
error_log /var/log/nginx/one.example_error.log;
access_log /var/log/nginx/one.example_access.log;
location /media/ {
alias /home/yourUsername/One/media/;
}
location /static/ {
alias /home/yourUsername/One/static/;
}
# Below is the juice. We're proxying the request to the sock we created
# earlier via the gunicorn process via SystemD
location / {
proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;
proxy_set_header Host $http_host;
proxy_redirect off;
proxy_pass http://unix:/home/yourUsername/One/one.sock;
}
location ~* \.(jpg|jpeg|png|gif|ico|css|js)$ {
expires 30d;
}
location /robots.txt {
alias /home/yourUsername/One/static/robots.txt;
}
location /favicon.ico {
alias /home/yourUsername/One/static/favicon.ico;
}
}
server {
listen 80;
server_name one.example.com;
return 301 https://$server_name$request_uri;
}
Some Litmus test
At this stage, what we’ve done, is it working?
We don’t know yet, so let’s find out
sudo systemctl start gunicorn
sudo systemctl enable gunicorn
Of course none of the above commands would work if you don’t have gunicorn installed. Then,
sudo systemctl daemon-reload
Doing the daemon-reload ensures new service files added, in our case, one.example.service and two.example.service are tucked into the SystemD fold and recognized.
At this point, if all is good, you should be able to run,
sudo systemctl status one.example.service
If it ain’t running, then sudo systemctl start one.example.service should bring it up.
Do check the status if any errors are coming up. If none, then we’re good on the site of gunicorn. Hurray!
Nginx
On the side of Nginx, let’s link the one.example.com and two.example.com files into the /etc/nginx/sites-enabled/folder. We do that via
sudo ln -s /etc/nginx/sites-available/one.example.com /etc/nginx/sites-enabled/
Then, we run
sudo nginx -t
If all passes, we’re good to go.
Reload Nginx. sudo service nginx reload
Conclusion
Is it working?
Now you noticed only the files for the Django Project One were created in the above explanations. Simply duplicate whatever the file, and replace with details related to the Django Project Two.
Lemme know in the comments if any issues.

