#!/usr/bin/env bash # Mailwolt Backup – läuft als root via sudo, liest DB-Credentials aus .env set -euo pipefail APP_DIR="/var/www/mailwolt" APP_USER="www-data" OUT_DIR="${APP_DIR}/storage/app/backups" STAMP="$(date +%Y-%m-%d_%H-%M-%S)" OUT_FILE="${OUT_DIR}/clubird_${STAMP}.tar.gz" TMP_DIR="$(mktemp -d /tmp/clubird_backup_XXXXXX)" cleanup(){ rm -rf "$TMP_DIR"; } trap cleanup EXIT mkdir -p "$OUT_DIR" chown "${APP_USER}:${APP_USER}" "$OUT_DIR" 2>/dev/null || true # ── Datenbank ────────────────────────────────────────────────────────────── ENV_FILE="${APP_DIR}/.env" DB_HOST="127.0.0.1"; DB_PORT="3306"; DB_USER=""; DB_PASS=""; DB_NAME="" if [[ -f "$ENV_FILE" ]]; then DB_HOST="$(grep '^DB_HOST=' "$ENV_FILE" | head -1 | cut -d= -f2- | tr -d '"' | tr -d "'")" DB_PORT="$(grep '^DB_PORT=' "$ENV_FILE" | head -1 | cut -d= -f2- | tr -d '"' | tr -d "'")" DB_USER="$(grep '^DB_USERNAME=' "$ENV_FILE" | head -1 | cut -d= -f2- | tr -d '"' | tr -d "'")" DB_PASS="$(grep '^DB_PASSWORD=' "$ENV_FILE" | head -1 | cut -d= -f2- | tr -d '"' | tr -d "'")" DB_NAME="$(grep '^DB_DATABASE=' "$ENV_FILE" | head -1 | cut -d= -f2- | tr -d '"' | tr -d "'")" fi DUMP_FILE="${TMP_DIR}/database.sql" if [[ -n "$DB_NAME" ]]; then MYSQL_PWD="$DB_PASS" mysqldump \ -h "${DB_HOST:-127.0.0.1}" -P "${DB_PORT:-3306}" \ -u "$DB_USER" \ --single-transaction --routines --triggers \ "$DB_NAME" > "$DUMP_FILE" 2>&1 echo "✓ Datenbank gesichert" else echo "✗ DB_DATABASE nicht in .env gefunden" fi # ── Quellen sammeln ──────────────────────────────────────────────────────── SOURCES=("$DUMP_FILE") for MAIL_DIR in /var/vmail /var/mail/vhosts /home/vmail; do if [[ -d "$MAIL_DIR" ]]; then SOURCES+=("$MAIL_DIR") echo "✓ Maildirs: $MAIL_DIR" break fi done for CFG_DIR in /etc/postfix /etc/dovecot /etc/opendkim /etc/rspamd /etc/letsencrypt; do if [[ -d "$CFG_DIR" ]]; then SOURCES+=("$CFG_DIR") echo "✓ $CFG_DIR" fi done if [[ -f "${APP_DIR}/.env" ]]; then SOURCES+=("${APP_DIR}/.env") echo "✓ .env" fi # ── Archiv erstellen ─────────────────────────────────────────────────────── tar --ignore-failed-read -czf "$OUT_FILE" "${SOURCES[@]}" 2>&1 || true chown "${APP_USER}:${APP_USER}" "$OUT_FILE" 2>/dev/null || true echo "ARTIFACT:${OUT_FILE}"