Dovecot Systax Problem
parent
b038fc3a26
commit
5cb0e82347
|
|
@ -25,7 +25,7 @@ log "Let's Encrypt Deploy-Hooks und Wrapper anlegen …"
|
||||||
# -------------------------------------------------------------------
|
# -------------------------------------------------------------------
|
||||||
# 2) POSIX-kompatibler Deploy-Wrapper (von Certbot aufgerufen)
|
# 2) POSIX-kompatibler Deploy-Wrapper (von Certbot aufgerufen)
|
||||||
# -------------------------------------------------------------------
|
# -------------------------------------------------------------------
|
||||||
cat >/usr/local/sbin/mw-deploy.sh <<'WRAP'
|
cat >/usr/local/sbin/mailwolt-deploy.sh <<'WRAP'
|
||||||
#!/bin/sh
|
#!/bin/sh
|
||||||
# POSIX-safe Certbot deploy-hook (ohne bashisms)
|
# POSIX-safe Certbot deploy-hook (ohne bashisms)
|
||||||
set -eu
|
set -eu
|
||||||
|
|
@ -130,7 +130,7 @@ fi
|
||||||
|
|
||||||
exit 0
|
exit 0
|
||||||
WRAP
|
WRAP
|
||||||
chmod +x /usr/local/sbin/mw-deploy.sh
|
chmod +x /usr/local/sbin/mailwolt-deploy.sh
|
||||||
|
|
||||||
# -------------------------------------------------------------------
|
# -------------------------------------------------------------------
|
||||||
# 3) Certbot deploy-hook, der den Wrapper aufruft
|
# 3) Certbot deploy-hook, der den Wrapper aufruft
|
||||||
|
|
@ -138,7 +138,7 @@ chmod +x /usr/local/sbin/mw-deploy.sh
|
||||||
install -d -m 0755 /etc/letsencrypt/renewal-hooks/deploy
|
install -d -m 0755 /etc/letsencrypt/renewal-hooks/deploy
|
||||||
cat >/etc/letsencrypt/renewal-hooks/deploy/50-mailwolt-certs.sh <<'HOOK'
|
cat >/etc/letsencrypt/renewal-hooks/deploy/50-mailwolt-certs.sh <<'HOOK'
|
||||||
#!/bin/sh
|
#!/bin/sh
|
||||||
exec /usr/local/sbin/mw-deploy.sh
|
exec /usr/local/sbin/mailwolt-deploy.sh
|
||||||
HOOK
|
HOOK
|
||||||
chmod +x /etc/letsencrypt/renewal-hooks/deploy/50-mailwolt-certs.sh
|
chmod +x /etc/letsencrypt/renewal-hooks/deploy/50-mailwolt-certs.sh
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -286,16 +286,7 @@ chmod 0750 /usr/local/sbin/mailwolt-remove-dkim
|
||||||
systemctl daemon-reload
|
systemctl daemon-reload
|
||||||
systemctl enable opendkim || true
|
systemctl enable opendkim || true
|
||||||
|
|
||||||
if command -v /usr/local/sbin/mw-apply-milters >/dev/null 2>&1; then
|
touch /run/mailwolt.need-apply-milters || true
|
||||||
/usr/local/sbin/mw-apply-milters
|
|
||||||
else
|
|
||||||
# Fallback: nur Rspamd + OpenDKIM, Port 11333
|
|
||||||
/usr/sbin/postconf -e "milter_default_action = accept"
|
|
||||||
/usr/sbin/postconf -e "milter_protocol = 6"
|
|
||||||
/usr/sbin/postconf -e "smtpd_milters = inet:127.0.0.1:11333, inet:127.0.0.1:8891"
|
|
||||||
/usr/sbin/postconf -e "non_smtpd_milters = inet:127.0.0.1:11333, inet:127.0.0.1:8891"
|
|
||||||
systemctl reload postfix || true
|
|
||||||
fi
|
|
||||||
|
|
||||||
chgrp _rspamd /etc/rspamd/local.d/*.inc /etc/rspamd/local.d/*.conf || true
|
chgrp _rspamd /etc/rspamd/local.d/*.inc /etc/rspamd/local.d/*.conf || true
|
||||||
chmod 0640 /etc/rspamd/local.d/*.inc /etc/rspamd/local.d/*.conf || true
|
chmod 0640 /etc/rspamd/local.d/*.inc /etc/rspamd/local.d/*.conf || true
|
||||||
|
|
|
||||||
|
|
@ -58,8 +58,6 @@ else
|
||||||
fi
|
fi
|
||||||
|
|
||||||
# Postfix-Milter-Kette konsistent setzen (Rspamd + OpenDKIM + optional OpenDMARC)
|
# Postfix-Milter-Kette konsistent setzen (Rspamd + OpenDKIM + optional OpenDMARC)
|
||||||
if command -v /usr/local/sbin/mw-apply-milters >/dev/null 2>&1; then
|
touch /run/mailwolt.need-apply-milters || true
|
||||||
/usr/local/sbin/mw-apply-milters
|
|
||||||
fi
|
|
||||||
|
|
||||||
log "[✓] OpenDMARC (ENABLE=${OPENDMARC_ENABLE}) bereit."
|
log "[✓] OpenDMARC (ENABLE=${OPENDMARC_ENABLE}) bereit."
|
||||||
|
|
@ -0,0 +1,24 @@
|
||||||
|
#!/usr/bin/env bash
|
||||||
|
set -euo pipefail
|
||||||
|
source ./lib.sh
|
||||||
|
|
||||||
|
# nur ausführen, wenn vorherige Schritte das Flag gesetzt haben
|
||||||
|
if [[ -f /run/mailwolt.need-apply-milters ]]; then
|
||||||
|
if command -v /usr/local/sbin/mailwolt-apply-milters >/dev/null 2>&1; then
|
||||||
|
log "Setze Postfix-Milter-Kette (Rspamd/OpenDKIM[/OpenDMARC]) …"
|
||||||
|
/usr/local/sbin/mailwolt-apply-milters || true
|
||||||
|
else
|
||||||
|
# Fallback (ident wie im Tool)
|
||||||
|
/usr/sbin/postconf -e "milter_default_action = accept"
|
||||||
|
/usr/sbin/postconf -e "milter_protocol = 6"
|
||||||
|
CHAIN="inet:127.0.0.1:11333, inet:127.0.0.1:8891"
|
||||||
|
systemctl is-active --quiet opendmarc && CHAIN="$CHAIN, inet:127.0.0.1:8893" || true
|
||||||
|
/usr/sbin/postconf -e "smtpd_milters = $CHAIN"
|
||||||
|
/usr/sbin/postconf -e "non_smtpd_milters = $CHAIN"
|
||||||
|
systemctl reload postfix || true
|
||||||
|
fi
|
||||||
|
rm -f /run/mailwolt.need-apply-milters || true
|
||||||
|
log "[✓] Milter-Kette angewandt."
|
||||||
|
else
|
||||||
|
log "Milter-Kette: kein Bedarf (Flag nicht gesetzt) – überspringe."
|
||||||
|
fi
|
||||||
|
|
@ -54,7 +54,7 @@ issue() {
|
||||||
certbot certonly \
|
certbot certonly \
|
||||||
--agree-tos -m "${LE_MAIL}" --non-interactive \
|
--agree-tos -m "${LE_MAIL}" --non-interactive \
|
||||||
--webroot -w "${ACME_WEBROOT}" -d "${host}" \
|
--webroot -w "${ACME_WEBROOT}" -d "${host}" \
|
||||||
--deploy-hook /usr/local/sbin/mw-deploy.sh \
|
--deploy-hook /usr/local/sbin/mailwolt-deploy.sh \
|
||||||
"${EXTRA_ARGS[@]}" "${CERTBOT_EXTRA[@]}" || true
|
"${EXTRA_ARGS[@]}" "${CERTBOT_EXTRA[@]}" || true
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -81,6 +81,26 @@ grep -q '^APP_KEY=' "$ENV_FILE" || echo "APP_KEY=" >> "$ENV_FILE"
|
||||||
sudo -u "$APP_USER" -H bash -lc "cd ${APP_DIR} && php artisan key:generate --force || true"
|
sudo -u "$APP_USER" -H bash -lc "cd ${APP_DIR} && php artisan key:generate --force || true"
|
||||||
|
|
||||||
# --- App-URL/Hosts ----------------------------------------------------------
|
# --- App-URL/Hosts ----------------------------------------------------------
|
||||||
|
#SERVER_PUBLIC_IPV4="${SERVER_PUBLIC_IPV4:-}"
|
||||||
|
#if [[ -z "$SERVER_PUBLIC_IPV4" ]] && command -v curl >/dev/null 2>&1; then
|
||||||
|
# SERVER_PUBLIC_IPV4="$(curl -fsS --max-time 2 https://ifconfig.me 2>/dev/null || true)"
|
||||||
|
# [[ "$SERVER_PUBLIC_IPV4" =~ ^([0-9]{1,3}\.){3}[0-9]{1,3}$ ]] || SERVER_PUBLIC_IPV4=""
|
||||||
|
#fi
|
||||||
|
#[[ -n "$SERVER_PUBLIC_IPV4" ]] || SERVER_PUBLIC_IPV4="$(detect_ip)"
|
||||||
|
#
|
||||||
|
#UI_CERT="/etc/ssl/ui/fullchain.pem"
|
||||||
|
#UI_KEY="/etc/ssl/ui/privkey.pem"
|
||||||
|
#
|
||||||
|
#if [[ -n "${UI_HOST:-}" ]]; then
|
||||||
|
# APP_HOST_VAL="$UI_HOST"
|
||||||
|
# APP_URL_VAL="https://${UI_HOST}"
|
||||||
|
#else
|
||||||
|
# APP_HOST_VAL="$SERVER_PUBLIC_IPV4"
|
||||||
|
# SCHEME="http"
|
||||||
|
# [[ -s "$UI_CERT" && -s "$UI_KEY" ]] && SCHEME="https"
|
||||||
|
# APP_URL_VAL="${SCHEME}://${SERVER_PUBLIC_IPV4}"
|
||||||
|
#fi
|
||||||
|
|
||||||
SERVER_PUBLIC_IPV4="${SERVER_PUBLIC_IPV4:-}"
|
SERVER_PUBLIC_IPV4="${SERVER_PUBLIC_IPV4:-}"
|
||||||
if [[ -z "$SERVER_PUBLIC_IPV4" ]] && command -v curl >/dev/null 2>&1; then
|
if [[ -z "$SERVER_PUBLIC_IPV4" ]] && command -v curl >/dev/null 2>&1; then
|
||||||
SERVER_PUBLIC_IPV4="$(curl -fsS --max-time 2 https://ifconfig.me 2>/dev/null || true)"
|
SERVER_PUBLIC_IPV4="$(curl -fsS --max-time 2 https://ifconfig.me 2>/dev/null || true)"
|
||||||
|
|
@ -91,16 +111,24 @@ fi
|
||||||
UI_CERT="/etc/ssl/ui/fullchain.pem"
|
UI_CERT="/etc/ssl/ui/fullchain.pem"
|
||||||
UI_KEY="/etc/ssl/ui/privkey.pem"
|
UI_KEY="/etc/ssl/ui/privkey.pem"
|
||||||
|
|
||||||
if [[ -n "${UI_HOST:-}" ]]; then
|
# DEV-Modus: immer IP als Host, http (kein example.com / keine Fake-Domain)
|
||||||
APP_HOST_VAL="$UI_HOST"
|
if [[ "${DEV_MODE:-0}" = "1" || "${APP_ENV:-production}" = "local" ]]; then
|
||||||
APP_URL_VAL="https://${UI_HOST}"
|
|
||||||
else
|
|
||||||
APP_HOST_VAL="$SERVER_PUBLIC_IPV4"
|
APP_HOST_VAL="$SERVER_PUBLIC_IPV4"
|
||||||
SCHEME="http"
|
APP_URL_VAL="http://${APP_HOST_VAL}"
|
||||||
[[ -s "$UI_CERT" && -s "$UI_KEY" ]] && SCHEME="https"
|
else
|
||||||
APP_URL_VAL="${SCHEME}://${SERVER_PUBLIC_IPV4}"
|
# PROD/normal: wenn UI_HOST gesetzt → benutzen, sonst IP
|
||||||
|
if [[ -n "${UI_HOST:-}" ]]; then
|
||||||
|
APP_HOST_VAL="$UI_HOST"
|
||||||
|
APP_URL_VAL="https://${UI_HOST}"
|
||||||
|
else
|
||||||
|
APP_HOST_VAL="$SERVER_PUBLIC_IPV4"
|
||||||
|
SCHEME="http"
|
||||||
|
[[ -s "$UI_CERT" && -s "$UI_KEY" ]] && SCHEME="https"
|
||||||
|
APP_URL_VAL="${SCHEME}://${APP_HOST_VAL}"
|
||||||
|
fi
|
||||||
fi
|
fi
|
||||||
|
|
||||||
|
|
||||||
# --- .env schreiben ---------------------------------------------------------
|
# --- .env schreiben ---------------------------------------------------------
|
||||||
upsert_env APP_URL "${APP_URL_VAL}"
|
upsert_env APP_URL "${APP_URL_VAL}"
|
||||||
|
|
||||||
|
|
@ -160,6 +188,11 @@ upsert_env REDIS_CACHE_DB "1"
|
||||||
upsert_env REDIS_CACHE_CONNECTION "cache"
|
upsert_env REDIS_CACHE_CONNECTION "cache"
|
||||||
upsert_env REDIS_CACHE_LOCK_CONNECTION "default"
|
upsert_env REDIS_CACHE_LOCK_CONNECTION "default"
|
||||||
|
|
||||||
|
upsert_env BACKUP_DEFAULT_CRON "0 3 * * *"
|
||||||
|
upsert_env BACKUP_LOCAL_PATH "/var/backups/mailwolt"
|
||||||
|
upsert_env BACKUP_COMPRESSION "zstd"
|
||||||
|
upsert_env BACKUP_RETENTION_COUNT "7"
|
||||||
|
|
||||||
upsert_env BROADCAST_DRIVER "reverb"
|
upsert_env BROADCAST_DRIVER "reverb"
|
||||||
upsert_env QUEUE_CONNECTION "redis"
|
upsert_env QUEUE_CONNECTION "redis"
|
||||||
upsert_env LOG_CHANNEL "daily"
|
upsert_env LOG_CHANNEL "daily"
|
||||||
|
|
@ -234,6 +267,7 @@ sudo -u "$APP_USER" -H bash -lc "cd ${APP_DIR} && php artisan migrate --force"
|
||||||
# --- Seeder (legt Domains/DKIM etc. an) -------------------------------------
|
# --- Seeder (legt Domains/DKIM etc. an) -------------------------------------
|
||||||
if [[ "${BASE_DOMAIN}" != "example.com" ]]; then
|
if [[ "${BASE_DOMAIN}" != "example.com" ]]; then
|
||||||
sudo -u "$APP_USER" -H bash -lc "cd ${APP_DIR} && php artisan db:seed --class=SystemDomainSeeder --force"
|
sudo -u "$APP_USER" -H bash -lc "cd ${APP_DIR} && php artisan db:seed --class=SystemDomainSeeder --force"
|
||||||
|
sudo -u "$APP_USER" -H bash -lc "cd ${APP_DIR} && php artisan db:seed --class=SystemBackupSeeder --force"
|
||||||
fi
|
fi
|
||||||
|
|
||||||
# --- DKIM für SYSMAIL_DOMAIN via App erzeugen & per Helper einhängen --------
|
# --- DKIM für SYSMAIL_DOMAIN via App erzeugen & per Helper einhängen --------
|
||||||
|
|
|
||||||
|
|
@ -4,7 +4,7 @@ source ./lib.sh
|
||||||
|
|
||||||
log "Update-Wrapper & Sudoers …"
|
log "Update-Wrapper & Sudoers …"
|
||||||
|
|
||||||
WRAPPER="/usr/local/sbin/mw-update"
|
WRAPPER="/usr/local/sbin/mailwolt-update"
|
||||||
LOGFILE="/var/log/mailwolt-update.log"
|
LOGFILE="/var/log/mailwolt-update.log"
|
||||||
STATEDIR="/var/lib/mailwolt/update"
|
STATEDIR="/var/lib/mailwolt/update"
|
||||||
SUDOERS="/etc/sudoers.d/mailwolt-update"
|
SUDOERS="/etc/sudoers.d/mailwolt-update"
|
||||||
|
|
@ -91,9 +91,9 @@ chown root:root "$WRAPPER"
|
||||||
|
|
||||||
# Sudoers: www-data (Laravel) & mailwolt dürfen den Wrapper laufen lassen
|
# Sudoers: www-data (Laravel) & mailwolt dürfen den Wrapper laufen lassen
|
||||||
cat > "$SUDOERS" <<'EOF'
|
cat > "$SUDOERS" <<'EOF'
|
||||||
Defaults!/usr/local/sbin/mw-update !requiretty
|
Defaults!/usr/local/sbin/mailwolt-update !requiretty
|
||||||
www-data ALL=(root) NOPASSWD: /usr/local/sbin/mw-update
|
www-data ALL=(root) NOPASSWD: /usr/local/sbin/mailwolt-update
|
||||||
mailwolt ALL=(root) NOPASSWD: /usr/local/sbin/mw-update
|
mailwolt ALL=(root) NOPASSWD: /usr/local/sbin/mailwolt-update
|
||||||
EOF
|
EOF
|
||||||
|
|
||||||
chown root:root "$SUDOERS"
|
chown root:root "$SUDOERS"
|
||||||
|
|
|
||||||
|
|
@ -0,0 +1,267 @@
|
||||||
|
#!/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_INTERVAL}
|
||||||
|
Persistent=true
|
||||||
|
|
||||||
|
[Install]
|
||||||
|
WantedBy=timers.target
|
||||||
|
EOTIM
|
||||||
|
|
||||||
|
systemctl daemon-reload
|
||||||
|
|
||||||
|
if [[ "${BACKUP_ENABLED}" = "1" ]]; then
|
||||||
|
log "Aktiviere Backup-Timer (${BACKUP_INTERVAL}) …"
|
||||||
|
systemctl enable --now mailwolt-backup.timer
|
||||||
|
else
|
||||||
|
log "Timer bleibt deaktiviert (BACKUP_ENABLED=0)"
|
||||||
|
fi
|
||||||
|
|
||||||
|
log "[✓] Backup-Setup abgeschlossen."
|
||||||
|
|
@ -17,7 +17,7 @@ systemctl enable --now monit
|
||||||
|
|
||||||
# Helper-Skripte
|
# Helper-Skripte
|
||||||
install -d -m 0755 /usr/local/sbin
|
install -d -m 0755 /usr/local/sbin
|
||||||
cat >/usr/local/sbin/mw-redis-ping.sh <<'EOSH'
|
cat >/usr/local/sbin/mailwolt-redis-ping.sh <<'EOSH'
|
||||||
#!/usr/bin/env bash
|
#!/usr/bin/env bash
|
||||||
set -euo pipefail
|
set -euo pipefail
|
||||||
PASS=""
|
PASS=""
|
||||||
|
|
@ -30,16 +30,16 @@ else
|
||||||
exit 1
|
exit 1
|
||||||
fi
|
fi
|
||||||
EOSH
|
EOSH
|
||||||
chmod 0755 /usr/local/sbin/mw-redis-ping.sh
|
chmod 0755 /usr/local/sbin/mailwolt-redis-ping.sh
|
||||||
|
|
||||||
cat >/usr/local/sbin/mw-rspamd-heal.sh <<'EOSH'
|
cat >/usr/local/sbin/mailwolt-rspamd-heal.sh <<'EOSH'
|
||||||
#!/usr/bin/env bash
|
#!/usr/bin/env bash
|
||||||
set -euo pipefail
|
set -euo pipefail
|
||||||
install -d -m 0755 -o _rspamd -g _rspamd /run/rspamd || true
|
install -d -m 0755 -o _rspamd -g _rspamd /run/rspamd || true
|
||||||
[ -S /var/lib/rspamd/rspamd.sock ] && rm -f /var/lib/rspamd/rspamd.sock || true
|
[ -S /var/lib/rspamd/rspamd.sock ] && rm -f /var/lib/rspamd/rspamd.sock || true
|
||||||
systemctl restart rspamd
|
systemctl restart rspamd
|
||||||
EOSH
|
EOSH
|
||||||
chmod 0755 /usr/local/sbin/mw-rspamd-heal.sh
|
chmod 0755 /usr/local/sbin/mailwolt-rspamd-heal.sh
|
||||||
|
|
||||||
# WoltGuard Wrapper + Unit
|
# WoltGuard Wrapper + Unit
|
||||||
cat >/usr/local/bin/woltguard <<'EOSH'
|
cat >/usr/local/bin/woltguard <<'EOSH'
|
||||||
|
|
@ -113,7 +113,7 @@ check process redis with pidfile /run/redis/redis-server.pid
|
||||||
if failed host 127.0.0.1 port 6379 for 2 cycles then restart
|
if failed host 127.0.0.1 port 6379 for 2 cycles then restart
|
||||||
if 5 restarts within 5 cycles then alert
|
if 5 restarts within 5 cycles then alert
|
||||||
|
|
||||||
check program redis_ping path "/usr/local/sbin/mw-redis-ping.sh"
|
check program redis_ping path "/usr/local/sbin/mailwolt-redis-ping.sh"
|
||||||
if status != 0 for 2 cycles then exec "/bin/systemctl restart redis-server"
|
if status != 0 for 2 cycles then exec "/bin/systemctl restart redis-server"
|
||||||
EOF
|
EOF
|
||||||
|
|
||||||
|
|
@ -121,8 +121,8 @@ cat >/etc/monit/conf.d/rspamd.conf <<'EOF'
|
||||||
check process rspamd with pidfile /run/rspamd/rspamd.pid
|
check process rspamd with pidfile /run/rspamd/rspamd.pid
|
||||||
start program = "/bin/systemctl start rspamd"
|
start program = "/bin/systemctl start rspamd"
|
||||||
stop program = "/bin/systemctl stop rspamd"
|
stop program = "/bin/systemctl stop rspamd"
|
||||||
if failed port 11333 for 2 cycles then exec "/usr/local/sbin/mw-rspamd-heal.sh"
|
if failed port 11333 for 2 cycles then exec "/usr/local/sbin/mailwolt-rspamd-heal.sh"
|
||||||
if failed port 11334 for 2 cycles then exec "/usr/local/sbin/mw-rspamd-heal.sh"
|
if failed port 11334 for 2 cycles then exec "/usr/local/sbin/mailwolt-rspamd-heal.sh"
|
||||||
if 5 restarts within 5 cycles then alert
|
if 5 restarts within 5 cycles then alert
|
||||||
EOF
|
EOF
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -202,6 +202,12 @@ APP_ENV=${APP_ENV}
|
||||||
CLAMAV_ENABLE=${CLAMAV_ENABLE}
|
CLAMAV_ENABLE=${CLAMAV_ENABLE}
|
||||||
OPENDMARC_ENABLE=${OPENDMARC_ENABLE}
|
OPENDMARC_ENABLE=${OPENDMARC_ENABLE}
|
||||||
FAIL2BAN_ENABLE=${FAIL2BAN_ENABLE}
|
FAIL2BAN_ENABLE=${FAIL2BAN_ENABLE}
|
||||||
|
|
||||||
|
BACKUP_ENABLED=0
|
||||||
|
BACKUP_INTERVAL=daily
|
||||||
|
BACKUP_RETENTION_DAYS=7
|
||||||
|
BACKUP_DIR=/var/backups/mailwolt
|
||||||
|
BACKUP_USE_ZSTD=1
|
||||||
EOF
|
EOF
|
||||||
chmod 600 /etc/mailwolt/installer.env
|
chmod 600 /etc/mailwolt/installer.env
|
||||||
|
|
||||||
|
|
@ -210,9 +216,9 @@ for STEP in \
|
||||||
10-provision \
|
10-provision \
|
||||||
20-ssl 21-le-deploy-hook 22-dkim-helper \
|
20-ssl 21-le-deploy-hook 22-dkim-helper \
|
||||||
30-db 40-postfix 50-dovecot \
|
30-db 40-postfix 50-dovecot \
|
||||||
60-rspamd-opendkim 61-opendmarc 62-clamav 63-fail2ban \
|
60-rspamd-opendkim 61-opendmarc 62-clamav 63-fail2ban 64-apply-milters \
|
||||||
70-nginx 75-le-issue 80-app 88-update-wrapper 90-services \
|
70-nginx 75-le-issue 80-app 88-update-wrapper 90-services \
|
||||||
92-sudoers-npm 95-woltguard 98-motd 99-summary
|
92-sudoers-npm 93-backup-tools 95-woltguard 98-motd 99-summary
|
||||||
do
|
do
|
||||||
log ">>> Running ${STEP}.sh"
|
log ">>> Running ${STEP}.sh"
|
||||||
bash "./${STEP}.sh"
|
bash "./${STEP}.sh"
|
||||||
|
|
|
||||||
Loading…
Reference in New Issue