Installing Ghost blog on Fedora

My ghost blog is at version 0.7.8 so it's getting a bit outdated with the release of 0.11.3 (and soon the 1.0!). I decided to install it on a Fedora VM and found that there aren't many articles out there.

So here it is: A how-to for installing Ghost on Fedora 25 as a system service and proxied through nginx. If you're more interested in applying my automation efforts on a fresh droplet, I'm working on a script that automates most of the steps in this article.

Prerequisites

This post is specific to Fedora and I'm using DigitalOcean's 1-CPU 512MiB droplet using Fedora 25.

Enable the swapfile for 512MiB VMs

To prevent Ghost's npm install --production call from failing, a swapfile needs to be created. Read the Fedora manual entry for the quick details, or DigialOcean has a detailed post.

Commands to enable a swapfile:

fallocate -l 1G /swapfile  
chmod 0600 /swapfile  
mkswap /swapfile  
swapon /swapfile  
echo "/swapfile swap swap sw 0 0" >> /etc/fstab  

Verify it's enabled with swapon -s.

Set selinux to permissive

The Ghost service won't start if selinux is enforcing so we want to set it to permissive. I have a TODO on configuring this properly. Stop the enforcement by modifying /etc/selinux/config and setting SELINUX=permissive. Reboot.

Install Ghost

Ghost needs a few OS dependencies then we can use npm to install ghost. However, it's bad practice to use npm with root so we'll create a ghost user and fix permissions on the webroot.

Here's how to do the above as root:

# Install deps
dnf install -y nginx nodejs npm python unzip  
mkdir -p /var/www/ghost

# Fetch and extract source
pushd /var/www/ghost  
  curl -L https://github.com/TryGhost/Ghost/releases/download/0.11.3/Ghost-0.11.3.zip -o ../ghost.zip
  unzip ../ghost.zip -d .
popd

# Create a system user and fix permissions
useradd --system --create-home --shell /bin/false --user-group ghost  
chown -R ghost:ghost /var/www/ghost

# Install Ghost using a non-root account
sudo -H -u ghost /bin/bash -c "cd /var/www/ghost && npm install --production"

If the npm install --production step fails check that the swapfile is enabled and check permissions. Look at the troubleshooting guide for more tips.

Configuration

This part isn't so much fun. There are a few pieces to configure: systemd unit file for a Ghost service; nginx server; nginx to proxy to ghost; ghost.

Ghost systemd unit file

A nice-to-have is Ghost to start on boot and restart itself after a crash. We can do that by creating a systemd unit file.

Create /etc/systemd/system/ghost.service:

[Unit]
Description=ghost  
After=network.target

[Service]
Type=simple  
WorkingDirectory=/var/www/ghost  
User=ghost  
Group=ghost  
Environment=NODE_ENV=production  
ExecStart=/usr/bin/node index.js  
Restart=on-failure  
SyslogIdentifier=ghost

[Install]
WantedBy=multi-user.target  

Now scan for the new unit file, enable ghost on boot, and start it:

systemctl daemon-reload  
systemctl start ghost  
systemctl enable ghost  

Make sure Ghost is running with systemctl status ghost and looking for active (running) in the output. If it failed: double check permissions, selinux policy, and the installation steps.

Nginx server configuration

This how-to assumes a fresh host and the stock configuration has a conflicting default_server. We'll use the below config and not define a server block.

Create /etc/nginx/nginx.conf:

user nginx;  
worker_processes auto;  
error_log /var/log/nginx/error.log;  
pid /run/nginx.pid;  
include /usr/share/nginx/modules/*.conf;

events {  
  worker_connections 1024;
}

http {  
  log_format  main  '$remote_addr - $remote_user [$time_local] "$request" '
                    '$status $body_bytes_sent "$http_referer" '
                    '"$http_user_agent" "$http_x_forwarded_for"';
  access_log  /var/log/nginx/access.log  main;
  sendfile            on;
  tcp_nopush          on;
  tcp_nodelay         on;
  keepalive_timeout   65;
  types_hash_max_size 2048;
  include             /etc/nginx/mime.types;
  default_type        application/octet-stream;
  include /etc/nginx/conf.d/*.conf;
  gzip on;
  gzip_disable "msie6";
}

NGINX proxy configuration

Our nginx configuration will read configurations from /etc/nginx/conf.d/*.conf, and that's where we'll create the server block to proxy.

Create /etc/nginx/conf.d/mydomain.conf with a simple server block:

server {  
  listen 80 default_server;
  server_name mydomain.com;
  client_max_body_size 2G;
  location / {
    proxy_pass http://localhost:2368;
    proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;
    proxy_set_header Host $http_host;
    proxy_set_header X-Forwarded-Proto $scheme;
    proxy_buffering off;
  }
}

Have nginx start on boot and start it:

systemctl enable nginx  
systemctl start nginx  

Use systemctl status nginx to see if things are working. If so, navigate to http://<yourdomain> and check that ghost is working. It should be :)

Ghost configuration

Ghost has a default configuration that "works" but it's not ideal. Look at /var/www/ghost/config.example.js and read the Ghost manual. Be sure to update the file permissions if any new files are added.

Next Steps

With Ghost installed and working you'll want to change the theme. Probably configure a comment service like Disqus. Email and Domain Keys Identified Mail (DKIM) using AWS. Setup HTTPS using letsencrypt. Maybe add a load balancer if you're really cool.

Let me know if this has worked for you!


Powered by Digital Ocean

Click the image for a $10 referral