Blogging with org-page
By Calum MacRae
January 18, 2015
I moved my blogging framework from Jekyll over to org-page yesterday, so I figured I'd write about it!
Why I moved
Before I moved to org-page yesterday, I'd been blogging with Jekyll for a while. Granted, I don't write often (something which is going to change).
I like Jekyll - it's simple. There's not really any messing around. You just write your posts in markdown, then use git and post-commit hooks to generate/publish the site on your remote system. Not to mention, you can also use jekyll serve
to serve up your site locally, so you can see how your changes appear, prior to committing.
As I'm writing, I really do find myself wondering if I had a good reason to move to org-page. If simply wanting to blog using Emacs and org-mode is a good reason, well, there you have it.
I spend all day in Emacs, both at home and at work, a lot of which I'm sat in org-mode. I'm still fairly new to Emacs, I haven't even been using it a year. But I find myself in the position many do: I just want to do everything from Emacs. It really is an operating system of its own. So, I suppose, quite naturally I wanted to move my writing to an Emacs based framework.
Writing markdown in Emacs, then using magit to commit and push my changes was just fine. But I really do love org-mode, as everyone should! So, the prospect of writing in org-mode captivated me.
That's quite enough meaningless rambling, trying to justify why I switched from a perfectly good framework to another perfectly good framework…
The stack (wow, so DevOps)
So, org-page takes org-mode syntax, then spits out HTML, just like most static site generators take a more simplistic markup language and churn out HTML. What's nice about org-page is that you have a source branch, where all your .org
files sit, then, upon invoking M-x op/do-publication
, you have the option to send the generated HTML to either a directory, or, dump them into the master
branch. When you opt to send your HTML to the master
branch, you also have the option to auto-commit & auto-push (if you have a remote repo set-up). I think this is really nice, and ties in really well with how I opted to handle the deployment of my site.
Although I'm a puppeteer by day, at work, my infrastructure at home is not nearly as diverse and sophisticated. So I opted to use Ansible. That's not to say Ansible can't handle diverse/sophisticated infrastructures, it certainly can - I have my reasons (I'll write about my experiences with Ansible in a future post, for now, let's focus on this "stack" ;)). Whilst using Ansible at home for managing my little environment, I quite often use it's git module. It's really handy for ensuring the latest code is deployed to systems. I figured this went hand in hand with exactly what I was looking to do: publish my post from org-page, auto-commit/push to the master
branch hosted on my GitLab host, then Ansible comes along and deploys the latest publication to nginx on my blog host.
This was all really simple to get it up and running. Each of the services mentioned above I run in "smart zones" on the incredible SmartOS, all on a little HP Proliant Microserver (Gen 7).
The Git service used here really doesn't matter, nor does the webserver software. It could be a simple Git repo on the filesystem with no frontend, and any webserver could be used, like Apache or httpd.
Chuck it together in Ansible
The only part I suppose I really need to detail here is the Ansible code I threw together to do it. It's so simple, as most stuff is with Ansible, it only took me a few minutes!
Let's first take a look at a snippet from my inventory file:
[webservers] blog.cmacr.ae web.cmacr.ae sab.cmacr.ae tater.cmacr.ae beardy.cmacr.ae
Obviously, this is my collection of webservers. Simple enough. The host we're interested in is blog.cmacr.ae
.
Next up, here's the little playbook I threw together, along with it's defaults bellow:
---
# File: roles/webservers/tasks/main.yml
- name: Ensure nginx is installed
pkgin: name=nginx state=present
- name: Ensure nginx is running & enabled
service: name=nginx enabled=yes state=running
- name: Ensure site content is up to date
git: repo={{ site_repo }} dest={{ site_dest }} update=yes accept_hostkey=yes
when: site_uses_git
---
# File: roles/webservers/defaults/main.yml
site_uses_git: False
As you can see, in the last "play" of the playbook 'Ensure site content is up to date', there's a conditional - denoted by when
. This evaluates the variable site_uses_git
for a boolean value. The code above it (simply ensuring some code is up to date) will only be run when site_uses_git
evaluates to True
. I've set the default value for this to be False
in the roles/webservers/defaults/main.yml
file, as right now my blog is the only host that I need this functionality for.
For the latest site data to be deployed to blog.cmacr.ae
, the site_uses_git
variable needs to be set to True, also the site_repo & site_dest variables need values. These are set within the host_vars/
directory, in a YAML file with the name of the FQDN of the system you want to inherit the contained code:
---
# File: host_vars/blog.cmacr.ae
site_uses_git: True
site_repo: ssh://git@gitlab.cmacr.ae/cmacrae/blog
site_dest: /opt/local/etc/nginx/org_page
And there you have it! I have a playbook called site.yml which ensures common properties are as desired across particular nodes in my infrastructure. The webservers playbook is included in this run:
- name: Apply webserver configuration
gather_facts: False
hosts: webservers
roles:
- webservers
so any time I do M-x op/do-publication
and commit/push to the master
branch of my repo, Ansible comes along and deploys the HTML to blog.cmacr.ae
any time within 30 minutes. I could of course have this interval be more frequent, or manually run the playbook myself if I wanted the content to be updated sooner for any reason.
So, there you have it
Using Emacs, Git, and Ansible to deploy a static site. Quick to set up, and hassle free once it's all in place :)
- Posted on:
- January 18, 2015
- Length:
- 5 minute read, 1019 words