Fabric Bolt

Fabric Bolt is a Python/Django project that allows you to deploy code stored in source control (a project) to a target server (host). Fabric Bolt provides convenient web interfaces to configure both the projects and the hosts. Additionally, deployment history and logs are stored so that you know who deployed what on which day.

Build Status

https://travis-ci.org/worthwhile/fabric-bolt.png?branch=develop https://coveralls.io/repos/worthwhile/fabric-bolt/badge.png?branch=master

Users Guide

Installing Fabric Bolt

To run Fabric Bolt you’ll need:

  • A UNIX-based operating system
  • Python 2.7
  • python-setuptools, python-dev, libxslt1-dev, libxml2-dev
  • A real database (PostgreSQL is preferred, MySQL also works)

You can run Fabric Bolt on an existing server/host, but this guide will assume that Fabric Bolt is the only thing running on the server.

This guide will step you through setting up a virtualenv, installing the required packages, and configuring the basic web service.

Quickstart

If you are familiar with running a django project that has been pip installed, you can use these steps to get Fabric Bolt running. Otherwise skip this and use the detailed directions below.

  1. Install:

    pip install fabric-bolt
  2. Initialize settings file. (To specify file location, enter as the second argument.):

    fabric-bolt init [~/.fabric-bolt/settings.py]
  3. Modify generated settings file to enter database settings.

  4. Migrate db:

    fabric-bolt migrate
  5. Run:

    fabric-bolt runserver

Note:

If you have created a settings file at a different location than the default, you can use the –config option on any command (besides the init command) to specify the custom file path. Alternatively, you can set an env variable: FABRIC_BOLT_CONF.

Setting up an Environment

The first thing you’ll need is the Python virtualenv package. You probably already have this, but if not, you can install it with:

easy_install -UZ virtualenv

Once that’s done, choose a location for the environment, and create it with the virtualenv command. For our guide, we’re going to choose /www/fabric-bolt/:

virtualenv /www/fabric-bolt/

Finally, activate your virtualenv:

source /www/fabric-bolt/bin/activate

Note

Activating the environment adjusts your PATH, so that things like easy_install now install into the virtualenv by default.

Install Fabric Bolt

Once you have the environment setup you can install Fabric Bolt and all its dependencies with pip (virtualenv comes with a copy of pip which gets copied into every new environment you create):

pip install fabric-bolt

Don’t be worried by the amount of dependencies Fabric Bolt has. Our philosophy is to use the right tool for the job, and to not reinvent them if they already exist.

Initializing the Configuration

After Fabric Bolt has been installed, you will need to create and configure a settings.py file. We have packaged Fabric Bolt with a utility to generate a settings.py file for you:

fabric-bolt init

Or, optionally, you can provide a path to the settings file:

fabric-bolt init /etc/fabric-bolt/settings.py

The settings file will be located at ~/.fabric-bolt/settings.py. And should be edited for your database configuration:

vi ~/.fabric-bolt/settings.py

The configuration for the server is based on the settings file, which contains a basic Django project configuration:

# ~/.fabric-bolt/settings.py

DATABASES = {
    'default': {
        'ENGINE': 'django.db.backends.postgresql_psycopg2',  # We suggest PostgreSQL for optimal performance
        'NAME': 'fabric-bolt',
        'USER': 'postgres',
        'PASSWORD': '',
        'HOST': '',
        'PORT': '',
        'OPTIONS': {
            'autocommit': True,
        }
    }
}

Configure Outbound Mail

Several settings exist as part of the Django framework which will configure your outbound mail server. For the standard implementation, using a simple SMTP server, you can simply configure the following:

EMAIL_HOST = 'localhost'
EMAIL_HOST_PASSWORD = ''
EMAIL_HOST_USER = ''
EMAIL_PORT = 25
EMAIL_USE_TLS = False

Being that Django is a pluggable framework, you also have the ability to specify different mail backends. See the official Django documentation for more information on alternative backends.

Running Migrations

Fabric Bolt provides an easy way to run migrations on the database on version upgrades. Before running it for the first time you’ll need to make sure you’ve created the database:

# If you're using Postgres, and kept the database ``NAME`` as ``fabric-bolt``
$ createdb -E utf-8 fabric-bolt

Once done, you can create the initial schema using the migrate command:

$ fabric-bolt migrate

Next, create a super user by doing the following:

# create a new user
$ fabric-bolt --config=/etc/fabric-bolt/settings.py createsuperuser

