4 min read

Automated Ghost CMS Backups: Cron + Rclone to Google Drive (Full Guide)

Automated Ghost CMS Backups: Cron + Rclone to Google Drive (Full Guide)

Introduction

Right after moving Ghost CMS from KVM 4 to KVM 2 in the last post, one question immediately hit me: what about backups?

Hostinger's Daily Backup add-on costs an extra $6/month, which works out to $144 over a 24-month plan. Moving house to save money only to turn around and pay for backups is completely backwards, so I decided to write my own script: schedule backups with cron and sync them to Google Drive with rclone. Zero cost (well, there is some cloud cost~~).

Backup Strategy

Item Setting
Backup frequency Every 12 hours
Local retention 7 days
Google Drive retention 90 days
Backup contents MySQL database + Ghost content folder + config
Size per backup About 160MB (DB 15MB + Content 145MB)

Step 1: Create the Backup Directory

sudo mkdir -p /var/backups/ghost
sudo chown youruser:youruser /var/backups/ghost

Step 2: Write the Backup Script

cat > ~/ghost-backup.sh << 'EOF'
#!/bin/bash
# Ghost CMS Auto Backup Script
# Local retention 7 days, Google Drive retention 90 days

BACKUP_DIR="/var/backups/ghost"
DATE=$(date +%Y%m%d_%H%M%S)
GHOST_DIR="/var/www/ghost"

echo "[$(date)] Starting Ghost backup..."

# Back up the database
mysqldump --no-tablespaces -u ghost_user -p'你的密碼' ghost_db > "$BACKUP_DIR/ghost-db-$DATE.sql"

# Back up the content folder (themes, images, config file)
sudo tar czf "$BACKUP_DIR/ghost-content-$DATE.tar.gz" -C "$GHOST_DIR" content/ config.production.json

# Delete local backups older than 7 days
find "$BACKUP_DIR" -name "ghost-*" -mtime +7 -delete

echo "[$(date)] Backup complete: $BACKUP_DIR/ghost-db-$DATE.sql + ghost-content-$DATE.tar.gz"

# Upload to Google Drive
rclone copy "$BACKUP_DIR/ghost-db-$DATE.sql" gdrive:ghost-backups/
rclone copy "$BACKUP_DIR/ghost-content-$DATE.tar.gz" gdrive:ghost-backups/

# Delete Google Drive backups older than 90 days
rclone delete gdrive:ghost-backups/ --min-age 90d

echo "[$(date)] Uploaded to Google Drive"
EOF

chmod +x ~/ghost-backup.sh

Step 3: Fix the Content Folder Permission Issue

Ghost's content folder is owned by ghost:ghost, so a regular user running tar will hit Permission denied. Set up passwordless sudo for tar:

echo "youruser ALL=(ALL) NOPASSWD: /usr/bin/tar" | sudo tee /etc/sudoers.d/ghost-backup

Now the sudo tar in the script won't get stuck waiting for a password.

Step 4: Install and Configure Rclone

Install Rclone

sudo apt install -y rclone

If apt can't find it, use the official install script:

curl https://rclone.org/install.sh | sudo bash

Set Up the Google Drive Connection

The VPS has no browser, so you need to authorize in headless mode:

rclone config

Follow the steps in order:

  1. n (New remote)
  2. Enter gdrive for the Name
  3. Choose drive (Google Drive) for Storage
  4. client_id → just press Enter (use the built-in key)
  5. client_secret → just press Enter
  6. scope → choose 1 (Full access)
  7. service_account_file → Enter to skip
  8. Edit advanced config → n
  9. Use auto config → n (important! On a VPS you must choose No)

At this point a string of authorization commands appears:

rclone authorize "drive" "eyJzY29wZSI6ImRyaXZlIn0"

Complete the Authorization on Your Local Machine

Run that command on a computer that has a browser (your Kali box):

# First install rclone (if you haven't already)
curl https://rclone.org/install.sh | sudo bash

# Run the authorization
rclone authorize "drive" "eyJzY29wZSI6ImRyaXZlIn0"

The browser opens the Google login page automatically, and once you authorize, the terminal prints a token string. Copy the whole token and paste it back into the VPS at the config_token> prompt.

Finally:

  • Configure as Shared Drive → n
  • Keep this remote → y
  • q to quit

Test the Connection

# Create the backup folder on Google Drive
rclone mkdir gdrive:ghost-backups

# Confirm the folder exists
rclone lsd gdrive:

Step 5: Set Up the Cron Schedule

Run the backup automatically every 12 hours, with logs written to /var/log/ghost-backup.log:

(crontab -l 2>/dev/null; echo "0 */12 * * * /home/youruser/ghost-backup.sh >> /var/log/ghost-backup.log 2>&1") | crontab -

Confirm the cron entry was added successfully:

crontab -l
# You should see:
# 0 */12 * * * /home/youruser/ghost-backup.sh >> /var/log/ghost-backup.log 2>&1

Step 6: Full Test Run

bash ~/ghost-backup.sh

Expected output:

[Sun Mar  1 11:57:06 UTC 2026] Starting Ghost backup...
[Sun Mar  1 11:57:12 UTC 2026] Backup complete: /var/backups/ghost/ghost-db-20260301_115706.sql + ghost-content-20260301_115706.tar.gz
[Sun Mar  1 11:57:31 UTC 2026] Uploaded to Google Drive

Confirm the files are on Google Drive:

rclone ls gdrive:ghost-backups/
# 151230801 ghost-content-20260301_115706.tar.gz
#  15515331 ghost-db-20260301_115706.sql

Restore Procedure (Just in Case)

If the day ever comes that you actually need to restore, just pull the files back from Google Drive:

# List available backups
rclone ls gdrive:ghost-backups/

# Download the backup for a specific date
rclone copy gdrive:ghost-backups/ghost-db-20260301_115706.sql /tmp/
rclone copy gdrive:ghost-backups/ghost-content-20260301_115706.tar.gz /tmp/

# Restore the database
mysql -u ghost_user -p ghost_db < /tmp/ghost-db-20260301_115706.sql

# Restore content
cd /var/www/ghost
sudo tar xzf /tmp/ghost-content-20260301_115706.tar.gz

# Fix permissions
sudo chown -R ghost:ghost /var/www/ghost/content

# Restart Ghost
ghost restart

Cost Comparison

Option Two-year cost
Hostinger Daily Backup $6/month × 24 = $144
DIY Cron + Rclone + Google Drive $0

Same result, $144 saved, and the backup frequency (every 12 hours) is even higher than Hostinger's Daily Backup. Google Drive gives you 15GB free, and at 160MB per backup, 90 days of backups comes to about 28.8GB... uh, which actually exceeds 15GB.

⚠️ Space estimate: 160MB × 2/day × 90 days = 28.8GB, over Google Drive's free 15GB. In practice, since it backs up every 12 hours and starts deleting old files after 90 days, the steady state settles at around 28.8GB. If you run out of space, you can drop the Google Drive retention to 45 days (about 14.4GB), or upgrade to Google One 100GB ($1.99/month).

Conclusion

Rolling your own backups is easier than it sounds; the whole setup took about 10 minutes. The key pieces are:

  1. mysqldump to back up the database
  2. tar to package up content and config
  3. rclone to push it all to Google Drive
  4. cron to run it on a schedule
  5. find / rclone delete to clean up old backups automatically

Next time the VPS acts up, I can restore within 15 minutes. Peace of mind.