Ghost is one of the nicest writing experiences in blogging. The catch? A normal Ghost install expects a server, a database, and usually a hosting bill.
GitHub Pages is free and reliable — but it only serves static files. It will not run Ghost for you.
So the real question is not “Can Ghost run on GitHub Pages?”
It is: Can I write in Ghost locally, then publish a static copy of my blog for free?
Yes. And after years of people hitting broken images, localhost links on the live site, and Python 2 install failures, that workflow finally got a proper refresh.
This post walks through the problem, the approach, and how to set it up with Ghost on GitHub Pages v3.0.0 — a major release that replaces the old brittle path with something you can actually maintain in 2026.
The problem in plain terms
You probably want some mix of these:
- Ghost’s editor and admin UI
- A public blog URL
- $0/month hosting
- No Kubernetes, no managed DB, no “just spin up a droplet”
GitHub Pages is perfect for the hosting part. Ghost is perfect for the writing part. They do not speak the same language out of the box.
The workable pattern has always been:
- Run Ghost on your machine (
localhost) - Generate a static HTML snapshot of the site
- Push that snapshot to a GitHub Pages repo
- Repeat whenever you publish a new post
That idea is solid. The tooling around it was the painful part.
What used to go wrong
If you tried this years ago (or inherited an old setup), you may remember:
- Python 2 / buster dependency hell on modern machines
- Live pages whose nav or tags pointed to
http://localhost:2368 - Broken images after publish
- Scripts that published too much (or hung for confusing reasons)
- Docs that assumed you already knew what a “static generator” was
Those were not niche complaints. They showed up repeatedly as real issues — and they are exactly what v3 targets.
What Ghost on GitHub Pages actually does
Ghost on GitHub Pages is a small open-source toolkit that wires that local-Ghost → static-site → GitHub Pages loop together for you.
At a high level:
Edit in Ghost (localhost:2373)
↓
gssg builds static HTML/CSS/assets
↓
Push to your GitHub repo
↓
Live blog on GitHub Pages
You keep writing in Ghost. Visitors get a fast static site. GitHub hosts it for free.
What’s new in v3.0.0
Version 3 is a real major update after a long stretch:
| Before (Classic v2) | Now (v3) |
|---|---|
| Python 2 + buster | Node.js + wget only |
| Fragile link/image rewrite | Publishing via gssg |
| Manual / risky upgrades |
./migrate.sh with automatic backup |
| Sparse docs | Plain-English guides in docs/
|
It also addresses long-standing bugs around localhost links, image paths, install errors, and publishing the wrong set of files. Details live in the changelog and v3 release notes.
Live demos:
Who this is for (and who it is not)
Good fit if you:
- Want Ghost’s writing UX without paying for Ghost(Pro) or a VPS
- Are fine editing locally and running a deploy script when ready
- Prefer GitHub Pages (or can adapt the same static output elsewhere)
- Use macOS, Linux, or Windows via WSL
Not a great fit if you need:
- Live server-side Ghost features on the public site (members, dynamic search, server-rendered previews, etc.)
- Instant publish from any device without touching your machine
- A fully managed “click publish and forget” SaaS
Be honest with yourself here: this is static publishing with Ghost as the CMS, not “Ghost Cloud for free.”
Tutorial: set up a free Ghost blog on GitHub Pages
Prerequisites
Before installing:
- Node.js LTS (v18 or v20) — nodejs.org
- wget
- A free GitHub account and a public repository for the blog
- Internet access for the initial Ghost download
On macOS:
brew install wget
node --version
On Ubuntu/Debian:
sudo apt-get update
sudo apt-get install -y wget
node --version
Create an empty public GitHub repo (for example my-blog) and keep the clone URL handy.
Full checklist: Requirements.
Step 1 — Download v3
Grab the latest release:
github.com/paladini/ghost-on-github-pages/releases/latest
Extract it somewhere memorable.
Step 2 — Install
cd path/to/ghost-on-github-pages
chmod +x install.sh
./install.sh
This takes a few minutes. It installs Ghost locally. Your blog folder ends up at ~/.ghost.
When prompted, you can publish to GitHub immediately or skip and do it later.
Step 3 — Configure Ghost
Open:
http://localhost:2373/ghost
Create your admin account, write a test post, poke around the editor.
Local preview of the site:
http://localhost:2373
Step 4 — Publish to GitHub Pages
If you skipped deploy during install:
cd ~/.ghost
./deploy.sh
The script asks for:
- GitHub username
- Repository name
- Repository URL
Wait ~10 minutes for Pages to catch up, then open:
https://YOUR_USERNAME.github.io/YOUR_REPO
Sanity checklist
- [ ] Local blog loads at
http://localhost:2373 - [ ]
./deploy.shfinishes cleanly - [ ] The GitHub repo has new static files
- [ ] The public URL loads
- [ ] Post/tag links do not point at localhost
If something fails, start here: Troubleshooting.
Updating later
- Edit at
http://localhost:2373/ghost - Publish again:
cd ~/.ghost
./deploy.sh
That is the whole loop.
How publishing works under the hood
When you run deploy.sh, the flow is roughly:
- Ensure Ghost is available locally
- Use gssg to crawl/generate a static copy of the site
- Rewrite URLs so the public site uses your GitHub Pages domain — not
localhost - Push only the static output to your configured repo
- GitHub Pages serves those files
v3 also includes helpers like scripts/validate-static.sh so you can catch broken links/images before visitors do, plus optional multi-site deploy profiles (deploy.sh --site / sites.conf) if you maintain more than one blog.
Saved deploy settings live in ~/.ghost/deploy.conf, so you are not retyping repo details every time.
Features worth knowing about
Beyond “install and deploy,” v3 ships with:
- Simpler dependency story — no Python 2
- More reliable static output — fewer broken images / localhost leaks
-
Migration path from Classic v2 —
./migrate.shwith automatic backup - Plain-English documentation — getting started, deploy, glossary, troubleshooting
- Static validation script — catch bad links/images pre-publish
- Multiple GitHub repos / site profiles — useful if you run more than one site
- CI in the project itself — shellcheck + validation tests on the toolkit
If you are on Classic v2 and it still publishes fine, you can stay. Migrate when you hit Python errors, broken assets, localhost links, or you are setting up a new machine and do not want to resurrect Python 2.
Migration guide: docs/MIGRATION.md.
A note on expectations
This project will not magically turn GitHub Pages into a full Ghost server. Comments widgets, membership, newsletters, and other dynamic Ghost features need a real Ghost host or third-party services.
What it does well is the thing many indie writers and side-project blogs actually need:
A pleasant editor locally + a free, fast, public static blog.
If that is your goal, the v3 path is substantially less painful than the Classic era.
Quick links
- Repo: paladini/ghost-on-github-pages
- Latest release: v3.0.0 / latest
- Getting started: docs/v3/GETTING-STARTED.md
- Migration from Classic: docs/MIGRATION.md
- v3 demo: paladini.github.io/ghost-on-github-pages-demo
Questions and bug reports welcome via GitHub Issues. Docs contributions count too — you do not need to be a developer to help.
If this saved you a hosting bill (or an afternoon fighting Python 2), a star on the repo helps other people find it.
Top comments (0)