Setting up your server with apache2 and wsgi

Having designed a portfolio site with django, I never imagined hosting a server would be so annoying and confusing. So here’s absolutely everything you need to know, do and should’nt when setting up your website with apache2 and python framework.

Assumptions

I assume that you have a django website ready. If you don’t, https://docs.djangoproject.com/en/3.0/intro/tutorial01/ is a good place to start. Ill also assume you have a virtual machine in aws and have connected to it through ssh, check https://docs.aws.amazon.com/AWSEC2/latest/UserGuide/AccessingInstancesLinux.html. The server we will be discussing is a ubuntu server, and not windows. Python3 will be used everywhere.

Installing the required

Apache2 is a well tested web server software that can serve your content to users. Some of you might be wondering why use apache when django provides a server on its own. But this server is a test server and cannot be used for deployment. Django is in the business of building frameworks not servers(their words not mine). So we need to use apache to get the most out of our django application and actually host it. A list of applications necessary are,

Before installing anything always make sure all package names are updated using

sudo apt-get update
  • Apache2
sudo apt-get install apache2
  • Apache2-dev
sudo apt-get install apache2-dev
  • pip3
sudo apt-get install python3-pip

pip is a necessary tool for handling python packages. The 3 in python is crucial because all ubuntu systems ship with both python2 and python3 and by default python refers to python2. This will save you a lot of headaches later on in the set up. (It is also recommended that you explicitly use python3 whenever its used from now on)

  • virtualenv
python3 -m pip install virtualenv

Here using virtualenv is advantageous and offers more functionality than using the venv package. It also creates a activate_this.py file which makes it a lot easier to activate the virtual environment. The python3 is necessary everywhere for all this to work smoothly as you never want version mismatch in python.

  • mod_wsgi
python3 -m pip install mod_wsgi

wsgi stands for web server gateway interface, which creates a link between your server hosting application(apache) and your web framework application(django) and allows your app to be served. Although there are a lot of methods to install mod_wsgi and a lot of different standalone wsgi packages, it is recommended that you use pip.

  • Your django application git repo cloned

Get your django application onto github and clone it in your remote machine. from here on, I will refer to this app as thissite with this django structure and its location is probably /home/ubuntu/

thissite/
    mysite/
        manage.py
        mysite/
            __init__.py
            settings.py
            urls.py
            asgi.py
            wsgi.py
        polls/
            __init__.py
            admin.py
            apps.py
            migrations/
                __init__.py
            models.py
            static/
                polls/
                   #staticfiles
            tests.py
            views.py

this should be familiar if you have created a django app or visited the link at the top. and explaining this is not within the scope of this post. we will be dealing with and editing the wsgi.py and the settings.py files only.

  • django

Move into your thissite folder. Here were going to create a virtual environment. This is essential if you want to host multiple sites with the same server. A virtual environment is an isolated space where installing packages wont interfere with other such environments. To create a new environment named myvenv type from within thissite folder

virtualenv myvenv

this creates a new folder named myvenv which we will use to activate and deactivate the environment. To activate the environment,

source mvenv/bin/activate

now install django into your environment with

python3 -m pip install django

Now with everything installed and available we are ready to get into setting up our apache server.

Configuring

The first thing to do is point apache2 to our installed wsgi module. This is done by finding the location where pip has installed the mod_wsgi package

mod_wsgi-express module-config

This outputs the location of the package in the first line.

LoadModule wsgi_module /usr/local/lib/python2.7/site-packages/mod_wsgi/server/mod_wsgi-py36.so
WSGIPythonHome /usr/local/lib

Copy the entire first line (with ctrl+shift+c). Move onto folder , /etc/apache2/mods-available which is where all apache2 modules available for use are present. now create a new file named wsgi.load using your favourite editor. (nano and vi are good options). Then paste the line you copied onto the file and save.

Now that the module is pointed to the right place, in order to enable it use the command

sudo a2enmod wsgi

where sudo is to execute as root user, a2enmod is short for apache2 enable module. next is to restart the apache2 with new configuration.

