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!