Skip to content
Switch branches/tags
Go to file

Latest commit


Git stats


Failed to load latest commit information.
Latest commit message
Commit time



Some assumptions

These are based on my workflow/project layout.

  • Nginx's root is in /usr/share/nginx
  • Each project exists in /usr/share/nginx/$PROJECT
  • My virtualenv (venv) is located in $PROJECT/venv
  • Files are being served by www-data:www-data (this needs to change)
  • I run these commands ON the server. While Fabric's strength is remote/SSH functionality/support, this is simply a part of my workflow/(bad?)habit.

Based on the above, I think the rest will make sense.

def backup_web():
    """ Backup a specified directory/project """
    tar ="/tmp/%s-%s-web-bkup.tar.bz2" % (date, project),
    tar.add("/usr/share/nginx/%s" % (project))

The above block simply utilizes Python's stdlib tarfile to create a compressed archive of the web_root. While a part of this is redundant since a lot of this exists in the git repo, I have more warm fuzzies simply zipping up the entire project.

Because I'm a Sys Admin at heart, who managed backups for years, you can never have too many backups and as such, in addition to the project files, I also back up the database before anything is done:

def backup_db():
    """ backup a specified database """
    local("su postgres -c '/usr/bin/pg_dump -Fc %sdb >
        /opt/pg/bkup/%sdb-%s.dump'" % (project, project, date))

What the above is doing is simply switching to the postgres user, and doing a pg_dump to a .dump file. This dump can be restored with pg_restore.

As mentioned above, because I'm doing a git pull as the root user, I need to change the owner of these files to ensure Nginx can serve them.

def change_owner():
    """ This is a hack -- git is ran as root and will own whatever is
    pulled """
    local("chown -R www-data:www-data web_site/")

Something else commonly done in django projects is syncing the database, and if you use South, migrating these when the schema or data changes.

def syncdb():
    local("source venv/bin/activiate && ./ syncdb")

def migrate_app(app):
    local("source venv/bin/activate && ./ migrate %s" % (app))

def migrate_all():
    local("source venv/bin/activate && ./ migrate")

syncdb is pretty self explanatory I think. migrate_app allows me to do a fab migrate_app:app and it will run a migrate app. migrate_app is more likely to be used if I were managing migrations manually, rather than during a deployment where it is simply easier to migrate all the databases.

And here is where it all comes together.

def publish():

Simple right? Basically, it will back up the project's files, then the project's database and then do a git pull.

As a part of my workflow and my git hooks the work flow is a little more like:

  • back up project's files
  • back up project's database
  • do a git pull
  • if a requirements.txt file changed, do a pip install -U prod-requirements.txt
  • if a settings or a models file changed, restart uWSGI
  • if a migrations file exists, do a ./ syncdb && ./ --migrate
  • change the owner of the files in project's root to www-data:www-data


My fabfile for my django projects



No releases published


No packages published