sudo systemctl restart apache2

If everything went as per plan mod_wsgi is loaded into apache and were good to go. One way to check if wsgi has been loaded is by typing

apache2ctl -M

This gives a list of all loaded modules and the last one will be wsgi. Next step is pointing apache to the django directory and the wsgi.py file inside. This is done by moving into directory /etc/apache2/sites-available and creating a new file named mysite.com.conf (mysite.com is your domain name, that will be used to access your site). Inside this file place the following lines, which ill explain.

<VirtualHost *:80>
        ServerName mysite.com
        ServerAlias www.mysite.com
        ServerAdmin yourmailis@zzz.com

        DocumentRoot /home/ubuntu/thissite

        <Directory /home/ubuntu/thissite>
        Order allow,deny
        Allow from all
        Require all granted
        </Directory>

        Alias /static /home/ubuntu/thissite/mysite/polls/static

        <Directory /home/ubuntu/thissite/mysite/polls>
        order allow,deny
        Allow from all
        Require all granted
        </Directory>

        WSGIDaemonProcess myapp python-path='/home/ubuntu/thissite/myvenv-packages:/home/ubuntu/thissite/mysite'
        WSGIProcessGroup myapp
        WSGIApplicationGroup %{GLOBAL}

        WSGIScriptAlias / /home/ubuntu/thissite/mysite/mysite/wsgi.py
        <Directory /home/ubuntu/thissite/mysite/mysite>
        Order allow,deny
        Allow from all
        Require all granted
        </Directory>

        ErrorLog /var/log/apache2/error.log
</VirtualHost>

This might look like a lot of info but is actually pretty basic when broken down

The first part is where basic server details such as admin mail id and the server name(domain name) are set. The document root directory is the place where apache will look for your website, but be careful not to put any sensitive files here as anyone from the web can access these files if inside the folder, for django you could even point it to an empty folder

The directory tag is how apache is given directions to the folder.

Alias /static is used to give apache the static files for your project so it can serve it directly instead of django.

The last part is where a daemon process is started and is set to use the python virtual environment. This is the recommended way of using modules inside the environment and if you want to host multiple sites.

Finally the WSGIScriptAlias points to the wsgi.py file in your django web application. After all this is set use the command

sudo a2ensite mysite.com
sudo systemctl restart

now everything that needs to be configured in your apache side is done.

The next step is to chang the wsgi.py file in your django application. So move to /home/ubuntu/thissite/mysite/mysite and open wsgi.py file with a text editor.

python_home = '/home/ubuntu/thissite/myvenv'

activate_this = python_home + '/bin/activate_this.py'
exec(open(activate_this).read(),dict(__file__=activate_this))

import os

from django.core.wsgi import get_wsgi_application

os.environ.setdefault('DJANGO_SETTINGS_MODULE', 'portfolio.settings')

application = get_wsgi_application()

The extra bit of code takes advantage of the activate_this file in your virtual environment and activates it from there instead of from apache itself. Which makes it easier to host. The final setting is to change the Settings.py file. add this line at the end of the file.

STATIC_ROOT = '/home/ubuntu/thissite/mysite/polls/static'

and also change ALLOWED_HOSTS to

ALLOWED_HOSTS = ['*']

to allow any ip addresss. Finally assign the domain name to your local ip address by going to /etc and adding the following line to your hosts file

172.17.0.1 mysite.com www.mysite.com

So whenever your server recieves a request for your domain name your local host is actually served.(If youre using a domain name from godaddy or google domains make sure you edit the A files to point to your remote machines external ip. for more details on this visit my previous blog post.)

Now if all went good you should be able to see your beautiful server when you type your domain name. If something unusual happens check your error log file at /var/log/apache2/error.log

Here are all the complete references https://modwsgi.readthedocs.io/en/develop/getting-started.html https://www.shellhacks.com/modwsgi-hello-world-example /https://pypi.org/project/mod-wsgi/

heres my portfolio I built with the same cconfiguration mentioned here, http://ramprakash.blog/

Leave a comment