Skip to main content

Goodbye WordPress, Hello Ghost

3 min read

Older Article

This article was published 13 years ago. Some information may be outdated or no longer applicable.

I’ve stopped using WordPress. I’d been running it for years (my first WordPress blog goes back to 2006), but the time came for something different. Most people would argue WordPress isn’t just a blogging engine anymore. It’s a CMS. That exact observation led John O’Nolan to sketch out an idea for an engine that’s 100% about blogging. And Ghost was born.

Ghost is purely a blogging platform. It runs on node.js and its source code is fully available on GitHub.

I’m running the blog on an Ubuntu (12.04) Amazon EC2 instance with nginx handling the reverse proxy. There weren’t many instructions on how to set this up, so here’s what I did.

First, upgrade nginx to 1.4.3 (latest at the time of writing). Check your version:

$ nginx -v
nginx version: nginx/1.4.3

A standard sudo apt-get update may not be enough on the EC2 instance. Here’s what worked:

  1. Add the nginx repo deb [http://nginx.org/packages/ubuntu/](http://nginx.org/packages/ubuntu/) precise nginx to /etc/apt/sources.list
  2. Add a public key sudo apt-key adv --keyserver [keyserver.ubuntu.com](http://keyserver.ubuntu.com) --recv-keys ABF5BD827BD9BF62
  3. Remove existing nginx: sudo apt-get remove nginx-full && sudo apt-get remove nginx-common (this does not remove your server configuration files)
  4. sudo apt-get install nginx will now install from the official repo

Once that’s done, follow the Ghost installation walkthrough to install node.js, npm, and Ghost itself. After you’ve configured Ghost and set up config.js correctly, it’s time to get the reverse proxy running. Follow these steps:

  1. SSH into your server and remove the default nginx configuration file under /etc/nginx/sites-available/default
  2. Create a file under the same path, named after your site, e.g.: /etc/nginx/sites-available/mysite. The content:
server {
    listen 80;
    server_name YOUR-DOMAIN;
    access_log /var/log/nginx/YOUR-DOMAIN.log;

    location / {
        proxy_set_header X-Real-IP $remote_addr;
        proxy_set_header HOST $http_host;
        proxy_set_header X-NginX-Proxy true;
        proxy_pass http://127.0.0.1:2368;
        proxy_redirect off;
        proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;
        proxy_max_temp_file_size 0;

        client_max_body_size       10m;
        client_body_buffer_size    128k;

        proxy_connect_timeout 90;
        proxy_send_timeout 90;
        proxy_read_timeout 90;

        proxy_buffer_size 4k;
        proxy_buffers 4 32k;
        proxy_busy_buffers_size 64k;
        proxy_temp_file_write_size 64k;
    }
}

Swap YOUR-DOMAIN for your actual domain address (it appears twice).

Now create a symbolic link from sites-available to sites-enabled. Run sudo ln -s ../sites-available/YOUR_DOMAIN YOUR-DOMAIN from inside the sites-enabled folder.

Restart nginx.

If everything’s wired up correctly, navigating to your domain should show Ghost’s welcome page.

A few extra notes. If you’re also changing your domain, you’ll want to add some 301 redirects from the old domain to the new one. Make sure the WordPress link structure redirects to the Ghost link structure properly. In my case (WordPress was set up with ‘domain/year/month/day/article-title’), I’m using this redirect in .htaccess:

RewriteCond %{HTTP_HOST} !old-domain$ [NC]
RewriteRule ^([0-9]+)/([0-9]+)/([0-9]+)/(.*)$ http://new-domain/$4 [L,R=301]

One more warning. I tried to be clever: after importing the JSON dump from WordPress into Ghost, I realised I needed to update all internal links from the WP structure to the new Ghost structure. I opened the file, did a find-and-replace, saved it, and re-imported. Everything broke. Ghost duplicated every post. I had to connect to the sqlite database to sort it out. Be careful with that.

Good luck with the transition!