logo

Blogging with Ghost

I was fed up with the "kitchen sink" approach of WordPress, so I went looking for an alternative - I found Ghost!

So, my first blog post is about how I started Ghost-ing...

The Ghost Logo

Install Node.js

$ curl -sL https://deb.nodesource.com/setup | sudo bash -
$ sudo apt-get install -y nodejs
$ sudo apt-get install -y build-essential

Check it all went according to plan:

$ curl -sL https://deb.nodesource.com/test | bash -

Install Ghost

$ curl -L https://ghost.org/zip/ghost-latest.zip -o ghost.zip
$ unzip -uo ghost.zip -d ghost
$ cd /path/to/ghost
$ npm install --production

Take a look at config.json

$ npm start --production

Front Ghost with Nginx

$ nano /etc/nginx/sites-available/my-domain.com
server {  
  listen my-ip:80;
  listen my-ip:443 ssl;

  server_name www.my-domain.com;
  access_log /var/log/nginx/www.my-domain.com.log;

  ssl_certificate     /etc/nginx/ssl/www.my-domain.com.unified.crt;
  ssl_certificate_key /etc/nginx/ssl/www.my-domain.com.key;

  ssl_protocols TLSv1 TLSv1.1 TLSv1.2;https://www.ssllabs.com/ssltest
  ssl_ciphers ECDH+AESGCM:DH+AESGCM:ECDH+AES256:DH+AES256:ECDH+AES128:DH+AES:ECDH+3DES:DH+3DES:RSA+AESGCM:RSA+AES:RSA+3DES:!aNULL:!MD5:!DSS;
  ssl_prefer_server_ciphers on;
  ssl_session_cache shared:SSL:10m;
  ssl_session_timeout 10m;

  add_header Strict-Transport-Security "max-age=31536000; includeSubdomains";

  if ($ssl_protocol = "") {
    rewrite ^ https://$server_name$request_uri? permanent;
  }

  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;
  }
}

This re-directs non-SSL to SSL, and uses a free StartCom Certificate and cypher suite that passes Qualys SSL Server Test with an A+.

Finally...

Start Ghost on Boot

$ sudo nano /etc/init/my-domain-com-ghost-production.conf
start on filesystem and started networking  
stop on shutdown

respawn  
respawn limit 5 30

env name=mydoman-com-ghost-production  
env uid=mydomainuser  
env gid=mydomainuser  
env daemon=/usr/bin/node  
env path=/path/to/ghost/index.js

script  
    export NODE_ENV=production
    exec start-stop-daemon --start --make-pidfile --pidfile /var/run/$name.pid --name $n$
end script