My very first post on this blog was on Setting Up Pelican and its blog deployment on Github-Pages. It's already been around a year since I started blogging here and this blog has gone through a lot of theme changes and hosting changes since then. After Github Pages I hosted it on OpenShift and now on VPS.

With Github-Pages and OpenShift publishing the blog was easier. I just had to generate the site using pelican command and then after versioning the changes just do a git-push abd the changes were live. But now it is slightly challenging since I am responsible for hosting I had to copy the generated HTML files to server and since a lot of files were generated it wasn't easy for me to even identify the changed files.

After a little bit of googling I came across rsync utility in linux that is commonly used by system administrators for syncing up local and remote directories. However to my surprise I never noticed that Pelican also provides a way to easily deploy your blog using fabric. This was game changing for me. After reading through it's documentation I modified the fabfile.py generated during pelican-quickstart to add ssh-key for accessing my VPS.

    from fabric.api import *
    import fabric.contrib.project as project
    import os
    import shutil
    import sys
    import SocketServer

    from pelican.server import ComplexHTTPRequestHandler

    # Local path configuration (can be absolute or relative to fabfile)
    env.deploy_path = 'output'
    DEPLOY_PATH = env.deploy_path

    # Remote server configuration
    production = 'khirod@205.147.97.134:22'
    dest_path = '/var/www/blog.khirodkant.in'
    env.key_filename = '/home/bunty/.ssh/id_rsa'

    # Port for `serve`
    PORT = 8000

    def clean():
        """Remove generated files"""
        if os.path.isdir(DEPLOY_PATH):
            shutil.rmtree(DEPLOY_PATH)
            os.makedirs(DEPLOY_PATH)

    def build():
        """Build local version of site"""
        local('pelican -s pelicanconf.py')

    def rebuild():
        """`clean` then `build`"""
        clean()
        build()

    def regenerate():
        """Automatically regenerate site upon file modification"""
        local('pelican -r -s pelicanconf.py')

    def serve():
        """Serve site at http://localhost:8000/"""
        os.chdir(env.deploy_path)

        class AddressReuseTCPServer(SocketServer.TCPServer):
            allow_reuse_address = True

        server = AddressReuseTCPServer(('', PORT), ComplexHTTPRequestHandler)

        sys.stderr.write('Serving on port {0} ...\n'.format(PORT))
        server.serve_forever()

    def reserve():
        """`build`, then `serve`"""
        build()
        serve()

    def preview():
        """Build production version of site"""
        local('pelican -s publishconf.py')


    @hosts(production)
    def publish():
        """Publish to production via rsync"""
        local('pelican -s publishconf.py')
        project.rsync_project(
            remote_dir=dest_path,
            exclude=".DS_Store",
            local_dir=DEPLOY_PATH.rstrip('/') + '/',
            delete=True,
            extra_opts='-c',
        )

Understanding this fabfile.py is quite easy. The methods declared can be used with command line tool fab to perform certain operations. As an example suppose if I want to test the blog locally then I would issue a command fab build serve then it will automatically do the static HTML generation and serving for me. And when I'm satisfied with the changes all I have to is issue another command fab publish and changes go live on my server.

The interesting thing is it uses rsync to sync directories and hence it is efficient way to sync files over a network.

Conclusion is fabric is a python library for streamlining the use of SSH for application deployment or system administration tasks. You can use it too. Just think of possibilities. See ya !