All Unkept
Posted in: Python, Django  —  April 01, 2013 at 06:24 PM

Best practices with Django on WebFaction

by Luke Plant

This blog post is about deploying Django apps. It is addressed primarily to WebFaction, but applies to any other hosts else with one-click installers for this kind of app.

First, many thanks to WebFaction for their great service and support. I've got very few complaints about them in general.

However, I think their approach to setting up Django projects is far from ideal, and makes life harder than it needs to be.

The WebFaction Django docs tell us to create a new Django app by using the control panel and choosing an app of type ‘Django’ and then choosing your Django version. This will install an Apache instance with mod_wsgi, and a copy of the Django sources, and set up a basic Django app skeleton.

There are lots of problems with this:

  1. What happens when there is a security issue with Django?

    The user will need to have an upgrade mechanism. This is covered in the docs, but it is an 11 step process.

    And this process is a process they will first have to do in their development environment for testing, in some way, and then again on their live box. How many people will actually do that, especially for security releases that they don't feel they need?

    Experienced developers, of course, don't do this. For Django, I've used virtualenv and pip, and removed the existing copy of Django that WebFaction put there. Of course, I needed to use virtualenv and pip anyway, and so will 99% of all Django users. So my upgrade procedure for Django, like for any dependency, looks like this:

    1. Edit requirements.txt
    2. $ pip install -r requirements.txt
    3. Test and fix - automated or manual etc.
    4. Check in the changes to source control.
    5. $ fab deploy

    Note that this includes local upgrade as well as remote. It is much, much easier and much less error prone than the process WebFaction describes.

  2. It uses an Apache instance.

    Apache is a massive overkill for this kind of thing. Just figuring out the mod_wsgi settings for threads and processes nearly made my head explode, and I'm a reasonably experienced web developer.

    Most experienced Django developers are not recommending Apache. They use gunicorn or uWSGI or similar.

    And what happens if there is a security issue with the Apache version installed? Would users get any notifcation of this? How would they upgrade Apache? I have no idea—I know how to compile Apache from source, but I've no idea what compilation settings WebFaction uses etc. So far the only solution I've come up with to this worry is to migrate my projects to gunicorn.

  3. It goes against the grain of how people will want to upload their apps.

    New Django developers will follow the tutorial, or something similar like a django-cms setup guide, so that when they first come to deploy their app they will have a working app, with settings file etc. that they just want to deploy.

    Experienced Django developers will not be following a tutorial, but will have a very similar set of files that they want to upload.

    They will not start with a settings file or project layout generated by WebFaction. That is just a confusion that gets in the way.

    Rather, they will want to customise their settings.py file, or create a new one for deployment, and insert into it the database settings, and maybe a few other tweaks.

    Then they will simply want to upload it, including a requirements.txt file, and have it run.

As a contrast to the process WebFaction have documented, here is my process for deploying a new app on WebFaction:

  • On WebFaction control panel, set up:
    • a 'Custom app (listening on port)' application
    • a static-only app for static assets
    • a static-only app for user uploaded media
    • a database

(I've actually got a script that automates this, but that's another matter).

  • In my project sources:
    • copy the database details to a settings.py file
    • update some paths in my fabfile.py
    • check in to VCS
    • $ fab deploy
  • On my WebFaction server, I setup a crontab command that runs gunicorn if it is not running. (This command actually calls a command in fabfile.py, which has been uploaded to the server).

To upgrade Django or any other dependency, including gunicorn, I do:

  • Edit requirements.txt
  • Check in to VCS
  • $ fab deploy

For initial setup, this is easier than the process WebFaction have documented. For upgrades, it is much easier. As an experienced developer, I'm happy writing this myself, and I've got some template fabfile.py files I can use for new projects.

But newbies get the much harder processes, and they are still left with big hurdles when it comes to:

  • uploading their own code
  • adding dependencies
  • upgrading dependencies

The ‘one-click installers’ WebFaction features sound great in theory, but in practice they are doing their users a disservice. Please give us, and especially newbies, a method that we will want to use long term.

Designing such a method is hard, and will probably involve a set of instructions rather than a ‘one-click’ experience, especially when different Django developers do things different ways. But newbies often don't have opinions like experienced developers do, and, as long as the process allows customisation, experienced developers will be able to customise it. IMO, the default process should leave newbies with a setup that encourages the following best practices and de-facto standards:

  • virtualenv and pip
  • gunicorn (or alternative, or at least something that can be upgraded easily)
  • fabric (or alternative, but should be mainly Python or shell commands, so an experienced developer can customise)
  • ./manage.py collectstatic
  • VCS - Mercurial or Git or (Please don't make it force one or another)
  • settings.py

I have a starter fabfile.py I used a while back, and have tried to update according to the way I now use gunicorn. It isn't properly tested in its own right, but it could be a useful starting point.

Perhaps one approach is to have a public repository (mirrored in different popular VCS systems), which includes some basic files (requirements.txt, fabfile.py, settings_webfaction.py, wsgi.py) that can be merged into a developer's project sources. Picky developers can override what they want, but newbies will have something that works well.

With that kind of process, I'd feel happy to recommend Django newbies to use WebFaction. At the moment, I could only recommend experienced developers to use it for Django deployments, and tell them to ignore WebFaction's own docs about deployment.

Comments §

blog comments powered by Disqus