Continuously Deploying Kirby CMS

January 13, 2016 3 mins read

Continuously Deploying Kirby CMS

Kirby CMS is a flat file CMS and powers my website. Therefore, I store all related files under version control in a git repository. Dealing only with files makes deploying a new version to my server a breeze. Well, at least it should. My website is hosted on a shared hosting provider, where I only have limited shell access.

Building

Kirby CMS is installed through git submodules. That makes installing and updating Kirby very simple and controllable. And the good thing is that you do simple things more frequently!

All frontend assets like stylesheets and JavaScripts are processed by Brunch to generate the production versions. Brunch is node-based and requires several node packages to work. Therefore, I leverage GitLab CI to build a production ready snapshot of the website. In order to do so, my .gitlab-ci.ymlcontains the following configuration:

job1:
    script: |
        # GitLab 7.14 cannot handle submodules, thus we have to
        git submodule update --init --recursive
        npm install
        bower install
        brunch build --production        

Deploying

Having built all required assets, the website is ready to be deployed. As the website needs to be deployed to a shared hosting environment, I use Rsync to sync all updated files to the web server serving my website. The rsync command I use only pushes new or updated files to the server and removes files on the server not present in the source anymore. Credits for the rsync options go to an awesome Stack Overflow answer on the topic.

My rsync command to deploy the website now looks as follows:

#!/bin/sh
rsync --checksum \
    --ignore-times \
    --human-readable \
    --progress \
    --itemize-changes \
    --archive \
    --recursive \
    --update \
    --verbose \
    --executability \
    --delete \
    --delay-updates \
    --compress --skip-compress=gz/zip/z/rpm/deb/iso/bz2/t[gb]z/7z/mp[34]/mov/avi/ogg/jpg/jpeg/png/gif \
    --exclude-from=./deploy-ignore.txt \
    /LOCAL_PATH/ \
    USER@HOST:/REMOTE_PATH/

Note the extra --delete flag I have added compared to the answer on Stack Overflow. The flag takes care of deleting files on the production server, that do not exist on the build server. The deploy-ignore.txt file contains source paths that should be ignored by the rsync command. The files listed in there will not be uploaded. I have excluded all files, that are not required in production:

- node_modules
- bower_components
- .git
+ site/cache/.gitkeep
- site/cache
- panel

Zero Downtime Deployment

The described build process and deployment currently takes around 30-40 seconds to complete. The actual deployment with the rsync command only takes a few seconds, depending on how many files need to be transferred. However, during these few seconds the productive system may be in a corrupted state, potentially leading to failures if any requests occur in that time frame.

With the current traffic and the in fact very small time frame, chances of unpleasing a reader are very low. However, with a blue green deployment setup it would easily be possible to achieve zero downtime, especially as there is no database to consider.

How do you handle deployments to your personal website? I’d be interested to hear from your setup!

Comments

👋 I'd love to hear your opinion and experiences. Share your thoughts with a comment below!

comments powered by Disqus