Run your own Ghost blog and newsletter: domain, email, members and backups

Deploy Ghost from Zenavo's template, bind an HTTPS domain, create the admin account, set up email so member sign-ups and newsletters work, and back up both MySQL and the content folder.

This post is also available in 简体中文, 繁體中文, 日本語, Español and Bahasa Indonesia.

Ghost is an open-source publishing platform: posts, paid or free memberships and newsletters all live in one admin, with a clean editor and search-friendly themes. If you want a blog of your own without looking after WordPress plugins, Ghost is a good fit.

This guide uses Zenavo's Ghost template to run Ghost and MySQL on a server you rent or own, then sets up the domain, email and backups.

Before you start

  • A Linux server connected to Zenavo. The template asks for about 1 GB of memory; leave room for MySQL too.
  • A domain for the blog, such as blog.example.com.
  • An SMTP account from an email provider (used later). Member sign-ups, login links and staff invitations all go by email.

Deploy the template

Open the Ghost template. Before deploying, it asks for the Site URL: the full address readers will use, such as https://blog.example.com. It creates two services:

Service What it holds
mysql MySQL 8.4, volume /var/lib/mysql, generated root password
ghost ghost:5-alpine on HTTP port 2368, content folder /var/lib/ghost/content (images and themes)

The Site URL becomes the ghost service's url variable. Ghost builds every link from it, so it must match the domain you end up using exactly, https:// included.

Bind the domain and create the admin

On the ghost service's Networking tab, bind the same domain to port 2368, add an A record pointing to the server, and wait for HTTPS (Domains & HTTPS).

Open https://blog.example.com/ghost and follow the steps to name the site and create the first admin account. The admin is always at /ghost. As with any self-hosted app, do this yourself as soon as the domain works.

To move to another domain later, change the url variable, redeploy, and bind the new domain. Changing the domain without url leaves links pointing at the old address.

Set up email

Ghost sends two kinds of email:

  • Transactional: staff invitations, password resets, member sign-ups and login links. Any SMTP service works.
  • Bulk newsletters: posts sent to every subscriber. Ghost currently sends these only through Mailgun, configured in the admin under Settings → Email newsletter with your Mailgun domain and API key.

Set up transactional email in the ghost service's Variables. Ghost writes nested settings with double underscores:

Variable Example
mail__transport SMTP
mail__options__host smtp.example.com
mail__options__port 465
mail__options__secure true
mail__options__auth__user your SMTP user name
mail__options__auth__pass your SMTP password
mail__from "Blog name" <noreply@example.com>

Redeploy the ghost service, then invite a staff member or sign up as a member with another address to check the email arrives.

Some server providers block outgoing SMTP ports, which shows up as timeouts. Use another port your email provider offers (such as 2525), or ask the server provider to unblock it. Also set up SPF and DKIM for your domain as your email provider describes, or mail tends to land in spam.

A few settings before you write

  • Settings → General: site title, description, time zone and language.
  • Settings → Design: pick a theme or upload your own; themes are stored in the content folder.
  • Settings → Membership: whether readers can sign up, and whether some posts are for members only.
  • Settings → Code injection: a place for an analytics script, such as self-hosted Umami or Plausible.

Back up

Ghost keeps its data in two places: posts, members and settings in MySQL; images, themes and uploads in the ghost service's /var/lib/ghost/content volume. Back up both.

  • Back up the database any time from the mysql service's Backup & Restore tab.
  • The content folder is a volume: stop the project while backing it up, then start it again.

Ghost's own export (in the admin settings) saves posts and settings as JSON, handy for moving to another Ghost, but it leaves out images. For data that matters, download a backup to keep and restore it once into a new project to check it. See Backup & Restore.

Upgrade

The template runs ghost:5-alpine, so a redeploy pulls the latest Ghost 5. Back up MySQL and the content folder and read the release notes first. Major upgrades may migrate the database, and going back to the old image may not undo that; restore the backup from before the upgrade instead.

FAQ

Links on the site point to localhost or the old domain? The url variable doesn't match the address you're using. Set it to the full, correct address and redeploy.

Members don't receive login emails? Look for mail errors in the ghost service's logs. Usually the SMTP port is blocked, the user name or password is wrong, or the mail__from domain isn't verified with your email provider.

Can I move over from WordPress or elsewhere? Ghost has official migration tools and guides for WordPress, Substack and others. Imported images go into the content folder, so include it in your backups.

Ghost or WordPress? For writing and newsletters with little upkeep, choose Ghost; for many plugins, a shop or complex pages, WordPress fits better. Zenavo has a WordPress template too.

Start from the Ghost template: match the domain and url first, then create the admin, set up email, and back up both the database and the content folder.