Deploying Django with uWSGI
Date: 2024-12-19
Category: Tutorial
I've been playing with Django recently, and as such I needed to look into deploying these sites. I picked uWSGI because it seemed like the easyest way to do so.
Installing uWSGI
There are two ways you can install uWSGI: From source, and as a system package. The documentation recomends to start with the source distribution, as each distribution might use a slightly difirent layout for configuration, this is what I'll use.
First, download the latest version of uWSGI from the official site to a location on your server (for example /usr/src)
cd /usr/src
wget https://files.pythonhosted.org/packages/24/c2/d58480aadc9a1f420dd96fc43cf0dcd8cb5ededb95cab53743529c23b6cd/uwsgi-2.0.28.tar.gz
tar xzf uwsgi-2.0.28.tar.gz
cd uwsgi-2.0.28/
Next, we'll need to install some basic dependencies and run the compilation
sudo apt install build-essential python3-dev
make
The compilation will take about 30 seconds, and will produce a binary called uwsgi
in the current directory. Copy uwsgi to /usr/local/bin
.
cp uwsgi /usr/local/bin/
Creating the uWSGI service
Next, we need to to create a service file, I want to run multiple sites so I'll use uwsgi's emperor mode. Create the file /etc/systemd/system/emperor.uwsgi.service
and place the following inside it:
[Unit]
Description=uWSGI Emperor
[Service]
ExecStart=/usr/local/bin/uwsgi --ini /etc/uwsgi/emperor.ini
RuntimeDirectory=uwsgi
Restart=always
KillSignal=SIGQUIT
Type=notify
StandardError=syslog
NotifyAccess=all
[Install]
WantedBy=multi-user.target
Next, create the directory to house the configuration files
mkdir -p /etc/uwsgi/vassals
create /etc/uwsgi/emperor.ini
and place the following content inside it
[uwsgi]
emperor = /etc/uwsgi/vassals
Where uid/gid are the uid/gid of the user you want to run your apps as.
Next, create the file for your app, for example /etc/uwsgi/vassals/vincent-blog.ini
:
[uwsgi]
chdir=/var/www/vincent-blog/
module=mysite.wsgi:application
socket=/run/uwsgi-vincent-blog.sock
workers=2
harakiri=30
max-requests=5000
vacuum=true
home=/var/www/vincent-blog/.venv
uid=vincent
gid=vincent
chown-socket=www-data:www-data
- chdir means it will change directory to the application directory
- module is the module we want to run
- socket means it will open a uwsgi socket at localhost:3030, we will configure apache to point to this TCP socket.
- workers is the number of workers, a good value is the number of cores of your machine
- harakiri means processes longer than 30 seconds will be terminated (this prevents a runaway script from hanging
- max-requets means a worker will be respawned after 5000 requests
- home is the virtual environment of the application
Configuring our webserver
Nginx
With Nginx, you only need to add the following to your server block
location /media/ {
root /path/to/media
}
location /static/ {
root /path/to/static
}
location / {
uwsgi_pass unix:///run/uwsgi-vincent-blog.sock;
include uwsgi_params;
}
Apache
In Apache, you can enable mod_proxy
and mod_proxy_uwsgi
like so:
sudo a2enmod proxy proxy_uwsgi
Then add the following to your vhost
# ...
Alias /static /var/www/vincent-blog/staticfiles
Alias /media /var/www/vincent-blog/media
ProxyPass "/static" !
ProxyPass "/media" !
ProxyPreserveHost On
ProxyPass "/" "unix:/run/uwsgi-vincent-blog.sock|uwsgi://localhost:3030/"
# ...
Then restart apache and your site should be up.