feat: init
This commit is contained in:
commit
8cfede9f57
28 changed files with 2129 additions and 0 deletions
97
modules/wiki-primary/backup.nix
Normal file
97
modules/wiki-primary/backup.nix
Normal file
|
|
@ -0,0 +1,97 @@
|
|||
{ 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" <<METRICS
|
||||
# HELP backup_b2_sync_success Whether the last B2 sync succeeded (1=success, 0=failure)
|
||||
# TYPE backup_b2_sync_success gauge
|
||||
backup_b2_sync_success $SYNC_SUCCESS
|
||||
METRICS
|
||||
|
||||
echo "Backup complete."
|
||||
'';
|
||||
in
|
||||
{
|
||||
systemd.services.wiki-backup = {
|
||||
description = "Wiki database and image backup to Backblaze B2";
|
||||
after = [ "mysql.service" ];
|
||||
serviceConfig = {
|
||||
Type = "oneshot";
|
||||
ExecStart = backupScript;
|
||||
User = "root";
|
||||
IOSchedulingClass = "idle";
|
||||
CPUSchedulingPolicy = "idle";
|
||||
};
|
||||
};
|
||||
|
||||
systemd.timers.wiki-backup = {
|
||||
description = "Daily wiki backup timer";
|
||||
wantedBy = [ "timers.target" ];
|
||||
timerConfig = {
|
||||
OnCalendar = "*-*-* 04:00:00";
|
||||
Persistent = true;
|
||||
RandomizedDelaySec = "15m";
|
||||
};
|
||||
};
|
||||
|
||||
systemd.tmpfiles.rules = [
|
||||
"d /var/backups/mysql 0750 root root -"
|
||||
];
|
||||
|
||||
age.secrets.b2-credentials = {
|
||||
file = ../../secrets/b2-credentials.age;
|
||||
owner = "root";
|
||||
group = "root";
|
||||
mode = "0400";
|
||||
};
|
||||
}
|
||||
Loading…
Add table
Add a link
Reference in a new issue