TL Nguyen

Notes And Thoughts

Howdy, welcome to my geeky corner. This blog is all about my hobbies, tech tutorials and open source projects


Setting up a self-hosted blog using Raspberry Pi and Ghost

Hey, you probably assumed why I'm writing this article :-D . Yup, this blog is hosted on my home server using a Raspberry PI mini-computer.


Brief Intro

I've been using Raspberry PI for a while, mostly as a SVN server and network-attached storage (NAS), where i can easily get access to all of my files and projects. For NAS, it's a little bit overkill because you probably will want to attach it with an external HHD for bigger storage, that means you need more energy to power the HHD, your HDD will run on USB 2.0, not SATA interface, that means the speed is a little bit slower (even though the theoretical speed of USB 2.0 is faster than SATA). I use a 1A power adapter for my RaspberryPI and it's probably not enough since the RaspberryPI seems to hang up quiet often... because of those reasons, I decided not to use it as a NAS anymore. So instead of that, why not a web server to host my personal blog ;-). Yup, it's extremely low power (1A * 5V = 5W for max consumption), it runs on Linux, it's ideal for a web server.

In this tutorial, I will show you how I managed all the setup around this blog in the greatest details. So let's begin


Project Info

Softwares requirements

Hardwares requirements


Installing Raspbian OS

Download the latest version of Raspbian and unzip it (the version during this post is 2014-01-07-wheezy-raspbian.img), and then download Win32 Disk Imager for writing this image file to RaspberryPI's MicroSD card, unzip and start it. You should see the following window

At the Image File field, choose the image file of the downloaded raspbian image. Insert the MicroSD to our PC and choose its directory at the Device field, and then click Write, wait the progress bar to reach at 100% and you're done. Easy huh ? :-D


Raspbian first start and configuration

Insert the microSD to our RaspbianPI (PI server), connect it to a monitor and usb keyboard, and then start it up. After a while, you should see the raspi-config program running

  • Choose Expand Filesystem to expand all the volumn of our microSD storage.
  • Change the user password with your password (the default username/password is : pi/raspberry)

  • Choose Advanced Options:

  • In the advanced options, change the hostname if you plan to use more than 1 raspberryPI ( for example: piserver).

  • Choose Memory Split and *split the shared memory for GPU to the minimum *(16 MB), because we won't need alot of graphic using it as a headless server, duh
  • At last, the most important thing, choose SSH and Enable it, so we can access it through the SSH.
  • Choose back, and then finish, reboot the PI server, after that login with the username pi and your password that you've set earlier.

Setting up a static IP

Now we should see the console of raspbian OS. The first thing we have to do is to set our IP to be static:

  • Use nano to modify the configuration file for network interfaces

    sudo nano /etc/network/interfaces
    
  • You will see the iface eth0 inet dhcp line, replace this line with

    iface eth0 inet static
        address 192.168.1.200
        netmask 255.255.255.0
        gateway 192.168.1.1
    

Where the netmask and gateway are from your network settings, and the address will be the static IP of our PI server.

Save it with Ctrl + O and exit Ctrl + X

  • You can now shutdown the PI server by using sudo halt now command. Disconnect it from the monitor and keyboard, connect it to our router and start it up again.

Using Putty to login to PI server remotely

  • Download Putty for remote control our PI server through SSH, and then start the program, you should see the following window

  • Enter the PI server IP that we setted up ealier (mine is 192.168.1.200) at the HostName(or IP address) field and then click Open. Putty now will connect you to the PI server. Login with username/password and you will see its console.

Done! you've successfuly logged in \m/. Now you can do a quick update, just to make sure that you have the latest packages of your softwares

sudo apt-get update
sudo apt-get upgrade

Installing NodeJS

At the time of writing this post, the latest version of Node is : node-v0.10.26.tar.gz. So to download, compile and install Node, enter these commands

cd ~
wget http://nodejs.org/dist/v0.10.26/node-v0.10.26.tar.gz
tar -xzf node-v0.10.26.tar.gz
cd node-v0.10.26
./configure
make
sudo make install

Warning : you have to wait around 3 hours for node to be compiled, so... be patience :-P

Note : You can use the link http://nodejs.org/dist/node-latest.tar.gz to download the latest version of Node instead of the concrete version

You can check after that, if Node is installed properly, by checking the versions of Node and Node Packaged Modules (npm)

node -v
npm -v

If they reply the correct versions, so everythings are good, congratulation :-D


Installing Ghost

Download the latest version of Ghost, unzip it and then install it using npm

wget https://ghost.org/zip/ghost-latest.zip
unzip ghost-latest.zip -d blog
cd blog/
sudo npm install --production

Install sqlite3 to your PI server

sudo apt-get install sqlite3

Edit the configuration file in your ghost folder using nano

cp config.example.js config.js
nano config.js

