Skip to content

Backup & Recovery

Backup and restore your Mist installation.

What to Backup

1. SQLite Database (Critical)

The database contains all your Mist data:

  • Users, sessions, and authentication tokens
  • Projects and team members
  • Applications and configurations
  • Deployments and deployment history
  • Environment variables (including secrets)
  • Domains and SSL certificate tracking
  • GitHub App credentials
  • Audit logs

Location: /var/lib/mist/mist.db

Size: Typically 10-100 MB depending on usage

Critical Data

This is the single most important file to backup. Without it, you lose all configuration and deployment history.

2. SSL Certificates (Important)

Let's Encrypt SSL certificates for your domains.

Location: /opt/mist/letsencrypt/acme.json

Note: Certificates can be re-issued by Let's Encrypt, but backing them up prevents rate limiting and downtime during recovery.

3. Traefik Configuration (Auto-Generated)

Dynamic Traefik routing configuration.

Location: /var/lib/mist/traefik/dynamic.yml

Note: This file is auto-generated from the database, so restoring the database will recreate it.

4. User Uploads (Optional)

User avatars and uploaded files.

Location: /var/lib/mist/uploads/

Size: Usually small (< 100 MB)

5. Application Data (Important for Databases)

If you're running databases (PostgreSQL, MySQL, MongoDB, Redis) as applications in Mist, their data is stored in Docker volumes.

List volumes:

bash
docker volume ls | grep mist

Backup application volumes separately if they contain important data.

What NOT to Backup

  • /var/lib/mist/logs/ - Build logs (can be large, usually not needed)
  • Git repositories - Cloned from source, can be re-cloned
  • Docker images - Can be rebuilt
  • /var/lib/mist/traefik/dynamic.yml - Auto-generated from database

Manual Backup

Quick Database Backup

bash
# Stop Mist service for consistency
sudo systemctl stop mist

# Backup database with timestamp
sudo cp /var/lib/mist/mist.db /var/backups/mist_$(date +%Y%m%d_%H%M%S).db

# Start Mist service
sudo systemctl start mist

# Verify backup
ls -lh /var/backups/mist_*.db

Hot Backup (No Downtime)

SQLite supports online backups. You can backup without stopping Mist:

bash
# Create backup directory
sudo mkdir -p /var/backups/mist

# Hot backup using SQLite
sqlite3 /var/lib/mist/mist.db ".backup /var/backups/mist_$(date +%Y%m%d_%H%M%S).db"

Full System Backup

Backup all Mist data including database, certificates, and uploads:

bash
# Create backup directory
sudo mkdir -p /var/backups/mist

# Stop Mist for consistency (optional for hot backup)
sudo systemctl stop mist

# Backup everything
sudo tar -czf /var/backups/mist_full_$(date +%Y%m%d_%H%M%S).tar.gz \
  /var/lib/mist/mist.db \
  /var/lib/mist/uploads \
  /opt/mist/letsencrypt/acme.json \
  /opt/mist/traefik-static.yml

# Start Mist
sudo systemctl start mist

# Verify backup
ls -lh /var/backups/mist_full_*.tar.gz

Backup Database Volumes (for Database Applications)

If you run databases (PostgreSQL, MySQL, etc.) as applications in Mist:

bash
# List all Docker volumes
docker volume ls

# Backup a specific volume
docker run --rm -v app-123_data:/data -v /var/backups:/backup \
  alpine tar -czf /backup/app-123_data_$(date +%Y%m%d).tar.gz -C /data .

Automated Backup Script

Create /usr/local/bin/mist-backup.sh:

bash
#!/bin/bash

# Mist Automated Backup Script
BACKUP_DIR="/var/backups/mist"
DATE=$(date +%Y%m%d_%H%M%S)
RETENTION_DAYS=30
DB_PATH="/var/lib/mist/mist.db"
CERT_PATH="/opt/mist/letsencrypt/acme.json"

# Create backup directory
mkdir -p $BACKUP_DIR

# Hot backup database using SQLite (no downtime)
if [ -f "$DB_PATH" ]; then
    sqlite3 $DB_PATH ".backup $BACKUP_DIR/mist_$DATE.db"
    echo "✅ Database backed up: mist_$DATE.db"
else
    echo "❌ Database not found at $DB_PATH"
    exit 1
fi

# Backup SSL certificates
if [ -f "$CERT_PATH" ]; then
    cp $CERT_PATH $BACKUP_DIR/acme_$DATE.json
    echo "✅ Certificates backed up: acme_$DATE.json"
fi

# Backup user uploads (if exists)
if [ -d "/var/lib/mist/uploads" ]; then
    tar -czf $BACKUP_DIR/uploads_$DATE.tar.gz -C /var/lib/mist uploads
    echo "✅ Uploads backed up: uploads_$DATE.tar.gz"
fi