All schema changes and database upgrades are handled via the migrate command, and this is the first thing you’ll want to run when upgrading to future versions of Fabric Bolt.

Note

Internally, this uses South to manage database migrations.

Starting the Web Service

FOR TESTING, Fabric Bolt can be run with the basic webserver that comes packaged with django. This can be started with fabric-bolt runserver, or if you’re using a custom settings file

# Fabric Bolt's server runs on port 8000 by default. Make sure your client reflects
# the correct host and port!
fabric-bolt --config=/etc/fabric-bolt/settings.py runserver

You should now be able to test the web service by visiting http://localhost:8000/.

You should NOT run Fabric Bolt in production with runserver. Follow the directions below to run Fabric Bolt with uWSGI and Nginx.

Setup a Reverse Proxy

By default, Fabric Bolt runs on port 8000. Even if you change this, under normal conditions you won’t be able to bind to port 80. To get around this (and to avoid running Fabric Bolt as a privileged user, which you shouldn’t), we recommend you setup a simple web proxy.

Proxying with Apache

Apache requires the use of mod_proxy for forwarding requests:

ProxyPass / http://localhost:8000/
ProxyPassReverse / http://localhost:8000/
ProxyPreserveHost On
RequestHeader set X-Forwarded-Proto "https" env=HTTPS

You will need to enable headers, proxy, and proxy_http apache modules to use these settings.

Proxying with Nginx

You’ll use the builtin HttpProxyModule within Nginx to handle proxying:

location / {
  proxy_pass         http://localhost:8000;
  proxy_redirect     off;

  proxy_set_header   Host              $host;
  proxy_set_header   X-Real-IP         $remote_addr;
  proxy_set_header   X-Forwarded-For   $proxy_add_x_forwarded_for;
  proxy_set_header   X-Forwarded-Proto $scheme;
}

See Configuring Fabric Bolt with Nginx for more details on using Nginx.

Enabling SSL

If you are planning to use SSL, you will also need to ensure that you’ve enabled detection within the reverse proxy (see the instructions above), as well as within the Fabric Bolt configuration:

SECURE_PROXY_SSL_HEADER = ('HTTP_X_FORWARDED_PROTO', 'https')

Running Fabric Bolt as a Service

We recommend using whatever software you are most familiar with for managing Fabric Bolt processes. For us, that software of choice is Supervisor.

Configure supervisord

Configuring Supervisor couldn’t be more simple. Just point it to the fabric-bolt executable in your virtualenv’s bin/ folder and you’re good to go.

[program:fabric-bolt-web]
directory=/www/fabric-bolt/
command=/www/fabric-bolt/bin/fabric-bolt start
autostart=true
autorestart=true
redirect_stderr=true

Indices and tables

Configuring Fabric Bolt with Nginx

Nginx provides a very powerful platform for running in front of Fabric Bolt.

Below is a sample configuration for Nginx:

http {

  server {
    listen   80;

    proxy_set_header   Host                 $http_host;
    proxy_set_header   X-Real-IP            $remote_addr;
    proxy_set_header   X-Forwarded-For      $proxy_add_x_forwarded_for;
    proxy_set_header   X-Forwarded-Proto    $scheme;
    proxy_redirect     off;

    # keepalive + raven.js is a disaster
    keepalive_timeout 0;

    # use very aggressive timeouts
    proxy_read_timeout 5s;
    proxy_send_timeout 5s;
    send_timeout 5s;
    resolver_timeout 5s;
    client_body_timeout 5s;

    # buffer larger messages
    client_max_body_size 150k;
    client_body_buffer_size 150k;

    location / {
      proxy_pass        http://localhost:8000;
    }

  }
}

Proxying uWSGI

We recommend that you setup uWSGI to run Fabric Bolt (rather than relying on the built-in django webserver).

Within your uWSGI configuration, you’ll need to export your configuration path as well the wsgi.py module:

[uwsgi]
env = FABRIC_BOLT_CONF=/etc/fabric-bolt/settings.py
module = wsgi.py

; spawn the master and 4 processes
http-socket = :8000
master = true
processes = 4

; allow longer headers for raven.js if applicable
; default: 4096
buffer-size = 32768

Overview

Hosts

Hosts are simply an IP address or DNS name. Hosts are globally defined and can be targets for several projects in Fabric Bolt.

Host Roles

