Create a gist now

Instantly share code, notes, and snippets.

What would you like to do?


  • Node.js
  • Ruby
  • Bundler


This one's pretty simple, just change directory to somewhere sensible and run the following commands:

git clone "" $dirName
cd $dirName
git submodule update --init
npm install -g grunt-cli
npm install
bundle install
grunt init
npm start

If all goes well, you can now go to http://localhost:2368/ and see your wonderful new blog in all its un-styled glory. Go to http://localhost:2368/ghost/ to see the backend and create a new post (just enter your details to create an Administrator login).

Pretty cool huh? Okay, now time to make it purty...


No go and find yourself a theme that you like and drop it into content/themes.

Here's where I went looking for themes:

You'll need to restart Ghost before it'll allow you to select newly install themes, so go back to your console and press Ctrl-C to terminal Ghost and then run npm start to start it up again. Now go to http://localhost:2368/ghost/settings/general/ and select one of the themes that you added in the Theme section of the form.

Now add your theme to the repo, or see below for bonus points:

git add -f "content/themes/{{theme directory}}"
git commit -m"Added theme"


Because Ellie was available on Github, and because I like to keep things neat and tidy I added Ellie as a git submodule and then created my own copy (I could have used a fork but, uh I didn't) which I added to my repo. This allows me to pull updates to Ellie in the future if I like, and copy them over to my theme.

This process was:

git submodule add -f "" "content/themes/ellie"
mkdir "content/themes/$dirName"
cp -r "content/themes/ellie/*" "content/themes/$dirName"
git add -f "content/themes/$dirName"
git commit -m"Added themes"


Now you need to tell Ghost where your blog lives, so open up config.js in your editor of choice.

In the development section, change to localhost In the production section, change to the hostname you're going to use on the sever and change the port to '80' Replace host: '' with host: '' to accept connections from anywhere If you're on EC2 then you can use the and change it to your domain later.

Now add these changes to your Git repo:

git add -f "config.js"
git commit -m "Updated config"


Okay now we need to push our changes to a Git repository. I recommend you create one on Github or Bitbucket (Bitbucket will let you keep your code private if that's your thing). This post assumes Github, but the same applies to Bitbucket.

When you complete this process they will provide you with a URL that you can use to push your changes:

Github example

You'll need to go through the process of setting up your SSH keys so that you don't need to enter your username and password every time, and so that you can access your repo from the server later on.

Now, copy that URL and:

git remote rename origin upstream
git remote add origin "{{the URL you copied before}}"
git push origin master --set-upstream

Congratulations, you've just pushed a Git repository!


We're going to use Upstart to make sure that our server starts when the instance boots up. Create a new file upstart.conf in your text editor of choice and copy the code from this Gist into it, changing /data/my-blog to the whatever you used for $dirName above.

Now add this to Git using:

git add upstart.conf
git commit -m"Added upstart.conf"
git push origin master


Okay, so if you don't already have an EC2 instance then you create one using these instructions. Then you should SSH to your instance so we can set up Ghost.

You'll want to use SSH Agent Forwarding so that you can access your Git repo from the server. You can do this by adding -A to your SSH command, but I recommend adding the following entry in your ~/.ssh/config file:

Host {{your domain name}}
    Hostname {{EC2 domain name e.g.}}
    User ubuntu
    IdentityFile ~/.ssh/{{path to your Amazon .pem file}}
    ForwardAgent yes

This allows you to SSH to {{your domain name}} and to then authenticate over SSH as though you're on your local machine:

ssh {{your domain name}}

(Answer yes to the warning about the fingerprint.)


Okay, so you've SSHed to your instance. Now you'll need a few packages installed first:

sudo apt-get update
sudo apt-get install git nodejs npm ruby1.9.1 -y
~~sudo ln -s nodejs /usr/bin/node~~
sudo npm config set registry
sudo npm cache clean -f
sudo npm install -g n
sudo n stable
sudo npm install npm grunt-cli forever -g
sudo gem install bundler

If you want to run multiple sites on this instance then you'll need to set up Nginx or some other reverse proxy to listen on port 80 and then pass the requests to the appropriate process for each website. But that's outside the scope of this post, so I'm assuming that this is the only site you're running on this instance.

Now, let's clone your Ghost repo on the instance. Feel free to change $dirName to whatever you want.

sudo mkdir -p $dirName
sudo chown ubuntu $dirName
cd $dirName
git clone "{{the repository URL you copied from Github before}}" $dirName

(Answer yes to the warning about the fingerprint, then...)

git submodule update --init
sudo npm install
grunt init
grunt prod
sudo NODE_ENV="production" npm start

If everything's worked then you should be able to go to http://{{your domain name}}/ghost/settings/general/ and select your theme, and your shiny new blog will be online at http://{{your domain name}}/.


Copy the upstart.conf file into /etc/init so that your blog starts when the instance boots up:

cp upstart.conf "/etc/init/my-blog.conf"

Make sure you check that it does start by rebooting the instance using shutdown -r now.


Now you've got your very own blog, and it's yours to do with as you please!

You can make some changes to your theme, add them to Git (using git add, git commit and git push). Then when you're happy with them, SSH to your server, cd /data/my-blog and run run git pull to update your blog.

One final note: your server isn't set up to send email yet, but that's a topic for yourself to work out - I'm out of time here :)

# An example upstart script for running a Node.js process as a service
# using Forever as the process monitor. For more configuration options
# associated with Forever, see:
# You will need to set the environment variables noted below to conform to
# your use case, and should change the description.
description "Example upstart script for a Node.js process"
start on startup
stop on shutdown
# This line is needed so that Upstart reports the pid of the Node.js process
# started by Forever rather than Forever's pid.
expect fork
# The following environment variables must be set so as to define
# where Node.js and Forever binaries and the Node.js source code
# can be found.
# The example environment variables below assume that Node.js is
# installed into /home/node/local/node by building from source as outlined
# here:
# It should be easy enough to adapt to the paths to be appropriate to a
# package installation, but note that the packages available for Ubuntu in
# the default repositories are far behind the times. Most users will be
# building from source to get a more recent Node.js version.
# The full path to the directory containing the node and forever binaries.
# env NODE_BIN_DIR="/home/node/local/node/bin"
# Set the NODE_PATH to the Node.js main node_modules directory.
# env NODE_PATH="/home/node/local/node/lib/node_modules"
# The directory containing the application Javascript file.
# env APPLICATION_DIRECTORY="/home/node/my-application"
# The application start Javascript filename.
# env APPLICATION_START="start-my-application.js"
# Log file path.
# env LOG="/var/log/my-application.log"
env NODE_BIN_DIR="/usr/bin/node"
env NODE_PATH="/usr/local/lib/node_modules"
env APPLICATION_DIRECTORY="/data/my-blog"
env APPLICATION_START="index.js"
env LOG="/var/log/my-blog.log"
env NODE_ENV="production"
# Add the node executables to the path, which includes Forever if it is
# installed globally, which it should be.
# The minUptime and spinSleepTime settings stop Forever from thrashing if
# the application fails immediately on launch. This is generally necessary to
# avoid loading development servers to the point of failure every time
# someone makes an error in application initialization code, or bringing down
# production servers the same way if a database or other critical service
# suddenly becomes inaccessible.
exec forever --sourceDir $APPLICATION_DIRECTORY -a -l $LOG \
--minUptime 5000 --spinSleepTime 2000 start $APPLICATION_START
end script
pre-stop script
# Add the node executables to the path.
# Here we're using the pre-stop script to stop the Node.js application
# process so that Forever is given a chance to do its thing and tidy up
# its data. Note that doing it this way means that each application that
# runs under Forever must have a different start file name, regardless of
# which directory it is in.
exec forever stop $APPLICATION_START >> $LOG
end script
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment