Photo by COPPERTIST WU on Unsplash
According to the official documentation, Django projects should be served by a proper web server using a uWSGI (Universal WebService Gateway Interface.
In this article, I will explain the whole process of serving Django projects using Nginx on an Ubuntu 22 VPS (Virtual Private Server).
Django setup
Before you start hosting the project, you should ensure the website listens to the correct hostname. In this article, the project "Django Haxor" will be hosted at django.haxor.no, with a project named "djangohaxor". Rename the project and hostnames as you see fit.
Start by adding the correct hostname on which the website will be hosted in your settings file.
...
ALLOWED_HOSTS = [
'localhost',
'127.0.0.1',
'django.haxor.no'
]
...
Installing the project
Typically, your Django project has a git repository. Clone the repository into your desired directory (usually the /var/www directory on Debian-based operating systems like Ubuntu), and install the dependencies.
# Install Python dependencies
python3 -m venv venv
chmod +x venv/bin/activate
source venv/bin/activate
pip install -r requirements.txt
# Install JavaScript dependencies
npm install
Once the dependencies are installed, run your migrations, or import a DB dump into your database manager.
Finally, add .env files or make your secrets accessible to the Django app.
uWSGI installation
Once you have cloned your git repository to the VPS and installed your dependencies, you must install several packages on the OS, including the uwsgi Python package (if not already a part of your requirements.txt file.
sudo apt install python3-dev gcc ibxml2-dev
pip install uwsgi
Serve with supervisor
To create a *daemon that manages the uWSGI, I prefer to use "supervisor". I find the configuration files more straightforward than systemctl config files. Because of this, I first make sure that "supervisor" is installed before continuing.
sudo apt update
sudo apt install supervisor
Once installed, the config file can be created.
sudo vim /etc/supervisor/conf.d/django.haxor.no.conf
[program:django_haxor]
directory=/var/www/django.haxor.no
command=/var/www/django.haxor.no/venv/bin/uwsgi --socket djangohaxor.sock --module djangohaxor.wsgi --chmod-socket=666
autostart=true
autorestart=true
Update supervisor, to add the project to the list of daemons it manages. By adding it, it will be automatically started, and will be running when the VPS boots.
sudo supervisorctl update
Once added, the Django project can be managed using these commands:
sudo supervisorctl start django_haxor
sudo supervisorctl stop django_haxor
sudo supervisorctl restart django_haxor
sudo supervisorctl status django_haxor
Nginx Reverse Proxy
When the project is managed and running it can be made available on the internet by using Nginx as a webserver. Nginx will use the socket created by the uWSGI and serve it under the hostname you define.
Start by ensuring you have the uwsgi_params file in the nginx config directory.
uwsgi_param QUERY_STRING $query_string;
uwsgi_param REQUEST_METHOD $request_method;
uwsgi_param CONTENT_TYPE $content_type;
uwsgi_param CONTENT_LENGTH $content_length;
uwsgi_param REQUEST_URI $request_uri;
uwsgi_param PATH_INFO $document_uri;
uwsgi_param DOCUMENT_ROOT $document_root;
uwsgi_param SERVER_PROTOCOL $server_protocol;
uwsgi_param REQUEST_SCHEME $scheme;
uwsgi_param HTTPS $https if_not_empty;
uwsgi_param REMOTE_ADDR $remote_addr;
uwsgi_param REMOTE_PORT $remote_port;
uwsgi_param SERVER_PORT $server_port;
uwsgi_param SERVER_NAME $server_name;
You can then create a basic virtual host config file that connect to the Django app.
sudo vim /etc/nginx/sites-available/django.haxor.no.conf
upstream djangohaxor{
server unix:///var/www/django.haxor.no/djangohaxor.sock;
}
server {
listen 80;
server_name django.haxor.no;
charset utf-8;
# max upload size
client_max_body_size 50M;
location / {
uwsgi_pass djangohaxor;
include uwsgi_params;
}
}
Once created, a symlink has to be made to enable the site.
sudo ln -s /etc/nginx/sites-available/django.haxor.no.conf /etc/nginx/sites-enabled/
Finally, test the config file for syntax errors and restart nginx to start serving the website.
sudo nginx -t
nginx: the configuration file /etc/nginx/nginx.conf syntax is ok
nginx: configuration file /etc/nginx/nginx.conf test is successful
sudo systemctl restart nginx
If you can verify with your browser that you can access your project over HTTP, you can create a TLS certificate and start serving the project on HTTPS by running Certbot.
sudo certbot --nginx -d django.haxor.no
I hope this guide was helpful.