Skip to content

VPS Backup - Overall Concept

This document defines the architecture, schedules, and implementation protocols for the CFS Platform backup systems on the Strato Virtual Private Server (VPS).


📅 1. Backup Strategy Overview

To ensure maximum availability, disaster recovery capability, and absolute data integrity, the system implements a multi-tiered, localized, and cloud-replicated backup protocol.

Backup Paradigm

  • Zero-Trust Compute: Compute resources (containers) are fully disposable; all persistent state resides in isolated docker volumes or bind-mounted directories.
  • Restic Cloud Sync: Sourced from the local repository, executing directly against Google Drive via an rclone bridge.
  • Client-Side Encryption: All snapshots are encrypted client-side using Restic's standard AES-256 CTR encryption scheme before leaving the VPS.
  • Self-Healing Integrity: Automatic pruning, validation, and regular restic check sweeps.

🏗️ 2. Core Infrastructure Layers & Targets

LayerPersistent StateRTO / RPO TargetBackup Protocol
System DatabasesMariaDB 10.11 instances (Active)RTO: < 1 hour / RPO: 24 hoursIntegrated database file structures (volumes)
System ConfigurationsDocker Compose & .env propertiesRTO: < 10 mins / RPO: Git syncGit repository + localized docker backup sweeps
Ollama Model Weights/root/.ollama volumeRTO: < 30 mins / RPO: StaleDownload caching (re-pullable from registry)
Open WebUI StateNamed volume dataRTO: < 30 mins / RPO: 24 hoursDaily Restic cloud snapshots
IDE Persistent DataPersistent profile directoryRTO: < 30 mins / RPO: 12 hoursAutomated Restic cloud snapshots

⏱️ 3. Execution Schedules & Retention Policies

Backup Schedules

ScopeFrequencyExecution WindowRetention PeriodDestination
Daily Restic BackupDaily (via Cron)02:00 AM UTC30 Days (Rolling Window)Google Drive: backups/vps-daily
Monthly Full BackupMonthly (via Cron)Monthly12 Months (Rolling)Google Drive: backups/vps-monthly

Retention Policies (Restic Prune Specs)

  • Daily Backup Snapshots: Keep the last 30 daily snapshots.
  • Monthly Backup Snapshots: Keep the last 12 monthly snapshots.

🛠️ 4. Technical Implementations & Scripts

4.1 Daily Backup Script (daily-backup.sh)

This script runs daily at 02:00 AM, backing up volumes, configuration folders, and root directories.

bash
#!/bin/bash
# Daily Restic Backup Script (Google Drive)
# Target: Restic Repo via rclone bridge

set -e
set -o pipefail

# Load environment variables
if [ -f "/var/lib/backups/.env" ]; then
    source "/var/lib/backups/.env"
elif [ -f "$(dirname "$0")/../config/.env" ]; then
    source "$(dirname "$0")/../config/.env"
fi

RESTIC_REPO=${RESTIC_REPOSITORY:-"rclone:gdrive:backups/vps-daily"}
RESTIC_PASSWORD_FILE=${RESTIC_PASSWORD_FILE:-"/etc/restic/.password"}
LOG_FILE=${LOG_FILE:-"/var/log/restic-backup.log"}
LOCK_FILE="/var/run/restic-backup.lock"

export RESTIC_REPOSITORY="${RESTIC_REPO}"
export RESTIC_PASSWORD_FILE="${RESTIC_PASSWORD_FILE}"
export GOMAXPROCS=4

log() {
    echo "[$(date +'%Y-%m-%d %H:%M:%S')] $1" | tee -a "$LOG_FILE"
}

# Error handling
handle_error() {
    local line=$1
    log "ERROR: Script failed at line $line"
    if [ -n "$ALERT_EMAIL" ]; then
        local msg="/tmp/backup_error_$(date +%s).msg"
        echo "Error running $(basename "$0") on $(hostname) at line $line." >> "$msg"
        tail -n 50 "$LOG_FILE" >> "$msg"
        mail -s "Backup FAILED: $(hostname) - $(basename "$0")" "$ALERT_EMAIL" < "$msg"
        rm -f "$msg"
    fi
    cleanup
    exit 1
}

cleanup() {
    rm -f "$LOCK_FILE"
}
trap cleanup EXIT
trap 'handle_error $LINENO' ERR

if [ -f "$LOCK_FILE" ]; then
    log "ERROR: Backup already in progress (lock file exists)."
    exit 1
fi
touch "$LOCK_FILE"

log "===== BACKUP START ====="
restic unlock || log "Warning: Could not unlock repository..."

nice -n 19 ionice -c 3 restic backup \
    --verbose \
    --one-file-system \
    /var/lib/docker/volumes/ \
    /root/ \
    /etc/ \
    /opt/ \
    /home/ \
    --exclude="*.tmp" \
    --exclude="*.log" \
    --exclude="*.cache"

