Do you truly control your content if you post it on Medium?

At the beginning of this year, I switched from Medium to a static site powered by Ghost. Although Ghost(Pro) is a strong choice if you have paying subscribers, it is impossible to beat static hosting for a simple blog. Static sites are fast, secure, and free.

Here's a quick rundown of my reasoning and approach - from editing in Ghost's world-class UI to deploying for free on a static hosting provider like Netlify.


I was looking for a blogging solution that met these requirements:

  • Slick UI: Even though I use vim and markdown daily, I prefer a Medium-like freeform writing experience.
  • Self-hosted: Full control of my content with no vendor lock-in, paywalls, or subscription pop-ups.
  • High availability: I should never receive a monitoring alert for my personal blog.
  • Exceptional performance: I want the page to load fast!
  • Secure and low-maintenance: After supporting dozens of WordPress sites over more than a decade, I have grown weary of hacked plugins and frequent patching cycles.

Static 👻

Even though I use markdown every day in my work, I prefer the WYSIWYG writing experience of a web UI. Ghost's UI is fantastic!

The main drawback of Ghost is the same as WordPress: every request depends on a database. Each time a user visits a page on the site, the following steps take place:

  1. The web server passes the end user's request to a running application server (Node.js for Ghost, PHP for WordPress).
  2. The application server analyzes the incoming request and dispatches requests to the database for necessary content (MySQL for Ghost).
  3. The application server renders the content from the database into a web page.
  4. The web server passes the resulting page back to the end user.

This architecture requires significant compute and memory resources on both the application server and database server. It is susceptible to performance issues due to spikes in demand. And achieving high availability requires a database cluster and web load balancer. Lots of distinct parts to deploy, secure, and operate.

The advent of the JAMstack architecture has brought static sites into the limelight. By moving steps 2 and 3 to the beginning, Ghost can generate each page on the site in advance. Then, it's easy to upload the static site to a free or almost-free hosting provider (see below for suggestions).

Fast and secure sites and apps delivered by pre-rendering files and serving them directly from a CDN, removing the requirement to manage or run web servers. - JAMstack

Static sites have a significantly smaller attack surface than sites driven by databases and application code. Bugs, vulnerabilities, and build issues can be identified by the build phase, rather than when the site is live.

You get the rich editing of Ghost while enjoying all of the operational and cost advantages of a static JAM site:

  • Never worry about scaling when traffic spikes.
  • Never apply a critical security patch at midnight.
  • Who cares if your Ghost database is temporarily down?

Making Ghost Static

First, setup a private Ghost instance to use for editing, formatting, and peer review. This can be a very small VM, since it doesn't have to serve any production traffic. Defying traditional best-practices, it's even safe to co-locate MySQL on the same system! Ghost(Valet) is very reasonably priced if you need a hand with this step.

You can secure access to this system with a firewall or VPN. A better approach is to use an authentication proxy like oauth2-proxy or pomerium for a user-friendly, "zero trust" solution.

Then, use Ghost Static Site Generator (gssg) to create a static mirror of the site that is hosted by Netlify:

Generate a static site from ghost and deploy using a CI - Fried-Chicken/ghost-static-site-generator

gssg will spider your local Ghost site, creating a fully static copy. Here's the short Makefile I use:

	rm -rf static/
	gssg --url --domain
	cp ghost/etc/keybase.txt static/
	cp static/404/index.html static/404.html

You can publish this copy to your Netlify site with their CLI or by (recommended) linking a Git repository. Netlify offers 100GB of bandwidth/month for free, which is plenty for most use cases. They also take care of TLS certificates automatically.

Netlify: All-in-one platform for automating modern web projects
Deploy modern static websites with Netlify. Get CDN, Continuous deployment, 1-click HTTPS, and all the services you need. Get started for free.

Of course, there are dozens of static hosting options similar to Netlify. Github Pages, AWS S3+CloudFront, AWS Amplify, Firebase Hosting, and Azure Static Web Apps are all safe choices with generous free tiers.

A Critical Limitation: Interactivity 🚨

By creating a static Ghost site, you naturally break all interactive features. Say goodbye to Ghost's library of integrations, and you won't be able to monetize with Ghost's membership and subscription management.

It's easy to include contact/feedback forms with tools like Netlify Forms or Upscribe. You can embed rich media, social media, and all kinds of Javascript widgets (weather, news, etc.). But if you intend to have users login to your site, you'll need a database-backed service.

For paid creators, Substack is growing in popularity with its focus on newsletters. Truly complex sites with many editors should evaluate Drupal or consider custom development. But I would encourage you to check out Ghost(Pro) - your subscription goes back into the Ghost foundation, making the software even better.

It Works!

This site is created with Ghost and hosted by the fine folks at Netlify. It's fast:

The next time you need to deploy a fast, secure, simple blog, think about the juicy combination of Ghost's UI and free static hosting.

Let me know if you end up using this approach! Follow me at @nedmcclain for updates on web performance, infrastructure, and operations.


Note: I have no affiliation with or sponsorship from Ghost or Netlify. I pay for Netlify's "Pro" account, and it's worth every penny.

Ghost name and logo are trademarks of the Ghost Foundation.
Photo by
Patrick Tomasso on Unsplash.