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.com
andtwo.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:
yourUsername
is your username. That’s the logged in user.one
is where the root project of the Django application is. In this case, where themanage.py
is as well- We’re using
virtualenvwrapper
thus our virtual environments for pip are within the~/.virtualenvs
You could put it literally anywhere you want. Just point to it. - We’re using
unix:sock
approach here. You can read about what that is. - If you created your Django project using the command,
django-admin.py startproject One
, theOne.wsgi:application
would be found within theOne/One/wsgi.py
file. Notice we’re pointing to the file without the extension. In thewsgi.py
file, there’s theapplication
function - The virtual environment for the
one
above 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 sock
s 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.