Ghost CMS is a powerful and user-friendly open-source blogging platform that allows you to create professional-looking blogs. In this tutorial, we will explore the step-by-step process of deploying Ghost CMS on a server powered by Rocky Linux 9. By following these instructions, you will be able to install Ghost CMS using Nginx as a web server and MySQL as a database. Additionally, we will secure our installation with an SSL certificate provided by Let’s Encrypt.
Prerequisites
Before we begin, please make sure you have the following prerequisites:
- A server running Rocky Linux 9
- A non-root user with sudo privileges
- A fully qualified domain name (FQDN) pointing to your server. For the purpose of this tutorial, we will use
ghost.example.com
as the domain name.
Let’s get started by updating our system and installing some necessary utility packages.
$ sudo dnf update $ sudo dnf install wget curl nano unzip yum-utils -y
Step 1 – Configure Firewall
The first step in setting up Ghost CMS on Rocky Linux 9 is to configure the firewall. Rocky Linux uses Firewalld Firewall by default. Let’s check the status of the firewall:
$ sudo firewall-cmd --state
If the firewall is running, you can proceed to list all the services and ports active on the firewall:
$ sudo firewall-cmd --permanent --list-services
By default, the public zone is active, which is the zone we will use. We need to open HTTP and HTTPS ports for Ghost CMS to function properly:
$ sudo firewall-cmd --add-service=http --permanent $ sudo firewall-cmd --add-service=https --permanent
Finally, reload the firewall to apply the changes:
$ sudo firewall-cmd --reload
Step 2 – Install Nginx
Rocky Linux 9 comes with an older version of Nginx. To install the latest version, we need to add the official Nginx repository. Let’s create and open the /etc/yum.repos.d/nginx.repo
file:
$ sudo nano /etc/yum.repos.d/nginx.repo
Paste the following code into the file:
[nginx-stable]
name=nginx stable repo
baseurl=http://nginx.org/packages/centos/$releasever/$basearch/
gpgcheck=1
enabled=1
gpgkey=https://nginx.org/keys/nginx_signing.key
module_hotfixes=true
[nginx-mainline]
name=nginx mainline repo
baseurl=http://nginx.org/packages/mainline/centos/$releasever/$basearch/
gpgcheck=1
enabled=0
gpgkey=https://nginx.org/keys/nginx_signing.key
module_hotfixes=true
Save the file and exit the text editor. Now, we can install Nginx:
$ sudo dnf install nginx -y
Verify the installation by checking the Nginx version:
$ nginx -v
Make sure Nginx is enabled and started:
$ sudo systemctl enable nginx --now
Check the status of the Nginx server:
$ sudo systemctl status nginx
Step 3 – Install Node.js
Ghost CMS requires Node.js to function properly. Let’s install Node.js version 16:
$ curl-fsSL https://rpm.nodesource.com/setup_16.x | sudo bash- $ sudo dnf install -y nodejs
Verify the Node.js installation:
$ node --version
At the time of writing this tutorial, Ghost CMS does not support Node.js version 18. Please refer to the Ghost documentation for the latest supported Node.js version.
Step 4 – Install MySQL
Ghost CMS requires a database to store its content. In this tutorial, we will use MySQL as the database management system. Let’s install MySQL:
$ sudo dnf install mysql-server -y
Check the version of MySQL:
$ mysql --version
Enable and start the MySQL service:
$ sudo systemctl enable mysqld --now
Check the status of the MySQL service:
$ sudo systemctl status mysqld
By default, MySQL allows Unix authentication for local connections. However, for MySQL versions 8.0.28 and above, we need to set a password for the root user using the MySQL shell:
$ sudo mysql
Enter the following command to set the password for the root user:
mysql> ALTER USER 'root'@'localhost' IDENTIFIED WITH mysql_native_password BY 'YourPassword12!';
Exit the MySQL shell:
mysql> exit
Run the MySQL secure installation script to further secure the MySQL installation:
$ sudo mysql_secure_installation
Follow the prompts to set up the Validate Password Component, password validation policy, and remove anonymous users, disallow remote root logins, and remove the test database.
Step 5 – Install Ghost
Now that we have all the prerequisites in place, we can proceed with installing Ghost CMS. The installation process involves three components: Ghost-CLI, Ghost blog package, and the configuration of the blog.
Install Ghost-CLI
Ghost-CLI is a command-line tool that helps you install and manage Ghost CMS. Let’s install Ghost-CLI globally:
$ sudo npm install ghost-cli@latest -g
Prepare Ghost Directory
Create the root directory for Ghost:
$ sudo mkdir -p /var/www/html/ghost
Set the ownership of the directory to the current user:
$ sudo chown $USER:$USER /var/www/html/ghost
Set the correct directory permissions:
$ sudo chmod 755 /var/www/html/ghost
Switch to the Ghost directory:
$ cd /var/www/html/ghost
Install Ghost
Installing Ghost CMS is a simple one-command process:
$ ghost install
During the installation, Ghost-CLI will prompt you with several questions to configure the blog. Let’s go through each question:
- Blog URL: Enter your complete blog URL with the HTTPS protocol (e.g.,
https://ghost.example.com
). - MySQL Hostname: Press Enter to use the default value of
localhost
since our Ghost install and MySQL are on the same server. - MySQL Username: Enter
root
as your MySQL username. - MySQL Password: Enter the root password you set during the MySQL installation.
- Ghost database name: Give a name for your Ghost database (e.g.,
ghostdb
). - Sudo password: Enter your system’s sudo password to perform elevated commands.
- Set up a ghost MySQL user?: Press Y to create a separate MySQL user for Ghost.
- Set up Nginx?: As of now, Ghost-CLI cannot detect our Nginx installation, so it will skip this step. We will configure Nginx manually.
- Set up SSL?: Since we skipped the Nginx configuration, SSL setup will also be skipped.
- Set up systemd?: Press Y to set up a system service for Ghost.
Finally, press Y to start your Ghost installation. The service will start, but we will need to configure Nginx and SSL to make it work.
Step 6 – Install SSL
Before we can configure Nginx with SSL, we need to install the Certbot tool and obtain an SSL certificate from Let’s Encrypt. We will use Snapd to install Certbot:
$ sudo dnf install epel-release -y $ sudo dnf install snapd -y $ sudo systemctl enable snapd.socket --now $ sudo ln -s /var/lib/snapd/snap/snap $ echo'export PATH=$PATH: /var/lib/snapd/snap/bin' | sudo tee -a /etc/profile.d/snapd.sh $ sudo snap install core $ sudo snap refresh core $ sudo snap install --classic certbot $ sudo ln -s /snap/bin/certbot /usr/bin/certbot
With Certbot installed, let’s generate an SSL certificate for our domain:
$ sudo certbot certonly --nginx --agree-tos --no-eff -email --staple-ocsp --preferred-challenges http -m test@example.com -d ghost.example.com
This command will download the SSL certificate to the /etc/letsencrypt/live/ghost.example.com
directory on your server. Additionally, let’s generate a Diffie-Hellman group certificate:
$ sudo openssl dhparam-dsaparam -out /etc/ssl/certs/dhparam.pem 4096
To ensure that the SSL renewal works fine, perform a dry run of the renewal process:
$ sudo certbot renew --dry-run
If you encounter no errors, your certificate will renew automatically.
Step 7 – Configure Nginx
Now that we have our SSL certificate, we need to configure Nginx to serve Ghost CMS. Let’s create and open the /etc/nginx/conf.d/ghost.conf
file:
$ sudo nano /etc/nginx/conf.d/ghost.conf
Paste the following configuration into the file, replacing all instances of ghost.example.com
with your domain:
server { listen 80; listen [::]:80; server_name ghost.example.com; return 301 https://$server_name$request_uri; } server { listen 443 ssl http2; listen [::]:443 ssl http2; server_name ghost.example.com; access_log /var/log/nginx/ghost.access.log; error_log /var/log/nginx/ghost.error.log; client_max_body_size 20m; http2_push_preload on; # Enable HTTP/2 Server Push ssl_certificate /etc/letsencrypt/live/ghost.example.com/fullchain.pem; ssl_certificate_key /etc/letsencrypt/live/ghost.example.com/privkey.pem; ssl_trusted_certificate /etc/letsencrypt/live/ghost.example.com/chain.pem; ssl_session_timeout 1d; # Enable TLS versions (TLSv1.3 is required upcoming HTTP/3 QUIC). ssl_protocols TLSv1.2 TLSv1.3; # Enable TLSv1.3's 0-RTT. Use $ssl_early_data when reverse proxying to # prevent replay attacks. # @see: https://nginx.org/en/docs/http/ngx_http_ssl_module.html#ssl_early_data ssl_early_data on; ssl_ciphers 'ECDHE-ECDSA-AES256-GCM-SHA384:ECDHE-RSA-AES256-GCM-SHA384:ECDHE-ECDSA-CHACHA20-POLY1305:ECDHE-RSA-CHACHA20-POLY1305:ECDHE-ECDSA-AES256-SHA384:ECDHE-RSA-AES256-SHA384'; ssl_prefer_server_ciphers on; ssl_ecdh_curve X25519:prime256v1:secp384r1:secp521r1; ssl_session_cache shared:SSL:50m; ssl_session_tickets off; # OCSP Stapling --- # fetch OCSP records from URL in ssl_certificate and cache them ssl_stapling on; ssl_stapling_verify on; ssl_dhparam /etc/ssl/certs/dhparam.pem; add_header X-Early-Data $tls1_3_early_data; location / { proxy_set_header Host $http_host; proxy_set_header X-Real-IP $remote_addr; proxy_set_header X-Forwarded-Proto https; proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for; proxy_pass http://localhost:2368; } }
Save the file and exit the text editor. Now, open the /etc/nginx/nginx.conf
file:
$ sudo nano /etc/nginx/nginx.conf
Add the following line before the line include /etc/nginx/conf.d/*.conf;
:
server_names_hash_bucket_size 64;
Save the file and exit the text editor. Verify the Nginx configuration:
$ sudo nginx -t
If there are no errors, reload the Nginx server:
$ sudo systemctl reload nginx
Step 8 – Configure SELinux
SELinux is a security feature that provides an additional layer of protection. We need to allow Nginx to connect to the network. Run the following command to configure SELinux:
$ sudo setsebool -P httpd_can_network_connect1
Step 9 – Run the Site
Now that our Nginx and SSL configurations are in place, we can test our Ghost CMS installation. Open https://ghost.example.com
in your web browser. If everything is set up correctly, you should see a page indicating a successful installation of Ghost CMS.
Step 10 – Complete the Setup
To finish setting up your Ghost blog, visit https://ghost.example.com/ghost
in your browser. This URL will redirect you to the Ghost’s Admin Panel, where you can complete the setup process.
You will be prompted to create your Administrator account and choose a blog title. Enter your details and click the “Create account & start publishing” button to proceed.
After creating your account, you will be taken to the Ghost’s Administration panel. From here, you can explore various features, including writing your first post, customizing your site, and importing members.
To switch to dark mode, simply click on the toggle switch next to the settings gear button at the bottom of the settings page.
Step 11 – Configure Mailer
Ghost CMS not only acts as a blogging platform but also as a newsletter manager. For day-to-day operations, you can use any transactional mail service to work with Ghost for sending mail. If you want to send newsletters via Ghost, the only officially supported bulk mailer is Mailgun. However, you can also use other newsletter services through the Zapier integration feature of Ghost.
To configure an SMTP service for transactional emails, open the /var/www/html/ghost/config.production.json
file:
$ sudo nano /var/www/html/ghost/config.production.json
Find the following lines:
"mail": { "transport": "Direct" },
Replace them with the following code:
"mail": { "from": "'Acme Support' test@example.com", "transport": "SMTP", "options": { "host": "YOUR-SES-SERVER-NAME", "port": 465, "service": "SES", "auth": { "user": "YOUR-SES-SMTP-ACCESS-KEY-ID", "pass": "YOUR-SES-SMTP-SECRET-ACCESS-KEY" } } },
Here, we are using Amazon SES as the SMTP service. If you want to use Mailgun, use the following code instead:
"mail": { "from": "'Acme Support' test@example", "transport": "SMTP", "options": { "service": "Mailgun", "host": "smtp.mailgun.org", "port": 587, "secure": true, "auth": { "user": "test@example.com", "pass": "1234567890" } } },
Save the file and exit the text editor. Finally, restart the Ghost application for the changes to take effect:
$ ghost restart
To configure the newsletter settings, go to the Ghost Admin Panel and navigate to the Settings > Email newsletter section. Click on the Mailgun configuration link to expand the options. Fill in your Mailgun Region, domain, and API key. Click the Save button to save the settings.
To test the newsletter delivery, open any post, go to its settings, and click the Email newsletter option. Send a test email to verify if the newsletter delivery is working correctly.
Step 12 – Update Ghost
Periodically updating Ghost CMS is crucial to ensure you have the latest features, bug fixes, and security patches. There are two types of updates: minor updates and major updates.
For minor updates, it is recommended to take a full backup of your Ghost installation:
$ cd /var/www/html/ghost $ ghost backup
To perform a minor update, run the following command:
$ ghost update
For major updates, you should refer to the official Ghost documentation for a detailed update guide. The steps may vary depending on your current version and the major version you want to update to.
Congratulations! You have successfully deployed Ghost CMS on Rocky Linux 9 using Nginx and MySQL. You can now start creating and publishing content on your blog.
For reliable and efficient cloud hosting solutions, consider Shape.host’s Linux SSD VPS services. Shape.host offers scalable and secure hosting options to empower your business with top-notch performance and reliability.