When I first setup my Ghost blog on my own server (a self-managed Linode which has been great and I highly recommend them), I installed Node.js directly under my main user account. I eventually ran into the problem of needing/wanting to use different versions of Node.js for different applications, so I uninstalled Node.js and installed/used nvm instead. It occurred to me that I might be better off running the Ghost application under a different user account, so that it could manage it’s own nvm/Node.js versions and global npm packages. I did nothing about it at the time, but I recently wanted to be able to run two applications which needed different Node.js versions simultaneously.
My Linode is running CentOS 7, but the process should be pretty similar across Linux distributions, this is an overview of how I’m setup to run Ghost:
- Node.js and npm are installed and managed by nvm
- The Ghost application is setup under
/var/www/benbooth.co
- nginx is being used as a reverse proxy to forward requests to the Ghost application
- The Ghost application is always running and starts on server start using PM2
- Keymetrics monitoring through PM2
Create the new user
Let’s get started, firstly you’ll need to create the new user:
[user]$ sudo useradd [username]
I’m creating a user called ghost
to run my blog, so I’d run sudo useradd ghost
(tip: to fully delete the user including home directory, use sudo userdel -r ghost
). If you want to set a password for the new user type passwd [username]
. I don’t want to be able to login directly to this user, so I’m not going to set a password, we can switch to the new user by typing:
[user]$ sudo su ghost
Which switches to the new user, but stays in the same working directory. Pass the -l
(or just -
) option to login to the new users’ home directory (eg. sudo su - ghost
).
Setup Node.js using nvm
Next we need to install nvm and then install Node.js. Download and run the nvm installer script (this is the latest version at the time of writing, check the nvm GitHub repo for the latest version). If you haven’t already, change to the new user first sudo su - ghost
.
[ghost]$ curl -o- https://raw.githubusercontent.com/creationix/nvm/v0.25.4/install.sh | bash
Then install a Node.js version and tag it as default
. (You might need to source ~/.bashrc
before you use nvm if you just installed it):
[ghost]$ nvm install 0.10
[ghost]$ nvm alias default 0.10
At the time of writing, Ghost requires Node.js version 0.10.*
(0.10.38
is the latest at the time of writing).
Install PM2
Installing PM2 is a straight-forward npm global install:
[ghost]$ npm install -g pm2
Stop the existing Ghost instance
Next, if you haven’t already, stop the existing Ghost instance running under your user account (exit
the ghost
user shell to take you back to your user shell):
[user]$ pm2 stop ghost
[user]$ pm2 delete ghost
[user]$ pm2 save
This is assuming you were already running the blog using PM2 with the name ghost
. pm2 save
dumps the list of currently running processes to file so it can be restored later, this is one part of keeping Ghost running even after the server restarts. To cleanup the rest, run these commands too (we’ll set these up again with the new user account):
[user]$ sudo chkconfig --del pm2-init.sh
[user]$ sudo rm /etc/init.d/pm2-init.sh
[user]$ sudo rm /var/lock/subsys/pm2-init.sh
Run the Ghost application under the new user account
Next you’ll need to get Ghost running under the new user account. Firstly, change the ownership of all files (my Ghost instance is installed to /var/www/benbooth.co
):
[user]$ cd /var/www/
[user]$ sudo chown -R ghost:ghost benbooth.co/
I don’t think it would be necessary, but just to be sure, I cleared out the node_modules
and re-installed the dependencies under the new user account (remember to change to the new user account):
[user]$ sudo su ghost
[ghost]$ cd benbooth.co/
[ghost]$ rm -rf node_modules/*
[ghost]$ npm install --production
Finally, run the Ghost application using PM2 and save the running PM2 processes to file:
[ghost]$ NODE_ENV=production pm2 start index.js --name "ghost"
[ghost]$ pm2 save
Persist Ghost application across server restarts
Keeping PM2 and your Ghost application running across server restarts is a little different depending on your OS/distribution, but PM2 will try to help you as much as possible. Just run:
[ghost]$ pm2 startup [platform]
For me, running CentOS, I run pm2 startup centos
. This will not work because it needs to be run using sudo
and I don’t want to give my ghost
user sudo
permission. It will give you a full command that you can run using sudo
but linked to the ghost
user, copy that command. Now exit
from the ghost
shell back to your user shell and either run the copied command using sudo
, or sudo su
to get a root
shell, and then run the copied command.
At this stage I found that the startup script wasn’t actually bringing up the PM2 daemon, I had to manually edit the /etc/init.d/pm2-init.sh
file to fix an issue (I’m assuming this is a bug, so should be temporary):
[user]$ sudo vim /etc/init.d/pm2-init.sh
Look for the line USER=[username]
. In my case, this was set to USER=root
and I just had to change it to USER=ghost
and save the file.
Extra: Add Keymetrics monitoring
Keymetrics offers good free monitoring for PM2 applications, if you haven’t already, register for an account. You’ll get a private key and a secret key. Linking it to your PM2 instance is super-simple:
[ghost]$ pm2 link [YOUR_SECRET_KEY] [YOUR_PUBLIC_KEY]
If you keep an eye on the Keymetrics dashboard, you should start seeing a heartbeat from your server shortly.
If you already had Keymetrics running under your user account, and aren’t running any other PM2 applications, feel free to delete the Keymetrics link:
[user]$ pm2 link delete [YOUR_PUBLIC_KEY]