{ config, pkgs, lib, ... }: let backupScript = pkgs.writeShellScript "wiki-backup" '' set -euo pipefail BACKUP_DIR="/var/backups/mysql" TEXTFILE_DIR="/var/lib/prometheus-node-exporter/textfile" TIMESTAMP=$(date +%Y%m%d-%H%M%S) # Cleanup old local backups (keep 7 days) find "$BACKUP_DIR" -maxdepth 1 -type d -mtime +7 -exec rm -rf {} + 2>/dev/null || true # Dump database with mydumper echo "Starting database dump..." ${pkgs.mydumper}/bin/mydumper \ --database noisebridge_mediawiki \ --outputdir "$BACKUP_DIR/$TIMESTAMP" \ --threads 2 \ --compress \ --routines \ --triggers \ --events \ --logfile "$BACKUP_DIR/mydumper.log" # Sync to Backblaze B2 echo "Syncing to Backblaze B2..." export RCLONE_CONFIG_B2_TYPE=b2 export RCLONE_CONFIG_B2_ACCOUNT=$(cat ${config.age.secrets.b2-credentials.path} | ${pkgs.jq}/bin/jq -r .keyID) export RCLONE_CONFIG_B2_KEY=$(cat ${config.age.secrets.b2-credentials.path} | ${pkgs.jq}/bin/jq -r .applicationKey) SYNC_SUCCESS=0 ${pkgs.rclone}/bin/rclone sync "$BACKUP_DIR" b2:noisebridge-wiki-backup/mysql/ \ --transfers 4 \ --checkers 8 \ --b2-hard-delete \ && SYNC_SUCCESS=1 # Sync uploaded images to B2 ${pkgs.rclone}/bin/rclone sync /var/lib/mediawiki/images/ b2:noisebridge-wiki-backup/images/ \ --transfers 4 \ --checkers 8 \ || SYNC_SUCCESS=0 # Back up Tor hidden service keys (losing these = losing the .onion address) ${pkgs.rclone}/bin/rclone sync /var/lib/tor/onion/ b2:noisebridge-wiki-backup/tor-keys/ \ --transfers 1 \ || true # Write metrics for Prometheus textfile collector (no leading whitespace!) cat > "$TEXTFILE_DIR/backup.prom" <<'METRICS' # HELP backup_latest_timestamp_seconds Unix timestamp of latest backup # TYPE backup_latest_timestamp_seconds gauge METRICS echo "backup_latest_timestamp_seconds $(date +%s)" >> "$TEXTFILE_DIR/backup.prom" cat >> "$TEXTFILE_DIR/backup.prom" <