Here’s the straight path to getting Ghost running on DigitalOcean. I’ll show you two clean ways: the super-fast 1-Click image, and the rock-solid manual install that gives you full control. I’ll also cover mail, SSL, backups, updates, and the gotchas that trip people up.
If you’re wondering whether Ghost is still worth self-hosting: yes. It’s lean, modern, and production-ready. I’ve been around enough CMS setups to know that “simple” usually hides a mess. Ghost is the rare one that actually means it.
What you’ll get by the end
- A production Ghost instance behind NGINX, with HTTPS from Let’s Encrypt
- Systemd keeping Ghost alive across reboots
- MySQL 8 configured the way Ghost expects it (no socket auth shenanigans)
- A sane update/backup routine you can live with
Ghost’s current stack: Ubuntu 22.04/24.04, NGINX, MySQL 8, and Node 22 LTS. Don’t improvise on versions; Ghost v6+ requires Node 22 LTS and won’t support older LTS lines anymore.
Option A — DigitalOcean Marketplace (fastest)
If you want the quickest path from zero to live, spin up the Ghost 1-Click Droplet and finish the CLI prompts. It wires up NGINX, SSL, systemd, and MySQL for you.
High-level flow
- Create the Ghost 1-Click Droplet (choose at least 1GB RAM; I prefer 2GB for headroom).
- Point your domain’s A record to the Droplet IP. Do this before running Ghost’s setup, so SSL can provision.
- SSH in and follow the prompts to complete
ghost install
(the image drops you right into it).
If the 1-Click image is temporarily out of date (it happens), skip to Option B and do the manual install—it’s just as clean, and you’ll be current on Node/CLI.
Option B — Manual install with Ghost-CLI (my default)
This takes a few more minutes but gives you a clean, reproducible setup on any Ubuntu 22.04/24.04 Droplet.
1) Create your Droplet & point DNS
- Pick Ubuntu 22.04 or 24.04, 1–2GB RAM.
- In your DNS, add an A record for your domain to the Droplet’s IPv4. Do this now; we’ll need it for SSL. Ghost’s official install assumes the DNS is already in place.
2) SSH in and create a non-root sudo user
Ghost’s own docs warn not to name the user ghost
(it conflicts with the CLI).
ssh root@YOUR_DROPLET_IP
adduser deploy
usermod -aG sudo deploy
su - deploy
3) Update base packages
sudo apt-get update
sudo apt-get upgrade -y
4) Install NGINX and open the firewall
Ghost expects NGINX (not Apache). The CLI will generate site configs for you.
sudo apt-get install -y nginx
sudo ufw allow 'Nginx Full' || true
5) Install MySQL 8 and switch root to password auth
Ubuntu ships MySQL with socket auth for root; Ghost needs password auth.
sudo apt-get install -y mysql-server
sudo mysql
ALTER USER 'root'@'localhost' IDENTIFIED WITH 'mysql_native_password' BY 'REPLACE_ME_STRONG';
FLUSH PRIVILEGES;
exit
6) Install Node 22 LTS (Nodesource method Ghost recommends)
Don’t use distro Node, nvm on servers, or random PPAs.
sudo apt-get 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-get update
sudo apt-get install -y nodejs
node -v
7) Install Ghost-CLI globally
This is the supported way to install/operate Ghost in production.
sudo npm install -g ghost-cli@latest
ghost --version
8) Create the web root and set permissions
sudo mkdir -p /var/www/ghost
sudo chown deploy:deploy /var/www/ghost
sudo chmod 775 /var/www/ghost
cd /var/www/ghost
9) Run the installer (wires up NGINX, SSL, MySQL, systemd)
ghost install
You’ll be prompted for:
- Blog URL – use
https://yourdomain.com
(not an IP). - MySQL –
localhost
, userroot
, and the password you set above; the CLI can create a scoped DB user for you (say yes). - NGINX – let the CLI create the config.
- SSL – say yes; Let’s Encrypt will be provisioned automatically.
- systemd – yes.
When it asks to start Ghost, say yes.
Now visit https://yourdomain.com/ghost
to create your admin account.
Optional but sensible on small Droplets: add swap
1GB RAM is the minimum; adding a small swap file prevents OOM kills during updates or theme builds.
sudo fallocate -l 2G /swapfile
sudo chmod 600 /swapfile
sudo mkswap /swapfile
sudo swapon /swapfile
echo '/swapfile none swap sw 0 0' | sudo tee -a /etc/fstab
- Transactional mail (sign-in links, staff invites) can use any SMTP (Postmark, Sendgrid, SES, your own). Configure via Ghost config/CLI.
- Newsletter sending requires a bulk-mail API Ghost supports. As of now, Ghost supports Mailgun for bulk newsletters. If you don’t plan to send newsletters by email, you can skip Mailgun entirely and just publish on the site.
You can also set SMTP directly with ghost config
flags (see CLI docs for options).
Day-2 Ops: updates, logs, SSL renewals, backups
Update Ghost safely
cd /var/www/ghost
ghost update
If Node LTS ever bumps again, update Node first, then force-reinstall your current Ghost to rebuild native deps:
# Update Node to a supported version per docs, then:
ghost version
ghost update --force
Ghost’s Node version policy and step-by-step upgrade notes are here; Ghost v6+ requires Node 22 LTS.
Check health & logs
ghost ls
ghost doctor
ghost log
CLI commands and flags are documented in detail.
Renew or (re)issue SSL
ghost setup ssl
Ghost-CLI manages Let’s Encrypt for you via its setup stages.
Backups (two easy layers)
- Quick site backup (CLI): creates a zip with data you’ll need to restore.
- Content export (inside Admin): JSON export of posts/tags/pages/settings; good for migrations and “belt-and-suspenders”.
cd /var/www/ghost
ghost backup
(If you rely on comments or custom extras, complement with DB dumps and content/
copies. The forum docs and admin export pages explain what’s included/excluded and how to handle migrations cleanly.)
Common pitfalls (so you don’t waste a Saturday)
- Wrong Node version. If you see “Unsupported version of Node,” you’re not on 22 LTS. Fix Node with the Nodesource steps above, then
ghost update --force
. The supported-versions matrix is explicit. - DNS not pointed before SSL. The ACME challenge will fail if your A record isn’t live. Point DNS first, wait a minute, then run
ghost install
/ghost setup ssl
. - MySQL root using socket auth. Set
mysql_native_password
exactly as shown earlier. Otherwise Ghost can’t auth. - Low RAM during updates. Add a small swap; it’s cheap stability.
- 1-Click image lagging behind. If the marketplace image ever ships with an outdated Node/CLI, manual install avoids the dead-end.
Bonus: moving, staging, and recovery
- Migrate/restore by doing a clean install on the new box, importing your content export, copying
content/
assets, restoring theme(s), and switching DNS. - Rollback a bad update quickly:
cd /var/www/ghost
ghost update --rollback
CLI has a built-in rollback if an update misbehaves.
Sanity checklist (quick pass)
- Ubuntu 22.04/24.04 ✅
- Node 22 LTS ✅
- MySQL 8 with password auth ✅
- NGINX via Ghost-CLI config ✅
- Let’s Encrypt via Ghost-CLI ✅
- systemd enabled ✅
- DNS A record in place ✅
- Backups tested once ✅
If you follow those exactly, this setup will run for years with minimal drama—and when you do need to update, it’ll be routine.