# Remove old backups (keep last N days)
find $BACKUP_DIR -name "mist_*.db" -mtime +$RETENTION_DAYS -delete
find $BACKUP_DIR -name "acme_*.json" -mtime +$RETENTION_DAYS -delete
find $BACKUP_DIR -name "uploads_*.tar.gz" -mtime +$RETENTION_DAYS -delete

echo "✅ Backup completed at $DATE"
echo "📁 Backup location: $BACKUP_DIR"

# Optional: Copy to remote server
# rsync -avz $BACKUP_DIR/ user@backup-server:/backups/mist/

Make executable and schedule:

bash
# Make script executable
sudo chmod +x /usr/local/bin/mist-backup.sh

# Test the script
sudo /usr/local/bin/mist-backup.sh

# Schedule daily backups at 2 AM
(crontab -l 2>/dev/null; echo "0 2 * * * /usr/local/bin/mist-backup.sh") | crontab -

# Verify cron job
crontab -l

Backup Frequency

  • Development: Daily backups with 7-day retention
  • Production: Daily backups with 30-day retention + offsite copies
  • Critical systems: Multiple daily backups + real-time replication

Backup to Cloud Storage

AWS S3

bash
# Install AWS CLI
curl "https://awscli.amazonaws.com/awscli-exe-linux-x86_64.zip" -o "awscliv2.zip"
unzip awscliv2.zip
sudo ./aws/install

# Configure credentials
aws configure
# Enter: Access Key ID, Secret Access Key, Region

# Backup to S3
aws s3 cp /var/backups/mist/mist_$(date +%Y%m%d_%H%M%S).db \
  s3://your-bucket/mist-backups/

# Automated S3 backup (add to backup script)
aws s3 sync /var/backups/mist/ s3://your-bucket/mist-backups/ --delete

Backblaze B2

bash
# Install B2 CLI
sudo pip3 install b2

# Authenticate
b2 authorize-account <keyId> <applicationKey>

# Create bucket (one-time)
b2 create-bucket mist-backups allPrivate

# Upload backup
b2 upload-file mist-backups /var/backups/mist/mist_latest.db mist_$(date +%Y%m%d).db

Rsync to Remote Server

bash
# Setup SSH key (one-time, run as backup user)
ssh-keygen -t ed25519 -f ~/.ssh/backup_key -N ""
ssh-copy-id -i ~/.ssh/backup_key user@backup-server

# Sync backups
rsync -avz -e "ssh -i ~/.ssh/backup_key" \
  /var/backups/mist/ \
  user@backup-server:/backups/mist/

# Add to automated script
rsync -avz --delete \
  /var/backups/mist/ \
  user@backup-server:/backups/mist/

Rclone (Universal Cloud Backup)

Rclone supports 40+ cloud providers (S3, Google Drive, Dropbox, OneDrive, etc.):

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

# Configure cloud provider (interactive)
rclone config

# Backup to cloud
rclone copy /var/backups/mist/ remote:mist-backups/ -v

# Automated sync (add to backup script)
rclone sync /var/backups/mist/ remote:mist-backups/ --delete-excluded

Restore from Backup

Database Restore

bash
# Stop Mist service
sudo systemctl stop mist

# Backup current database (just in case)
sudo cp /var/lib/mist/mist.db /var/lib/mist/mist.db.before-restore

# Restore database from backup
sudo cp /var/backups/mist/mist_20250122_140000.db /var/lib/mist/mist.db

# Fix permissions (important!)
sudo chown $USER:$USER /var/lib/mist/mist.db
sudo chmod 644 /var/lib/mist/mist.db

# Start Mist service
sudo systemctl start mist

# Verify service is running
sudo systemctl status mist

# Check logs for errors
journalctl -u mist -f

Permission Issues

Make sure the database file is owned by the user running the Mist service (usually the user who installed Mist, not mist or root).

Full System Restore

bash
# Stop Mist service
sudo systemctl stop mist

# Extract full backup
sudo tar -xzf /var/backups/mist_full_20250122.tar.gz -C /

# Or restore individual files
sudo tar -xzf /var/backups/mist_full_20250122.tar.gz \
  -C / \
  var/lib/mist/mist.db \
  opt/mist/letsencrypt/acme.json

# Fix permissions
sudo chown -R $USER:$USER /var/lib/mist
sudo chmod 600 /opt/mist/letsencrypt/acme.json

# Restart services
sudo systemctl start mist
docker compose -f /opt/mist/traefik-compose.yml restart

# Verify everything is running
sudo systemctl status mist
docker ps | grep traefik

Restore SSL Certificates

bash
# Stop Traefik
docker compose -f /opt/mist/traefik-compose.yml down

# Restore certificates
sudo cp /var/backups/mist/acme_20250122.json /opt/mist/letsencrypt/acme.json
sudo chmod 600 /opt/mist/letsencrypt/acme.json

