Self-hosted blog,
one command away.
Ghostberry installs a production-ready Ghost CMS on your Raspberry Pi, fronted by a Cloudflare Tunnel โ no exposed ports, hardened containers, encrypted nightly backups.
$ curl -fsSL https://raw.githubusercontent.com/dm807cam/ghostberry/main/install.sh | sudo bash
Works on Raspberry Pi OS Bookworm (64-bit) and Debian / Ubuntu. Add
--harden for ufw + unattended-upgrades.
What's in the box
Sensible defaults for a homelab that you'd actually trust in production.
Zero exposed ports
Traffic only reaches Ghost through your Cloudflare Tunnel. DDoS protection and WAF for free.
Hardened containers
All capabilities dropped by default, no-new-privileges, memory caps, log rotation.
Encrypted backups
Nightly mysqldump + content tar, AES-256 via OpenSSL pbkdf2. restore.sh included.
Systemd-native
Starts on boot, restarts on failure, integrates with journalctl like anything else.
Pi-aware bootstrap
Enables memory cgroups, ensures 2 GB swap, installs Docker โ all idempotent.
One-file config
Everything tunable lives in .env โ image pins, memory caps, mail, retention.
How it works
Three things to do โ the installer handles the rest.
-
Flash 64-bit Raspberry Pi OS
Pi 4 (2 GB+) or Pi 5. Enable SSH, log in. That's the only manual prep.
-
Create a Cloudflare Tunnel
In the Zero Trust dashboard โ Networks โ Tunnels. Add a public hostname pointing to
http://ghost:2368. Copy the tunnel token. -
Run the installer
Paste the one-liner, give it your domain and the token, wait ~3 minutes. Then visit
https://your-domain/ghostto create your admin account.
FAQ
The questions that come up before you commit to running the script.
What does the installer actually do?
It checks you're on Debian/Pi OS aarch64, enables memory cgroups in the boot cmdline if
missing, ensures โฅ 2 GB of swap, installs Docker via the official convenience script, clones
the repo to /opt/ghostberry, writes .env (with auto-generated
40-char DB passwords and a backup encryption key), installs a systemd unit, drops a daily
backup cron, and starts the stack. Re-run it any time โ it's idempotent.
Why Cloudflare Tunnel?
Your Pi never opens an inbound port. The tunnel makes an outbound connection to
Cloudflare; their edge routes requests back through it. You get DDoS protection, a WAF,
and TLS without managing certificates โ and you can put Cloudflare Access in front of
/ghost if you want SSO on the admin panel.
Can I add my SMTP credentials during install?
Yes. The installer prompts you with an optional SMTP section after the
Cloudflare token โ host, port, username, password, from-address. Skip it and Ghost still
runs; mail features just stay off until you add the values to .env later.
For unattended installs, pre-set MAIL_HOST, MAIL_USER,
MAIL_PASSWORD, MAIL_FROM as environment variables and the
prompt is skipped automatically.
How are secrets handled?
Everything sensitive lives in /opt/ghostberry/.env, mode 600,
owned by your user. Database passwords and the backup encryption key are generated locally
with OpenSSL โ they never leave the device.
What if I lose the Pi?
Restore from a backup archive on a fresh Pi. The encryption key in .env is
the only thing you must back up out-of-band โ keep it in your password manager. The
installer + your encrypted archive get you back to identical state.
Will it run on a Pi Zero / 32-bit OS?
No. Ghost and MySQL 8 require 64-bit ARM and at least ~1.5 GB of RAM in practice. A Pi 4 with 2 GB works; 4 GB is comfortable.
Is curl-piped-to-bash safe?
You're trusting this repo either way โ the alternative (clone, then run) executes the same code. If you'd rather inspect first, the script is plain bash: read install.sh on GitHub before piping it.