Flask on Apache with mod_wsgi


Nowadays making a proxy from an nginx to a gunicorn socket running on supervisor or systemd makes things so easier that most of us even forgot how deployment was before. Recently I was asked to deploy a flask application on already working Apache2 instance. In this blog post I will describe steps and problems using mod_wsgi on Apache.

First of all, install python, pip and mod_wsgi: apt install python3-dev python3-pip libapache2-mod-wsgi

Restart apache2 service and verify that wsgi module is loaded: sudo apache2ctl -M|grep -i wsgi

Create a projectname.wsgi file in your project:

import sys
sys.path.insert(0, '/path/to/project')

from app import app as application
application.root_path = '/path/to/project'

The first thing will add your python files to the python path, that is needed to find the app.py file (where your flask app is located). The second part will tell the application where the root is, it is required for loading templates.

Create a configuration file (projectname.conf - .conf extension is required for the new version of Apache) for your project under /etc/apache2/sites-available:

<VirtualHost *:<PORT>>
   ServerName <DOMAIN.NAME>
   WSGIDaemonProcess <projectname> user=<user> group=www-data threads=2
   WSGIScriptAlias / /path/to/project/projectname.wsgi
<Directory /path/to/project>
     WSGIProcessGroup <projectname>
     WSGIApplicationGroup %{GLOBAL}
     Order deny,allow
     Allow from all
   Alias "/static/" "/path/to/project/static/"
   <Directory /path/to/project/static/>
     Order allow,deny
     Allow from all
   ErrorLog /path/to/logs/error.log
   CustomLog /path/to/logs/access.log combined

Link the configuration file to the enabled folder:

cd ../sites-enabled & ln -s ../sites-available/projectname.conf projectname.conf.

Reload apache2 service and check if the website is online.

Most notable difference between gunicorn is that you will not be able to open files from the relative path. You can use current_app.root_path to access path and it is true for all plugins too (in my case, one of the plugins was storing a session file in the project root). Also defining PROJECT_ROOT can be helpful: PROJECT_ROOT = os.path.dirname(os.path.abspath(__file__))

Currently unrated


There are currently no comments

New Comment


required (not published)