Last time I reset my blog,[1] I chose a static site generator called Hyde[2] because it is based on Python and Django[3]. 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[4]. Or Sinatra.[5] Or I could build it in Tako[6] 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 platform is based on a handful of interesting technologies that I wanted to learn more about:
Amazon Web Services[7] 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[8] micro instance virtual private server right now as an online coding server pretty much specifically so I can invite other devs in on tmux[9] for remote pairing, but that's not actually relevant to my blog platform. For that, I'm using Route53[10] and S3[11], but it's all giving me a good opportunity to come up to speed on a lot of their tech.
S3[11] 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[10] 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.
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[12], which is a tool for quickly deploying local virtual machines using VirtualBox.[13] Vagrant deploys the virtual machine and then uses Chef (or Puppet,[14] a similar tool) to provision it.
What I've done this time around is create a Vagrant project (available on my Github[15]) that sets up my development environment on any machine with Vagrant installed. The blog is also on Github[16] 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[17] 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.[18]
I'm also preparing a presentation for the Milwaukee PHP User's Group[19], one of our excellent local (Milwaukee) tech meetups. My presentation is on creating and using virtual development environments:[20]
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.
I've mentioned Flask[21] in other blog posts. It's a Python microframework originally inspired by Ruby's Sinatra[5] and written by Armin Ronacher[22]. I'm a big fan of Armin's work, which includes not only Flask but also Werkzeug,[23] Jinja2,[24], and Sphinx.[25]
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,[26] 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.
python sitebuilder.py
) it launches a development server on port 8000 (which Vagrant has forwarded to port 8000 on the host computer.)python sitebuilder.py build
it freezes the website into the ./build directory.python sitebuilder.py deploy
it freezes the website and copies the contents of the ./build directory to the S3 bucket, taking the site live.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,[27] 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[28] over Markdown.[29] 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.[30] 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.
Blogging is inherently organized by time, and my platform supports that. I think it'd be nice to also support tags. If I do that, I'll just use Javascript to make a faceted filter - check or uncheck tags or categories and articles appear or disappear.
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.
I blogged about the last blog reset too in Blog reset. I blogged about starting this blog in Instantiate blog almost two years ago. ↩
Hyde is a static site generator inspired by Ruby's Jekyll[4]. ↩
Django is a powerful and monolithic web application platform. ↩
Jekyll is a Ruby-based static site generator. I don't consider myself a Ruby programmer, but I suspect that's changing. ↩ ↩
Sinatra is a brilliantly simple web application microframework in Ruby. It's one of the reasons I'll probably become a Ruby programmer. ↩ ↩
Tako is a functional web framework in Javascript for Node.js. ↩
AWS is Amazon Web Services, Amazon's platform for developing "web scale" applications in the cloud. ↩
EC2, or Elastic Compute Cloud is Amazon AWS' virtual private server offering. ↩
TMUX is a "terminal multiplexer" that I find useful when sharing a coding session with another programmer. ↩
S3, or Simple Storage Service is Amazon AWS' cloud-based file store. ↩ ↩
Vagrant is a tool for creating lightweight, reproducable, portable development and QA environments. ↩
VirtualBox makes virtual machines run on a variety of host platforms including at least Linux, MAC OS X, and Windows. ↩
Puppet is a configuration management tool similar in some ways to Chef. I'm using Chef without much review of Puppet, so I can't add a whole lot more here. ↩
This is my code repository for my blog dev environment using Vagrant and Chef. ↩
This is my code repository for my blog and static site generator. ↩
Tartan Solutions is my $dayjob. ↩
Opscode Chef comes in a online version that's pretty slick. I'm using it. ↩
Milwaukee has a ton of great meetups. The PHP User's Group is just one of them. ↩
I'll be presenting on February 12, 2013 at 6 PM if you're in the area and available. ↩
Flask is a Python microframework, originally inspired by Sinatra. It's my framework of choice for most things. ↩
Check out Armin online. He's pretty damn cool. ↩
Werkzeug is a whiskey library. No, a WSGI brilary. No, A whiskey a-go-go. I forget, what were we talking about? ↩
Jinja2 is a Python templating engine with a lot of features. ↩
Sphinx is a Python-based documentation platform used by lots and lots of projects, including ↩
Frozen-Flask turns Flask into a static site generator. ↩
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. ↩
YAML is a way to store data in a way that computers find meaningful and people find comfortable. ↩
Markdown is a markup language, kinda like HTML but way easier to use and much nicer to read. ↩