Deploying Python 3 WSGI applications with mod_wsgi
A little while back I wrote a simple Kanban board using Flask. After finally publishing the code, this post is going to look at running Python 3 WSGI applications, like the Kanban board, under Apache using mod_wsgi.
Installing packages
The first thing to do is install Apache and the Python 3 version of mod_wsgi, this can be done with the following command:
apt-get install libapache2-mod-wsgi-py3 apache2
For the example in this post, the WSGI application is going to be downloaded from GitHub, and use a Python 3 virtual environment. Therefore the following packages also need to be installed:
apt-get install python3-venv git
Creating a user account
It's good practise to use a separate user account to run the WSGI application. A user account can be created using useradd:
useradd \
--shell /sbin/nologin \
--create-home \
--home-dir /srv/kanban \
kanban
Note: the shell for the account has been set to /sbin/nologin
to prevent
interactive login sessions.
Cloning the Application
Once the user account is ready the application code can be cloned with a command similar to the following:
sudo -u kanban \
git clone https://github.com/FloatingOctothorpe/python-kanban.git \
/srv/kanban/python-kanban
Note: the command above should be run from a directory the kanban
user
can read (e.g. /
).
For the example in this post, Python modules are going to be installed to a virtual environment. The virtual environment can be created with the following commands:
sudo -u kanban python3 -m venv /srv/kanban/venv
sudo -u kanban bash -c '
source /srv/kanban/venv/bin/activate;
pip install -r /srv/kanban/python-kanban/requirements.txt'
Once the virtual environment has been created, it should be possible to run the
Flask application directly as the kanban
user with a command similar to the
following:
sudo -u kanban bash -c '
source /srv/kanban/venv/bin/activate;
cd /srv/kanban/python-kanban;
FLASK_APP=main.py flask run'
Configuring Apache
Assuming the application runs without a problem the last thing to do is
configure Apache to run the application. This involves creating two files, a
WSGI application script file (/srv/kanban/python-kanban/kanban.wsgi
), and an
Apache config file (/etc/apache2/conf-available/kanban.conf
).
WSGI application script file
For the example in this post, the WSGI application script should contain the following:
#!/usr/bin/env python3
import os
import sys
os.chdir(os.path.dirname(__file__))
sys.path.insert(0, os.path.dirname(__file__))
from main import app as application
Note: os.chdir
and sys.path.insert
are used to make sure the
application's current working directory is /srv/kanban/python-kanban
and code
from the directory can be imported.
Apache config
The Apache config should look similar to the following:
WSGIDaemonProcess kanban user=kanban group=kanban threads=5 python-home=/srv/kanban/venv
WSGIScriptAlias /kanban /srv/kanban/python-kanban/kanban.wsgi
<Directory /srv/kanban/python-kanban/>
WSGIProcessGroup kanban
WSGIApplicationGroup %{GLOBAL}
Require all granted
</Directory>
The first line tells Apache to create a daemon process which will run the Kanban application using the WSGIDaemonProcess directive. The following line uses the WSGIScriptAlias directive to map a URL to the application. Finally the Directory section maps the directory to the process and application groups and grants access to the directory.
Enabling new configuration
Once the WSGI script and Apache config are in place the following commands can be used to pick up the new config:
a2enconf kanban
systemctl reload apache2
If everything goes well there should now be an apache2
process running as the
kanban
user, and the application should be available:
$ pgrep -u kanban -a
5474 /usr/sbin/apache2 -k start
$ curl --head http://localhost/kanban/
HTTP/1.1 200 OK
...
Note: If the http status from curl is not 200, check
/var/log/apache2/error.log
for details.