You will find a section production: {...} (it's actually a js object :-P), between the curly brackets represent all the settings for your ghost in production mode. Change them to your specific settings. For example :

url: 'http://yourwebsite.com',
mail: {
    transport: 'SMTP',
    options: {
        service: 'Gmail',
        auth: {
            user: 'yourgmail@gmail.com', //make a new one, don't use ur personal email
            password: 'yourgmailpassword'
        }
},
database: {
    client: 'sqlite3',
    connection: {
        filename: path.join(__dirname, '/content/data/ghost.db')
    },
    debug: false
},
server: {
    host: '192.168.1.200' // IP address of the PI server
    port: '80'
}

Save it with Ctrl + O and exit Ctrl + X

Done, you've completed installing node, now start it in the server

npm start --production

Using your browser and check the following link : http://192.168.1.200 (IP address of the PI server)

It should access to your ghost blog, you can go to your admin panel through this link : http://192.168.1.200/ghost/ . For the first time access, you have to insert your email and password.


Starting a service for Ghost

First you have to install Forever so we could continue running the Node server after the end of the SSH session

sudo npm install forever -g

Create a script in /etc/init.d so Forever will always start and as a service after restarts

sudo nano /etc/init.d/ghost

Now you can put some code in it

#! /bin/sh
# /etc/init.d/ghost

case "$1" in
    start)
        echo "Starting ghost"
        sudo NODE_EVN=production forever start /home/pi/blog/index.js
        ;;
    stop)
        echo "Stopping ghost"
        sudo forever stop /home/pi/blog/index.js
        ;;
    *)
        echo "Usage /etc/init.d/ghost {start|stop}"
        exit 1
        ;;
esac

exit 0

Save it with Ctrl + O and exit Ctrl + X

Make the script executable

sudo chmod 755 /etc/init.d/ghost

Done, your ghost will always start and running whenever you restart your PI server.

To test your script you can do the following commands

Start:

sudo /etc/init.d/ghost start

Stop:

sudo /etc/init.d/ghost stop

Usage:

sudo /etc/init.d/ghost 

Installing a ftp server

First, install the ftp server to your Pi

sudo apt-get install vsftpd

Modify ftp server configurations using nano

nano /etc/vsftpd.conf

Edit or uncomment the following lines

Anonymous_enable=NO
Local_enable=YES
Write_enable=YES
Ascii_upload_enable=YES
Ascii_download_enable=YES

Save it with Ctrl + O and exit Ctrl + X

Restart the ftp server

sudo /etc/init.d/vsftpd restart

Done, you can now using some FTP client (FileZilla) to connect to your PI server from your PC.


Using Uno theme by Dale-Anthony

I've found this free theme after setting up my blog, it looks pretty neat and simple to modify

From your Pi server, you can clone the theme project to your themes folder of Ghost:

cd blog/content/themes
git clone https://github.com/daleanthony/Uno.git

Or you can just download Uno, unzip it and then use the FTP client to connect to Pi Server and then copy unzipped Uno folder to your ghost's themes folder

Warning : You may need to restart Ghost after that, try using Stop and Start commands above

Now browse to your blog's admin panel and change your blog's theme to Uno: SETTINGS => THEME => Uno

You can modify Uno theme following the Uno FAQ steps.

The only thing i've done more is removing the homepage of the theme, I think the homepage is a little bit redundant, and it makes better UX without the homepage (just my opinion). So all you have to do is to modify the assets/js/main.js file in the Uno theme folder. Here is the modified code :

$(document).ready(function() {

    var goToBlog = function(){
        if ($('.panel-cover').hasClass('panel-cover--collapsed')) return;
        currentWidth = $('.panel-cover').width();
        if (currentWidth < 1100) {
            $('.panel-cover').addClass('panel-cover--collapsed');
            $('.content-wrapper').addClass('animated slideInRight');
        } else {
            $('.panel-cover').css('max-width',currentWidth);
            $('.panel-cover').animate({'max-width': '530px', 'width': '40%'}, 1000, swing = 'swing', function() {} );
        }
      }   

    $('body').removeClass('no-js');

    $('a.blog-button').click(goToBlog);

    if (window.location.hash && window.location.hash == "#blog") {
        $('.panel-cover').addClass('panel-cover--collapsed');
    }

    $('.btn-mobile-menu').click(function() {
        $('.navigation-wrapper').toggleClass('visible animated bounceInDown');
        $('.btn-mobile-menu__icon').toggleClass('icon-list icon-x-circle animated fadeIn');
    });

    $('.navigation-wrapper .blog-button').click(function() {
        $('.navigation-wrapper').toggleClass('visible');
        $('.btn-mobile-menu__icon').toggleClass('icon-list icon-x-circle animated fadeIn');
    });

    goToBlog();
});
comments powered by Disqus