Skip to content

Backup and Restore

Hop3 provides a backup and restore system to protect your applications and data. This guide covers how to use it.

Table of Contents

Overview

What's Included in a Backup?

Every Hop3 backup includes:

  • Source Code: Complete git repository with all commits and history
  • Data Directory: Application data files and user-uploaded content
  • Persistent Volumes: Every [[volumes]] volume, archived as its own unit (opt out per-volume with [volumes.backup] include = false)
  • Environment Variables: All configuration settings and secrets
  • Attached Services: Database dumps (PostgreSQL, etc.) and service data
  • Application Metadata: Hostname, port, and deployment configuration

Backup Format

Backups are stored as directories containing:

/var/hop3/backups/apps/<app-name>/<backup-id>/
├── metadata.json         # Backup manifest with checksums
├── source.tar.gz         # Git repository archive
├── data.tar.gz           # Application data archive
├── env.json              # Environment variables
├── volume-<name>.tar.gz  # One archive per persistent [[volumes]] volume
└── addons/               # Addon backups
    └── postgres_<name>.sql

Each file is verified with SHA256 checksums to ensure data integrity.

Backup IDs

Each backup has a unique ID in the format: YYYYMMDD_HHMMSS_<random>

Example: 20251108_143022_a8f3d9

Quick Start

Create Your First Backup

# Backup an application
hop3 backup create --app my-app

# Output:
# Creating backup for app 'my-app'...
#
# Backup created successfully!
#
# Backup ID: 20251108_143022_a8f3d9
# Location: /var/hop3/backups/apps/my-app/20251108_143022_a8f3d9
# Total size: 15.6 MB
#
# To restore this backup:
#   hop3 backup restore 20251108_143022_a8f3d9

List All Backups

hop3 backup list

# Output:
# BACKUP ID              APP         SIZE     CREATED              STATUS      SERVICES
# 20251108_143022_a8f3d9 my-app      15.6 MB  2025-11-08 14:30:22  COMPLETED   my-database
# 20251107_093015_b7e4c8 my-app      15.4 MB  2025-11-07 09:30:15  COMPLETED   my-database

Restore a Backup

hop3 backup restore 20251108_143022_a8f3d9

# Output:
# Restoring backup 20251108_143022_a8f3d9...
#
# Restore completed successfully!
#
# Application: my-app
# Hostname: myapp.example.com
# Port: 8000
#
# To start the application:
#   hop3 app restart --app my-app

Creating Backups

Basic Backup

Create a backup of an application:

hop3 backup create --app <app-name>

Example:

hop3 backup create --app blog

This creates a complete backup including: - Source code - Data directory - Environment variables - All attached services (PostgreSQL, Redis, etc.)

Backup Without Services

To create a backup excluding attached addons (databases, caches):

hop3 backup create --app <app-name> --no-addons

Use case: Quickly back up just the application code and data when addons are backed up separately.

What Happens During Backup?

  1. Validation: Verifies the application exists
  2. Directory Creation: Creates a uniquely identified backup directory
  3. Source Backup: Archives the git repository
  4. Data Backup: Archives the data directory
  5. Environment Backup: Exports environment variables to JSON
  6. Service Backup: Calls backup() on each attached service
  7. Checksum Generation: Calculates SHA256 for all files
  8. Metadata Creation: Generates metadata.json with inventory
  9. Database Update: Records backup in database

The process is atomic: if any step fails, partial backups are cleaned up automatically.

Listing Backups

List All Backups

hop3 backup list

Shows all backups across all applications in a table format.

Filter by Application

hop3 backup list <app-name>

Example:

hop3 backup list --app blog

Shows only backups for the specified application.

Limit Results

hop3 backup list --limit <N>

Example:

hop3 backup list --limit 10

Shows the 10 most recent backups (default limit is 20).

Combined Filtering

hop3 backup list --app blog --limit 5

Shows the 5 most recent backups for the "blog" application.

Viewing Backup Details

Get Detailed Information

hop3 backup show <backup-id>

(hop3 backup info is an accepted alias.)

Example:

hop3 backup show 20251108_143022_a8f3d9

Output:

Backup Information
==================================================

Backup ID: 20251108_143022_a8f3d9
Application: my-app
Created: 2025-11-08T14:30:22Z
Total Size: 15.6 MB
Format Version: 1.0
Hop3 Version: 0.8.0

Contents:
  - Environment: 12 variables

File Checksums:
  ✓ source.tar.gz
     sha256:abc123def456...
  ✓ data.tar.gz
     sha256:def456ghi789...
  ✓ env.json
     sha256:ghi789jkl012...

Addons Included: (1)
  - postgres:my-database (8.2 MB)

Application State:
  hostname: myapp.example.com
  port: 8000
  run_state: RUNNING

Integrity: ✓ All checksums valid

Verify Backup Integrity

The backup show command automatically verifies all checksums and reports integrity status.

Restoring Backups

Basic Restore

Restore an application from a backup:

hop3 backup restore <backup-id>

Example:

hop3 backup restore 20251108_143022_a8f3d9

