This repo has been archived as Webfaction has gone out of business.
Fabric file and related resources for deploying a Mezzanine project to a Webfaction shared hosting account.
- Copy
fabfile.py, anddeploy/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 toreal_project_name(). This corresponds with the "inner" project folder, where yourlocal_settings.pyresides. - Configure the contents of the
FABRICdictionary in yourlocal_settings.pyas shown infabsettings.py. Lines that are commented out are optional. Don't forget to setALLOWED_HOSTSto the value it should have in production.
In your dev machine
- Mezzanine (4+)
- Django (1.7+)
- Fabric
- A git/mercurial repo with your project files (optional)
- A pip requirements file
In your Webfaction account
- pip
- virtualenv
- supervisor
- Git app (optional)
- memcached
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 theFABRICdictionary. From here on, all commands are run from the project root in your local machine. - Run
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. - Run
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
fab deploy. - If you want to wipe out all traces of the project in your server, you can
run
fab remove. The prerequistes will persist. - Get a list of all available tasks with
fab --list.
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.
How is this different from the Webfaction tutorial on installing Django?
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.
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 protected]. This is a prompt for the SSH password for your Webfaction server. It is stored inlocal_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.
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
the NUM_WORKERS setting in the FABRIC dictionary of your local_settings
and doing a deploy to apply the changes.
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.
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.
You can partially mitigate this by periodically starting supervisord and
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.pidThere's an edge case with this approach: Gunicorn's PID file could potentially
prevent 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
PID and 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 -deleteBecause 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 symlink54 to symlink_static_only if you
wish.
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 namedgit_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 defineADMIN_PASS. - 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:
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 remotelyfab pullmedia # Download the remote media files into the local project
fab pushmedia # Upload the local media files into the remote projectMake sure you define TWITTER_PERIOD in your deploy settings first.
fab setup_twitterThis 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
your 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": "[email protected]", # Use your Webfaction usernamefab setup_email
fab deploy- 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.