I have long been thinking of a migration - WordPress running on PHP seemed too heavy for a low-end VPS. Finally I decided to go with Ghost, a light-weight blogging platform on Node.js.

Backup Posts and Media Files

To ensure a migration with little downtime, first we have to migrate the existing posts in WordPress to the new Ghost installation. To achieve this, we used the WordPress plugin Ghost Export.
To export the post contents, you should:

  1. In the wordpress admin console, on the left side go to Tools > Export to Ghost
  2. Scroll to the Bottom and press "Download Ghost File"
  3. Save it somewhere (the file name may look like wp2ghost_export_1234567898.json)
    If you have SSH or FTP access to your site (which is the common case), you can SSH/FTP to your site, go to your WordPress install folder, download the whole ./wp-content/uploads directory to your local computer.

Make Ghost Work

I have Ubuntu 12.04 installed on my VPS. To install node.js and NPM, you should better build it from source. Isaac Z. Schlueter has a nice Gist on how to build node.js in an instant.
When node.js is ready, go to https://ghost.org/download/ to download the latest version of Ghost. Follow the install guidelines on GitHub to install ghost.
Before you type npm start on the terminal, you should first change the config.js in the Ghost root directory. Change the url: 'http://my-ghost-blog.com' to url: 'http://your-vps-ip:2368'. You should also allow traffic through port 2368 in your firewall settings, for my case, ufw allow 2368.

Now type npm start, and you should see something like:

> [email protected] start F:\Workspace\WebDesign\Ghost
> node index

Migrations: Up to date at version 003
Ghost is running in development...
Listening on 127.0.0.1:2368
Url configured as: http://your-vps-ip:2368

Importing Posts

Open the wp2ghost_export_1234567898.json in a pure text editor (Notepad, Sublime Text, etc.). Then use Search and Replace to replace all urls in the form your-blog-url/wp-content/uploads/* to your-blog-url/content/images/*.

Now visit http://your-vps-ip:2368/ghost/debug in your web browser.
Click Choose File and select the file you saved using the Ghost Plugin and click Import. You should see all your posts in Ghost after a while.

Switch to Ghost with Zero Downtime

If you are using Apache, follow the steps to proxy the traffic for node.js:

First create a site config file in /etc/apache2/sites-available, which contains lines like

<VirtualHost *:80>
    ServerName blog.amayume.net
    ServerAdmin [email protected]

    DocumentRoot /var/www/ghost
    <Directory />
        Options FollowSymLinks
        AllowOverride All
    </Directory>

    ProxyPass / http://localhost:2368/

    ErrorLog ${APACHE_LOG_DIR}/ghost_error.log

    # Possible values include: debug, info, notice, warn, error, crit,
    # alert, emerg.
    LogLevel warn

    CustomLog ${APACHE_LOG_DIR}/ghost_access.log combined

</VirtualHost>

Then use a2ensite the-site-file-name to enable the site configuration. DO NOT forget to disable the original site config for WordPress using a2dissite!

Finally use service apache2 reload to apply the changes. Users should see no downtime as the settings are applied almost instantly.

The steps are similar if you are using Nginx.

Extra Step: Make Ghost Run Forever

Sites encounter problems. Node.js is single threaded and does not have a built-in restart mechanism. Thus a custom restart mechanism has to be provided in order to make the site stable.

A lot of old posts suggests the use of forever. In my view, forever is pretty much obsolete and it is also incompatible with Ubuntu 12.04LTS.
I used pm2 to do the same thing. just type npm install pm2@latest -g to install pm2.
Then type pm2 start index.js in the Ghost root and it should rock!