Install Ghost on ServerPilot and Digital Ocean in 2022

Start by creating a new app (eg. ghost_app). PHP version doesn't matter since we run NodeJS anyway. I used an existing serverpilot user. If you choose a different name for the app and a different user remember that  PATH will change later on in the guide: /srv/users/USERNAME/apps/APPNAME/

Login is as root and install or update NodeJS to v 16.17.0. which is the lates supported version for Ghost.


curl -sL | sudo -E bash
sudo apt-get install -y nodejs
node -v

And you will get the version

> 16.17.0

While you are logged in as root create a ghost user:

adduser ghostinstall
usermod -aG sudo ghostinstall

And install Ghost-CLI (or update if you already have it installed like I did)

npm install -g ghost-cli@latest

Now log in with the new user ghostinstall (this is a different/second user name than the serverpilot user we used creating the app. You will now chown the folder to the new user and remove index.php in the public folder. The public folder needs to be completely empty!

ssh ghostinstall@YOUR_IP_ADDRESS
cd /srv/users/serverpilot/apps/ghost_app/
sudo chown -R ghostinstall:ghostinstall .

cd public
rm index.php

Create a new Database in Serverpilot and call it ghost_db and write down the username and password which be generated for you (a long hex value). You will need all the info in the next step.

Now while in /srv/users/serverpilot/apps/ghost_app/public

ghost install

You will need to provide some info in the last step. If you for some reason make blunder you can run ghost setup to correct the info.

? Enter your blog URL: https://YOURDOMAIN
? Enter your MySQL hostname: localhost
? Enter your MySQL username: SOME_HEX_VALUE
? Enter your MySQL password: [hidden] SOME_HEX_VALUE
? Enter your Ghost database name: ghost_db

✔ Configuring Ghost
✔ Setting up instance
+ sudo chown -R ghost:ghost /srv/users/serverpilot/apps/ghost_App/public/content
? Sudo Password [hidden]
✔ Setting up "ghost" system user
ℹ Setting up "ghost" mysql user [skipped]
Nginx is not installed. Skipping Nginx setup.
ℹ Setting up Nginx [skipped]
Nginx setup task was skipped, skipping SSL setup
ℹ Setting up SSL [skipped]
? Do you wish to set up Systemd? Yes
? Do you want to start Ghost? Yes

And the final steps

Check which port your ghost is running (2368 is default) but I have two other ghost instances running already so my port is 2370.

cd /srv/users/serverpilot/apps/ghost_app/public
cat config.production.json
  "url": "https://YOURDOMAIN",
  "server": {
    "port": 2370,
    "host": ""
nano .htaccess

And paste this, save and exit (Ctrl+X and Yes) and use the portnumber from above.

RewriteRule index.html http://localhost:2370/ [P]
RewriteRule (.*) http://localhost:2370/$1 [P]

And at last you need the serverpilot to own the .htaccess file

sudo chown -R serverpilot:serverpilot .htaccess


Permission error when running ghost run

ghost run
  throw err;

Error: Cannot find module '/srv/users/serverpilot/apps/ghost_app/public/current/index.js'
    at Function.Module._resolveFilename (node:internal/modules/cjs/loader:956:15)
    at Function.Module._load (node:internal/modules/cjs/loader:804:27)
    at Function.executeUserEntryPoint [as runMain] (node:internal/modules/run_main:81:12)
    at node:internal/main/run_main_module:17:47 {
  requireStack: []

Fix (if you you are logged in as ghostinstall and run ghost run )

sudo chown -R ghostinstall:ghostinstall ./content

✖ Starting Ghost: newii-se
A GhostError occurred.

Message: Could not communicate with Ghost
Suggestion: journalctl -u ghost_newii-se -n 50

Remove the bootstrap-socket section in config.production.json

nano config.production.json

Use Ctrl+K to remove one line in nano

  "bootstrap-socket": {
    "port": 8000,
    "host": "localhost"

Don't forget to remove the comma to make it a valid JSON

  "process": "systemd",
  "paths": {
    "contentPath": "/srv/users/serverpilot/apps/ghost_app/public/content"

Change permission of the content folder. (Ghost will tell you to run with ghost:ghost - that is wrong if your ghostinstall. (Same as the error with ghost run)

sudo chown -R ghostinstall:ghostinstall ./content

Make sure systemd uses the correct User ID for ghostinstall

cat /etc/passwd | grep ghostinstall
ghostinstall:x:1006:1006:Ghost Install,,,:/home/ghostinstall:/bin/bash
sudo cat /lib/systemd/system/ghost_example-com.service
Description=Ghost systemd service for blog: newii-se

ExecStart=/usr/bin/node /usr/bin/ghost run


Start the service deamon manually instead of ghost run

sudo systemctl start ghost_example-com

Ghost assumes the User ID in /lib/systemd/system/ghost_example-com.service must be ghost

✖ Starting Ghost: newii-se
A SystemError occurred.

Message: Systemd process manager has not been set up or is corrupted.
Help: Run ghost setup linux-user systemd and try again.

Fix: Just start the deamon instead of ghost run

sudo systemctl start ghost_example-com

Use useful commands (note the use of dash instead of the dot, and small-caps)

systemctl cat ghost_example-com.service
journalctl -u ghost_example-com -n 50
stat --format '%a' <file>

Installing Ghost as an App in ServerPilot -
Updated Note 4/2/19: While the information below is still valid, I’ve since moved away from ServerPilot and now use RunCloud. You can read my post as to why I switched here. ServerPilot is great, and I recommend them to anyone. I use their service almost exclusively to manage multiple WordPress inst…
#1 · A fix for the “Systemd process manager has not been set up or is corrupted” Ghost error
This error can be caused by an issue with permissions
SystemError occurred when running ghost start: “Systemd process manager has not been set up or is corrupted.”
Here is the output from ghost setup systemd: stephen@builders:/var/www/$ ghost setup systemd Love open source? We’re hiring Node.js Engineers to work on Ghost full-time. Systemd service has already been set up. Skipping Systemd se…