Last time I reset my blog, I chose a static site generator called Hyde because it is based on Python and Django. It was a good choice at the time, but since then it's become heavy and I got tired of carrying it. In fact, in May 2012 I accidentally deleted my blog dev virtualenv environment and decided then I'd rather move the site to a new platform than rebuild the environment. After all, I keep telling myself I need to learn Jekyll. Or Sinatra. Or I could build it in Tako on Node.js. In fact, at various times I think I started all of those projects.
So after a mere 8 months of false starts and procrastination, I managed to move my blog. And make it prettier.
The new setup
The new platform is based on a handful of interesting technologies that I wanted to learn more about:
- Amazon Web Services Route53 and S3 Simple Storage Service
- Vagrant and Chef
- Python Flask microframework
- YAML and Markdown
Amazon Web Services
Amazon Web Services offers a bunch of technologies at affordable pay-per-use prices. I did a largish project on AWS a couple years ago but haven't been using them much until recently, when I decided to take advantage of the "free" tier. I'm using an EC2 micro instance virtual private server right now as an online coding server pretty much specifically so I can invite other devs in on tmux for remote pairing, but that's not actually relevant to my blog platform. For that, I'm using Route53 and S3, but it's all giving me a good opportunity to come up to speed on a lot of their tech.
S3 provides file storage in the cloud. With the right permissions on files, you can share them with the world just like a web server would. Since my blogging platform is a "static site generator" (it builds a collection of static files that make up the site), I need someplace to store the files that's accessible via the internet.
Route53 is the special sauce that makes my static files accessible via my domain. This is a fairly recent addition to the AWS product line. First, it provides Domain Name Services or DNS for any domain pointed there. Second, it let's you associate a host in your DNS with a bucket in your S3. With that, any file I upload to S3 can be served at http://version2beta.com. Mission accomplished.
Vagrant and Chef
Chef is a server management tool that let's you associate a server (node) with cookbooks and recipes that install, configure, and maintain the software on the server. More advanced use lets you associate your server with one or more roles (like application server, or database server, load balancer, or super-secret-international-spyperson-hacking-platform) in an environment (like development, QA, production, or maybe destructive-test-grounds).
Chef works well with Vagrant, which is a tool for quickly deploying local virtual machines using VirtualBox. Vagrant deploys the virtual machine and then uses Chef (or Puppet, a similar tool) to provision it.
What I've done this time around is create a Vagrant project (available on my Github) that sets up my development environment on any machine with Vagrant installed. The blog is also on Github of course, so in one command, I build everything I need in a development server to work on my blog. It's an on-demand environment. Pretty slick.
I've been killing birds with stones all over the place with Vagrant and Chef. One of my current $dayjob projects is to create a portable development environment that's quick and easy for a dev to deploy. Another is to create QA environments that are disposable and fast. A third is to set up our production systems on Opscode's Hosted Chef environment.
I'm also preparing a presentation for the Milwaukee PHP User's Group, one of our excellent local (Milwaukee) tech meetups. My presentation is on creating and using virtual development environments:
Virtual development environments keep your workspace clean and predictable in dev and production, and creating a virtual development machine with Vagrant is quick and easy once you have all the pieces in place. Rob Martin (@version2beta) is going to put all the pieces together and hand them to you, and then show you how you can use them.
Python Flask microframework
I've mentioned Flask in other blog posts. It's a Python microframework originally inspired by Ruby's Sinatra and written by Armin Ronacher. I'm a big fan of Armin's work, which includes not only Flask but also Werkzeug, Jinja2,, and Sphinx.
I find writing web applications and restful services in Flask pretty easy. But it wasn't until I was looking at my options for replacing Hyde on this blog that I discovered Frozen-Flask, a Flask extension that takes a static snapshot of a Flask application and stores it in a file system. Frozen-Flask makes Flask into a static site generator.
My Flask application is really quite simple.
- If I run it directly (
python sitebuilder.py) it launches a development server on port 8000 (which Vagrant has forwarded to port 8000 on the host computer.)
- If I run
python sitebuilder.py buildit freezes the website into the ./build directory.
- If I run
python sitebuilder.py deployit freezes the website and copies the contents of the ./build directory to the S3 bucket, taking the site live.
YAML and markdown
Finally it comes down to content, which if I understand correctly is an important part of a blog.
My content is stored in flat files. I like this. It makes it very easy to do version control and store them at Github. In fact with Github's new online editing, I can even create and edit blog posts through their web interface.
My content is divided into "pages" and "articles". Pages are manually linked to the navigation, or referenced on other pages. Articles are blog posts and always sorted in reverse chronological order (most recent first).
Each page or article is in it's own text file. The raw file is YAML over Markdown. There's a YAML header that contains a short and long title (the short title is used for the H1 tag, the long title is used for the title attribute in links), and an excerpt or summary. Articles also have a published attribute with the date and time to show as the published timestamp. These YAML fields are arbitrary though - what they're called only has relevance if they're referenced in a template or the program logic, so any fields can be added at any time. In fact, I'll probably add tags at some point, which will require updating the controller and the templates.
After the YAML header, there's a blank line. After that, there's markdown defining the main content for the page or article. Easy-peasy.
I hadn't intended to use YAML as my metadata transport. I wanted to use JSON for all of the content definitions, and support a variety of backends including CouchDB. But JSON doesn't support multiline strings (you must embed the carriage returns) and I don't have a JSON+Markdown editor that I can connect to CouchDB. So that's a project I might take on.
Check it out
Check out the code for my blog platform on Github at https://github.com/Version2beta/version2beta.
Check out the Vagrant + Chef setup at https://github.com/Version2beta/vagrant-chef-flask. I'll be building a couple more open source versions of that getup for PHP stuff in preparation for my February presentation.
Flask is a Python microframework, originally inspired by Sinatra. It's my framework of choice for most things. ↩
Github provides online editors now. With these editors you can change existing files or create new ones right from the website. In fact, you can even edit other people's repos online. It forks them for you, and on commit will helpfully send a pull request. ↩
Talk back to me
You can comment below. Or tweet at me. I'm always open to a good conversation.