Installing Ghost on DreamHost 2022

I've used and supported Wordpress for the last 10+ years for my own blogs and those of my friends, family and clients.  I grew tired of the constant security updates and issues that arose over the years.  It came to a head recently when Dreamhost disabled my wife's personal blog.  Their security staff identified malware that was sending large amounts of email.  Dreamhost's response and handling of the situation made it more difficult, but that's another story for later.

I decided if I was rebuilding her blog, I might look to see what else was available.  I looked at several different options and I found Ghost to be compelling.  It seemed to be simple, elegant and provide for easy customization.  I ran it locally in docker and explored using the Wordpress plugin to create a Ghost export file and import it locally.

The following guide is a list of steps I took and I'm documenting it here for the next time I need to do this for myself or someone else.  If you're on Dreamhost and looking to install Ghost, this may be helpful for you too.


The prerequisites to this guide is to have a Dreamhost account, add a domain with a configuration that enables Phusion Passenger, nodejs and an ssh user.

Install nvm

curl -o- https://raw.githubusercontent.com/nvm-sh/nvm/v0.39.1/install.sh | bash

I had to source my .bashrc every time I logged in to ensure I could use anything I installed.  I'm sure there's probably something else to configure with Dreamhost to avoid this, but at the time of this writing I didn't take the time to research.

source ~/.bashrc

Find a version of node supported by both DH and Ghost.  12 is the latest version I could find that worked.

nvm install 12
nvm use 12

Change to the domain directory,  remove the public directory and install ghost via the installer

cd {domain}
rm -rf public
npm install ghost-cli@latest -g

Fix the permissions on the home directory.

chmod 755 $HOME

Install ghost with the following command and answer any prompts.

ghost install --db=sqlite3 --no-setup-linux-user --no-setup-nginx --no-setup-ssl --no-setup-systemd

Create an app.js file in {domain} directory for Phusion Passenger to run and add the following line to it

const app = require('./current/index.js');

Change the config file to set the url, port and host

vim config.production.json
{
    "url": "https://somedomain.net",
        "server": {
        "port": 443,
        "host": "0.0.0.0"
    },
    "database": {
        "client": "sqlite3",
        "connection": {
        "filename": "/home/someuser/somedomain.net/content/data/ghost.db"
        }
    },
    "mail": {
        "transport": "Direct"
    },
    "logging": {
        "transports": [
            "file",
            "stdout"
        ]
    },
    "process": "systemd",
    "paths": {
        "contentPath": "/home/someuser/somedomain.net/content"
    }
}
cd ~/
mkdir tmp
touch tmp/restart.txt

Create the public directory and .htaccess file


mkdir {domain}/public
vim {domain}/public/.htaccess
# paste the following code into the .htaccess file.
# change the $USER to your actual username 
PassengerNodejs /home/$USER/.nvm/versions/node/v12.22.9/bin/node
PassengerFriendlyErrorPages on

Update (16 March 2022):

At this point you maybe find yourself with a non-working app.  I had to "Reload HTTP" from the Dreamhost panel for the site to start working properly.

Subscribe to Ryan Brady

Don’t miss out on the latest issues. Sign up now to get access to the library of members-only issues.
jamie@example.com
Subscribe