Migrating from Wordpress to GhostJs on the Raspberry Pi

This might be useful if you are finding Wordpress and the LAMP stack a little slow on the Raspberry Pi.

Hardware

The first step is to get a Pi2 - this will require you to purchase a new 2.1w power supply and possibly new memory if you're using one of the old, large format cards. You'll know pretty quickly if the old power supply is not up to scratch - the Pi2 will start rebooting when it tries to do anything substantial, like installing new packages.

The second optimisation you can make at the hardware stage is buying a high-speed USB key. This will be much faster than running from an SD card and is better suited to frequent read/writes. It's simple enough to do, open cmdline.txt on the SD card and change root=/dev/mmcblk0p2 to root=/dev/sda2.

Preparation

Before you tear down your existing site, make sure you install the Ghost Export plugin to download all your posts as JSON. You'll also need to run the Categories-to-Tags plugin first because Ghost can't deal with categories yet.

I also found that the plugin needed some help to work. I had to add this line to /var/www/wordpress/wp-content/plugins/ghost/class-ghost.php;

add_theme_support('post-thumbnails');

and there was also some clean-up required in the output. In the end, the easiest thing to do was export an empty blog from Ghost and replace the <posts> section with the output from Wordpress.

You'll also need to handle your images outside Ghost. You can use the recommended Cloudinary solution but for now it is probably just best to take a copy of your wordpress/wp-content/uploads directory for safe-keeping.

Installation

Next you'll need to install NodeJs and GhostJs. Not so easy on the Pi2. First of all there's a problem with the latest version Node with GhostJs, specifically how it links to SqlLite, and I had to downgrade to version v0.10.38 to get it to work.

These steps should do the trick;

wget https://ghost.org/zip/ghost-latest.zip  
unzip -d ghost ghost-latest.zip  
cd ghost/  
npm install  

You will need to customise the config.example.js file and rename it to config.js. I found that using Forever worked best for keeping Ghost up and running. The command line to add Ghost looks like NODE_ENV=production forever start index.js

Now you should be able to access Ghost via http://localhost/ghost/debug - this is where you import the JSON file you carefully exported earlier.

Congratulations! You now have a rather plain Ghost installation.

Load Balancing

One of the main reasons for having a blog hosted on a Raspberry Pi is to avoid having to use cloud storage but there is nowhere to host images or static content with Ghost occupying port 80. This is where Nginx comes in;

apt-get install nginx  
service nginx start  

This should get things started. Nginx is extremely fast at rewriting urls and serving static content.

You can point Nginx at your directories with a configuration that looks something like this (presuming you left Ghost running on port 2368);

/etc/nginx/sites-enabled/default

        location / {
                proxy_buffering off;
                proxy_set_header Host $http_host;
                proxy_set_header X-Real-IP $remote_addr;
                proxy_set_header X-Scheme $scheme;
                proxy_pass http://localhost:2368;
                proxy_pass_header X-CSRF-Token;
                client_max_body_size 10M;
        }
        rewrite ^(/wordpress/.*) $1 break;
        location /wordpress {
                internal;
               autoindex on;
                root /<path-to-your-wp-content-copy>;
                expires 1h;
        }
Statistics

So what are the results like? Well here are the raw stats accessing my site;

Wordpress 13.2 MB 22.02s (onload: 21.56s)

GhostJs 105.6 KB (onload: 607ms)

This is very misleading though; the default Ghost skin only shows a preview of the first few posts and includes no plugins. The Wordpress pages is loading widgets, flash movies and video clips. Still, by removing the webserver, database and the php engine and then precompiling the pages, serving with Node and delivering static files with Nginx, you are guaranteeing a massive boost to page delivery.