Dovecot Systax Problem

main
boksbc 2025-10-24 01:06:44 +02:00
parent b038fc3a26
commit 5cb0e82347
10 changed files with 357 additions and 37 deletions

View File

@ -25,7 +25,7 @@ log "Let's Encrypt Deploy-Hooks und Wrapper anlegen …"
# -------------------------------------------------------------------
# 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
# POSIX-safe Certbot deploy-hook (ohne bashisms)
set -eu
@ -130,7 +130,7 @@ fi
exit 0
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
@ -138,7 +138,7 @@ chmod +x /usr/local/sbin/mw-deploy.sh
install -d -m 0755 /etc/letsencrypt/renewal-hooks/deploy
cat >/etc/letsencrypt/renewal-hooks/deploy/50-mailwolt-certs.sh <<'HOOK'
#!/bin/sh
exec /usr/local/sbin/mw-deploy.sh
exec /usr/local/sbin/mailwolt-deploy.sh
HOOK
chmod +x /etc/letsencrypt/renewal-hooks/deploy/50-mailwolt-certs.sh

View File

@ -286,16 +286,7 @@ chmod 0750 /usr/local/sbin/mailwolt-remove-dkim
systemctl daemon-reload
systemctl enable opendkim || true
if command -v /usr/local/sbin/mw-apply-milters >/dev/null 2>&1; then
/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
touch /run/mailwolt.need-apply-milters || 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

View File

@ -58,8 +58,6 @@ else
fi
# Postfix-Milter-Kette konsistent setzen (Rspamd + OpenDKIM + optional OpenDMARC)
if command -v /usr/local/sbin/mw-apply-milters >/dev/null 2>&1; then
/usr/local/sbin/mw-apply-milters
fi
touch /run/mailwolt.need-apply-milters || true
log "[✓] OpenDMARC (ENABLE=${OPENDMARC_ENABLE}) bereit."

View File

@ -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

View File

@ -54,7 +54,7 @@ issue() {
certbot certonly \
--agree-tos -m "${LE_MAIL}" --non-interactive \
--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
}

View File

@ -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"
# --- 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:-}"
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)"
@ -91,16 +111,24 @@ fi
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
# DEV-Modus: immer IP als Host, http (kein example.com / keine Fake-Domain)
if [[ "${DEV_MODE:-0}" = "1" || "${APP_ENV:-production}" = "local" ]]; then
APP_HOST_VAL="$SERVER_PUBLIC_IPV4"
SCHEME="http"
[[ -s "$UI_CERT" && -s "$UI_KEY" ]] && SCHEME="https"
APP_URL_VAL="${SCHEME}://${SERVER_PUBLIC_IPV4}"
APP_URL_VAL="http://${APP_HOST_VAL}"
else
# 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
# --- .env schreiben ---------------------------------------------------------
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_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 QUEUE_CONNECTION "redis"
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) -------------------------------------
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=SystemBackupSeeder --force"
fi
# --- DKIM für SYSMAIL_DOMAIN via App erzeugen & per Helper einhängen --------

View File

@ -4,7 +4,7 @@ source ./lib.sh
log "Update-Wrapper & Sudoers …"
WRAPPER="/usr/local/sbin/mw-update"
WRAPPER="/usr/local/sbin/mailwolt-update"
LOGFILE="/var/log/mailwolt-update.log"
STATEDIR="/var/lib/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
cat > "$SUDOERS" <<'EOF'
Defaults!/usr/local/sbin/mw-update !requiretty
www-data ALL=(root) NOPASSWD: /usr/local/sbin/mw-update
mailwolt ALL=(root) NOPASSWD: /usr/local/sbin/mw-update
Defaults!/usr/local/sbin/mailwolt-update !requiretty
www-data ALL=(root) NOPASSWD: /usr/local/sbin/mailwolt-update
mailwolt ALL=(root) NOPASSWD: /usr/local/sbin/mailwolt-update
EOF
chown root:root "$SUDOERS"

267
scripts/93-backup-tools.sh Normal file
View File

@ -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."

View File

@ -17,7 +17,7 @@ systemctl enable --now monit
# Helper-Skripte
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
set -euo pipefail
PASS=""
@ -30,16 +30,16 @@ else
exit 1
fi
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
set -euo pipefail
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
systemctl restart rspamd
EOSH
chmod 0755 /usr/local/sbin/mw-rspamd-heal.sh
chmod 0755 /usr/local/sbin/mailwolt-rspamd-heal.sh
# WoltGuard Wrapper + Unit
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 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"
EOF
@ -121,8 +121,8 @@ cat >/etc/monit/conf.d/rspamd.conf <<'EOF'
check process rspamd with pidfile /run/rspamd/rspamd.pid
start program = "/bin/systemctl start 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 11334 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/mailwolt-rspamd-heal.sh"
if 5 restarts within 5 cycles then alert
EOF

View File

@ -202,6 +202,12 @@ APP_ENV=${APP_ENV}
CLAMAV_ENABLE=${CLAMAV_ENABLE}
OPENDMARC_ENABLE=${OPENDMARC_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
chmod 600 /etc/mailwolt/installer.env
@ -210,9 +216,9 @@ for STEP in \
10-provision \
20-ssl 21-le-deploy-hook 22-dkim-helper \
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 \
92-sudoers-npm 95-woltguard 98-motd 99-summary
92-sudoers-npm 93-backup-tools 95-woltguard 98-motd 99-summary
do
log ">>> Running ${STEP}.sh"
bash "./${STEP}.sh"