Recommended VPS Complete list of best VPS hosting providers.

How to Install Ghost with Nginx on CentOS

This tutorial explains step by step guide (with pics) about how to install and setup Ghost blogging script with Nginx running at frontend while Node.js at the backend of CentOS virtual private server / vps.

As we all know that Ghost is a publishing script developed to run on Node.js, a development platform can be installed even on a low end vps and supports web server out of the box. It means basically Node.js requires no additional web server, unlike PHP. But however, in production server, using only Node.js is really not-so wise practice. And here Nginx is available for the cool action. Nginx is really a phenomenal free web server with unbelievable performance. Nginx is used for almost everything: gzip encoding, static file serving, HTTP caching, SSL handling, load balancing and spoon feeding clients.

Ghost + Nginx + Node.js = Awesome! While Node.js itself doesn’t need thirdparty web server, but you’ll need to do some advanced optimization tasks to use Node.js as production environment especially if you are targeting thousands online visitors hourly. So this is why Nginx comes in handy because it requires not-so advanced optimization and setup tasks. Well at least, many have been familiar with Nginx.

Some Ingredients..

..used in this tutorial:

  1. A VPS running CentOS. I use CentOS 6 32-bit running on a 128MB low end VPS by RamNode (SSD OpenVZ plan). You can use 64-bit especially if your box has more than 1024MB of RAM.
  2. Putty or Terminal on Mac and Linux to access your server.
  3. Basic knowledge about common bash command to manage a Linux vps.
  4. A cup of coffee or tea.

The Steps

Step 1 – Open up Putty or Terminal then login to your server as root or any user with root / sudo privilege.

Step 2 – In order to have Ghost lives on your server, the main requirement is Node.js must be available there. So go ahead install Node.js following my previous guide.

Step 3 – Next, install Ghost on your server via this guide. The steps are clear enough but one thing to note for this tutorial: pay attention to Step 12 point 3. Do not replace port 2368 with 80. You can leave the port as it is or use common secondary web port like 81, 82, or 8080. In this guide I stay with port 2368 (default).


Also, in the host part, use

Install Nginx

Step 4 – Now this part we’ll try to install Nginx on CentOS. You can follow my previous guide or simply follow what I gonna tell you below.

Step 4.a. Create nginx.repo file in yum.repos.d, nano editor will come in handy:

nano /etc/yum.repos.d/nginx.repo

Step 4.b. Now put these lines there:

name=nginx repo



Now save that file by hitting Control+O on your keyboard then Control+X to exit nano editor.

Step 4.c. Now install nginx using simple yum command:

yum install nginx -y



Once done, you’ll see something like this:

install nginx

Yayy! It’s Nginx v1.4.4.

Configuring Nginx

Step 5 – Now go to nginx default configuration directory:

cd /etc/nginx/



Step 5.a. Now make a backup copy of nginx.conf file (just for in case if things gone wrong):

cp nginx.conf nginx.conf.bak



Step 5.b. Open up nginx.conf file using file editor:

nano nginx.conf

Step 5.c. Delete everything in there and replace it with the text below:

user nginx;
worker_processes 1;
pid /var/run/;

