ContextDx
New: architecture for every role
Docs
Pricing
Blog
Boards
Getting StartedCore ConceptsPlatform FeaturesReference & ResourcesSelf-HostedSources

Self-Hosted

Installation GuideTroubleshooting GuideBackup & Restore GuideSSL & Reverse Proxy Guide
Self-Hosted
Installation GuideTroubleshooting GuideBackup & Restore GuideSSL & Reverse Proxy Guide
Self-HostedBackup & Restore Guide

Last updated June 23, 2026

Backup & Restore Guide

This guide covers how to backup and restore your data, including database and application data.

Table of Contents

  1. Overview
  2. Data Locations
  3. Backup Database
  4. Backup Application Data
  5. Restore Database
  6. Restore Application Data
  7. Automated Backups
  8. Best Practices

Related Guides:

  • Installation Guide
  • Troubleshooting Guide
  • SSL & Reverse Proxy Guide

Overview

Your data lives in two main locations:

  • PostgreSQL database - User data, configurations, sessions
  • Data volume - Cache, entitlements, uploaded files

Regular backups are essential for disaster recovery and data protection.

Data Locations

VolumeContentsPriority
contextdx-dataSessions, cache, entitlementsMedium
postgres-dataDatabase (user data, configurations)High

To see your volumes:

BASH
docker volume ls | grep contextdx

Backup Database

Quick Backup

BASH
# Create backup directory
mkdir -p backups

# Backup database to SQL file
docker compose -f docker-compose.production.yml exec postgres \
  pg_dump -U contextdx contextdx > backups/backup-$(date +%Y%m%d).sql

Compressed Backup

For larger databases, compress the backup:

BASH
docker compose -f docker-compose.production.yml exec postgres \
  pg_dump -U contextdx contextdx | gzip > backups/backup-$(date +%Y%m%d).sql.gz

Backup with Timestamp

BASH
TIMESTAMP=$(date +%Y%m%d_%H%M%S)
docker compose -f docker-compose.production.yml exec postgres \
  pg_dump -U contextdx contextdx > backups/backup-${TIMESTAMP}.sql
echo "Backup created: backups/backup-${TIMESTAMP}.sql"

Verify Backup

Check that the backup file is valid:

BASH
# Check file size (should not be empty)
ls -lh backups/backup-*.sql

# Check file content (should start with PostgreSQL dump header)
head -20 backups/backup-$(date +%Y%m%d).sql

Backup Application Data

Backup Data Volume

BASH
# Backup the data volume to a tar archive
docker run --rm \
  -v contextdx-data:/data \
  -v $(pwd)/backups:/backup \
  alpine tar czf /backup/data-$(date +%Y%m%d).tar.gz /data

Windows PowerShell

POWERSHELL
# Backup data volume
docker run --rm `
  -v contextdx-data:/data `
  -v ${PWD}/backups:/backup `
  alpine tar czf /backup/data-$(Get-Date -Format "yyyyMMdd").tar.gz /data

Restore Database

Standard Restore

BASH
# Stop the server first (prevents data inconsistency)
docker compose -f docker-compose.production.yml stop server

# Restore from backup
cat backups/backup-20240115.sql | docker compose -f docker-compose.production.yml exec -T postgres \
  psql -U contextdx contextdx

# Start server
docker compose -f docker-compose.production.yml start server

Restore Compressed Backup

BASH
# Stop the server
docker compose -f docker-compose.production.yml stop server

# Restore from compressed backup
gunzip -c backups/backup-20240115.sql.gz | docker compose -f docker-compose.production.yml exec -T postgres \
  psql -U contextdx contextdx

# Start server
docker compose -f docker-compose.production.yml start server

Full Database Reset and Restore

If you need to completely reset the database:

BASH
# Stop all services
docker compose -f docker-compose.production.yml down

# Remove the database volume
docker volume rm contextdx_postgres-data

# Start postgres only
docker compose -f docker-compose.production.yml up -d postgres

# Wait for postgres to be ready
sleep 10

# Restore from backup
cat backups/backup-20240115.sql | docker compose -f docker-compose.production.yml exec -T postgres \
  psql -U contextdx contextdx

# Start all services
docker compose -f docker-compose.production.yml up -d

Restore Application Data

Restore Data Volume

BASH
# Stop services
docker compose -f docker-compose.production.yml down

# Remove existing volume (if needed)
docker volume rm contextdx-data

# Recreate volume and restore
docker run --rm \
  -v contextdx-data:/data \
  -v $(pwd)/backups:/backup \
  alpine sh -c "cd /data && tar xzf /backup/data-20240115.tar.gz --strip 1"

# Start services
docker compose -f docker-compose.production.yml up -d

Automated Backups

Linux/macOS (Cron)

Set up daily automated backups:

BASH
# Edit crontab
crontab -e

# Add this line (runs at 2 AM daily)
0 2 * * * cd /path/to/contextdx && docker compose -f docker-compose.production.yml exec -T postgres pg_dump -U contextdx contextdx > backups/backup-$(date +\%Y\%m\%d).sql

Backup Script

Create a comprehensive backup script:

BASH
#!/bin/bash
# backup.sh - ContextDx backup script

BACKUP_DIR="/path/to/contextdx/backups"
TIMESTAMP=$(date +%Y%m%d_%H%M%S)
RETENTION_DAYS=30

# Create backup directory
mkdir -p $BACKUP_DIR

# Backup database
echo "Backing up database..."
docker compose -f docker-compose.production.yml exec -T postgres \
  pg_dump -U contextdx contextdx | gzip > $BACKUP_DIR/db-${TIMESTAMP}.sql.gz

# Backup data volume
echo "Backing up data volume..."
docker run --rm \
  -v contextdx-data:/data \
  -v $BACKUP_DIR:/backup \
  alpine tar czf /backup/data-${TIMESTAMP}.tar.gz /data

# Remove old backups
echo "Cleaning up old backups..."
find $BACKUP_DIR -name "*.sql.gz" -mtime +$RETENTION_DAYS -delete
find $BACKUP_DIR -name "*.tar.gz" -mtime +$RETENTION_DAYS -delete

echo "Backup complete: ${TIMESTAMP}"

Make it executable and schedule:

BASH
chmod +x backup.sh

# Add to crontab (runs at 2 AM daily)
crontab -e
0 2 * * * /path/to/contextdx/backup.sh >> /path/to/contextdx/backup.log 2>&1

Windows (Task Scheduler)

Create a PowerShell backup script:

POWERSHELL
# backup.ps1 - ContextDx backup script

$BackupDir = "C:\contextdx\backups"
$Timestamp = Get-Date -Format "yyyyMMdd_HHmmss"
$RetentionDays = 30

# Create backup directory
New-Item -ItemType Directory -Force -Path $BackupDir

# Backup database
Write-Host "Backing up database..."
docker compose -f docker-compose.production.yml exec -T postgres `
  pg_dump -U contextdx contextdx | Out-File "$BackupDir\db-$Timestamp.sql"

