How to setup a Ghost Blog with SSL on Ubuntu
Datememe is a new 100% free online dating site. Just because it's free doesn't mean you can't enjoy premium features found on other paid websites. No fake users, no paid features, just free online chat to help you meet that someone special. What are you waiting for?
This blog is running my fork of Ghost. I decided to use Ghost for this blog because datememe is also written in nodejs so I've got some experience with it. While Ghost is missing some basic features like scheduling posts, commenting and proper SSL support this functionality shouldn't be too hard to add myself. I really like the markdown editor and the code is pretty nice to work with so lets get started. I already had a nodejs app running on my root domain so I wanted to run Ghost using the same runtime and in the directory blog from my root domain. There were a few issues I needed to work out to get ghost working for me: production install from git setup in a directory using unix domain sockets let's encrypt ssl all the things add commenting setup with upstart same runtime as datememe use Bugsnag for error reporting Here are the steps i used to install ghost on my production box from git. I'm using Node 5.5 in my production environment so i needed to make some changes to package.json to get everything working correctly. Just change engines to include your Node version. In my environment NODE_ENV=production so i needed: Now you can run finish the install Your blog is ready to be started once you edit the config.js file with your url etc. You don't want your blog on a subdomain. Throwing it in a directory will increase your search rankings. Here is the config required for nginx to load your ghost blog in a directory: I like to always run nodejs apps using domain sockets rather than binding to ports as unix domain sockets are much faster and less risky from a security standpoint. Here is the relevant nginx config that defines the upstream to the ghost domain socket: Modify your config.js and change: Your ghost blog is configured to listen on a domain socket. While building out my own commenting would be trivial lots of sites use Disqus and it looks good with the default ghost theme so I just added that using the installation instructions for ghost here. I run ubuntu on VPS Dime and it uses upstart scripts found in /etc/init. Here is the upstart script i use for my blog. Save this file as /etc/init/dm_blog.conf. You will need to add forever for this to work: Now you can start your blog with: When your VPS reboots it will wait for redis to start then start your blog. Really there is little excuse for not using SSL, it's free and easy to provide basic encryption protecting your users from malicious service providers or governments that would like to change your content before its delivered to the client. Setting up SSL is so easy with Let's Encrypt. I followed this tutorial to auto regenerate certificates every 60 days and configure nginx to use them. To force my sites to use ssl I use nginx to redirect any http traffic to https with a directive like this: The setup for SSL on Ghost is weird. If you set your url in config.js to use https it puts the blog in a redirect loop. After digging through the code i found you are supposed to specify urlSSL in your config like so: This will allow the software to work but Ghost will still use the http url for meta tags like canonical url etc. To fix that you need to modify the code in: Just change: to: Passing true to getBaseURL will return the https url instead of the http url. Now when your articles are shared you will not have a costly redirect from http to https slowing your blog load time. What good is your blog if it doesn't work? I need to install bugsnag on the client and server to make sure stuff is working and to be notified if any unhandled exceptions happen. So here are the steps to set it up on the client and server. If your new to Ghost you might not have a clue where to add the bugsnag code to the ghost project to get it to work. You want to add your bugsnag cdn script to the head: The file you want to modify is: Add your bugsnag cdn script tag: Before {{ghost_head}} around Line 21. First you'll need to install the bugsnag module. Now you'll need to modify some code: To the very top of the file add the line: In the init function on Line 63 add the following: Restart your blog: I hope these tips help you out when setting up your blog. If you haven't decided on a host for your blog I recommend VPS Dime. A VPS with 6GB of ram for 7$ a month is more than enough to host your Ghost blog and handle lots of traffic. This setup is also easy to move to Amazon or Google if you want to use auto scaling. I'm still not finished with modifying my ghost blog. A few issues i'd like to tackle in future blog posts are: Scheduling Posts Accelerated Mobile Pages Better Structured Data Address bugs found by Bugsnag Develop a plugin Theme creation If your struggling with something on your own Ghost blog let me know in the comments and maybe i can help. Datememe is a new 100% free online dating site. Just because it's free doesn't mean you can't enjoy premium features found on other paid websites. No fake users, no paid features, just free online chat to help you meet that someone special. What are you waiting for?Getting Ghost to work for me
Installing Ghost from git
git clone https://github.com/radiofrequency/Ghost /var/www/dm_blog
cd /var/www/dm_blog
npm install -g grunt-cli
engines: {
node: "~0.10.0 || ~0.12.0 || ^4.2.0 || ^5.5.0"
}
npm install --dev
grunt init
grunt prod
cp config.example.js config.js
Install in a directory
location ^~ /blog {
proxy_read_timeout 600s;
proxy_set_header Host $host;
proxy_set_header X-Real-IP $remote_addr;
proxy_set_header x-forwarded-for $remote_addr;
proxy_set_header X-Queue-Start "t=${msec}000";
proxy_set_header X-NginX_Proxy true;
proxy_set_header X-Forwarded-Proto https;
proxy_pass http://dm_blog;
proxy_redirect off;
}
Unix Domain Sockets
upstream dm_blog {
server unix:/var/run/dm_blog.sock;
}
server: {
socket: '/var/run/dm_blog.sock'
}
Commenting
Upstart Script
description "dm blog"
start on started redis
stop on shutdown
expect fork
setuid www
env NODE_ENV="production"
env SPIN_SLEEP_TIME="60000"
chdir /var/www/dm_blog
script
exec /var/www/dm_blog/node_modules/forever/bin/forever start --spinSleepTime 30000 --pidFile /var/run/dm-blog.pid -l /var/log/dm-blog.log -a -d /var/www/dm_blog/index.js
end script
npm install forever --save
sudo start dm_blog
SSL
Let's Encrypt
Nginx
server {
listen 80;
server_name datememe.com www.datememe.com;
return 301 https://$server_name$request_uri;
}
Ghost
url: 'http://www.datememe.com/blog',
urlSSL: 'https://www.datememe.com/blog',
core/server/data/meta/canonical_url.js
return config.urlJoin(config.getBaseUrl(false),
getUrl(data, false));
return config.urlJoin(config.getBaseUrl(true),
getUrl(data, false));
Bugsnag
Client Side
content/templates/casper/default.hbs
<script
src="//d2wy8f7a9ursnm.cloudfront.net/bugsnag-2.min.js"
data-apikey="YOURAPIKEY">
</script>
Server Side
npm install bugsnag --save
core/server/index.js
var bugsnag = require("bugsnag");
bugsnag.register("YOURAPIKEY", {
releaseStage: process.env,
notifyReleaseStages: ["production"]
});
sudo restart dm_blog
Build your Blog
Up Next