Restore to Different Application

Clone an application by restoring to a new name:

hop3 backup restore <backup-id> --target-app <new-name>

Example:

hop3 backup restore 20251108_143022_a8f3d9 --target-app blog-staging

This creates a completely independent copy of the application.

What Happens During Restore?

  1. Load Metadata: Reads and validates metadata.json
  2. Version Check: Verifies Hop3 version compatibility
  3. Checksum Verification: Validates all file checksums
  4. App Stop: Stops the application if running
  5. Source Restore: Extracts git repository
  6. Data Restore: Extracts data directory
  7. Environment Restore: Imports environment variables
  8. Service Restore: Calls restore() on each service
  9. Metadata Update: Restores hostname, port settings
  10. Database Update: Records restore completion

The restore process includes safety checks at every step.

After Restore

After restoring, you typically need to restart the application:

hop3 app restart --app <app-name>

Deleting Backups

Delete a Single Backup

hop3 backup destroy <backup-id>

Example:

hop3 backup destroy 20251108_143022_a8f3d9

Output:

Delete backup 20251108_143022_a8f3d9?

Backup details:
  Application: my-app
  Size: 15.6 MB
  Created: 2025-11-08 14:30:22

This action cannot be undone.
Type 'yes' to confirm: yes

✓ Backup deleted successfully

What Gets Deleted?

  • All backup files (source, data, env, services)
  • Backup directory
  • Database record

Warning: This operation is irreversible. Always verify the backup ID before confirming.

Best Practices

How Often Should I Backup?

  • Before deployments: Always create a backup before deploying new code
  • Daily: For production applications with frequent changes
  • Weekly: For stable applications with infrequent updates
  • Before major changes: Database migrations, configuration changes, etc.

Backup Retention

Recommended retention policies:

  • Critical applications: Keep 30+ days of daily backups
  • Standard applications: Keep 7-14 days of backups
  • Development/staging: Keep 3-7 days of backups

Backup Storage

  • Backups are stored in /var/hop3/backups/
  • Monitor disk space regularly
  • Consider setting up automated cleanup for old backups
  • Plan for approximately 2-3x the size of your application data

Naming Conventions

When cloning applications via restore, use clear naming:

# Good naming examples
hop3 backup restore <id> --target-app myapp-staging
hop3 backup restore <id> --target-app myapp-backup-20251108
hop3 backup restore <id> --target-app myapp-test

# Avoid ambiguous names
hop3 backup restore <id> --target-app myapp2  # Not clear what this is

Testing Restores

Periodically test your backups:

  1. Create a backup
  2. Restore to a test application name
  3. Verify the restored application works
  4. Delete the test application
hop3 backup create --app devel-app
hop3 backup restore <backup-id> --target-app devel-app-test
hop3 app restart --app devel-app-test
# Test the application
hop3 app destroy --app devel-app-test

Security Considerations

Important:

  • Backups contain environment variables, which may include secrets (API keys, passwords)
  • Backup files are stored with restricted permissions (600/700)
  • Consider implementing backup encryption for sensitive data (future feature)
  • Limit access to the hop3 server to authorized personnel only

Backup Before:

Always create a backup before:

  • Deploying new application versions
  • Running database migrations
  • Changing environment variables
  • Modifying application configuration
  • Performing system maintenance

Quick pre-deployment checklist:

# 1. Create backup
hop3 backup create --app myapp

# 2. Deploy new version
hop3 deploy --app myapp

# 3. If something goes wrong, restore
hop3 backup restore <backup-id>
hop3 app restart --app myapp

Troubleshooting

"Application not found"

Error:

Error: Application 'myapp' not found

Solution: Check the application name:

hop3 app list

"Backup not found"

Error:

Error: Backup '20251108_143022_a8f3d9' not found

Solution:

# List all backups to verify the ID
hop3 backup list

# Check if you have the correct app name
hop3 backup list --app myapp

"Checksum mismatch"

Error:

Error: Checksum mismatch for source.tar.gz
Expected: sha256:abc123...
Got: sha256:def456...

Meaning: The backup file has been corrupted or modified.

Solution: - Do not use this backup - Use a different backup - Investigate how the file was corrupted - Create a new backup from the current state

"Insufficient disk space"

Error:

Error: Insufficient disk space for backup

Solution:

# Check disk space
df -h /var/hop3/backups

# Delete old backups
hop3 backup list
hop3 backup destroy <old-backup-id>

# Or clean up other files

"Permission denied"

Error:

Error: Permission denied: /var/hop3/backups/apps/myapp/...

Solution: This usually indicates a system-level issue. Contact your system administrator or check file permissions:

ls -la /var/hop3/backups/

Restore Fails Partway Through

If a restore fails:

  1. Check the error message: it indicates which step failed
  2. Verify the application state: it may be partially restored
  3. Try the restore again: some failures are transient
  4. Use a different backup if the issue persists

The restore process is idempotent: you can safely retry.

Service Restore Fails

Error:

Error: Failed to restore service 'my-database': Connection refused

