Why self-host Ghost on a VPS
Ghost combines what WordPress does laboriously and what Substack charges dearly for: a clean editor, excellent native performance (Node.js), integrated member and paid-subscription management via Stripe, and newsletter sending without a plugin. But Ghost(Pro) bills by audience, and newsletter platforms take a commission on your revenue. By hosting it on your VPS, you keep 100% of your paying subscribers (excluding Stripe fees), you customize the theme without restriction, and you control your email list, your most valuable asset.
The benefits of a self-hosted Ghost
- No platform commission on your paid subscriptions (excluding Stripe)
- Native performance: pages served in a few tens of milliseconds
- Integrated newsletters and members, without a stack of plugins
- Full customization of the Handlebars theme and complete API access
- Control of your subscriber list and your data
- A fixed VPS cost regardless of the number of readers
Realistic prerequisites
Ghost is lightweight: a 1-2 vCPU / 2 GB RAM VPS handles a blog with comfortable traffic; move up to 4 GB if your audience grows fast. It needs a MySQL 8 database (recommended in production), Docker + Compose, and a transactional SMTP service (Mailgun, Postmark, etc.) for reliable delivery of newsletters and member emails. Plan for a blog.yourdomain.com domain with its SSL certificate.
Step-by-step deployment
Compose Ghost and its database
In docker-compose.yml, declare the official ghost:5-alpine image and a mysql:8 service. Link them on an internal network, persist the content in a /var/lib/ghost/content volume and the MySQL data in a dedicated volume.
Set the URL and the database
Define url=https://blog.yourdomain.com (crucial: Ghost generates all its links from this value) and the database__connection__* variables pointing to the MySQL service.
Configure email sending
Set the mail__transport=SMTP variables and your transactional provider's credentials. This is essential for newsletters and members' login emails.
Launch and access the admin
Start with docker compose up -d, then go to /ghost to create the owner account and configure the site. Verify the sending of a test email from the settings.
Place the SSL reverse proxy
Configure Nginx/Caddy in HTTPS in front of Ghost's port 2368. With Caddy, the Let's Encrypt certificate is automatic; also enable compression and caching of static assets.
Connect Stripe and publish
Connect your Stripe account in Settings > Members to enable paid subscriptions, define your tiers, then publish your first article and send your first newsletter.
Place a CDN or a page cache (Cloudflare in proxy mode, or an Nginx proxy_cache) in front of Ghost: since almost all public content is static, you absorb traffic spikes (the Hacker News or social-media effect) without overloading the VPS, while keeping the admin and member pages dynamic and excluded from the cache via rules on /ghost and /members.
The official documentation
For advanced configuration and options specific to the tool, refer to the official Ghost documentation. This guide covers going live on a VPS; the vendor's docs remain the reference for fine-tuning, major updates and specific use cases.