Setup Django server with Apache virtual host and Python virtual environment
Tags: tutorial, python, django, apache
Published: 2020-09-20 16:06:31

---
title: Setup Django server with Apache virtual host and Python virtual environment
published: true
date: 2020-08-05 16:06:09 UTC
tags: tutorial,python,django,apache
canonical_url: https://medium.com/@victorleungtw/setup-django-server-with-apache-virtual-host-and-python-virtual-environment-2e31f198f3c8
---

It took me a while to get everything works together, so I would like to document some of the steps and save you some time in the future.

First of all, assuming that you already have your CentOS / Ubuntu instance running and python already available. Then create a folder for your project with corresponding permission:

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

You may initiate the project as well if you haven’t already:

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

Then the server can be run via command at port 8000 by default:

```
python manage.py runserver
```

To make your Django server ready for production, you may want to edit the **setting.py** with below settings:

```
DEBUG = False 

ALLOWED\_HOSTS = ['\*'] 

STATIC\_URL = '/static/' 
STATIC\_ROOT = os.path.join(BASE\_DIR, 'static')
```

And you can build the static files with the command below:

```
python manage.py collectstatic --noinput
```

Secondly, serve your web application through the Apache web server. Assuming that you installed apache2 via yum / apt-get package manager, then enable virtual hosts for your project. Create the below file:

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

With 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>
  ServerAlias \*
  WSGIProcessGroup APPNAME
  Alias /robots.txt /opt/yourpath/projects/APPNAME/static/robots.txt
  Alias /favicon.ico /opt/yourpath/projects/APPNAME/static/favicon.ico
  Alias /static/ /opt/yourpath/projects/APPNAME/static/
  <Directory /opt/yourpath/projects/APPNAME/static>
    Require all granted
  </Directory>
  WSGIScriptAlias / /opt/yourpath/projects/APPNAME/APPNAME/wsgi.py
  <Directory /opt/yourpath/projects/APPNAME/APPNAME>
    <Files wsgi.py>
      Require all granted
    </Files>
  </Directory>
</VirtualHost>
```

Remember to replace all the APPNAME above with your Django project name. Then also create one for https:

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

And replace all APPNAME with your project name with below content:

```
<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>
  ServerAlias \*
  SSLEngine on
  SSLCertificateFile "/opt/yourpath/apache2/conf/yourpath/certs/server.crt"
  SSLCertificateKeyFile "/opt/yourpath/apache2/conf/yourpath/certs/server.key"
  WSGIProcessGroup APPNAME
  Alias /robots.txt /opt/yourpath/projects/APPNAME/static/robots.txt
  Alias /favicon.ico /opt/yourpath/projects/APPNAME/static/favicon.ico
  Alias /static/ /opt/yourpath/projects/APPNAME/static/
  <Directory /opt/yourpath/projects/APPNAME/static>
    Require all granted
  </Directory>
  WSGIScriptAlias / /opt/yourpath/projects/APPNAME/APPNAME/wsgi.py
  <Directory /opt/yourpath/projects/APPNAME/APPNAME>
    <Files wsgi.py>
      Require all granted
    </Files>
  </Directory>
</VirtualHost>
```

After you have edit the configuration restart the Apache server. The Django page should now be running.

Last but not the least, we can put all python dependency inside your isolated folder, instead of using the global python path. This would save you a lot of time to resolve those dependency hell problems as well as different Python version issues.

To use the virtualenv tool, simply run below inside your project directory.

```
pip install virtualenv 
virtualenv venv 
source venv/bin/activate
```

This would create a folder which contains all your python executable. Further pip install requirements would be inside this folder instead of the global path. Go back to edit the previous **project-vhost.conf** and **project-https-vhost.conf** , change the third line from:

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

To this:

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

Be careful to point the python home path to the venv folder, instead of the /bin executable nor the python location. Otherwise, you would hit 500 error. In case you can’t figure out the error, such as python dependency issue, you can check the Apache server error log here:

```
tail /opt/yourpath/apache2/logs/error\_log
```

That’s it. Go to your public IP address and you should be able to load the Django page.

P.S. one last tips: if you hit error below at the wsgi:

```
Timeout when reading response headers from daemon process
```

Edit the project-vhost.conf and project-https-vhost..conf, then add this line below the WSGIDaemonProcess:

```
WSGIApplicationGroup %{GLOBAL}
```

Somehow Python C extension modules, like numpy, are known to cause timeouts when used under mod\_wsgi.

_Originally published at_ [_https://victorleungtw.com_](https://victorleungtw.com/setup-django-server-with-apache-virtual-host-and-python-virtual-environment/) _on August 5, 2020._