Fabric file and related resources for deploying a Mezzanine project to a Webfaction shared hosting account.
deploy/to your Mezzanine project folder, replacing them if they already exist.
- Right after all the imports in
fabfile.py(line 27), substitute your project name in the call to
real_project_name(). This corresponds with the "inner" project folder, where your
- Configure the contents of the
FABRICdictionary in your
local_settings.pyas shown in
fabsettings.py. Lines that are commented out are optional. Don't forget to set
ALLOWED_HOSTSto the value it should have in production.
In your dev machine
- Mezzanine (4+)
- Django (1.7+)
- A git/mercurial repo with your project files (optional)
- A pip requirements file
In your Webfaction account
- Git app (optional)
Note: this script can install the server pre-requisites for you.
- To start, we assume you have a working Mezzanine project with Fabric
installed in your virtualenv. Your
local_settings.pyshould have all your Webfaction details filled in the
FABRICdictionary. From here on, all commands are run from the project root in your local machine.
fab installto install all pre-requisites and prepare your Webfaction account for hosting your projects. You only need to run this task once for each account. All subsequent projects deployed to the same server can skip this step.
fab deployto create your project in your Webfaction server and upload the latest version. Boom! Your site is live. Visit it in your browser.
- Subsequent deployments can be done with
- If you want to wipe out all traces of the project in your server, you can
fab remove. The prerequistes will persist.
- Get a list of all available tasks with
How is this different from the default Mezzanine fabfile?
This fabfile is based on the one provided by Mezzanine, but includes several tweaks to make it work in a shared hosting environment.
sudois never used since Webfaction accounts don't have this privilege.
- The Webfaction API is used heavily to fully automate the deployment. This includes creating domain and site records, apps, databases and cronjobs.
- The server-wide Nginx installation is used via a static app, instead of defining custom Nginx config files.
Deploying with Fabric has several advantages over the method provided by Webfaction:
- Fully automated. No need to login to the control panel at all. This was the main reason I created this fabfile, to speed up the transition from development to production on my client's projects.
- Uses Gunicorn as the application server instead of Apache.
- Installs everything according to Django best practices, instead of creating a Django App in the control panel which is hard to mantain up to date.
- Automates the installation of requirements, running of migrations, and database and static files backups.
- Uses supervisor for managing processes, wich is tidier than a cronjob for each Apache instance.
Why am I being prompted for a bunch of passwords when doing
This is largely because Fabric cannot "fake" password input for you. This is a list of common passwords you will be asked for, and some alternatives to get rid of them:
- SSH password: You might see a prompt like
Password for email@example.com. This is a prompt for the SSH password for your Webfaction server. It is stored in
local_settings.FABRIC["SSH_PASS"]. You can get rid of the prompt by using key-based authentication.
- Remote database password: As the name implies, this is the password for
the database in your Webfaction server. You can find it in
local_settings.FABRIC["DB_PASS"]. You can get rid of the prompt by creating a .pgpass file in the server.
- Local database password: The same as the previous one, but for your local
machine. This is stored in
local_settings.DATABASES["default"]["PASSWORD"]. You can also create a
.pgpassfile for your computer to get rid of the prompt.
How come I'm seeing several gunicorn processes running for each Mezzanine project?
Gunicorn uses a master process and a configurable number of worker processes to
serve a site. The Gunicorn docs recommend this number should depend on the
amount of processor cores, however, in my tests with my 16-core Webfaction
server this results in 33 processes, which quickly eats all my RAM. I recommend
you use anything from 2 to 6 workers for your projects. You can tweak this in
NUM_WORKERS setting in the
FABRIC dictionary of your
and doing a deploy to apply the changes.
I received an email from Webfaction saying that my resource usage is over limit. Why?
Your Webfaction hosting account has a limit on the amount of CPU and RAM you
can use. If by some reason your Mezzanine site is over that limit, you will
receive a warning for you to reduce the resource usage. Most of the time, this
means reducing the number of gunicorn worker processes. You can do this in the
FABRIC section of
local_settings.py, by setting
NUM_WORKERS to something
like 1 or 2 and doing a new deployment.
Webfaction killed my processes for resource overuse, now my site is down!
This means your usage was WAY over limit, and Webfaction killed your processes to immediately reduce your resource consumption. In order to bring your sites back up, you need to do the following:
- Consider reducing the amount of gunicorn workers, as explained in the previous point.
- SSH into your Webfaction account and restart supervisor:
supervisord -c ~/etc/supervisord.conf.
- Also restart memcached:
memcached -d -m 50 -s ~/memcached.sock -P ~/memcached.pid.
Webfaction experienced an outage / rebooted my server and my site is down!
You can partially mitigate this by periodically starting
memcache via a cronjob. You can also set the cronjob to be executed on
server reboot only:
# cron jobs @reboot ~/bin/supervisord -c ~/etc/supervisord.conf @reboot memcached -d -m 50 -s ~/memcached.sock -P ~/memcached.pid
There's an edge case with this approach: Gunicorn's PID file could potentially
gunicorn from starting again if it stores a PID it can't kill. This
might be the case after a server reboot, where the PID file would keep the old
gunicorn would try to kill it before starting again. You can get
around this by deleting all
gunicorn.pid files after a reboot.
# Add to your crontab BEFORE the line that starts supervisord @reboot find ~/webapps -maxdepth 2 -type f -name gunicorn.pid -delete
Why are you using a symlink to a static/php app instead of one to a static-only app?
Because by doing so you can specify expiration dates for static assets in
.htaccess in your root static directory. This prevents browsers from
requesting all your assets every time. Rationale, Question in QA site. You
can change the static app from
symlink_static_only if you
What exactly is the fabfile doing?
I recommend you take a look into the source to wrap your head around each task, but here is a quick run through them:
- If you use
fab installit will install and configure all pre- requesites. This includes setting up an account-level pip, virtualenv and supervisor installation. A supervisord conf file is created and memcached is started with an allocation of 50 Mb. If you're using git, a git application named
git_appis created in
~/webapps/git_app. All repos will live in there.
- A full project setup with
fab deploywill create a new virtualenv in the Webfaction server, create a site, database, a custom app, and a static app with the Webfaction API, and install all your project dependencies in the venv. It will create a site record in the project DB and a superuser if you define
- Afte the first time,
fab deploypushes all your changes to the server, collect's static files and restart's the gunicorn process via supervisor.
The fabfile comes with a few extra goodies not found in Mezzanine by default:
Sync the local database with the remote database
Local database must also be postgres.
fab pulldb # Download the remote DB and restore it locally fab pushdb # Upload the local DB and restore it remotely
Sync the local user-uploaded media with the server
fab pullmedia # Download the remote media files into the local project fab pushmedia # Upload the local media files into the remote project
Setup a cronjob to poll Twitter
Make sure you define
TWITTER_PERIOD in your deploy settings first.
Setup a mailbox to send emails from your server
This allows you to receive tracebacks if something goes wrong (if you add
yourself to the ADMINS setting), and make the contact forms actually send
notification emails. Make sure you have defined the three email settings in
FABRIC dictionary. You can fill these settings however you like, Fabric
will create the mailbox via the Webfaction API and hook your site to it. For example:
# in your FABRIC settings... "EMAIL_USER": "mezzanine", # Whatever you like "EMAIL_PASS": "mezzanine", # Whatever you like "DEFAULT_EMAIL": "firstname.lastname@example.org", # Use your Webfaction username
fab setup_email fab deploy
Known issues (please contribute!)
- Tested only with Python 2.7, Django 1.7-1.8, and Mezzanine 4.
- No support for MySQL.
- You can only deploy to one Webfaction server.