How To Serve Django python Applications with Apache and mod_wsgi on Ubuntu 20 LTS with virtualenv

Best way for stability is direct web server without running extra software layers. No virtualization and containers whatsoever. But as an application is already quite elderly and not using latest versions of python. It can be complicated to install directly on the server. I am giving an example of a working setup and number of attempts that ended with failure. I repeat for me the recent versions of python3 Django and postgres and elastic work best directly on the server without virtualization. This method is only published for information for the old version of the application where only the hardware layer needs to be updated and no software upgrade is desired.

Environment setup example.


import os

import sys

import site



os.environ["DJANGO_SETTINGS_MODULE"] = "jobfor.settings.settings"


execfile(activate_env, dict(__file__=activate_env))

#from raven.contrib.django.raven_compat.middleware.wsgi import Sentry

from django.core.wsgi import get_wsgi_application

#application = Sentry(get_wsgi_application())

application = get_wsgi_application()
Test performance with

apt-get install apache2-utils

apt-get install libapache2-mod-wsgi-py3

If you need configuration of static files and / or upload to media

ls -al /var/www/

chgrp -R www-data vindazo_de/

chmod -R g+w vindazo_de/

Example apache2 config

Working example

vim /etc/apache2/sites-enabled/000-default.conf

        LogLevel warn
        ErrorLog /var/log/apache2/
        CustomLog /var/log/apache2/ combined
        LimitRequestBody 5120000

        WSGIDaemonProcess processes=10 threads=10 python-path=/home/admin/auto-tweedehands/impex/ display-name=%{GROUP}
        WSGIScriptAlias / /home/admin/auto-tweedehands/impex/impex/

        <Directory /home/admin/auto-tweedehands/impex/>
                Require all granted

        Alias /media/ /home/admin/auto-tweedehands/media/
        <Location "/media">
                SetHandler None
                Options -Indexes
                AddType text/html php
                #AllowOverride None

        Alias /static/ /home/admin/auto-tweedehands/static/
        <Location "/static">
                SetHandler None
                Options -Indexes
                AddType text/html php
                #AllowOverride None

ErrorLog /var/log/apache2/vindazo_de_http_error.log
LogLevel warn
CustomLog /var/log/apache2/vindazo_de_http_custom.log combined

LimitRequestBody 5120000
WSGIDaemonProcess processes=100 threads=100 maximum-requests=100000 display-name=%{GROUP}
WSGIScriptAlias / /home/sites/development/de_vindazo/jobfor/

Alias /media/ /var/www/vindazo_de/media/
<Location "/media">
SetHandler None
Options -Indexes
AddType text/html php
#AllowOverride None

Alias /static/ /var/www/vindazo_de/static/
<Location "/static">
SetHandler None
Options -Indexes
AddType text/html php
#AllowOverride None

Install Apache modules

a2enmod headers

a2enmod expires

a2enmod rewrite

a2enmod ssl

systemctl restart apache2

Apache mod_wsgi without VirtualEnvirment and dockers

When you have decided to web server on Ubuntu without dockers en without VirtualEnvirment.

You can try but with me it has not worked recently because python 3 and python 2.7 could not run at the same time. While the method itself can be useful in some cases. Still, this method is only recommended with python and all recent Django and postgres packges.

Create requirements file

pip freeze > requirements-13-04-2021.txt

Copy all directories to new server development and deployment

apt-get update

apt install python2

apt-get install vim

curl --output


pip2 install -U pip setuptools wheel

Install all required package from requirements.xt

some problems with install

pip2 install blis==0.7.4



De-core-news-lg ( spacy )








I did not install these packages. I get an error from pip..

Then have installed the Dev version with gcc.

apt-get install python2-dev

apt install build-essential

After that all packages are installed.

Depending on the

pip2 install idna==2.10

pip2 install oauthlib==3.1.0


pip2 install psycopg2==2.6

pip2 install psycopg2==2.7

And problem with binary import error ( Problem loading psycopg2 with glibc 2.26, version GLIBC_PRIVATE psycopg2)

pip2 install psycopg2-binary

Then problem with

Could not run curl-config: [Errno 2] No such file or directory

Fix it with

apt install libcurl4-openssl-dev libssl-dev

Ok, about 1 hour to install django and all packages.

Tomorrow I will run a server.. In development mode and move apache configs and install memcached and Elasticsearch.

Apache configuration

apt install apache2

apt-get install libapache2-mod-wsgi


You don't have permission to access this resource.

Apache/2.4.41 (Ubuntu) Server at Port 80

vim /etc/apache2/apache2.conf


Require all granted


vim jobfor/


When I have added it in the path and all not helped. This error says that django is not installed and. It looks in default directory of operating system and its python3

ImportError: No module named django.core.wsgi


indicate to Python when it is initialised where its library files are installed

>>> sys.path

['', '/usr/lib/python2.7', '/usr/lib/python2.7/plat-x86_64-linux-gnu', '/usr/lib/python2.7/lib-tk', '/usr/lib/python2.7/lib-old', '/usr/lib/python2.7/lib-dynload', '/usr/local/lib/python2.7/dist-packages', '/usr/lib/python2.7/dist-packages']

Crashed and unable to run mod_wsgi with python2

If they had activated the Python 3 virtual environment and its bin directory was in there path, then likely they could simply run 'pip' rather than 'pip3'. You should run 'which pip' to verify whether it was coming from the virtual environment you expect.

The 'mod_wsgi-httpd' package is specifically for installing a distinct instance of Apache itself to get around issues where the system wide Apache is out of date or missing development header files, or otherwise can't modify the system wide configuration. It is generally of more relevance when you don't have root access to fix system wide issues and are only interested in running on an unprivileged port and so do not need root access. You would also have to be using 'mod_wsgi-express' from the 'mod_wsgi' package which was 'pip' installed after 'mod_wsgi-httpd' had been installed as that is the only way to use 'mod_wsgi-httpd' installed version of Apache.

So, for 'mod_wsgi-httpd' you would really want to ignore it. If you have already installed it, then 'pip' uninstall both it and 'mod_wsgi'. The latter needs to be uninstalled as it will be bound to the 'mod_wsgi-httpd' Apache version and the '' will not work with the system wide.

As to separate users steps in link, they look correct, although I would say that in step 3, it should be highlighted that the LoadModule and WSGIPythonHome lines to be added are what is output when running mod_wsgi-express install-module command. What are output is customised to match what your installation should be. So don't make up values, just use what that command output.

If you have a wsgi.load file still around, run sudo a2dismod wsgi to get rid of it or otherwise manually remove it. It is a left over from old system packaged mod_wsgi.

Non standard Apache installations

Connecting into Apache installation

mod_wsgi-express module-config