Ghost 1.0 on Laravel Forge

I have been running both my daughter's and my Ghost pre-1.0 blogs on Laravel Forge for quite a while, but installing it and getting it to run with the new ghost-cli
was a bit of a challenge, so I thought I'd write it up in case anyone else is interested.
First off this tutorial will assume you have a basic understanding of setting up a server on Forge, and a basic understanding of getting around on the command line, otherwise this may not be the right tutorial for you.
1. Let's create a new server
I prefer Linode, not only for their pricing, but for the incremental control you get in their backend panel.
Notice that I changed the database name, but you don't have to, and installed MariaDB.
Once the main process has begun, you'll receive a modal notice like so:
Make sure you write those down in case something happens with your email sent from Forge that contains these passwords.
Your panel should look similar to the below:
Now while your server is provisioning you can take your newly assigned IP address and point your domain to the server. I'll leave that up to you, if you have an option on TTL set it to 300 so it can propagate as quickly as possible.
Once you server is provisioned you should see this:
Click on the refresh icon to make sure you can connect to your server.
Once you know you can connect, we can move forward and add your blog domain.
2. Create Website
Since this is just a temp server and blog site for this tutorial, I set it up as a sub-domain off one of my main domains.
Notice I set the project type to Static HTML
and very important, set your Web Directory
to /ghost/current
, this is where your blog will be served from.
Once your site is created you can go ahead and remove the default
site.
Before we go on, let's make sure our domain has propagated, we can do that with the OpenDNS Cache Tool like so:
As you can see the domain is pointing to our server, so we're good to go. You want to wait till this is done before you move forward.
Let's continue.
3. Nginx and SSL
Ghost 1.0 is a whole new animal really, you should read up on it to get all the details, but with the ghost-cli
you'll have a wonderful new installation and upgrade experience, part of which is the built in Nginx
and SSL
options during the install.
But, because we want to manage those with Forge, we'll skip them during the ghost-cli
install later.
First, let's make sure our site is live, Forge will automatically set up a phpinfo
page for us so, click into your site and at the top right you'll see something similar to this:
The green arrow icon, circled in red here, will take you straight to your site and you should see the default phpinfo
page:
Perfect, we have some content so we can install Let's Encrypt.
Let's Encrypt
Click on your SSL tab, then the Let's Encrypt, remove the www
version of the domain (since I'm using a sub-domain, you may want to keep it):
Once your certificate is installed, go ahead and activate it, then check your site again to make sure you're getting the phpinfo
page via https
.
If you have success, we can move on.
Nginx Config
At the bottom of each page under your site there is an Edit Files button, click that then the Edit Nginx Configuration
The config for this server I'm setting up, looks like so:
# FORGE CONFIG (DOT NOT REMOVE!)
include forge-conf/blog.19peaches.com/before/*;
server {
listen 443 ssl http2;
listen [::]:443 ssl http2;
server_name blog.19peaches.com;
root /home/forge/blog.19peaches.com/ghost/current;
# FORGE SSL (DO NOT REMOVE!)
ssl_certificate /etc/nginx/ssl/blog.19peaches.com/228707/server.crt;
ssl_certificate_key /etc/nginx/ssl/blog.19peaches.com/228707/server.key;
ssl_protocols TLSv1 TLSv1.1 TLSv1.2;
ssl_ciphers 'ECDHE-RSA-AES128-GCM-SHA256:ECDHE-ECDSA-AES128-GCM-SHA256:ECDHE-RSA-AES256-GCM-SHA384:ECDHE-ECDSA-AES256-GCM-SHA384:DHE-RSA-AES128-GCM-SHA256:DHE-DSS-AES128-GCM-SHA256:kEDH+AESGCM:ECDHE-RSA-AES128-SHA256:ECDHE-ECDSA-AES128-SHA256:ECDHE-RSA-AES128-SHA:ECDHE-ECDSA-AES128-SHA:ECDHE-RSA-AES256-SHA384:ECDHE-ECDSA-AES256-SHA384:ECDHE-RSA-AES256-SHA:ECDHE-ECDSA-AES256-SHA:DHE-RSA-AES128-SHA256:DHE-RSA-AES128-SHA:DHE-DSS-AES128-SHA256:DHE-RSA-AES256-SHA256:DHE-DSS-AES256-SHA:DHE-RSA-AES256-SHA:AES128-GCM-SHA256:AES256-GCM-SHA384:AES128-SHA256:AES256-SHA256:AES128-SHA:AES256-SHA:AES:CAMELLIA:DES-CBC3-SHA:!aNULL:!eNULL:!EXPORT:!DES:!RC4:!MD5:!PSK:!aECDH:!EDH-DSS-DES-CBC3-SHA:!EDH-RSA-DES-CBC3-SHA:!KRB5-DES-CBC3-SHA';
ssl_prefer_server_ciphers on;
ssl_dhparam /etc/nginx/dhparams.pem;
add_header X-Frame-Options "SAMEORIGIN";
add_header X-XSS-Protection "1; mode=block";
add_header X-Content-Type-Options "nosniff";
index index.html index.htm index.php;
charset utf-8;
# FORGE CONFIG (DOT NOT REMOVE!)
include forge-conf/blog.19peaches.com/server/*;
location / {
try_files $uri $uri/ /index.php?$query_string;
}
location = /favicon.ico { access_log off; log_not_found off; }
location = /robots.txt { access_log off; log_not_found off; }
access_log off;
error_log /var/log/nginx/blog.19peaches.com-error.log error;
error_page 404 /index.php;
location ~ \.php$ {
fastcgi_split_path_info ^(.+\.php)(/.+)$;
fastcgi_pass unix:/var/run/php/php7.1-fpm.sock;
fastcgi_index index.php;
include fastcgi_params;
}
location ~ /\.(?!well-known).* {
deny all;
}
}
# FORGE CONFIG (DOT NOT REMOVE!)
include forge-conf/blog.19peaches.com/after/*;
We're going to make 4 edits:
- index
- location/
- error_page
- location ~ .php$
Scroll down in the file and change the index
line to:
index index.js index.html index.htm index.php;
Next remove the location/
block completely, we don't need this at all.
location / {
try_files $uri $uri/ /index.php?$query_string;
}
Next, change the error_page
to the following:
error_page 404 /index.js;
Lastly we're going to remove the entire php
location block so we can serve all our blog content via Node.
Find this block:
location ~ \.php$ {
fastcgi_split_path_info ^(.+\.php)(/.+)$;
fastcgi_pass unix:/var/run/php/php7.1-fpm.sock;
fastcgi_index index.php;
include fastcgi_params;
}
And replace it with the below:
location / {
proxy_pass http://127.0.0.1:2368;
proxy_http_version 1.1;
proxy_set_header Upgrade $http_upgrade;
proxy_set_header Connection 'upgrade';
proxy_set_header Host $host;
proxy_cache_bypass $http_upgrade;
}
Save and close the modal. Go out to main dashboard and check the Recent Events log and make sure that Nginx was reloaded, if not use the restart drop down in the server interface to restart Nginx.
4. Database
You will need a database tool to log into the database, unless you're a complete newbie to Forge, you already have one, so setting that up I'll leave to you as I can't give instructions for every tool out there.
I use Querious exclusively so any screens you find on this blog for database interaction will be examples from Querious.
Log in to the server with your database tool, and check that the ghostserver
database created by Forge and make sure that it's using the proper charset and collation. I want the most flexible unicode collation, it's up to you, but I'd prefer using utf8mb4
and utf8mb4_0900_ai_ci
, so I'll just drop this db and make a new one.
You can see now it's set up correctly, as I said this is optional, but I know it works so it's what I'm recommending.
5. Command Line Work
Time to log into the server via ssh
and get everything for installed for Ghost. The official Ghost docs is fairly close, but I found some variations that needed to be made in order to get this installed, hence the main reason for this tutorial.
But first things first, let's get logged in, open a terminal window:
$ ssh forge@IP_ADDRESS
Something I like to do, as a little tip, if I know I'm gonna be doing a bit of sudo work, I'll change my forge password to something simple, then change it back when I'm finished, that way I don't have to copy and paste my sudo pass all the time.
$ passwd
Enter the old pass then a new simple one and confirm. Just don't forget to change it back before you log out of the server.
Node JS
Forge installs node via NVM
and this conflicts with ghost-cli
so first we'll remove the existing Node install, and install from the NodeSource APT repository.
$ sudo rm -rf $NVM_DIR ~/.npm ~/.bower
$ unset NVM_DIR;
$ which node;
$ sudo rm -rf {path_to_node_version}
{path_to_node_version}
being the output from which node
Once complete which node
should return nothing.
Now let's install Node from NodeSource.
First add the repository.
$ curl -sL https://deb.nodesource.com/setup_6.x | sudo -E bash
This should install Node, but it installs it as /usr/bin/nodejs
instead of /usr/bin/node
, so to check it, run both:
$ which node
$ which nodejs
If you get nothing for either command, then install it manually like so:
$ sudo apt-get install -y nodejs
I've installed this several times and it always installs to /usr/bin/nodejs
so if it does for you, we need to move that to:
$ sudo mv /usr/bin/nodejs /usr/bin/node
Now check the Node version:
$ node -v
As of this writing, NodeSource installs v8.2.1 ARRGGGG! We need 6.5!
So, let's install n
so we can select which version we want to use.
$ sudo npm cache clean -f
$ sudo npm install -g n
$ sudo n 6.5
We should be good to go now, install ghost-cli
$ sudo npm i -g ghost-cli
Installing Ghost
Let's navigate to your domain directory, in our case here to:
$ cd blog.19peaches.com
When you list the directory you should see only the existing ghost
directory that Forge set up for us.
$ ls -a
Let's remove this entire directory:
$ sudo rm -rf ghost
This will remove the current
directory and our phpinfo
page as well.
Let's make a new ghost directory and move into it:
$ mkdir ghost && cd ghost
Now we can run the ghost-cli
installer:
$ ghost install
If you get a permission error, follow the resolution shown by ghost-cli
.
During the installation you will be prompted for the following (I've written the answers as well for this install)
Enter your blog URL: http://blog.19peaches.com
Enter your MySQL hostname: 127.0.0.1
Enter your MySQL username: forge
Enter your MySQL password: [Forge created Database password]
Enter your Ghost database name: ghostserver
# DO NOT SET UP NGINX
# Answering no will skip the SSL set up as well
Do you wish to set up Nginx? n
# DO NOT SET UP GHOST MYSQL USER
Do you wish to set up "ghost" mysql user? n
# SAY YES TO SYSTEMD
Do you wish to set up Systemd? Y
Do you want to start Ghost? Y
Now go check your site!
If for some reason you get an error, try restarting ghost and nginx.
$ sudo ghost restart
$ sudo service nginx restart
Don't forget if you changed your password to change it back before you log out.
6. Conclusion
Laravel Forge is an amazing tool and sets up such a great server environment, don't just use it for your Laravel or PHP sites, it's great for everything, even if you have to do some customizing to get there.
There's more configuration you can do of course, and you need to log in and make your account and all that, upload a theme etc.
I love Ghost and I think you'll really love this new version.
See ya out there.