After originally starting the first incarnation of this blog a few years ago, I managed a whopping two posts before life got in the way. I decided recently to restart the initiative, and have another go at putting something of substance down on paper. Even if not one person reads anything I publish, the process of writing and externalizing what I’m learning will help me remember, and provide a personal reference of sorts.


RobBlog 1.0 was built on a public WordPress platform, from a hosting provider of which I have no intention of a continued relationship. When I was searching for a new platform, I was looking for something that would be simple to maintain, customizable, and where posts could be written in Markdown. After reading a great blog post by Scott Lowe, I decided to look into using GitHub Pages and Jekyll as the foundation for RobBlog 2.0. Without going into too much detail, Jekyll allows you to build a blog using a combination of Markdown and YAML, which is highly appealing to someone that doesn’t want to go down the web development rabbit-hole, ie: me.

Dev Environment

Once I’d made the decision on my Blogging platform, I realized that I’d like to build a development environment for working on the Blog itself. After years of use, my laptops had become slightly cluttered with multiple versions of Ruby, directory bloat, and so on. I therefore came to the conclusion that I would like a keep a clean slate and just focus on the Blog itself, and not managing the various packages and potential conflicts on my host machines. Also, as I move between two different computers regularly, it would be nice to share the same environment between the two workstations and maintain a consistent workflow, while allowing me to locally preview the site before publishing to the web.

I was already a user of both Vagrant and Ansible, so it was an easy decision to incorporate these two pieces of software into the creation of a portable blogging workstation.


The first step in creating the development environment was to create a new GitHub project.

Creating a new Git repo on GitHub

Be sure to check the Initialize this repository with a README button to ensure that there’s something in the repository, so it can be cloned right away.

Initializing a GitHub repo


I’ve made the assumption at this point that the reader already has a little bit of familiarity with Vagrant, but in a future blog post I’ll discuss a bit more about the ins and outs of this fantastic piece of software.

The first step in creating the development environment was to create a new Vagrant project with the provider and the default Vagrant box. This simply creates a generic Vagrantfile in the directory, which can be edited to suit. Alternatively, you could write a Vagrantfile from scratch; however, we’ve taken the easy route here to get going. We’ll start by cloning our new repository, using that directory as the root for our project.

$ git clone<username>/<repo name>.git

The Vagrant project is then initialized with the following:

$ cd <repo directory>
$ vagrant init

The vagrant init command creates a new Vagrantfile in the project directory, which is the recipe for our development box. My first edit to the Vagrantfile was replacing the default box (which is Ubuntu based) with a CentOS7 image. This is definitely a personal preference thing, as I’ve been been primarily a user of RHEL-based distributions for quite a long time. Feel free to continue with the base box, but you’ll have to edit the Ansible playbook to use apt instead of yum accordingly.

Therefore = "base"

is replaced with: = "centos/7"

By default, Jekyll uses port TCP/4000 to serve up our local copy of the site, so the next step is to forward port 4000 from the host through to the Vagrant box: "forwarded_port", guest: 4000, host: 4000

The final step in completing our Vagrantfile is to configure our provisioner. A provisioner is a tool that is kicked-off once the Vagrant box has been instantiated, with the goal of building the virtual machine up to a desired state. To configure Ansible as a the provisioner, the Vagrantfile has to reference the path to our playbook (which will be created in the next step). To keep things organized, I placed the playbook in a directory called provisioning, and simply called it playbook.yml.

config.vm.provision "ansible" do |ansible|
    ansible.playbook = "provisioning/playbook.yml"

Leaving the final Vagrantfile looking like so:

Vagrant.configure(2) do |config|

  # Set Vagrant box type = "centos/7"

  # Forward port TCP/4000 from the host to guest port TCP/4000, allowing for access to the Jekyll development server via http://localhost:4000 in your host's browser "forwarded_port", guest: 4000, host: 4000

  # Run Ansible provisioner on ./provisioning/playbook.yml
  config.vm.provision "ansible" do |ansible|
    ansible.playbook = "provisioning/playbook.yml"

The Vagrantfile itself is quite well documented, and all of the parameters that could be configured are documented on Vagrant’s website.


The next step in the process was to create a the Ansible playbook to actually build the services on the virtual machine. Playbooks are written in a simple YAML format, and are pretty easy to digest.

YAML files always start with


First, we’ll tell Ansible that we’d like to run this playbook against all hosts, as Vagrant simply runs it against the local box. Then, Ansible was told to perform remote commands as the user vagrant, which is the default user for the CentOS7 box.

- hosts: all
  remote_user: vagrant

The next step is to define the tasks that Ansible is to perform. First, the latest version of Extra Packages for Enterprise Linux (EPEL) is installed. The become: true parameter allows Ansible to become a user while running the command. The default become user is sudo; therefore, this is essentially telling Ansible to run the command with sudo.

- name: Install Extra Packages for Enterprise Linux (EPEL)
  yum: name=epel-release state=latest
  become: true

Further pre-requisites can be installed, such as Ruby, the Ruby development packages, and Ruby gems:

- name: Install Ruby
  yum: name=ruby state=latest
  become: true

- name: Install Ruby development packages
  yum: name=ruby-devel state=latest
  become: true

- name: Install Ruby gems
  yum: name=rubygems state=latest
  become: true

- name: Install NPM
  yum: name=npm state=latest
  become: true

Once the ruby packages have been installed, the github-pages ruby gem can be installed which takes care of the dependencies for github-pages:

- name: Install github-pages Ruby gem
  gem: name=github-pages state=latest

Vim and Git are installed to finalize the installation of tools:

- name: Install Git
  yum: name=git state=latest
  become: true

- name: Install Vim text editor
  yum: name=vim state=latest
  become: true

Finally, when the Vagrant VM is instantiated, I want it to pull down the latest version of the Blog source from GitHub.

- name: Clone github repo
  become: false
  git: repo= dest=~/

Now both the Vagrantfile and the Ansible playbook have been completed, they can be added to the repository, committed, and pushed to GitHub:

$ git add Vagrantfile ./provisioning/playbook.yml
$ git commit -m "Added Vagrantfiel and playbook.yml"
$ git push

Vagrant Up

When it’s time to work on the blog, from any machine that’s got Vagrant and Ansible installed, the repo just needs to be cloned, and then the vagrant up command issued:

$ git clone<username>/<repo name>.git
$ cd <repo name>
$ vagrant up

The Vagrant will instantiate the virtual machine, and then run the Ansible playbook. Once the provisioning process is complete, an ssh session can be established to the vagrant VM:

$ vagrant ssh

From here, it’s time to work on the blog. In order to preview the site, Jekyll can be started:

$ jekyll serve -D

Once it’s time to tidy up, changes can be pushed to GitHub, then the Vagrant box is destroyed.

$ exit
$ vagrant destroy

Next Steps

That’s it! A relatively simple process to maintain a clean, portable development environment that can be quickly spun up on any machine.

The files are available on GitHub, so feel free to fork the repository and edit it for your own purposes!