Software development and beyond

Deployment with Fabric

Deployment with Fabric

Fabric is a fantastic tool written in Python that we can utilize to execute shell commands on a remote computer via SSH, so any commands we would run locally on our computer we can run on remote servers without much effort. With Fabric, we create a local utility program to define local commands that will execute the remote ones.

We can execute anything with Fabric, so everything from deployment to complex server management is possible. In this post, I want to focus on web application deployment and creating a simple and automated deployment process with Fabric.

Let’s first think of how the deployment of our example application can work:

The best way would be to create a project with its Python virtual environment using Pipenv or Poetry, but we can also use the system Python for simplicity. Let’s start by installing Fabric:

pip install fabric

We need to prepare our Fabric file, where we will define our deploy command. Let’s save it in fabfile.py:

from fabric import Connection
from invoke import task


HOST = 'user@IPADDRESS'
GIT_DIR = '/home/git/.'
APP_DIR = '/home/serverapp'


@task
def deploy(ctx, version):
"""Deploy specific version of serverapp"""
connection = Connection(HOST)
branch = f'releases/v{version}'

# Checkout and pull changes from releases/<version> branch
connection.run(f'git -C {GIT_DIR} fetch origin {branch}')
connection.run(f'git -C {GIT_DIR} checkout {branch}')
connection.run(f'git -C {GIT_DIR} pull origin {branch}')

# Copy all files from GIT_DIR to APP_DIR
connection.run(f'rsync -av --progress {GIT_DIR} {APP_DIR} --exclude .git')

# Run any deployment scripts we need, e.g. update dependencies using Pipenv
connection.run(f'cd {APP_DIR} && pipenv sync')

# Restart application, assuming we have 'serverapp' systemd service defined
connection.run(f'sudo systemctl restart serverapp')

# Check the status of the service if deployment worked well
connection.run(f'sudo systemctl status serverapp --no-page')

This Fabric script defines one command called deploy, taking one argument called version. It will:

All there is left to do is to start our deployment! Run:

fab deploy -v 0.1.18

The command above will call our deploy command with 0.1.18 as our version argument. We can define any number of commands we want and run them individually like this. There is also a way to show all commands we have defined via Fabric:

fab --list

Another thing we will get for free with Fabric is that it will show us the output of the commands automatically, so when we run our deploy, we will see the output of git, rsync and systemd status commands on our command line, which is neat.

Fabric can be a great tool for many situations where writing pure shell scripts or using more heavy-weight tools is not desirable. Check out the documentation and make great stuff. I hope it will work well for you as well!

Last updated on 16.1.2020.

development-tools devops python