events {
    worker_connections 768;
    # multi_accept on;

http {

    proxy_cache_path  /var/cache/nginx levels=1:2 keys_zone=one:8m max_size=3000m inactive=600m;
    proxy_temp_path /var/tmp;
    include       mime.types;
    default_type  application/octet-stream;
    sendfile        on;
    keepalive_timeout  65;

    gzip on;
    gzip_comp_level 6;
    gzip_vary on;
    gzip_min_length  1000;
    gzip_proxied any;
    gzip_types text/plain text/css application/json application/x-javascript text/xml application/xml application/xml+rss text/javascript;

    gzip_buffers 16 8k;

    upstream ghost_upstream {
      keepalive 64;

    access_log /var/log/nginx/access.log;
    error_log /var/log/nginx/error.log;

    include /etc/nginx/conf.d/*.conf;

replace 1 at worker_processes line with the number of how many CPU your vps is allocated. You can ask your vps provider but most providers have it written in their website. In this example, Ramnode allows only 1 CPU access for the 128MB SSD VZ plan, so I use 1.

Also, replace 2368 with the port you defined in your config.js file at ghost folder (example: 8080, 81, 82, etc).


Once done, hit Control+O to save then Control+X to exit editor.

Step 5.d. Now create the virtual host file for your site’s domain:

nano /etc/nginx/conf.d/domain.conf

replace domain.conf with your actual domain. Example:

nano /etc/nginx/conf.d/servermomghost.conf

Step 5.e. Now put these lines of code there:

    server {
    listen 80;

    server_name domain.tld www.domain.tld;

    if ($host = 'domain.tld' ) {
            rewrite  ^/(.*)$  http://www.domain.tld/$1  permanent;

#        location ~ ^/(ghost/signup/) {
#                rewrite ^/(.*)$ http://domain.tld/ permanent;
#        }

    location ~ ^/(img/|css/|lib/|vendor/|fonts/|robots.txt|humans.txt) {
      root /var/www/core/client/assets;
      access_log off;
      expires max;

    location ~ ^/(shared/|built/) {
      root /var/www/core;
      access_log off;
      expires max;

    location ~ ^/(favicon.ico) {
      root /var/www/core/shared;
      access_log off;
      expires max;

    location ~ ^/(content/images/) {
      root /var/www;
      access_log off;
      expires max;

    location / {
      proxy_redirect off;
      proxy_set_header   X-Real-IP            $remote_addr;
      proxy_set_header   X-Forwarded-For  $proxy_add_x_forwarded_for;
      proxy_set_header   X-Forwarded-Proto $scheme;
      proxy_set_header   Host                   $http_host;
      proxy_set_header   X-NginX-Proxy    true;
      proxy_set_header   Connection "";
      proxy_http_version 1.1;
      proxy_cache one;
      proxy_cache_key ghost$request_uri$scheme;
      proxy_pass         http://ghost_upstream;

Replace domain.tld with your own domain name and its TLD. In my example it is


example of mine:


Another note: you can delete these lines if you don’t want to use www. These lines force your blog to be accessible via www so you can delete it if you don’t want www.

    if ($host = 'domain.tld' ) {
            rewrite  ^/(.*)$  http://www.domain.tld/$1  permanent;

also change /var/www at this part with actual directory where you put Ghost:

    location ~ ^/(content/images/) {
      root /var/www;
      access_log off;
      expires max;

In my example it is at /var/www/ghost.

Done? Save it and exit.

Step 5.f. Finally, text your nginx configuration before running it:

nginx -t

If everything is ok you should see the OK message:


Step 6 – Start nginx using this command, make sure you get OK message:

service nginx start



Install Forever Service

Step 7 – Now issue this command to install Forever, a service to keep Ghost alive in the background and restart it if it ever stops or crashes:

npm install forever -g



Step 8 – Create a file called “” in /var/www directory:

nano /var/www/

Step 9 – now put these lines there, save it and exit:


if [ $(ps aux | grep node | grep -v grep | wc -l | tr -s "\n") -eq 0 ]
    export PATH=/usr/local/bin:$PATH
    export NODE_ENV=production
    NODE_ENV=production forever start --sourceDir /var/www index.js >> /var/log/nodelog.txt 2>&1



Step 10 – Now issue this command syntax to make sure that newly created .sh file is executable:

chmod +x /var/www/



Step 11 – Next, you may want to fix some permissions a bit:

chown -R nginx:nginx /var/www/



Step 12 – Next, create a new cron, type this command:

crontab -e

Step 13 – Now put this in that file:

@reboot /var/www/



Done? Save it and exit. You’ll get a message saying “crontab: installing new crontab“:


Step 14 – Finally, go to /var/www folder:

cd /var/www

Step 15 – then start Ghost using this command:


That’s it. Now open up your browser and try accessing your blog.


Enjoy.. 🙂

credit to Gregg Housh.


Add a Comment

Your email address will not be published. Required fields are marked *

Get more stuff like this
in your inbox

Subscribe and get interesting stuff plus faster updates to your email.