# Compress
Compress-Archive -Path "$BackupDir\db-$Timestamp.sql" -DestinationPath "$BackupDir\db-$Timestamp.sql.zip"
Remove-Item "$BackupDir\db-$Timestamp.sql"

# Remove old backups
Get-ChildItem $BackupDir -Filter "*.zip" | Where-Object { $_.LastWriteTime -lt (Get-Date).AddDays(-$RetentionDays) } | Remove-Item

Write-Host "Backup complete: $Timestamp"

Schedule using Task Scheduler to run daily.

Best Practices

Backup Frequency

Data TypeRecommended Frequency
DatabaseDaily minimum, hourly for critical data
Data volumeWeekly or after significant changes

Storage Recommendations

  1. Offsite backups - Store backups in a different location

    • Cloud storage (S3, Azure Blob, Google Cloud Storage)
    • Different physical server
    • Network attached storage (NAS)
  2. Encryption - Encrypt backups containing sensitive data

    BASH
    # Encrypt backup with GPG
    gpg --symmetric --cipher-algo AES256 backups/backup-20240115.sql
  3. Retention policy - Keep multiple backup generations

    • Daily backups: 7 days
    • Weekly backups: 4 weeks
    • Monthly backups: 12 months

Testing Restores

Regularly test your backup restoration process:

  1. Monthly - Verify backup files are not corrupted
  2. Quarterly - Perform full restore test in staging environment
  3. Document - Keep restore procedures documented and up-to-date

Monitoring

Set up alerts for backup failures:

BASH
# Example: Send email on backup failure
./backup.sh || echo "Backup failed on $(date)" | mail -s "ContextDx Backup Failed" admin@example.com

Quick Reference

TaskCommand
Quick database backupdocker compose -f docker-compose.production.yml exec postgres pg_dump -U contextdx contextdx > backup.sql
Compressed backupdocker compose -f docker-compose.production.yml exec postgres pg_dump -U contextdx contextdx | gzip > backup.sql.gz
Restore databasecat backup.sql | docker compose -f docker-compose.production.yml exec -T postgres psql -U contextdx contextdx
Backup data volumedocker run --rm -v contextdx-data:/data -v $(pwd):/backup alpine tar czf /backup/data.tar.gz /data
List backupsls -lh backups/
PreviousTroubleshooting GuideNextSSL & Reverse Proxy Guide

On this page

Backup & Restore GuideTable of ContentsOverviewData LocationsBackup DatabaseQuick BackupCreate backup directoryBackup database to SQL fileCompressed BackupBackup with TimestampVerify BackupCheck file size (should not be empty)Check file content (should start with PostgreSQL dump header)Backup Application DataBackup Data VolumeBackup the data volume to a tar archiveWindows PowerShellBackup data volumeRestore DatabaseStandard RestoreStop the server first (prevents data inconsistency)Restore from backupStart serverRestore Compressed BackupStop the serverRestore from compressed backupStart serverFull Database Reset and RestoreStop all servicesRemove the database volumeStart postgres onlyWait for postgres to be readyRestore from backupStart all servicesRestore Application DataRestore Data VolumeStop servicesRemove existing volume (if needed)Recreate volume and restoreStart servicesAutomated BackupsLinux/macOS (Cron)Edit crontabAdd this line (runs at 2 AM daily)Backup Scriptbackup.sh - ContextDx backup scriptCreate backup directoryBackup databaseBackup data volumeRemove old backupsAdd to crontab (runs at 2 AM daily)Windows (Task Scheduler)backup.ps1 - ContextDx backup scriptCreate backup directoryBackup databaseCompressRemove old backupsBest PracticesBackup FrequencyStorage RecommendationsTesting RestoresMonitoringExample: Send email on backup failureQuick Reference