This post has been in my "TODO list" long enough. It's time to put it in words. Let's go!
Migration, a proper one
What I wanted to achieve
My aim was to migrate more than 6 years of content (posts and comments) from my previous blog at detronizator.org into a bloggart installation. Why bloggart? Nick Johnson, the original author of Bloggart on Appengine, wrote a series of article on how to build a nice, little, smart blogging app on App Engine. At the same time, work on txty.mobi started to get more and more engaging, making me a lover (and advocate) of Google App Engine. Plus, I was interested in "starting from scratch": Wordpress.org is a great project, but I just didn't feel it "mine enough". My blog must feel really mine: it's about me after all.
Quick and Easy? Not really...
Migrating all that shit from my previous host was clearly not an easy task. Some reasons were:
- My Wordpress installation was sitting on a MySQL DB: App Engine is based on Google Datastore API
- I decided to change domain to ivandemarino.me: this needed redirection handling, domain transfer and trying to look not too fool in crawler's eyes
- Comments: how the hell am I going to handle those given that Bloggart doesn't provide it but relays on Disqus?
It took some planning and step-by-step strategy. What follows is an attempt to do exactly that.
So, what's this all about?
This post will be a walk-through of what it got to do the Migration. It will have some of the characteristics of "classic" howtos, but I won't go too much in details when, in my opinion, a description of a trivial task will be enough.
Step 1: Export your Wordpress Data
Let's start easy. What you want to do is to backup your Wordpress blog. Here is how.
What we really need, though, is an "XML Export" of the blog. Matt here explains how to do exactly that. The result in my case was an enormous (for a personal irrelevant blog like mine) 6MB! Yes, I write a lot of bulls**t! ;) The result will be something looking like:
<rss xmlns:excerpt="http://wordpress.org/export/1.0/excerpt/" xmlns:content="http://purl.org/rss/1.0/modules/content/" xmlns:wfw="http://wellformedweb.org/CommentAPI/" xmlns:dc="http://purl.org/dc/elements/1.1/" xmlns:wp="http://wordpress.org/export/1.0/" version="2.0"> <channel> <title>Your blog title</title> <link>http://www.yourblog.com</link> <description>Bla bla bla</description> <pubDate>Sun, 30 May 2010 19:15:05 +0000</pubDate> <!-- ... more info about your blog ... --> <wp:category> <wp:category_nicename>cat</wp:category_nicename> <wp:category_parent/> <wp:cat_name>Category</wp:cat_name> <wp:category_description>Category Description</wp:category_description> </wp:category> <!-- ... more category ... --> <wp:tag> <wp:tag_slug>movie</wp:tag_slug> <wp:tag_name>movie</wp:tag_name> </wp:tag> <!-- ... more tag ... --> <item> <title>A blog post</title> <link>http://www.yourblog.com/2005/12/13/a-blog-post/</link> <pubDate>Tue, 13 Dec 2005 11:10:14 +0000</pubDate> <dc:creator><![CDATA[You]]></dc:creator> <category><![CDATA[Category]]></category> <!-- ... body and other stuff --> </item> <!-- ... more items/articles ... -->
Save it somewhere safe. Why do we need the XML? Isn't the SQL backup enough? No, because Bloggart has a nice tool to import the XML export. More about this later.
Step 2: Clone, Setup and Deploy the new blog
So, you want to get a nice clean installation of Bloggart in the cloud. Open your CLI and type:
$ git clone git://github.com/detro/bloggart.git $ cd bloggart $ git submodule update --init
This will clone the latest master of my branch of Bloggart, where I host all my additions, tweaks and changes to Bloggart. Nick's original branch hasn't been updated since June 2010.
application: field with your Application Identifier that you
just created here (you did it, right?).
Then, edit the
config.py following the internal comments/documentation; it should be pretty straightforward.
Bear in mind that there are configuration parameters
that are very much related with UI and stuff like that. But also there are parameters like
the Google Sitemap
or Disqus: take care of this stuff properly, otherwise you will get just an half-assed blog.
Take particular care of Disqus: once you create a forum (that will be populated by the comments on your new Blog) (ah, don't forget to note down the "Disqus Forum Name"), and logged in, you will need to retrieve something important: the "Disqus User Key". To do that, once you logged in Disqus, go at http://disqus.com/api/getmykey/, and annotate somewhere the key. You will need this later on as well.
No, I won't go more in details: if you are not techy enough to read the comments in the
config.py and figure out what to do, why are you even reading this?
Well, now you should be ready to deploy!
$ cd .. $ appcfg.py update bloggart
If you are not interested in migrating, but just starting a blog, then you are done. Your blog is up-and-running already. Otherwise, read on.
The great thing about Open Source software, is that there is almost always someone that had your problem before and found (or built) a solution. So that you can stand on shoulders of Giants. In this case is Andi Albrecht that added support for Wordpress migration in migrate.py. This suited my needs (and will probably suite yours).
migrate.py doesn't come with a great deal of UI. It's just a set of classes. We will have to fill the gap.
But fortunately Google App Engine is not short of surprises.
remote_api is a module introduced in 1.1.9 that allows remote access to the App Engine datastore, using the same APIs you know and love from writing App Engine Apps. What practically does, is provide a python-console that executes code in the context of your remote Application. Isn't that Great?
This great idea is made of two parts:
- a "handler", which you install on the server to handle remote datastore requests
- a "stub", which you set up on the client to translate datastore requests into calls to the remote handler
We already took care of the "handler", already set up in bloggart. You can create your "stub"
following the instruction here, or appreciate
that bloggart ALREADY provides one ready-to-go as well: find it at
ready, set, migrate
We are all set for using
remote.py and type:
import migrate; wpmig = migrate.WordpressMigration(path_to_your_wordpress_export_xml, the_disqus_key, the_disqus_forum_name); wpmig.migrate_all();
This will kick off Deferred Tasks that will store in App Engine your blog posts and in Disqus the associated comments.
wait, I'm having a problem here
Yes, what I just described might fail. For sure if you have an Export XML that takes more than 1MB.
In fact, the
remote_api are limited to handle HTTP File Uploads smaller than 1MB.
Myself I had a file of almost 7MB! How did I do then? I Googled, of course, and found a nice little script called choppedpress.py.
This little script does something extremely useful:
ChoppedPress lets you split the WordPress XML export file into smaller files that can be used to import your posts, comments, tags and categories into a new WordPress installation.
Use it to split your Wordpress Export XML into chunks (remember, smaller than 1MB). Then run the
and do like:
import migrate; wpmig = migrate.WordpressMigration(path_to_your_wordpress_export_xml-chunk-01, the_disqus_key, the_disqus_forum_name); wpmig.migrate_all(); wpmig = migrate.WordpressMigration(path_to_your_wordpress_export_xml-chunk-02, the_disqus_key, the_disqus_forum_name); wpmig.migrate_all(); wpmig = migrate.WordpressMigration(path_to_your_wordpress_export_xml-chunk-03, the_disqus_key, the_disqus_forum_name); wpmig.migrate_all(); ...
301 Permanent Redirect
Well, you don't necessarily need this, but it helps if you want to retain some of your old traffic.
301 Permanent Redirect from your old URL to the new one.
Need help for this? Just Google it.
Well, I'm sure this is a very "poor" how to: it could be definitely improved. But what would be the point if no one reads it?
Instead, if you find it useful and want to know more or just have questions, don't hesitate to leave a message here and I'll make sure to answer as quickly as I can. I'll even eventually update the post if I find that a particular aspect needs clarification: THIS will really help to improve the howto, collectively.
I really want to help people take a look at Bloggart, Nick's great idea: it's probably a very small project, but there are so many interesting things in it, that it's worth caring (if you are like me). This to say that this post is the first of more that will be focused on some of the new features I'm adding to bloggart.
Happy Bloggarting ;)