02 Oct

Setting up Django on WebFaction’s Apache with mod_wsgi

If you want to run a Django application on WebFaction, you may simply use their automatic application creation scripts. Unfortunately, if you want to place your application in a Virtualenv, the automatic installer will not help you. I’m sure that WebFaction will eventually add an installer to set this up, but for now, you can use the following tutorial. In this text we set up a Django project in a Virtualenv running on WebFaction’s Apache with mod_wsgi.

Create a new application

Let’s begin by setting up a generic mod_wsgi application in your WebFaction control panel. Log into the control panel, choose the option to add a new application and specify the following settings:

  • Name: test_app
  • App category: mod_wsgi
  • App type : mod_wsgi 3.4 / Python 2.7

The new application will be created in your home directory (~) under: ~/webapps/test_app.

The directory will contain two subdirectories:

  • apache2 – contains the Apache configuration files (apache2/conf) and scripts which let you control the server (apache2/bin)
  • htdocs – contains default page files.

Configure a new website to hook up your application to a domain. Test the website by visiting it in your browser. You should be greeted by a message beginning with the following text:

Welcome to your mod_wsgi website! It uses: Python 2.7....

If you see the above, then the generic application is set up correctly and we can proceed to turn it into a Virtualenv Django application.

Remove htdocs

The htdocs directory will not be needed, so feel free to remove it.

$ cd ~/webapps/test_app
$ rm -r htdocs

Install Virtualenv

Check if Virtualenv is installed on your server:

$ virtualenv --version
-bash: virtualenv: command not found

If Virtualenv is installed, you will see a version number when running the above command. If it’s missing you’ll see a command not found error message instead.

Steps to install Vitrualenv on a WebFaction server are the following:

$ mkdir -p ~/lib/python2.7/
$ easy_install-2.7 pip
$ pip install virtualenv

If you get an permission denied error try this command to install virtualenv inside your user folder:

$  pip install --user virtualenv

Verify that installation was successful:

$ virtualenv --version
1.10.1

Create a virtual environment

Let’s proceed to turn our application directory into a virtual Python environment:

$ cd ~/webapps/test_app
$ virtualenv .

This adds the folders and scripts for a virtual environment inside of the directory which WebFaction created for our application.

You can now activate the created environment:

$ source bin/activate
(test_app) $

Install Django and other dependencies

Once the initial Virtualenv setup is complete, you can install Django inside it’s lib/python2.7/site-packages directory.

(test_app) $ pip install django

Verify that Django installed correctly:

(test_app) $ django-admin.py --version
1.5.2

Your project will probably depend on other packages. You can install those from a REQUIREMENTS.txt file, which you can generate on your development server with the pip freeze command.

(test_app) $ pip install -r REQUIREMENTS.txt

Start a Django project

Let’s create a new Django project inside the virtual environment:

(test_app) $ django-admin.py startproject test_django

Directory structure

At this stage you should have created a directory structure resembling

this:

