Set Up a Django Server with Apache Virtual Host and Python Virtual Environment

August 05, 2020

It took me some time to get everything working together, so I'd like to document the steps to save you time in the future.

2020 08 06

Firstly, assume that you already have your CentOS/Ubuntu instance running and Python installed. Create a folder for your project and set the appropriate permissions:

    sudo mkdir /opt/yourpath/projects
    sudo chown $USER /opt/yourpath/projects

If you haven't already initialized your project, you can do so with:

    python -m pip install Django
    django-admin startproject APPNAME /opt/yourpath/projects/APPNAME

By default, the server runs on port 8000:

    python manage.py runserver

To prepare your Django server for production, edit the settings.py file with the following settings:

    DEBUG = False
    ALLOWED_HOSTS = ['*']
    STATIC_URL = '/static/'
    STATIC_ROOT = os.path.join(BASE_DIR, 'static')

Then, you can build the static files using:

    python manage.py collectstatic --noinput

Next, serve your web application via the Apache web server. Assuming you installed Apache2 through yum or apt-get, enable virtual hosts for your project and create the following file:

    touch /opt/yourpath/apache2/conf/vhosts/project-vhost.conf

With the content below:

    <IfDefine !IS_APPNAME_LOADED>
      Define IS_APPNAME_LOADED
      WSGIDaemonProcess APPNAME python-home=/opt/yourpath/python python-path=/opt/yourpath/projects/APPNAME
    </IfDefine>
    <VirtualHost 127.0.0.1:80 _default_:80>
    ...

Remember to replace all instances of APPNAME with your Django project name. Then, create another file for HTTPS:

    touch /opt/yourpath/apache2/conf/vhosts/project-https-vhost.conf

And populate it with similar content, replacing APPNAME as appropriate.

After updating the configurations, restart the Apache server. Your Django site should now be operational.

Lastly, isolate Python dependencies within a virtual environment to avoid dependency issues and version conflicts. Inside your project directory, run:

    pip install virtualenv
    virtualenv venv
    source venv/bin/activate

This creates a folder containing all your Python executables. Subsequent pip install commands will affect only this folder. Now, go back and edit project-vhost.conf and project-https-vhost.conf, changing the python-home path to point to the venv folder:

From:

    WSGIDaemonProcess APPNAME python-home=/opt/yourpath/python python-path=/opt/yourpath/projects/APPNAME

To:

    WSGIDaemonProcess APPNAME python-home=/opt/yourpath/projects/APPNAME/venv python-path=/opt/yourpath/projects/APPNAME

Be sure to point the Python home path to the venv folder, not to the /bin executable or the Python location, to avoid a 500 error. If you encounter issues, check the Apache server error log:

    tail /opt/yourpath/apache2/logs/error_log

That's it! Navigate to your public IP address, and you should see your Django page.

P.S. If you encounter a timeout error at the WSGI level:

    Timeout when reading response headers from daemon process

Edit project-vhost.conf and project-https-vhost.conf to add the following line below WSGIDaemonProcess:

    WSGIApplicationGroup %{GLOBAL}

This addition can resolve timeouts caused by Python C extension modules, such as NumPy.


Profile picture

Victor Leung, who blog about business, technology and personal development. Happy to connect on LinkedIn