Janik von Rotz

6 min read

Step by Step: Install Ghost Blog

Latest Version of this guide: https://gist.github.com/8542013

Finishing this guide you”ll get:

Specification of latest running installation:



Update Ubuntu

sudo apt-get update && sudo apt-get upgrade

Install additional packages

sudo aptitude install build-essential zip git


Change the default ssh port and disable root login

sudo vi /etc/ssh/sshd_config
Set Port [custom ssh port number]
Set PermitRootLogin no

Restart the ssh service

sudo /etc/init.d/ssh restart

Update firewall rules now to enable ssh connection with your custom port

Reconnect your ssh host with the new port number

ssh -p [custom ssh port number] user@host


Install Fail2Ban

sudo apt-get install fail2ban

Copy the configuration file

sudo cp /etc/fail2ban/jail.conf /etc/fail2ban/jail.local

Edit the config file

sudo vi /etc/fail2ban/jail.local

Make the following changes:

port     = [custom ssh port number]


enabled  = true
port     = [custom ssh port number]

Finish editing and restart fail2ban service

sudo service fail2ban restart


Edit the network configuration file

sudo vi /etc/sysctl.conf

Paste the this configuration file to improve network security

# /etc/sysctl.conf - Configuration file for setting system variables
# See /etc/sysctl.d/ for additional system variables
# See sysctl.conf (5) for information.

# Uncomment the next two lines to enable Spoof protection (reverse-path filter)
# Turn on Source Address Verification in all interfaces to
# prevent some spoofing attacks

# Uncomment the next line to enable TCP/IP SYN cookies
net.ipv4.tcp_max_syn_backlog = 2048
net.ipv4.tcp_synack_retries = 2
net.ipv4.tcp_syn_retries = 5

# Do not accept ICMP redirects (prevent MITM attacks)
net.ipv4.conf.all.accept_redirects = 0
net.ipv6.conf.all.accept_redirects = 0
net.ipv4.conf.default.accept_redirects = 0 
net.ipv6.conf.default.accept_redirects = 0

# Do not send ICMP redirects (we are not a router)
net.ipv4.conf.all.send_redirects = 0
net.ipv4.conf.default.send_redirects = 0

# Do not accept IP source route packets (we are not a router)
net.ipv4.conf.all.accept_source_route = 0
net.ipv6.conf.all.accept_source_route = 0
net.ipv4.conf.default.accept_source_route = 0
net.ipv6.conf.default.accept_source_route = 0

# Log Martian Packets
net.ipv4.conf.all.log_martians = 1
net.ipv4.icmp_ignore_bogus_error_responses = 1

# Ignore ICMP broadcast requests
net.ipv4.icmp_echo_ignore_broadcasts = 1

# Ignore Directed pings
net.ipv4.icmp_echo_ignore_all = 1


You can install node either from website or the from the git repo.

Install from source

Download Node.js with wget

wget http://nodejs.org/dist/node-latest.tar.gz

Unpack Node.js

tar -xzf node-latest.tar.gz
cd [node folder]

Install Node.js

sudo ./configure
sudo make
sudo make install

Check version of Node.js and npm

node -v
npm -v

Install with Git

Clone the Node.js repo

cd /usr/local/src
sudo git clone git://github.com/joyent/node.git

Check git tags to find the latest version

cd node
git tag

See the latest stable version on http://nodejs.org/

Checkout the latest version

sudo git checkout vX.X.X

Install Node.js

sudo ./configure
sudo make
sudo make install

Check version of Node.js and npm

node -v
npm -v

Update Node.js

Depending on how you”ve installed Node.js theres an update strategy

from source

Repeat the installation process above

with Git

Pull down the latest source code

cd /usr/local/src/node
sudo git checkout master
sudo git pull origin master

Check git tags to find the latest version

git tag

See the latest stable version on http://nodejs.org/

Compile the latest version

sudo git checkout vx.x.x
sudo ./configure
sudo make
sudo make install


Install Nginx

sudo apt-get install nginx

Create a Nginx site configuration file

sudo touch /etc/nginx/sites-available/ghost.conf
sudo vi /etc/nginx/sites-available/ghost.conf

Paste this config

server {
    listen 80;
    server_name [example.com];

    location / {
        proxy_set_header   X-Real-IP $remote_addr;
        proxy_set_header   Host      $http_host;

Create a symlink to your config file

sudo ln -s /etc/nginx/sites-available/ghost.conf /etc/nginx/sites-enabled/ghost.conf

Restart Ngnix

sudo service nginx restart

In case you”ll get this error

Restarting nginx: nginx: [emerg] could not build the server_names_hash, you should increase server_names_hash_bucket_size: 64


sudo vi /etc/nginx/nginx.conf
Set server_names_hash_bucket_size 128;
sudo service nginx restart


Create the website folder

sudo mkdir -p /var/www/
cd /var/www/

Download Ghost with wget

sudo wget https://ghost.org/zip/ghost-latest.zip

Unpack Ghost

sudo unzip -d ghost ghost-latest.zip
cd ghost/

Install Ghost

sudo npm install --production

In case of errors for sqlite3 installation

npm install sqlite3 --build-from-source

Install forever

sudo npm install forever -g

Configure Ghost (productive environment only)

sudo cp config.example.js config.js
sudo vi config.js
Set url: "http://[example.com]",

Start Ghost

sudo NODE_ENV=production forever start index.js

Start Ghost without forever

sudo npm start --production

Check if Ghost is running

forever list

Stop Ghost

forever stop index.js

Register your Ghost Account

Open your browser on http://[example.com]/ghost

Ghost Mail

Ghost uses Nodemailer to send e-mails, this modules has to be configured. Ghost supports various mail providers, you can see all of them in the Ghost mail documentation


Amazon’s SES (Simple EMail Service) provides a reliable service to send mails.


Create a new user in the IAM service console and store the access keys in a secure place.

Allow new user to send mail via SES with this policy configuration

  "Version": "2012-10-17",
  "Statement": [
      "Effect": "Allow",
      "Action": "ses:SendRawEmail",
      "Resource": "*"

Edit the Ghost config

sudo vi config.js

Add this mail configuration

mail: {
    transport: "SES",
    options: {
        AWSAccessKeyID: "[acccess key]",
        AWSSecretKey: "[secret key]"

Update mail settings

Set Email Address: [verified SES mail address]


sudo vi config.js

And add this mail configuration

mail: {
    fromaddress: "[verified SES mail address]",

Now you should be able to reset your Ghost password

However at the time of writting this mail configuration doesn”t seem to work despite it”s an offical Ghost configuration

In case you”ll get this error when trying to reset your password

Email Error: Email failed: 400 Sender MessageRejected Email address is not verified. 5a07d838-8381-11e3-ad96-5f67c4a04b97

Replace the the Ghost mail configuration with

mail: {
    transport: "SMTP",
    fromaddress: "[verified SES mail address]",
    host: "ssl://[SES smpt server address]",
    options: {
        port: 465,
        service: "SES",
        auth: {
            user: "[acccess key]",
            pass: "[secret key]"

You can get your smtp settings here


Install Node
Install Node on Ubuntu
Install Ghost
Deployment of Ghost
sqlite3 troubleshooting
nginx fix hash buck size
Install Ghost on Ubuntu, Nginx and MySQL
Fail2Ban SSH Hardening
Amazon EC2 Node Stack
SES mail configuration

Categories: Web engineering
Tags: aws , blogging , ec2 , ghost , git , guide , javascript , linux , nginx , node , npm , security , ssh , ubuntu
Improve this page
Show statistic for this page