GGlyphDocs

deployment

Backups

Back up the database, file volumes, and search indices.

Glyph state lives in three places. Back all three up to recover cleanly.

What to back up

PathWhat it containsCritical?
MySQL databaseDocumentation, refs, comments, users, workspaces, projects metadataYes - irreplaceable
volumes/data/Cloned Git repositories, uploaded filesYes for Local projects, recoverable from Git remote for others
volumes/meilisearch/Search indicesNo - can be rebuilt from the database

The MySQL backup is the most important - it's the only place documentation lives. The data volume matters mainly for Local Upload projects (no remote to recover from).

Manual backup

Database

cd /opt/glyph  # your install directory
 
docker exec glyph-db \
  mysqldump -u glyph -p"$(grep MYSQL_PASSWORD .env | cut -d= -f2)" glyph \
  | gzip > backups/glyph-db-$(date +%F-%H%M).sql.gz

Data volume

tar czf backups/glyph-data-$(date +%F-%H%M).tar.gz volumes/data/

Meilisearch indices (optional)

docker compose stop meilisearch
tar czf backups/glyph-meili-$(date +%F-%H%M).tar.gz volumes/meilisearch/
docker compose start meilisearch

Stopping Meilisearch ensures a consistent snapshot. Skip the stop/start if a slightly inconsistent backup is acceptable (it can always be rebuilt).

Automated nightly backup

Save this as /opt/glyph/backup.sh:

#!/bin/bash
set -euo pipefail
 
BACKUP_DIR=/opt/glyph/backups
KEEP_DAYS=14
 
cd /opt/glyph
mkdir -p "$BACKUP_DIR"
 
DATE=$(date +%F-%H%M)
PASS=$(grep ^MYSQL_PASSWORD= .env | cut -d= -f2)
 
# Database
docker exec glyph-db mysqldump -u glyph -p"$PASS" glyph \
  | gzip > "$BACKUP_DIR/db-$DATE.sql.gz"
 
# Data volume (Git repos)
tar czf "$BACKUP_DIR/data-$DATE.tar.gz" volumes/data/
 
# Prune old backups
find "$BACKUP_DIR" -name 'db-*.sql.gz'  -mtime +$KEEP_DAYS -delete
find "$BACKUP_DIR" -name 'data-*.tar.gz' -mtime +$KEEP_DAYS -delete
 
echo "Backup completed: $DATE"

Make it executable and schedule with cron:

chmod +x /opt/glyph/backup.sh
crontab -e

Add:

0 3 * * * /opt/glyph/backup.sh >> /var/log/glyph-backup.log 2>&1

Runs nightly at 3 AM, keeps 14 days of backups.

Off-site copy

Local backups protect against accidental deletion but not server loss. Sync the backups/ directory off-site:

rclone to S3 / B2 / etc.

# In the cron job, after backup
rclone sync /opt/glyph/backups remote:glyph-backups

rsync to another server

rsync -az /opt/glyph/backups/ user@backup-host:/path/to/glyph-backups/

Borg / Restic

For incremental, deduplicated, encrypted backups, use a tool like restic or borg.

Restoring

See Database for the restore command. After restoring the database:

  1. Restore volumes/data/ if needed.
  2. Optionally restore volumes/meilisearch/ - or trigger sync on each project to rebuild.

Testing the backup

A backup that's never been tested is not a backup. Once a quarter:

  1. Spin up a fresh Glyph instance on a separate machine or VM.
  2. Restore the latest backup.
  3. Sign in, browse a project, verify documentation is intact.

If anything fails, fix the backup script - not the production install.