log "Cleaning up old snapshots..."
restic forget --keep-daily 30 --prune --verbose

log "Verifying backup integrity..."
restic check --read-data-subset=10%

log "===== BACKUP END ====="

4.2 Monthly Full Backup Script (monthly-full-backup.sh)

This script captures the complete system file tree once a month, storing it in a dedicated monthly repository.

bash
#!/bin/bash
# Monthly Full-System Backup (Google Drive)
# Target: Dedicated Restic Repo

set -e
set -o pipefail

# Load environment variables
if [ -f "/var/lib/backups/.env" ]; then
    source "/var/lib/backups/.env"
elif [ -f "$(dirname "$0")/../config/.env" ]; then
    source "$(dirname "$0")/../config/.env"
fi

RESTIC_REPO=${RESTIC_REPOSITORY_MONTHLY:-"rclone:gdrive:backups/vps-monthly"}
RESTIC_PASSWORD_FILE=${RESTIC_PASSWORD_FILE:-"/etc/restic/.password"}
LOG_FILE="/var/log/monthly-backup.log"

export RESTIC_REPOSITORY="${RESTIC_REPO}"
export RESTIC_PASSWORD_FILE="${RESTIC_PASSWORD_FILE}"
export GOMAXPROCS=4

log() {
    echo "[$(date +'%Y-%m-%d %H:%M:%S')] $1" | tee -a "$LOG_FILE"
}

log "===== MONTHLY FULL BACKUP START ====="
restic unlock || log "Warning: Could not unlock repository..."

handle_error() {
    local line=$1
    log "ERROR: Script failed at line $line"
    if [ -n "$ALERT_EMAIL" ]; then
        local msg="/tmp/backup_error_$(date +%s).msg"
        echo "Error running $(basename "$0") on $(hostname) at line $line." >> "$msg"
        tail -n 50 "$LOG_FILE" >> "$msg"
        mail -s "Backup FAILED: $(hostname) - $(basename "$0")" "$ALERT_EMAIL" < "$msg"
        rm -f "$msg"
    fi
    exit 1
}
trap 'handle_error $LINENO' ERR

nice -n 19 ionice -c 3 restic backup \
    --verbose \
    --one-file-system \
    / \
    --exclude="/proc/*" \
    --exclude="/sys/*" \
    --exclude="/dev/*" \
    --exclude="/tmp/*" \
    --exclude="/run/*" \
    --exclude="/mnt/*" \
    --exclude="/media/*" \
    --exclude="/var/cache/*"

log "Cleaning up old monthly snapshots..."
restic forget --keep-monthly 12 --prune --verbose

log "Verifying integrity..."
restic check

log "===== MONTHLY FULL BACKUP END ====="

🔒 5. Security & Verification Measures

  • Encryption Standard: Restic uses AES-256 in counter mode (CTR) for data encryption and Poly1305 for integrity authentication.
  • Repository Locks: Restic locks the repository during writes to prevent concurrent execution conflicts.
  • Pruning Runs: Automated restic forget --prune safely removes unneeded chunks without compromising active chains.
  • Alert Trigger: Any error in backup scripts triggers a mail status update payload.

🚨 6. Disaster Recovery & Restoration Procedures

Phase 1: Re-instating Host Configurations

  1. Clone the core server configuration repository:

    bash
    git clone git@github.com:cfschacht-dotcom/CFS-SERVER-MANAGER.git /opt/cfs-infra

Phase 2: Restoring Container Storage Volumes

bash
# List all active snapshots on the cloud repository
restic -r rclone:gdrive:backups/vps-daily snapshots

# Restore the most recent snapshot targeting container volumes
restic -r rclone:gdrive:backups/vps-daily restore latest --target /

Phase 3: Infrastructure Verification

bash
# Spin up core infrastructure
cd /opt/cfs-infra && docker compose up -d

# Spin up platform containers
cd /opt/antigravity/data/PROJECT-DEVELOPMENT/cfs-platform && docker compose up -d

📊 7. Backup Topology Map

text
               +--------------------------------------+
               |          Strato VPS Host             |
               +--------------------------------------+

          ┌─────────────────────────┼─────────────────────────┐
          ▼                         ▼                         ▼
  +───────────────+         +───────────────+         +───────────────+
  |  Open WebUI   |         |      IDE      |         |   MariaDB     |
  |  User Data    |         |   Profiles    |         |  Databases    |
  +───────────────+         +───────────────+         +───────────────+
          │                         │                         │
          ▼                         ▼                         ▼
  +───────────────────────────────────────────────────────────────────+
  |                   Restic Backup Engine via Cron                   |
  +───────────────────────────────────────────────────────────────────+

                                    ▼ (rclone bridge sync)
                           +─────────────────+
                           |  Google Drive   |
                           |  Cloud Storage  |
                           +─────────────────+

Last Document Update: June 2026
Status: Approved & Implemented
Lead Engineer: Christian Friedrich Schacht

Released under proprietary license.