Published: August 01, 2018
Updated: January 30, 2019
Tags: Ghost, Backup, Restore
4 min read

Backing Up / Restoring Self-Hosted Ghost Instance

Ghost was updated to 2.0, the content of this blog is not tested

(Follow-up to the previous blog post regarding Ghost's Data Structure)

Relevant for self-hosted non-containerized Ghost 1.X, might not be suited in the future Ghost 2.0 release

This blog post doesn't cover the most "optimal" way to backup and restore your data. This post meant to be an overview of backing up and restoring self-hosted Ghost instance. There are plenty of scripts/tools that can help you backup your data in a more efficient way

There are a few ways we can backup a self-hosted Ghost instance.

Using Ghost's native tool

Ghost includes an option to export some of your instance's content into a (large) JSON file.

This feature is very user-friendly but doesn't guarantee that all of your content will be backed up [1].

Export content

In order to back up your data, navigate to the Ghost Dashboard > Labs > Export your content.

Ghost's native export tool

Resulting in a JSON file containing your data:

{"db":[{"meta":{"exported_on":1532812983681,"version":"1.25.2"},"data":{"app_fields":[],"app_settings":[],"apps":[],"brute":[{"key":"ymz9A0U3Tw7fLTdqMKCQoLfpnZjo19HSaVzbtct0pD
U=","firstRequest":1532805883312,"lastRequest":1532807549811,"lifetime":1532811149815,"count":2}],"invites":[],"migrations":[{"id":1,"name":"1-create-tables.js","version":"ini
t","currentVersion":"1.24"}
...

Import content

Ghost will notify you if it'll try to restore existing entries

In order to restore your data, navigate to Ghost Dashboard > Labs > Import content, browse for your JSON file and wait for it to finish importing,

Ghost's native import tool

Manual

We can back up content manually by copying Ghost's data directory on filesystem and backing up Ghost's database.

This is a more advanced and potentially destructive than using the built-in tool.

Backup filesystem

Navigate to your Ghost's installation directory and then browse the content subdirectory:

[22:20:15] ubuntu@website /var/www/ghost
$ cd content/
[22:20:18] ubuntu@website /var/www/ghost/content
$ ls -ltra
total 32
drwxrwxr-x 2 ghost  ghost  4096 Jul 14 16:48 apps
drwxrwxr-x 8 ghost  ghost  4096 Jul 14 16:48 .
drwxrwxr-x 2 ghost  ghost  4096 Jul 14 16:50 settings
drwxrwxr-x 2 ghost  ghost  4096 Jul 27 07:19 data
drwxrwxr-x 2 ghost  ghost  4096 Jul 28 00:00 logs
drwxrwxr-x 5 ubuntu ubuntu 4096 Jul 28 18:46 ..
drwxrwxr-x 3 ghost  ghost  4096 Jul 28 20:49 themes
drwxrwxr-x 2 ghost  ghost  4096 Jul 28 21:33 images

Backup everything into a compressed tar archive and save it in a directory (in this case it'll be saved in /tmp/ and the name format will be Content-Month-Day-Year-HourMinutes.tgz)

[03:52:12] ubuntu@website /var/www/ghost/content
$ sudo tar -caf /tmp/Content-$(date +"%b-%d-%Y_%H%m").tgz ./*

Verify that the archive contains all the relevant files

[03:52:16] ubuntu@website /var/www/ghost/content
$ sudo tar -tf /tmp/Content-Jul-29-2018_0307.tgz
./apps/
./data/
./data/redirects.json
./data/vkhitrin-com.ghost.2018-07-27.json
./images/
./logs/
./logs/https___www_vkhitrin_com_blog_production.log.6
....

Backup database

Make a dump of all the SQL commands needed to rebuild your database and save it to a file (in this case it'll be saved in /tmp/ and the name format will be ghost_db-Month-Day-Year-HourMinut
es
.sql):

[04:08:56] ubuntu@website /var/www/ghost/content
$ mysqldump -u root -p ghost_prod > /tmp/ghost_db-$(date +"%b-%d-%Y_%HH%m").sql
Enter password:

Verify the content of the file:

[04:12:00] ubuntu@website /var/www/ghost/content
$ cat /tmp/ghost_db-Jul-29-2018_0407.sql
-- MySQL dump 10.13  Distrib 5.7.22, for Linux (x86_64)
--
-- Host: localhost    Database: ghost_db
-- ------------------------------------------------------
-- Server version       5.7.22-0ubuntu0.16.04.1

/*!40101 SET @OLD_CHARACTER_SET_CLIENT=@@CHARACTER_SET_CLIENT */;
/*!40101 SET @OLD_CHARACTER_SET_RESULTS=@@CHARACTER_SET_RESULTS */;
/*!40101 SET @OLD_COLLATION_CONNECTION=@@COLLATION_CONNECTION */;
/*!40101 SET NAMES utf8 */;
/*!40103 SET @OLD_TIME_ZONE=@@TIME_ZONE */;
/*!40103 SET TIME_ZONE='+00:00' */;
/*!40014 SET @OLD_UNIQUE_CHECKS=@@UNIQUE_CHECKS, UNIQUE_CHECKS=0 */;
/*!40014 SET @OLD_FOREIGN_KEY_CHECKS=@@FOREIGN_KEY_CHECKS, FOREIGN_KEY_CHECKS=0 */;
/*!40101 SET @OLD_SQL_MODE=@@SQL_MODE, SQL_MODE='NO_AUTO_VALUE_ON_ZERO' */;
/*!40111 SET @OLD_SQL_NOTES=@@SQL_NOTES, SQL_NOTES=0 */;

--
-- Table structure for table `accesstokens`
--

DROP TABLE IF EXISTS `accesstokens`;
......

Restore content to filesystem from tar archive

Navigate to your Ghost's installation directory and then browse the content subdirectory:

[22:20:15] ubuntu@website /var/www/ghost
$ cd content/

Extract content from the tar archive (by default overrides files)

[05:11:20] ubuntu@website /var/www/ghost/content
$ sudo tar -xvf /tmp/Content-Jul-29-2018_0307.tgz

Restore content to database from dump

You may be required to drop tables before restoring from dump file

Execute SQL commands from SQL dump file:

[05:13:22] ubuntu@website /var/www/ghost/content
$ mysql -u root -p ghost_prod < /tmp/ghost_db-Jul-29-2018_0407.sql
Enter password:

  1. Official documentation of the in-built import/export tool ↩︎