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
| Path | What it contains | Critical? |
|---|---|---|
| MySQL database | Documentation, refs, comments, users, workspaces, projects metadata | Yes - irreplaceable |
volumes/data/ | Cloned Git repositories, uploaded files | Yes for Local projects, recoverable from Git remote for others |
volumes/meilisearch/ | Search indices | No - 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.gzData 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 meilisearchStopping 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 -eAdd:
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-backupsrsync 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:
- Restore
volumes/data/if needed. - 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:
- Spin up a fresh Glyph instance on a separate machine or VM.
- Restore the latest backup.
- Sign in, browse a project, verify documentation is intact.
If anything fails, fix the backup script - not the production install.