# Start Traefik
docker compose -f /opt/mist/traefik-compose.yml up -d

# Verify certificates are loaded
docker logs traefik 2>&1 | grep -i certificate

Restore Docker Volumes (Database Applications)

bash
# Stop the application container first
docker stop container-name

# Restore volume from backup
docker run --rm -v app-123_data:/data -v /var/backups:/backup \
  alpine sh -c "cd /data && tar -xzf /backup/app-123_data_20250122.tar.gz"

# Start the application container
docker start container-name

Disaster Recovery

Complete Server Loss

Follow these steps to recover from total server failure:

  1. Provision New Server

    bash
    # Same OS as original (Ubuntu 20.04+ recommended)
    # Install Docker first
    curl -fsSL https://get.docker.com | sh
  2. Install Mist

    bash
    curl -fsSL https://raw.githubusercontent.com/trymist/mist/main/install.sh | bash
  3. Stop Mist Service

    bash
    sudo systemctl stop mist
  4. Restore Database

    bash
    # Copy backup to new server
    scp backup-server:/backups/mist_latest.db /tmp/
    
    # Restore database
    sudo cp /tmp/mist_latest.db /var/lib/mist/mist.db
    sudo chown $USER:$USER /var/lib/mist/mist.db
  5. Restore SSL Certificates (optional, but recommended)

    bash
    # Copy certificates
    scp backup-server:/backups/acme.json /tmp/
    
    # Restore
    sudo cp /tmp/acme.json /opt/mist/letsencrypt/acme.json
    sudo chmod 600 /opt/mist/letsencrypt/acme.json
  6. Start Services

    bash
    sudo systemctl start mist
    docker compose -f /opt/mist/traefik-compose.yml restart
  7. Verify Recovery

    bash
    # Check Mist service
    sudo systemctl status mist
    
    # Check Traefik
    docker ps | grep traefik
    
    # Access web interface
    curl http://localhost:8080/health  # or your domain
  8. Update DNS (if IP changed)

    • Update A records to point to new server IP
    • Wait for DNS propagation (5-60 minutes)

Database Corruption

Check and recover from database corruption:

bash
# Check database integrity
sqlite3 /var/lib/mist/mist.db "PRAGMA integrity_check;"

# If output is "ok", database is fine
# If errors appear, restore from backup:

sudo systemctl stop mist
sudo cp /var/lib/mist/mist.db /var/lib/mist/mist.db.corrupted
sudo cp /var/backups/mist/mist_LATEST.db /var/lib/mist/mist.db
sudo systemctl start mist

Accidental Data Deletion

If you accidentally delete data through the UI:

bash
# Stop Mist immediately
sudo systemctl stop mist

# Restore from most recent backup
sudo cp /var/backups/mist/mist_$(ls -t /var/backups/mist/mist_*.db | head -1) \
  /var/lib/mist/mist.db

# Start Mist
sudo systemctl start mist

Recovery Point Objective (RPO)

Your RPO = time between backups. If you backup daily at 2 AM and disaster strikes at 1 PM, you lose up to 11 hours of data. For critical systems, increase backup frequency or use real-time replication.

Backup Best Practices

The 3-2-1 Rule

  • 3 copies of data
  • 2 different storage types
  • 1 offsite copy

Backup Checklist

  • [ ] Automated daily backups configured
  • [ ] Backups stored on separate disk/server
  • [ ] Offsite/cloud backup configured
  • [ ] Backup retention policy defined (7-30 days)
  • [ ] Backup integrity tested regularly
  • [ ] Restore procedure documented
  • [ ] Recovery time objective (RTO) defined
  • [ ] Recovery point objective (RPO) defined

Test Your Backups

Regularly test restore procedures:

bash
# Test restore on separate server
scp backup-server:/backups/mist_latest.db /tmp/test-restore.db
sqlite3 /tmp/test-restore.db "SELECT COUNT(*) FROM users;"

Coming Soon

The following backup features are planned for future releases:

  • Built-in Backup UI - Configure and manage backups from the dashboard
  • One-Click Restore - Restore from backup through the UI
  • Automated S3/Cloud Backup - Built-in integration with cloud storage
  • Scheduled Backups - Configure backup schedules per project or system-wide
  • Backup Verification - Automatic integrity checks and restore testing
  • Point-in-Time Recovery - Restore to a specific moment in time
  • Incremental Backups - Save storage with differential backups
  • Database Replication - Real-time database replication to standby server
  • Automated Application Volume Backups - Backup database volumes automatically
  • Backup Encryption - Encrypt backups at rest and in transit
  • Retention Policies - Flexible retention rules (hourly, daily, weekly, monthly)
  • Webhook Notifications - Get notified on backup success/failure

Getting Help

If you encounter issues with backup or recovery:

Released under the MIT License.