It is common to have hosts that perform a particular role. For instance we might have a host that is a database server, one that is a web server, and one that is an app server (performing background tasks). By specifying what role each host plays, Fabric Bolt can customize the commands that run against each host during a deployment. So database servers have migrations run against them and web servers have their static assets collected to a central place, but not vice versa.

Sometimes a particular host serves as a particular role for one project, but a different role for another project. So roles are assigned to hosts when you configure them on a project.

Projects

Projects are simply a deployment configuration. Each project can define a top level Project Configuration that includes things like the source control location, source code branch to use, host connection credentials, etc.

Projects also define their stages (more on stages below).

Project Stages

It is common for web developers to deploy their projects to a test/development/staging host for review before deploying to production. In Fabric Bolt we refer to those pieces of a deployment workflow as stages. In other words, we would always go through the following deployment stages for a particular project revision:

test -> staging -> production

Because stages can be as unique as the project code base itself, stages are configured per project and define stage specific configuration values that can override project configurations. Each Stage is simply a Host, Host Role, and Configuration values.

Deployment Tasks

Fabric Bolt uses a python package called Fabric to provide the core functionality of connecting to a remote host and executing shell commands on that host to perform a deployment. Because deployments typically have a large collection of commands that must be executed on a remote host, and those commands are usually grouped together to perform a particular deployment task, Fabric Bolt leverages Fabric tasks as deployment tasks. A deployment task is the same thing as a Fabric task, which is a collection of remote commands to run.

Deployment tasks are defined in a fabfile.py file that ships with Fabric Bolt. But you can provide your own fabfile.py if you want to customize the deployment tasks for a project.

Your deployment tasks are defined at the project level, but because Project Stages are the full configuration of a project and target host, deployment tasks are run from the project stage page.

Putting it Together

If we diagram this simple structure, it looks something like this:

Project
|_ Configurations (git repo, git branch, code_root, etc.)
|_ Deployment Tasks
|
|_ Test Stage
|  |_ Hosts (w/ roles)
|  |_ Configurations (git branch, settings_file, etc.)
|
|_ Production Stage
  |_ Hosts (w/ roles)
  |_ Configurations (git branch, settings_file, etc.)

Running a Deployment

Deployments are actually run against a project stage, since project stages fully define both the project and target hosts fully. To run a deployment:

  1. Define your hosts
  2. Create a project
  3. Configure the project with the source control repo to be deployed (and any other necessary configs)
  4. Add a stage
  5. Configure the stage with at least one host
  6. Select a deployment task to run against the stage
  7. Review the deployment details and provide comments about the deployment
  8. Click “Go!”

Deployments run in a background thread so you can navigate away from the deployment detail screen while a deployment is running. Fabric Bolt tracks the status of the deployment so that you can always come back later and check for success. However, from the deployment detail screen you can watch the live log of what commands are being run on the remote hosts while a deployment is running. After the deployment is complete the log is available for review. This is particularly helpful for resolving issues with failed deployments.

Users

Users are configured in the system with one of three roles. For details on these roles see the http://yourdomain.com/user/permissions/ page.

FAQ

What is the difference between a role and a host?

Fabric Bolt hosts are globally known servers that Fabric Bolt can deploy to. When configuring a stage you need to add servers to it in order to deploy it. Each time you add a host you give it a role like app. This host is then used by the stage as a application-server. You can also create your own custom roles like ferret_server and reference this role in a task.

How do I run a deployment?

Fabric Bolt uses the concept of Project Stages to allow for sufficient customization for a deployment. You will need to configure at least one host, one project, and one project stage. Once those items are properly configured you can select a deployment task to run on the Project Stage page.

Developers

Contributing

Want to contribute back to Fabric Bolt? This page describes the general development flow, our philosophy, the test suite, and issue tracking.

COMING VERY SOON!!

Reference

Changelog

v 0.1 (in development)
  • Added support for using the fabfile in each project’s repo
  • Added “launch window” feature
  • Added experimental socket.io support for deployment output. (use SOCKETIO_ENABLED setting)
  • Fixed an issue where deleted projects showed up in graphs and sidebar (issue #67)
  • Fixed an issue where admins could not set user’s user level. (issue #64)
  • Added alias to hosts model. (thanks Hedde!)
  • Added note in README about creating a super user (thanks madazone!)
  • Fixed injection security bug in fab command
  • Using virtualenv to run project fabfiles
  • Added task argument support!
  • Fabric task lists are now cached per project. Invalidate the cache on the project detail page.
  • Upgraded to django 1.7. IMPORTANT: run fabric-bolt migrate.

Indices and tables