Possible causes: - Service (PostgreSQL, Redis, etc.) is not running - Service credentials have changed - Service port is blocked

Solution:

# Check addon status
hop3 addon list

# Restart service if needed, then retry restore
hop3 backup restore <backup-id>

Advanced Topics

Backup File Structure

Understanding the backup structure can help with debugging:

/var/hop3/backups/apps/myapp/20251108_143022_a8f3d9/
│
├── metadata.json          # Backup manifest
│   └── Contains:
│       - Backup ID and timestamps
│       - File checksums (SHA256)
│       - Service information
│       - Application metadata
│
├── source.tar.gz          # Git repository
│   └── Contains:
│       - Complete git history
│       - All branches and tags
│       - .git directory
│
├── data.tar.gz            # Application data
│   └── Contains:
│       - User uploads
│       - Application-generated files
│       - Runtime data
│
├── env.json               # Environment variables
│   └── Contains:
│       - All config set variables
│       - System-set variables
│       - Service URLs
│
└── addons/                # Addon backups
    └── postgres_mydb.sql  # PostgreSQL dump
        - SQL dump file
        - Includes schema and data

Manual Backup Verification

You can manually verify a backup:

# Navigate to backup directory
cd /var/hop3/backups/apps/myapp/20251108_143022_a8f3d9/

# View metadata
cat metadata.json | python3 -m json.tool

# Verify a checksum manually
sha256sum source.tar.gz
# Compare with metadata.json

# List contents of archives (without extracting)
tar -tzf source.tar.gz | head -20
tar -tzf data.tar.gz | head -20

Service-Specific Backup Details

PostgreSQL Backups

PostgreSQL backups use pg_dump:

-- Backup format: Plain SQL
-- Can be inspected with a text editor
-- Contains:
CREATE DATABASE ...
CREATE TABLE ...
INSERT INTO ...

To manually inspect:

head -50 addons/postgres_mydb.sql

Other Addons

Other addons are backed up by their own backup()/restore() implementations:

  • MySQL: mysqldump SQL file
  • Redis: a JSON dump of the database's keys (via redis-cli)
  • S3/MinIO: the bucket's objects

Backup Performance

Large Applications

Applications with large data directories take longer to back up:

  • Backup time: ~1-5 minutes per GB
  • Compression: typically reduces size by 50-80%
  • Network: all transfers are local

Optimization Tips

  • Exclude temporary files: Clean up temp files before backup
  • Data directory: Keep only necessary files in data directory
  • Git repository: Regular cleanup (git gc) reduces repo size

Version Compatibility

Backups include the Hop3 version that created them:

  • Same version: Fully compatible
  • Newer Hop3: Generally compatible (backward compatible)
  • Older Hop3: May require manual intervention

Always check compatibility warnings during restore.

Disaster Recovery

In case of complete server failure, do the following:

  1. Install Hop3 on a new server
  2. Copy backups from the old server (or remote storage)
  3. Restore applications one by one:
    hop3 backup restore <backup-id>
    hop3 app restart --app <app-name>
    

Keep backups in multiple locations: - Local server - Remote backup server - Cloud storage (future feature)

Integration with CI/CD

Automate backups in your deployment pipeline:

#!/bin/bash
# deploy.sh

# Create backup before deployment
backup_id=$(hop3 backup create --app myapp | grep "Backup ID:" | awk '{print $3}')

# Deploy new version
hop3 deploy --app myapp

# If deployment fails, restore
if [ $? -ne 0 ]; then
    echo "Deployment failed, restoring backup..."
    hop3 backup restore $backup_id
    hop3 app restart --app myapp
    exit 1
fi

echo "Deployment successful! Backup ID: $backup_id"

Monitoring Backup Age

Create a monitoring script:

#!/bin/bash
# check-backup-age.sh

app_name="myapp"
max_age_days=1

latest_backup=$(hop3 backup list $app_name --limit 1 | tail -n 1 | awk '{print $4}')
current_date=$(date +%s)
backup_date=$(date -d "$latest_backup" +%s)
age_seconds=$((current_date - backup_date))
age_days=$((age_seconds / 86400))

if [ $age_days -gt $max_age_days ]; then
    echo "WARNING: Last backup is $age_days days old"
    # Send alert (email, Slack, etc.)
    exit 1
fi

echo "OK: Backup is recent ($age_days days old)"

Future Features

The following features are planned for future releases:

  • Automated Backups: Schedule backups with cron-like syntax
  • Retention Policies: Automatic cleanup of old backups
  • Backup Encryption: Encrypt backups at rest using age or GPG
  • Remote Storage: Push backups to S3, B2, or other remote storage
  • Incremental Backups: Save storage with incremental snapshots
  • Backup Monitoring: Email/webhook alerts for backup failures
  • Point-in-Time Recovery: Restore databases to specific timestamps

Getting Help

If you encounter issues:

  1. Check this documentation
  2. Review error messages carefully
  3. Check FAQ for common issues
  4. Report bugs at GitHub Issues
  5. Ask in Matrix Chat

Backups are your safety net: test them regularly and store them securely.