Self-hosting GHOST CMS with Google Cloud Platform, MySQL, sftp
All in one guide to create Ghost CMS on Google Cloud, with Cloudflare to set up a fast, functional, and affordable publishing platform.
Ghost CMS is excellent for writers, bloggers, and professional publishers. It comes with a sleek & modern user interface that allows paid subscriptions for members. Compared to WordPress, Ghost wins overall on its loading speed, functionality, and affordability. These are important factors for the admin considering SEO, work productivity, and reducing overhead.
Before getting started, consider your circumstances. This guide would be suitable if you're starting from scratch or looking for alternatives to avoid monthly subscription fee services like DigitalOcean. You can get your domain from here and set up your Cloudflare here.
If you were using SQLite or looking to upgrade GHOST from a different infrastructure, this guide will not be suitable.
Prerequisite
- Domain
- Google Cloud Platform (free - low cost)
- Cloudflare
- Ghost Client v5.8x.x
Setting up an instance in Google Cloud Platform
The following stack will be installed onto an instance in the Google Cloud platform. Take note of the versions for each technology stack below. This will affect the setup process.
Stack overview
- Ubuntu 20.04 or Ubuntu 22.04
- NGINX (minimum of 1.9.5 for SSL)
- Node Version: v18.20.3
- MySQL 8
- Systemd
- A server with at least 1GB memory
Step 1: Set up your account
You'll need to sign up for a free account on the Google Cloud Platform. For new customers, you can benefit from the $300 credits for 90 days. The program coverage is only based on these free usage limits.
Visit this page for more details on how to set up your free google cloud platform.
Once you're in your GCP dashboard, create a new project and select your project.
Step 2: Enable Compute Engine
Navigate to Compute Engine
You'll need to enable Compute Engine API, and set up your billing profile.
Step 3: Create & set up a VM instance
Navigate to Compute Engine > VM instance.
Create your instance with the following and leave the others as default.
Machine Configuration
- Series E2
- at least e2-micro
Boot disk
Operating system:
-
Ubuntu 22.04 LTS
x86/64, amd64 jammy image built on 2024-06-28 -
Boot disk type: Standard
-
Size: 30GB
Firewall
Allow HTTP traffic + Allow HTTPS traffic
Step 4: Update DNS with external IP address
Part of Ghost prerequisites is to set up the DNS record first.
You should update these records on Cloudflare so that SSL can be configured during setup.
A
name: yourdomain.com
value: external IP address
TXT
name: yourdomain.com
value: external IP address
CNAME
name: yourdomain.com
value: external IP address
Step 5: Set up Google Cloud instance
This part requires you to follow along step-by-step. By the end of step 5, you'll complete installing these within your Google Cloud instance.
- Ubuntu 20.04 or Ubuntu 22.04
- NGINX (minimum of 1.9.5 for SSL)
- Node Version: v18.20.3
- MySQL 8
- Systemd
- SSH Keys
The entire process takes about 1-2 hours depending on your internet speed.
Set up SSH keys
On your local machine, open up your terminal and key in this command.
Replace 'your_SSHkey_filename' with an SSH file name of your preference.
Important: Copy the command you've used and SSH key on your local notepad, you'll need this later.
Go to your GCP instance
- Click on the
Edit
button at the top. - Scroll down to the
SSH Keys
section. - Click on
Add item
and paste the public SSH key into the box.
Connecting to GCP instance
- Go back on your local machine's terminal
- Connect to your instance using SSH command
Update 'your_SSHkey_filename' , 'your_username', 'your_instsance_external_ip'
ssh -i ~/.ssh/your_SSHkey_filename your_username@your_instance_external_ip
Important: Copy the command you've used on your local notepad, you'll need this later.
If you're unclear about how to update - Here is an example.
Say you have the following details:
- SSH file name is ghost-instance
- Local machine username is admin
- GCP External IP address of 123.123.123
Your SSH command should look like this:
ssh -i ~/.ssh/ghost-instsance [email protected]
You should see results like below. Type 'yes' to accept into SSH.
Are you sure you want to continue connecting (yes/no/[fingerprint])? y
Please type 'yes', 'no' or the fingerprint: yes
Once successful, you'll see something like this:
Welcome to Ubuntu 22.04.4 LTS (GNU/Linux 6.5.0-1022-gcp x86_64)
* Documentation: https://help.ubuntu.com
* Management: https://landscape.canonical.com
* Support: https://ubuntu.com/pro
System information
System load: 0.0 Processes: 100
Usage of /: 6.4% of 28.89GB Users logged in: 0
Memory usage: 23% IPv4 address for ens4: 11.111.0.11
Swap usage: 0%
Now we can proceed with the next steps for setting up Ghost CMS on your Ubuntu 22.04 LTS instance.
Update Your System Packages
First, ensure that your system packages are up to date. Run the following commands:
sudo apt update
sudo apt upgrade -y
Install NGINX
- Install NGINX, which is required to serve Ghost CMS. Run the following commands:
sudo apt install nginx -y
- After installation, start and enable NGINX to ensure it runs on system startup:
sudo systemctl start nginx
sudo systemctl enable nginx
sudo ufw allow 'Nginx Full'
Review and Adjust Firewall Rules
- Check Existing Rules:
First, let's list the existing firewall rules to see if there might be any conflicts or missing rules.
codesudo ufw status verbose
Allow Essential Ports:
Ensure that the following ports are open:
- HTTP (80)
- HTTPS (443)
- SSH (22)
sudo ufw allow 80/tcp
sudo ufw allow 443/tcp
sudo ufw allow 22/tcp
Check and Adjust Incoming Traffic:
Allow incoming traffic for necessary services.
sudo ufw allow from any to any port 80,443 proto tcp
sudo ufw allow from any to any port 22 proto tcp
Allow Outbound Traffic:
Make sure that outbound traffic is not being restricted.
sudo ufw default allow outgoing
Apply the Changes: Enable the firewall with the new rules.
sudo ufw enable
Install MySQL
Ghost CMS requires MySQL. We'll install MySQL and set up a root password.
- Install MySQL Server:
sudo apt-get install mysql-server
- Create root user for MySQL
This command enters into mysql
sudo MySQL
Update permission for root user
- Replace
<your-new-root-password>
with your desired password.
ALTER USER 'root'@'localhost' IDENTIFIED WITH mysql_native_password BY '<your-new-root-password>';
Reread permission
FLUSH PRIVILEGES;
Exit sql
exit
- Verify MySQL
To verify that MySQL is working correctly, you can log in to the MySQL server using the new root password you set up. Here are the steps to do so:
Log in to MySQL:
mysql -u root -p
- Enter your root password when prompted.
- Check the MySQL version and show databases to ensure it is functioning correctly:
SELECT VERSION();
SHOW DATABASES;
Exit MySQL
exit
If you managed to successfully enter MySQL, you'll see a similar result like this
Welcome to the MySQL monitor. Commands end with ; or \g.
Your MySQL connection id is
Server version: 8.0.37-0ubuntu0.22.04.3 (Ubuntu)
Copyright (c) 2000, 2024, Oracle and/or its affiliates.
Oracle is a registered trademark of Oracle Corporation and/or its
affiliates. Other names may be trademarks of their respective
owners.
Type 'help;' or '\h' for help. Type '\c' to clear the current input statement.
Install Node.js
Next, we need to install Node.js, which is required to run Ghost CMS.
If you did not exit MySQL, please do so before running a new command.
- Install Node.js using NodeSource:
This will install Node.js version 18.x, which is recommended for running Ghost CMS
curl -fsSL https://deb.nodesource.com/setup_18.x | sudo -E bash -
sudo apt install -y nodejs
- Verify the installation:
Check that Node.js and npm (Node Package Manager) are installed correctly:
node -v
npm -v
These commands should display the installed versions of Node.js and npm without any errors. For example:
node -v
npm -v
v18.20.3
10.7.0
Install Ghost-CLI
Ghost-CLI is a command-line tool that helps in installing and managing Ghost CMS. You should still be SSH into your GCP instance when running this command. Let's install it globally into your GCP instance:
sudo npm install -g ghost-cli@latest
Install Ghost CMS
Now that Ghost-CLI is installed, we can proceed to install Ghost CMS. Change to the directory where you want to install Ghost (typically /var/www
for production installations) and run:
# Create directory: Change `sitename` to whatever you like
sudo mkdir -p /var/www/sitename
# Set directory owner: Replace <user> with the name of your user
sudo chown <user>:<user> /var/www/sitename
# Set the correct permissions
sudo chmod 775 /var/www/sitename
# Then navigate into it
cd /var/www/sitename
Run the install process
Start the installation of Ghost with this final command:
ghost install
Your terminal will start the installation, it will look something like this:
✔ Checking current folder permissions
✔ Checking memory availability
✔ Checking free space
✔ Checking for latest Ghost version
✔ Setting up install directory
✔ Downloading and installing Ghost v5.85.1
✔ Finishing install process
During the installation, the Ghost CLI will prompt a few questions. You'll need to enter information about your site accordingly
? Enter your blog URL: https://yourdomain.com
? Enter your MySQL hostname: 127.0.0.1
? Enter your MySQL username: root
? Enter your MySQL password: [typed_password_is_hidden]
? Enter your Ghost database name: [your_database_name]
✔ Configuring Ghost
✔ Setting up instance
To initiate your website, run ghost start
and ghost doctor
to debug any issues
Ghost update
To update your Ghost blog, run ghost update
. It takes about 10 minutes or less.
✔ Checking system Node.js version - found v18.20.3
✔ Ensuring user is not logged in as ghost user
✔ Checking if logged in user is directory owner
✔ Checking current folder permissions
✔ Checking folder permissions
✔ Checking file permissions
✔ Checking content folder ownership
✔ Checking memory availability
✔ Checking free space
✔ Checking for available migrations
✔ Checking for latest Ghost version
# 5.87.0
* 🎨 Updated editor toolbar and action button designs (#20405) - Sanne de Vries
* 🐛 Fixed default recipients setting not showing label filters (#20480) - Sag
---
View the changelog for full details: https://github.com/tryghost/ghost/compare/v5.86.2...v5.87.0
✔ Fetched release notes
☲ Downloading and updating Ghost to v5.87.0 > Installing dependencies > [3/5] Fetching packages...
View the changelog for full details: https://github.com/tryghost/ghost/compare/v5.86.2...v5.87.0
✔ Fetched release notes
✔ Downloading and updating Ghost to v5.87.0
+ sudo systemctl stop ghost
✔ Stopping Ghost
✔ Linking latest Ghost and recording versions
✔ Linking built-in themes
+ sudo systemctl start
✔ Restarting Ghost
ℹ Removing old Ghost versions [skipped]
Access Ghost Admin Panel:
Open your browser and navigate to your Ghost admin panel URL (https://yourdomain.com/ghost
) to set up your Ghost account.
SFTP into your Google Cloud Platform Instance
SFTP is another secure method to transfer files and allows more interactive file operations. This comes in handy if you prefer to manage your ghost files directly.
- Open a new terminal window on your Local Machine
- Get your SSH details, from your notepad
cat ~/.ssh/your_SSHkey_filename.pub
SSH into your GCP instance and edit the ~/.ssh/authorized_keys
file for the admin
user:
nano ~/.ssh/authorized_keys
Paste the contents of your local your_SSHkey_filename.pub
file into this file and save it.
- Verify SSH Configuration
Check your SSH configuration file (~/.ssh/config
) to ensure your gcp-instance
alias is correctly defined. Open the file using a text editor:
nano ~/.ssh/config
Ensure the configuration for your gcp-instance
looks like this:
Host gcp-instance
HostName 123.123.123.8 # Replace with your GCP instance IP address
User your_gcp_user
IdentityFile ~/.ssh/your_SSHkey_filename
HostName
: Should be the actual IP address of your GCP instance, not the placeholder123.123.123.8
.User
: Your username on the GCP instance.IdentityFile
: Path to your private key (your_SSHkey_filename
).
Save Changes and Exit:
After verifying and updating if necessary, save the changes (Ctrl + O
, then Enter
) and exit (Ctrl + X
) the editor.
- Access SFTP Connection
Once you've verified the SSH key setup, retry the SFTP connection:
sftp your_SSH_username_from_earlier@gcp_instance
Again, using the previous SSH details above as an example it will look something like this:
sftp admin@gcp-instance
Enter the passphrase for your SSH key if prompted. If everything is set up correctly, you should be able to connect without encountering the "Permission denied (publickey)" error.
Potential issues you may encounter
- During the 'ghost install' process, if your connection decides to drop or takes too long to load at any point, you can approach the issue with either of the solutions:
- Increase RAM
Stop your GCP instance, 'edit' the Machine Configuration to e2 small or medium for more RAM. - Partition MySQL with file Swap
Detailed steps are documented in this Ghost forum discussion
- For some reason, you had to reinstall the Ghost CLI due to interruption and
ghost install
orghost setup
does not work. You'll need to remove the existing Ghost CLI with these commands below:
You can either execute this command using the terminal in your local machine while SSH into your GCP instance or SSH in-browser from your GCP instance.
This command will recursively remove all files and subdirectories
sudo rm -rf /var/www/your_folder_name/*
Recreate the Directory:
After cleaning up, recreate the /var/www/your_folder_name
directory and ensure it's owned by your user:
sudo mkdir -p /var/www/your_folder_name
sudo chown $USER:$USER /var/www/your_folder_name
This ensures that the directory has the correct ownership and permissions for your user.
Retry Ghost Installation:
Navigate into the /var/www/your_folder_name
directory and attempt to install Ghost again:
cd /var/www/your_folder_name
ghost install
- Issues connecting to your MySQL database during the Ghost installation.
Access denied for user 'admin'@'localhost' (using password: YES)
This typically means that the MySQL credentials (username or password) provided during the Ghost installation do not match what MySQL expects. Here’s what you can do to troubleshoot and resolve the issue:
Verify admin
User Existence:
- Ensure that the
admin
user exists in MySQL and has the correct privileges for theyour_database_name
database.
USE mysql;
SELECT User, Host FROM mysql.user WHERE User='admin';
If the admin
user does not appear, you may need to create it and grant appropriate privileges:
CREATE USER 'admin'@'localhost' IDENTIFIED BY 'your_password';
GRANT ALL PRIVILEGES ON your_database_name.* TO 'admin'@'localhost';
FLUSH PRIVILEGES;
Verify Privileges for admin
:
- Double-check that the
admin
user has been granted all necessary privileges on theyour_database_name
database:
SHOW GRANTS FOR 'admin'@'localhost';
Ensure that the output includes privileges such as SELECT
, INSERT
, UPDATE
, DELETE
, etc., for the your_database_name
database.
Verify MySQL User Privileges:
- Ensure that the MySQL user (
admin
) has sufficient privileges on the Ghost database (your_database_name
). The user needs permissions likeSELECT
,INSERT
,UPDATE
,DELETE
, etc. - You can verify and grant privileges if needed by logging into MySQL:
mysql -u root -p
GRANT ALL PRIVILEGES ON your_database_name.* TO 'admin'@'localhost' IDENTIFIED BY 'your_password';
FLUSH PRIVILEGES;
Restart Ghost:
- After verifying and correcting any issues with MySQL credentials or privileges, restart Ghost:
sudo systemctl restart ghost_your_domain-com
Update Ghost Configuration:
- After verifying and ensuring the MySQL user (
admin
) and its privileges, update your Ghost configuration to reflect these credentials: - Typically, the Ghost configuration file (
config.production.json
or similar) should have these details. Ensure that thedatabase
section in your Ghost configuration file matches the MySQL setup:
To update the Ghost configuration file (config.production.json
) with the correct MySQL credentials (admin
user), follow these navigation steps:
- Access Your Server: Ensure you are logged into your server where Ghost is installed. If you are not already there, navigate to the directory where Ghost is installed. Us, Ghost is installed in
/var/www/your_folder_name/
.
cd /var/www/your_folder_name/
- Locate the Ghost Configuration File: In most cases, the Ghost configuration file is named
config.production.json
. It should be located in the root directory of your Ghost installation (/var/www/your_folder_name/
in this case). Look for a file namedconfig.production.json
or something similar. - Edit the Configuration File: Use a text editor to open the
config.production.json
file for editing. You can usenano
,vim
, or any text editor of your choice. Here, we'll usenano
as an example:
sudo nano /var/www/your_folder_name/config.production.json
This command opens the config.production.json
file in the nano
editor with superuser privileges (sudo
) to ensure you have permission to save changes.
Navigate to the Database Section: Inside the config.production.json
file, locate the database
section. It typically looks like this:
{
"url": "https://yourdomain.com",
"server": {
"port": 2368,
"host": "127.0.0.1"
},
"database": {
"client": "mysql",
"connection": {
"host": "127.0.0.1",
"user": "admin",
"password": "your_password", // Update this field with the correct password
"database": "your_database_name"
}
},
"mail": {
"transport": "Direct"
},
"logging": {
"transports": [
"file",
"stdout"
]
},
"process": "systemd",
"paths": {
"contentPath": "/var/www/your_folder_name/content"
},
"bootstrap-socket": {
"port": 8000,
"host": "localhost"
}
}
Steps to Update:
- Password Update: Replace
"your_password"
in the"password"
field with the actual password for theadmin
MySQL user - Save Changes: After updating the password, save the
config.production.json
file. If you're usingnano
, pressCtrl + X
, thenY
to confirm changes, andEnter
to write the filename. - Restart Ghost: Restart the Ghost service to apply the changes:
sudo systemctl restart ghost_yourdomain-com
Verify Operation:
Check the Ghost logs (journalctl -u ghost_yourdomain-com -n 50
) for any errors or warnings to ensure that Ghost starts correctly with the updated MySQL credentials.
Test Your Installation:
Visit your blog URL to ensure that Ghost is running and functioning properly with the updated configuration.
By following these steps, you should successfully update your Ghost configuration.