~/webapps/test_app
|-- apache2
|   |-- bin
|   |   |-- httpd
|   |   |-- httpd.worker
|   |   |-- restart             <== Scripts which start, stop and restart Apache
|   |   |-- start
|   |   `-- stop
|   |-- conf
|   |   |-- httpd.conf          <== Apache configuration file
|   |   `-- mime.types
|   |-- lib
|   |-- logs                    <== Apache error log is here
|   `-- modules
|-- bin                         <== Virtualenv scipts and binaries
|   |-- activate                <== Virtualenv activation script
|   |-- django-admin.py
|   |-- easy_install
|   |-- easy_install-2.7
|   |-- pip
|   |-- pip-2.7
|   |-- python -> python2.7
|   |-- python2 -> python2.7
|   `-- python2.7
|-- include
|-- lib
|   `-- python2.7
|       `-- site-packages       <== Virtualenv's Python packages directory
`-- test_django                 <== Your Django project directory
    |-- manage.py
    `-- test_django
        |-- __init__.py
        |-- settings.py
        |-- urls.py
        `-- wsgi.py             <== WSGI script file which Apache runs through mod_wsgi

Configure an Apache VirtualHost

We are now ready to configure Apache to serve our Django-powered webapp. In order to do this, we’ll need to modify the contents of the Apache configuration file located under apache2/conf/httpd.conf. Copy the original file to a backup for reference and make a note of the following values:

  • port number on which Apache listens to connections. This value is located in the line with the Listen directive of the original httpd.conf. In the example below we set this to 12345,
  • name of your application (test_app),
  • domain name which your website uses (example.com),
  • complete path to your application’s virtualenv and project directory: /home/my_username/webapps/test_app and /home/my_username/webapps/test_app/test_django,
  • complete path to your application’s WSGI script: /home/my_username/webapps/test_app/test_django/test_django/wsgi.py.

Use these values to customize the configuration template below and save it as your new httpd.conf:

1 import os
2 MEDIA_ROOT = os.path.normpath(os.path.join(os.path.dirname(__file__), '../../media/').replace('\\','/'))
3 STATIC_ROOT = os.path.normpath(os.path.join(os.path.dirname(__file__), '../../static/').replace('\\','/'))

Save the configuration to ~/webapps/test_app/apache2/conf/httpd.conf and restart Apache.

$ ./apache2/bin/restart

Visit your website again and you should be presented with Django congratulating you for setting your server up correctly.

Serving static and media files

The recommended way to serve static and media files on WebFaction is to use Nginx directly.

1   ServerRoot "/home/my_username/webapps/test_app/apache2"
2
3   LoadModule dir_module        modules/mod_dir.so
4   LoadModule env_module        modules/mod_env.so
5   LoadModule log_config_module modules/mod_log_config.so
6   LoadModule mime_module       modules/mod_mime.so
7   LoadModule rewrite_module    modules/mod_rewrite.so
8   LoadModule setenvif_module   modules/mod_setenvif.so
9   LoadModule wsgi_module       modules/mod_wsgi.so
10
11  KeepAlive Off
12  Listen 12345
13  MaxSpareThreads 3
14  MinSpareThreads 1
15  ServerLimit 1
16  SetEnvIf X-Forwarded-SSL on HTTPS=1
17  ThreadsPerChild 5
18
19  WSGIRestrictEmbedded On
20  WSGILazyInitialization On
21
22  NameVirtualHost *
23  <VirtualHost *>
24      ServerName example.com
25
26      # Logging configuration
27      LogFormat "%{X-Forwarded-For}i %l %u %t \"%r\" %>s %b \"%{Referer}i\" \"%{User-Agent}i\"" combined
28      CustomLog /home/my_username/logs/user/access_test_app.log combined
29      ErrorLog /home/my_username/logs/user/error_test_app.log
30
31      # Django WSGI settings
32      WSGIDaemonProcess test_app processes=5 python-path=/home/my_username/webapps/test_app/test_django:/home/my_username/webapps/test_app/lib/python2.7/site-packages:/home/my_username/webapps/test_app/lib/python2.7 threads=1
33      WSGIProcessGroup test_app
34      WSGIScriptAlias / /home/my_username/webapps/test_app/test_django/test_django/wsgi.py
35  </VirtualHost>

Let’s begin by creating the directories for static and media files.

$ cd ~/webapps/test_app
$ mkdir media static

In order to tell Django where the files should be stored, we should place the appropriate lines in the project’s settings.py file. I like to keep the location of media and static folders relative to the source code project, so I would set them in this way:

1   import os
2   MEDIA_ROOT = os.path.normpath(os.path.join(os.path.dirname(__file__), '../../media/').replace('\\','/'))
3   STATIC_ROOT = os.path.normpath(os.path.join(os.path.dirname(__file__), '../../static/').replace('\\','/'))

Let’s collect the static files from all applications to the static directory:

$ cd ~/webapps/test_app
$ source bin/activate
(test_app) $ cd test_app
(test_app) $ python manage.py collecstatic

We can now serve our static files. In the WebFaction control panel, add two new applications named test_app_media and test_app_static. Both will be defined using these settings:

  • App category: Symbolic link
  • App type: Symbolic link to static-only app
  • Extra info: the path to the file folder, i.e. /home/my_username/webapps/test_app/media or /home/my_username/webapps/test_app/static

The final step is to add these Nginx-powered folders to our website definition. On the website settings screen for your domain, in the Contents section, choose to add an application. Choose the option to reuse an existing application and set the test_app_media to serve everything under http://example.com/media and test_app_static for http://example.com/static.

webfaction-website-content

Contents section of website settings

Separating development and production settings

You will want to use slightly different settings for your development and production environments. In order to separate them you can create three separate settings files:

  • settings.py – global settings, which apply to both environments
  • settings_dev.py – your development environment specific settings
  • settings_prod.py – production environment specific settings

The settings_prod.py file should only contain the settings which are specific to this environment, but also import all the global settings. We can do this by importing global settings like this:

1   from .settings import *
2
3   # Define production-specific settings
4   DEBUG = False
5   TEMPLATE_DEBUG = DEBUG
6
7   DATABASES = {
8   # ... production server database settings ...
9   }

Django checks the environment variable named DJANGO_SETTINGS_MODULE to determine which settings file to use. If this environment variable is undefined, it will fall back to test_app.settings.

In order to use your new settings module in the shell, we can add a line to the end of the script which activates our virtual environment (bin/activate).

export DJANGO_SETTINGS_MODULE=test_app.settings_prod

Apache and mod_wsgi don’t know about our new settings yet. We can set the DJANGO_SETTINGS_MODULE dynamically inside the wsgi.py script. Create a wsgi_prod.py script which will contain the following:

1   import os
2   os.environ.setdefault("DJANGO_SETTINGS_MODULE", "test_app.settings_prod")
3   from django.core.wsgi import get_wsgi_application
4   application = get_wsgi_application()

Now instruct Apache to use this WSGI script by setting the WSGIScriptAlias directive line to:

1   WSGIScriptAlias / /home/my_username/webapps/test_app/test_django/test_django/wsgi_prod.py

Restart Apache and your application should run with production settings applied.

23 Jul

Deploying a Flask Project on WebFaction with Git [UPDATED]

I found it tedious having to redo the setup of my application on WebFaction whenever there is a new update of the application. I started looking for way to update the content of the application, without affecting the setup configurations of the application on WebFaction.
Step 1: Add your site to Your WebFaction Account
From your WebFaction console:
1.       Log into your WebFaction Console
2.       Go to your “Websites” tab, click the “Add New Website” button
3.      Enter the website name and domains as needed for your project
4.      Under the Contents section, choose Add an Application > Create a New Application
1.      Name to “myapp” 
2.      Set App Category to “mod_wsgi”
3.      App Type should be the most recent version of mod_wsgi that supports your Python version. Make sure that your Python version matches with your mod_wsgi choice ( “mod_wsgi 3.5/Python 2.7″ for this guide).
4.      Click the Save button to add that application
5.      Click the Save button to save your website
Now your WebFaction account should have a new domain, website, and mod_wsgi application.
Step 2: SSH into your new application
First, you’ll need to SSH into your webfaction account. Once you’re there, cd into your newly created application:
cd ~/webapps/myapp
In this directory, you’ll see two folders:
– apache2/      # This contains all of your Apache config and action files
– htdocs/       # This is the folder Apache to launch your project

Step 3: Upload your Flask project using Git

Upload the project/ folder to the application directory using Git. “myapp” directory is created

git clone https://username@bitbucket.org/uobis0/myapp.git

All following instructions will assume you’re still in this directory.

 virtualenv venv --python=python2.7
$ . venv/bin/activate
$ easy_install-2.7 flask    # Installs flask package for the app
$ pip install -r /myapp/app/requirements.txt  # Installs the packages for the app
$ deactivate

Now, my ~/webapps/myapp directory list looks like the following:

drwxr-xr-x 7 uobis uobis 4096 Nov 11 14:29 apache2/
drwxrwxr-x 5 uobis uobis 4096 Nov 11 14:40 venv/
drwxrwxr-x 6 uobis uobis 4096 Nov 14 16:46 myapp/
drwxr-xr-x 2 uobis uobis 4096 Nov 11 14:29 htdocs/
-rw-rw-r-- 1 uobis uobis 292 Nov 18 15:14 wsgi.py

Step 4: Edit apache2/conf/httpd.conf

Using your favorite command line editor, open up the apache2/conf/httpd.conf file:

vim ~/webapps/myapp/apache2/conf/httpd.conf

Load Alias module (optional)

You’ll see a section where Apache Modules are being loaded. I had to manually add the Alias module to the bottom of the list (shown below).

.
.
LoadModule wsgi_module       modules/mod_wsgi.so
LoadModule alias_module      modules/mod_alias.so    #Your version of mod_wsgi might not need to add this.

Modify Alias and <Directory>

Add the following parameters to your <Directory> section:

WSGIScriptAlias / /home/username/webapps/myapp/wsgi.py

<Directory /home/username/webapps/myapp/htdocs>
    AddHandler wsgi-script .py
    RewriteEngine on
    RewriteBase /
    WSGIScriptReloading On
</Directory>

Now for the final edit of the config file.

Step 5: Make sure your main file is right 

Ensure that, if your structure is package, your project’s __init__.py file is launching your Flask application. This is what the file at ~/webapps/myapp/app/__init__.py should look like:

from flask import Flask

# Setting up the App
app = Flask(__name__)
app.config.from_object('config')

# Importing the views for the rest of our site
from app import views

if __name__ == '__main__':
    app.run()

If you are using modules, the files should contain the app instantiation

app = Flask(__name__)

This will work nicely with our wsgi.py file, which we’ll set up next.

Step 6: Modify the htdocs/wsgi.py file

WebFaction should have created this file. In it are a few scripts, but you can completely remove those. Here is what the ~/webapps/myapp/wsgi.py file should contain:

import sys

# Active your Virtual Environment, which I'm assuming you've already setup
activate_this='/home/username/webapps/myapp/venv/bin/activate_this.py'
execfile(activate_this, dict(__file__=activate_this))

# Appending our Flask project files
sys.path.append('/home/username/webapps/myapp/myapp')

# Launching our app
from main import app as application

 

Step 7: Restart Apache

The last step will be to restart apache, like so:
~/webapps/myapp/apache2/bin/restart

 

Troubleshooting

If you’re having trouble, take a look at your logs in the ~/logs/users/ directory.

Application Updates

The steps above makes updates very easy:
cd ~/webapps/myapp/myapp
git pull https://username@bitbucket.org/accout/myapp.git

~/webapps/myapp/apache2/bin/restart