Ghost is a publishing platform for websites, newsletters, memberships, and subscription content. Its officially recommended production stack supports Ubuntu 24.04 with Nginx, MySQL 8, Node.js 22 LTS, systemd, and Ghost-CLI.
In this tutorial, you will prepare the server and DNS, install the supported stack, run Ghost-CLI as a non-root user, enable HTTPS, verify the systemd and Nginx services, create a complete backup, and update Ghost safely.
Step 1 — Prepare the Domain and Server
Create a DNS A record for the hostname that will serve Ghost:
blog.example.com -> your_server_ipv4
Publish an AAAA record only when IPv6 reaches the same VM correctly.
Check DNS from your local computer:
dig +short A blog.example.com dig +short AAAA blog.example.com
Ghost's production installer expects a registered domain. Do not use a raw IP address as the final publication URL.
Ghost officially recommends at least 1 GB RAM. A 2 GB VM is a safer minimum for Ubuntu, MySQL, Nginx, Ghost, updates, and modest traffic. Larger publications, newsletters, image processing, and additional services need more headroom.
Step 2 — Create a Non-Root Administrative User
Ghost-CLI must not be run as root. Also avoid naming the Linux account ghost, because that name conflicts with Ghost-CLI's service-management model.
When starting as root, create an account such as ghost-mgr:
adduser ghost-mgr usermod -aG sudo ghost-mgr su - ghost-mgr
Confirm sudo works:
sudo whoami
The expected output is root.
For a broader baseline before deployment, complete How to Harden an Ubuntu 24.04 Server.
Step 3 — Update Ubuntu and Configure UFW
Update installed packages:
sudo apt update sudo apt upgrade -y
Install basic tools:
sudo apt install -y ca-certificates curl gnupg
Allow SSH before enabling the firewall, then allow Nginx traffic:
sudo ufw allow OpenSSH sudo ufw allow 'Nginx Full' sudo ufw enable sudo ufw status numbered
Ports 80 and 443 must reach the server for public traffic and Let's Encrypt certificate issuance.
Step 4 — Install Nginx and MySQL 8
Install the web and database servers from Ubuntu's repositories:
sudo apt install -y nginx mysql-server
Enable and verify them:
sudo systemctl enable --now nginx mysql systemctl is-active nginx mysql
Check MySQL's version:
mysql --version
Ghost supports MySQL 8 for production. MariaDB and SQLite are not replacements for the officially supported production database in this Ghost-CLI deployment.
Step 5 — Configure MySQL for Ghost-CLI Setup
Ubuntu normally configures the MySQL root account with socket authentication. Ghost's official production installer requires a MySQL username and password so Ghost-CLI can create the publication database and a dedicated database user.
Open MySQL locally:
sudo mysql
Assign a unique administrative password using the method documented by Ghost:
ALTER USER 'root'@'localhost' IDENTIFIED WITH 'mysql_native_password' BY 'replace_with_a_long_unique_password'; FLUSH PRIVILEGES; EXIT;
Store this password in a password manager and test it:
mysql -u root -p
Exit after authentication succeeds:
EXIT;
During installation, allow Ghost-CLI to create a separate Ghost database account. The running application should not use the MySQL root account.
Do not expose MySQL port 3306 publicly for this single-server deployment.
Step 6 — Install the Supported Node.js Version
Ghost 6 currently requires Node.js 22 LTS. Install it system-wide from the NodeSource repository as documented by Ghost:
sudo apt update sudo apt install -y ca-certificates curl gnupg sudo mkdir -p /etc/apt/keyrings curl -fsSL https://deb.nodesource.com/gpgkey/nodesource-repo.gpg.key \ | sudo gpg --dearmor -o /etc/apt/keyrings/nodesource.gpg NODE_MAJOR=22 echo "deb [signed-by=/etc/apt/keyrings/nodesource.gpg] https://deb.nodesource.com/node_${NODE_MAJOR}.x nodistro main" \ | sudo tee /etc/apt/sources.list.d/nodesource.list sudo apt update sudo apt install -y nodejs
Verify the installed runtime:
node --version npm --version
Do not use a root-owned or per-user nvm installation for this production Ghost-CLI setup. Ghost recommends a system-wide Node.js installation.
Step 7 — Install Ghost-CLI
Install the current Ghost-CLI globally:
sudo npm install ghost-cli@latest -g
Verify it:
ghost --version ghost help
For Ghost 6, use a current Ghost-CLI release. Check compatibility before upgrades rather than assuming every future Node.js or Ghost major version is supported.
Step 8 — Create the Ghost Directory
Create a dedicated installation directory and give it to the non-root user:
sudo mkdir -p /var/www/blog.example.com sudo chown ghost-mgr:ghost-mgr /var/www/blog.example.com sudo chmod 775 /var/www/blog.example.com cd /var/www/blog.example.com
Replace ghost-mgr and the hostname with your actual account and domain.
Verify ownership:
pwd ls -ld .
Step 9 — Run the Ghost Production Installer
Start the interactive installation from the Ghost directory:
ghost install
Use these answers:
- Blog URL:
https://blog.example.com - MySQL hostname:
localhost - MySQL username:
root - MySQL password: the administrative password created earlier
- Ghost database name: a clear value such as
ghost_prod - Set up a Ghost MySQL user: Yes
- Set up Nginx: Yes
- Set up SSL: Yes
- Set up systemd: Yes
- Start Ghost: Yes
Ghost-CLI uses the MySQL administrator credentials during setup, then creates a restricted account for the Ghost database when you approve that option.
If SSL setup fails, correct DNS and firewall access, then run from the installation directory:
ghost setup ssl