268 lines
8.9 KiB
Bash
268 lines
8.9 KiB
Bash
#!/usr/bin/env bash
|
||
set -euo pipefail
|
||
source ./lib.sh
|
||
|
||
log "Backup/Restore – Tools, Config & Timer (installer.env) …"
|
||
|
||
# ─────────────────────────────────────────────────────────────
|
||
# 1) installer.env laden (ENV > installer.env > Defaults)
|
||
# ─────────────────────────────────────────────────────────────
|
||
if [[ -f /etc/mailwolt/installer.env ]]; then
|
||
# automatisch exportieren, damit ${VAR} später überall wirkt
|
||
set -a
|
||
# shellcheck disable=SC1091
|
||
source /etc/mailwolt/installer.env
|
||
set +a
|
||
else
|
||
log "[i] /etc/mailwolt/installer.env nicht gefunden – nutze Defaults."
|
||
fi
|
||
|
||
# ─────────────────────────────────────────────────────────────
|
||
# 2) Pfade & Defaults (werden durch ENV/installer.env überschrieben)
|
||
# ─────────────────────────────────────────────────────────────
|
||
CONF_DIR="/etc/mailwolt"
|
||
CONF_FILE="${CONF_DIR}/backup.conf"
|
||
BIN_DIR="/usr/local/sbin"
|
||
UNIT_DIR="/etc/systemd/system"
|
||
|
||
APP_DIR="${APP_DIR:-/var/www/mailwolt}"
|
||
|
||
# DB-Parameter aus installer.env (bzw. ENV) oder Fallbacks
|
||
DB_HOST="${DB_HOST:-127.0.0.1}"
|
||
DB_NAME="${DB_NAME:-mailwolt}"
|
||
DB_USER="${DB_USER:-mailwolt}"
|
||
DB_PASS="${DB_PASS:-}"
|
||
|
||
# Backup-Settings aus installer.env (bzw. ENV)
|
||
BACKUP_DIR="${BACKUP_DIR:-/var/backups/mailwolt}"
|
||
BACKUP_RETENTION_DAYS="${BACKUP_RETENTION_DAYS:-7}"
|
||
BACKUP_USE_ZSTD="${BACKUP_USE_ZSTD:-1}"
|
||
BACKUP_ENABLED="${BACKUP_ENABLED:-0}" # 0|1
|
||
BACKUP_INTERVAL="${BACKUP_INTERVAL:-daily}" # daily|weekly|monthly
|
||
|
||
install -d -m 0755 "$CONF_DIR" "$BACKUP_DIR"
|
||
|
||
# ─────────────────────────────────────────────────────────────
|
||
# 3) /etc/mailwolt/backup.conf (von UI/APP überschreibbar)
|
||
# ─────────────────────────────────────────────────────────────
|
||
cat > "$CONF_FILE" <<EOF
|
||
# MailWolt Backup Konfiguration (UI kann überschreiben)
|
||
APP_DIR="$APP_DIR"
|
||
BACKUP_DIR="$BACKUP_DIR"
|
||
RETENTION_DAYS="$BACKUP_RETENTION_DAYS"
|
||
USE_ZSTD="$BACKUP_USE_ZSTD"
|
||
|
||
# DB-Parameter
|
||
MYSQL_DB="$DB_NAME"
|
||
MYSQL_USER="$DB_USER"
|
||
MYSQL_PASS="$DB_PASS"
|
||
MYSQL_HOST="$DB_HOST"
|
||
MYSQL_PORT="3306"
|
||
EOF
|
||
|
||
chmod 0644 "$CONF_FILE"
|
||
log "[✓] config geschrieben: $CONF_FILE"
|
||
|
||
# ─────────────────────────────────────────────────────────────
|
||
# 4) /usr/local/sbin/mailwolt-backup (schreibt backup.status)
|
||
# ─────────────────────────────────────────────────────────────
|
||
cat > "${BIN_DIR}/mailwolt-backup" <<'EOSH'
|
||
#!/usr/bin/env bash
|
||
set -euo pipefail
|
||
|
||
log(){ echo "[$(date -Is)] $*"; }
|
||
|
||
# Konfiguration laden (ENV > Datei)
|
||
CONF="/etc/mailwolt/backup.conf"
|
||
[[ -f "$CONF" ]] && # shellcheck disable=SC1090
|
||
source "$CONF"
|
||
|
||
APP_DIR="${APP_DIR:-/var/www/mailwolt}"
|
||
BACKUP_DIR="${BACKUP_DIR:-/var/backups/mailwolt}"
|
||
RETENTION_DAYS="${RETENTION_DAYS:-7}"
|
||
USE_ZSTD="${USE_ZSTD:-1}"
|
||
|
||
MYSQL_DB="${MYSQL_DB:-mailwolt}"
|
||
MYSQL_USER="${MYSQL_USER:-mailwolt}"
|
||
MYSQL_PASS="${MYSQL_PASS:-}"
|
||
MYSQL_HOST="${MYSQL_HOST:-127.0.0.1}"
|
||
MYSQL_PORT="${MYSQL_PORT:-3306}"
|
||
|
||
STATE_DIR="/var/lib/mailwolt"
|
||
STATUS_FILE="${STATE_DIR}/backup.status"
|
||
install -d -m 0755 "$STATE_DIR" "$BACKUP_DIR"
|
||
|
||
START_TS="$(date +%s)"
|
||
TS="$(date -u +%Y%m%dT%H%M%SZ)"
|
||
TMP="$(mktemp -d /tmp/mwbackup.XXXXXX)"
|
||
trap 'rm -rf "$TMP"' EXIT
|
||
|
||
fail(){
|
||
local msg="${1:-backup failed}"
|
||
local now="$(date -Is)"
|
||
{
|
||
echo "time=${now}"
|
||
echo "size=0"
|
||
echo "dur=$(( $(date +%s) - START_TS ))s"
|
||
echo "ok=0"
|
||
echo "error=${msg}"
|
||
} > "$STATUS_FILE"
|
||
echo "[$now] ${msg}" >&2
|
||
exit 1
|
||
}
|
||
trap 'fail "unexpected error (exit $?)"' ERR
|
||
|
||
OUT="${BACKUP_DIR}/mailwolt-${TS}.tar"
|
||
log "⇒ starte Backup in $OUT …"
|
||
|
||
# 1) DB
|
||
log " • mysqldump …"
|
||
MYSQL_PWD="$MYSQL_PASS" mysqldump \
|
||
-h "$MYSQL_HOST" -P "$MYSQL_PORT" -u "$MYSQL_USER" \
|
||
--single-transaction --routines --events --triggers \
|
||
"$MYSQL_DB" > "$TMP/mysql.sql"
|
||
|
||
# 2) Maildir
|
||
log " • Maildir …"
|
||
tar -C / -cf "$TMP/mail.tar" var/mail/vhosts 2>/dev/null || true
|
||
|
||
# 3) App (ohne heavy dirs)
|
||
log " • App …"
|
||
tar -C / -cf "$TMP/app.tar" \
|
||
--exclude='var/www/mailwolt/vendor' \
|
||
--exclude='var/www/mailwolt/node_modules' \
|
||
--exclude='var/www/mailwolt/public/build' \
|
||
var/www/mailwolt
|
||
|
||
# 4) Configs
|
||
log " • Configs …"
|
||
mkdir -p "$TMP/files"
|
||
cp -a /etc/mailwolt "$TMP/files/" 2>/dev/null || true
|
||
cp -a /etc/postfix "$TMP/files/" 2>/dev/null || true
|
||
cp -a /etc/dovecot "$TMP/files/" 2>/dev/null || true
|
||
cp -a /etc/opendkim "$TMP/files/" 2>/dev/null || true
|
||
cp -a /etc/opendmarc "$TMP/files/" 2>/dev/null || true
|
||
cp -a /etc/rspamd "$TMP/files/" 2>/dev/null || true
|
||
cp -a /etc/ssl/ui "$TMP/files/" 2>/dev/null || true
|
||
tar -C "$TMP" -cf "$TMP/files.tar" files
|
||
|
||
# 5) Paket
|
||
log " • Archiviere …"
|
||
tar -C "$TMP" -cf "$OUT" mysql.sql mail.tar app.tar files.tar
|
||
|
||
# 6) Komprimieren (optional)
|
||
if [[ "${USE_ZSTD:-1}" = "1" ]] && command -v zstd >/dev/null 2>&1; then
|
||
log " • komprimiere (zstd) …"
|
||
zstd -f --rm -19 "$OUT"
|
||
OUT="${OUT}.zst"
|
||
fi
|
||
|
||
# 7) Retention
|
||
if [[ "$RETENTION_DAYS" =~ ^[0-9]+$ ]]; then
|
||
log " • Retention: lösche älter als ${RETENTION_DAYS} Tage …"
|
||
find "$BACKUP_DIR" -type f -mtime +"$RETENTION_DAYS" -name 'mailwolt-*' -delete || true
|
||
fi
|
||
|
||
# 8) Statusfile fürs UI
|
||
SIZE_BYTES="$(stat -c '%s' "$OUT" 2>/dev/null || echo 0)"
|
||
{
|
||
echo "time=$(date -Is)"
|
||
echo "size=${SIZE_BYTES}"
|
||
echo "dur=$(( $(date +%s) - START_TS ))s"
|
||
echo "ok=1"
|
||
echo "file=${OUT}"
|
||
} > "$STATUS_FILE"
|
||
chmod 0644 "$STATUS_FILE" 2>/dev/null || true
|
||
|
||
log "[✓] Backup fertig: $OUT"
|
||
EOSH
|
||
chmod 0755 "${BIN_DIR}/mailwolt-backup"
|
||
|
||
# ─────────────────────────────────────────────────────────────
|
||
# 5) /usr/local/sbin/mailwolt-restore
|
||
# ─────────────────────────────────────────────────────────────
|
||
cat > "${BIN_DIR}/mailwolt-restore" <<'EOSH'
|
||
#!/usr/bin/env bash
|
||
set -euo pipefail
|
||
log(){ echo "[$(date -Is)] $*"; }
|
||
|
||
ARCHIVE="${1:-}"
|
||
[[ -n "$ARCHIVE" ]] || { echo "Usage: mailwolt-restore <backup.tar[.zst]>"; exit 1; }
|
||
[[ -f "$ARCHIVE" ]] || { echo "Backup nicht gefunden: $ARCHIVE"; exit 1; }
|
||
|
||
TMP="$(mktemp -d /tmp/mwrestore.XXXXXX)"
|
||
trap 'rm -rf "$TMP"' EXIT
|
||
|
||
case "$ARCHIVE" in
|
||
*.zst) zstd -d -c "$ARCHIVE" > "$TMP/backup.tar" ;;
|
||
*) cp -a "$ARCHIVE" "$TMP/backup.tar" ;;
|
||
esac
|
||
|
||
log "⇒ entpacke …"
|
||
tar -C "$TMP" -xf "$TMP/backup.tar"
|
||
|
||
# Reihenfolge: DB → App → Mail → Config
|
||
if [[ -f "$TMP/mysql.sql" ]]; then
|
||
log " • MySQL wiederherstellen …"
|
||
mysql < "$TMP/mysql.sql"
|
||
fi
|
||
|
||
if [[ -f "$TMP/app.tar" ]]; then
|
||
log " • App → /var/www/mailwolt …"
|
||
tar -C / -xf "$TMP/app.tar"
|
||
fi
|
||
|
||
if [[ -f "$TMP/mail.tar" ]]; then
|
||
log " • Maildir → /var/mail/vhosts …"
|
||
tar -C / -xf "$TMP/mail.tar"
|
||
fi
|
||
|
||
if [[ -f "$TMP/files.tar" ]]; then
|
||
log " • Configs → /etc/* …"
|
||
tar -C / -xf "$TMP/files.tar"
|
||
fi
|
||
|
||
log "[✓] Restore abgeschlossen."
|
||
EOSH
|
||
chmod 0755 "${BIN_DIR}/mailwolt-restore"
|
||
|
||
log "[✓] Tools installiert: ${BIN_DIR}/mailwolt-backup, mailwolt-restore"
|
||
|
||
# ─────────────────────────────────────────────────────────────
|
||
# 6) systemd Service + Timer (Timer default via installer.env)
|
||
# ─────────────────────────────────────────────────────────────
|
||
cat > "${UNIT_DIR}/mailwolt-backup.service" <<'EOSVC'
|
||
[Unit]
|
||
Description=MailWolt Backup
|
||
|
||
[Service]
|
||
Type=oneshot
|
||
ExecStart=/usr/local/sbin/mailwolt-backup
|
||
Nice=10
|
||
IOSchedulingClass=best-effort
|
||
IOSchedulingPriority=7
|
||
EOSVC
|
||
|
||
cat > "${UNIT_DIR}/mailwolt-backup.timer" <<EOTIM
|
||
[Unit]
|
||
Description=MailWolt Backup Timer
|
||
|
||
[Timer]
|
||
OnCalendar=${BACKUP_ONCALENDAR}
|
||
Persistent=true
|
||
|
||
[Install]
|
||
WantedBy=timers.target
|
||
EOTIM
|
||
|
||
systemctl daemon-reload
|
||
|
||
if [[ "${BACKUP_ENABLED}" = "1" ]]; then
|
||
log "Aktiviere Backup-Timer (${BACKUP_ONCALENDAR}) …"
|
||
systemctl enable --now mailwolt-backup.timer
|
||
else
|
||
log "Timer bleibt deaktiviert (BACKUP_ENABLED=0)."
|
||
systemctl disable --now mailwolt-backup.timer >/dev/null 2>&1 || true
|
||
fi
|
||
|
||
log "[✓] Backup-Setup abgeschlossen." |