#!/usr/bin/env bash set -euo pipefail source ./lib.sh log "WoltGuard (Monit + Self-Heal) einrichten …" # ───────────────────────────────────────────────────────────── # Env nur nachladen, wenn Flags nicht bereits exportiert sind # ───────────────────────────────────────────────────────────── INSTALLER_ENV="/etc/mailwolt/installer.env" : "${CLAMAV_ENABLE:=}" ; : "${OPENDMARC_ENABLE:=}" ; : "${FAIL2BAN_ENABLE:=}" if [[ -z "${CLAMAV_ENABLE}${OPENDMARC_ENABLE}${FAIL2BAN_ENABLE}" && -r "$INSTALLER_ENV" ]]; then # shellcheck disable=SC1090 . "$INSTALLER_ENV" fi CLAMAV_ENABLE="${CLAMAV_ENABLE:-0}" OPENDMARC_ENABLE="${OPENDMARC_ENABLE:-0}" FAIL2BAN_ENABLE="${FAIL2BAN_ENABLE:-1}" # ───────────────────────────────────────────────────────────── # Monit installieren & aktivieren # ───────────────────────────────────────────────────────────── command -v monit >/dev/null || { apt-get update -qq; apt-get install -y monit; } systemctl enable --now monit # ───────────────────────────────────────────────────────────── # Helper-Skripte (laufen später eigenständig → Env selbst laden) # ───────────────────────────────────────────────────────────── install -d -m 0755 /usr/local/sbin # Redis-Ping (nimmt REDIS_PASSWORD aus installer.env oder .env) cat >/usr/local/sbin/mailwolt-redis-ping.sh <<'EOSH' #!/usr/bin/env bash set -euo pipefail INSTALLER_ENV="/etc/mailwolt/installer.env" APP_ENV="/var/www/mailwolt/.env" # Defaults REDIS_HOST="${REDIS_HOST:-127.0.0.1}" REDIS_PORT="${REDIS_PORT:-6379}" REDIS_PASSWORD="${REDIS_PASSWORD:-}" REDIS_PASS="${REDIS_PASS:-}" # Legacy # Installer-Env (falls vorhanden) [[ -r "$INSTALLER_ENV" ]] && . "$INSTALLER_ENV" || true # Falls .env existiert: Werte ergänzen, die noch leer sind if [[ -r "$APP_ENV" ]]; then [[ -z "${REDIS_HOST}" ]] && REDIS_HOST="$(grep -m1 -E '^REDIS_HOST=' "$APP_ENV" | cut -d= -f2- || true)" [[ -z "${REDIS_PORT}" ]] && REDIS_PORT="$(grep -m1 -E '^REDIS_PORT=' "$APP_ENV" | cut -d= -f2- || true)" [[ -z "${REDIS_PASSWORD}" ]] && REDIS_PASSWORD="$(grep -m1 -E '^REDIS_PASSWORD=' "$APP_ENV" | cut -d= -f2- || true)" fi # Legacy-Fallback: wenn PASSWORD leer, aber PASS gesetzt → übernehmen [[ -z "${REDIS_PASSWORD}" && -n "${REDIS_PASS}" ]] && REDIS_PASSWORD="$REDIS_PASS" # Quotes strippen strip(){ printf '%s' "$1" | sed -E 's/^"(.*)"$/\1/; s/^'\''(.*)'\''$/\1/'; } REDIS_HOST="$(strip "${REDIS_HOST:-}")" REDIS_PORT="$(strip "${REDIS_PORT:-}")" REDIS_PASSWORD="$(strip "${REDIS_PASSWORD:-}")" # redis-cli muss vorhanden sein command -v redis-cli >/dev/null 2>&1 || exit 1 BASE=(timeout 2 redis-cli --no-auth-warning --raw -h "$REDIS_HOST" -p "$REDIS_PORT") if [[ -n "$REDIS_PASSWORD" ]]; then CMD=("${BASE[@]}" -a "$REDIS_PASSWORD" ping) else CMD=("${BASE[@]}" ping) fi # Erfolgreich nur bei exakt "PONG" [[ "$("${CMD[@]}" 2>/dev/null || true)" == "PONG" ]] EOSH chmod 0755 /usr/local/sbin/mailwolt-redis-ping.sh # Rspamd-Heal (setzt Laufzeitverzeichnis, leert alte Socke, restarts rspamd) cat >/usr/local/sbin/mailwolt-rspamd-heal.sh <<'EOSH' #!/usr/bin/env bash set -euo pipefail INSTALLER_ENV="/etc/mailwolt/installer.env" APP_ENV="/var/www/mailwolt/.env" REDIS_HOST="${REDIS_HOST:-127.0.0.1}" REDIS_PORT="${REDIS_PORT:-6379}" REDIS_PASSWORD="${REDIS_PASSWORD:-}" [[ -r "$INSTALLER_ENV" ]] && . "$INSTALLER_ENV" if [[ -z "${REDIS_PASSWORD}" && -r "$APP_ENV" ]]; then REDIS_PASSWORD="$(grep -E '^REDIS_PASSWORD=' "$APP_ENV" | head -n1 | cut -d= -f2- || true)" fi # Rspamd Runtime fixen 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 # Neustart systemctl restart rspamd # Mini-Healthcheck sleep 2 ss -tln | grep -q ':11334' || echo "[WARN] Rspamd Controller Port 11334 nicht sichtbar" exit 0 EOSH chmod 0755 /usr/local/sbin/mailwolt-rspamd-heal.sh # ───────────────────────────────────────────────────────────── # WoltGuard Wrapper + Unit # ───────────────────────────────────────────────────────────── cat >/usr/local/bin/woltguard <<'EOSH' #!/usr/bin/env bash set -euo pipefail case "${1:-status}" in start) systemctl enable --now monit ;; stop) systemctl stop monit ;; status) monit summary || systemctl status monit || true ;; heal) monit reload || true; sleep 1; monit restart all || true ;; monitor) monit monitor all || true ;; unmonitor) monit unmonitor all || true ;; *) echo "Usage: woltguard {start|stop|status|heal|monitor|unmonitor}"; exit 2;; esac EOSH chmod 0755 /usr/local/bin/woltguard cat >/etc/systemd/system/woltguard.service <<'EOF' [Unit] Description=WoltGuard – Self-Healing Monitor for MailWolt After=network.target [Service] Type=oneshot ExecStart=/usr/local/bin/woltguard start ExecStop=/usr/local/bin/woltguard stop RemainAfterExit=yes [Install] WantedBy=multi-user.target EOF systemctl daemon-reload systemctl enable --now woltguard # ───────────────────────────────────────────────────────────── # Monit Basis + includes # ───────────────────────────────────────────────────────────── sed -i 's/^set daemon .*/set daemon 30/' /etc/monit/monitrc || true grep -q 'include /etc/monit/conf.d/*' /etc/monit/monitrc || echo 'include /etc/monit/conf.d/*' >>/etc/monit/monitrc install -d -m 0755 /etc/monit/conf.d # ───────────────────────────────────────────────────────────── # Monit Checks # ───────────────────────────────────────────────────────────── # 10 – Redis zuerst (abhängig für rspamd) cat >/etc/monit/conf.d/10-redis.conf <<'EOF' check process redis with pidfile /run/redis/redis-server.pid start program = "/bin/systemctl start redis-server" stop program = "/bin/systemctl stop redis-server" 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/mailwolt-redis-ping.sh" if status != 0 for 2 cycles then exec "/bin/systemctl restart redis-server" EOF # 20 – Rspamd (hängt von Redis ab), robust über process-matching cat >/etc/monit/conf.d/20-rspamd.conf <<'EOF' check process rspamd matching "/usr/bin/rspamd" start program = "/bin/systemctl start rspamd" stop program = "/bin/systemctl stop rspamd" depends on redis if failed host 127.0.0.1 port 11333 for 2 cycles then exec "/usr/local/sbin/mailwolt-rspamd-heal.sh" if failed host 127.0.0.1 port 11334 for 2 cycles then exec "/usr/local/sbin/mailwolt-rspamd-heal.sh" if 5 restarts within 5 cycles then alert EOF # 30 – Maildienste cat >/etc/monit/conf.d/30-postfix.conf <<'EOF' check process postfix with pidfile /var/spool/postfix/pid/master.pid start program = "/bin/systemctl start postfix" stop program = "/bin/systemctl stop postfix" if failed port 25 protocol smtp then restart if failed port 465 type tcpssl then restart if failed port 587 type tcp then restart if 5 restarts within 5 cycles then alert EOF cat >/etc/monit/conf.d/30-dovecot.conf <<'EOF' check process dovecot with pidfile /run/dovecot/master.pid start program = "/bin/systemctl start dovecot" stop program = "/bin/systemctl stop dovecot" if failed port 993 type tcpssl for 2 cycles then restart if failed port 24 protocol lmtp for 2 cycles then restart if 5 restarts within 5 cycles then alert EOF # 40 – Web/PHP cat >/etc/monit/conf.d/40-nginx.conf <<'EOF' check process nginx with pidfile /run/nginx.pid start program = "/bin/systemctl start nginx" stop program = "/bin/systemctl stop nginx" if failed port 80 type tcp then restart if failed port 443 type tcpssl then restart if 5 restarts within 5 cycles then alert EOF # 50 – DKIM/DMARC cat >/etc/monit/conf.d/50-opendkim.conf <<'EOF' check process opendkim with pidfile /run/opendkim/opendkim.pid start program = "/bin/systemctl start opendkim" stop program = "/bin/systemctl stop opendkim" if failed host 127.0.0.1 port 8891 type tcp for 2 cycles then restart if 5 restarts within 5 cycles then alert EOF # optional: OpenDMARC if [[ "$OPENDMARC_ENABLE" = "1" ]]; then cat >/etc/monit/conf.d/55-opendmarc.conf <<'EOF' check process opendmarc with pidfile /run/opendmarc/opendmarc.pid start program = "/bin/systemctl start opendmarc" stop program = "/bin/systemctl stop opendmarc" if 5 restarts within 5 cycles then alert EOF else rm -f /etc/monit/conf.d/55-opendmarc.conf || true fi # 60 – optional: ClamAV if [[ "$CLAMAV_ENABLE" = "1" ]]; then cat >/etc/monit/conf.d/60-clamav.conf <<'EOF' check process clamd with pidfile /run/clamav/clamd.pid start program = "/bin/systemctl start clamav-daemon" stop program = "/bin/systemctl stop clamav-daemon" if failed unixsocket /run/clamav/clamd.ctl for 3 cycles then restart if 5 restarts within 5 cycles then timeout EOF else rm -f /etc/monit/conf.d/60-clamav.conf || true fi # 70 – Fail2Ban (optional, standardmäßig aktiv) if [[ "$FAIL2BAN_ENABLE" = "1" ]]; then cat >/etc/monit/conf.d/70-fail2ban.conf <<'EOF' check process fail2ban with pidfile /run/fail2ban/fail2ban.pid start program = "/bin/systemctl start fail2ban" stop program = "/bin/systemctl stop fail2ban" if 5 restarts within 5 cycles then alert EOF else rm -f /etc/monit/conf.d/70-fail2ban.conf || true fi # ───────────────────────────────────────────────────────────── # Monit neu laden # ───────────────────────────────────────────────────────────── monit -t systemctl reload monit || systemctl restart monit systemctl status monit --no-pager || true log "[✓] WoltGuard aktiv." ##!/usr/bin/env bash #set -euo pipefail #source ./lib.sh # #log "WoltGuard (Monit + Self-Heal) einrichten …" # #set +u #[ -r /etc/mailwolt/installer.env ] && . /etc/mailwolt/installer.env #set -u #CLAMAV_ENABLE="${CLAMAV_ENABLE:-0}" #OPENDMARC_ENABLE="${OPENDMARC_ENABLE:-0}" #FAIL2BAN_ENABLE="${FAIL2BAN_ENABLE:-1}" # ## Pakete sicherstellen #command -v monit >/dev/null || { apt-get update -qq; apt-get install -y monit; } #systemctl enable --now monit # ## Helper-Skripte #install -d -m 0755 /usr/local/sbin #cat >/usr/local/sbin/mailwolt-redis-ping.sh <<'EOSH' ##!/usr/bin/env bash #set -euo pipefail #PASS="" #[ -r /etc/mailwolt/installer.env ] && . /etc/mailwolt/installer.env || true #if command -v redis-cli >/dev/null 2>&1; then # [[ -n "${REDIS_PASS:-}" ]] \ # && redis-cli -h 127.0.0.1 -p 6379 -a "$REDIS_PASS" ping | grep -q PONG \ # || redis-cli -h 127.0.0.1 -p 6379 ping | grep -q PONG #else # exit 1 #fi #EOSH #chmod 0755 /usr/local/sbin/mailwolt-redis-ping.sh # #cat >/usr/local/sbin/mailwolt-rspamd-heal.sh <<'EOSH' ##!/usr/bin/env bash #set -euo pipefail # #REDIS_HOST="${REDIS_HOST:-127.0.0.1}" #REDIS_PORT="${REDIS_PORT:-6379}" #REDIS_PASSWORD="${REDIS_PASSWORD:-}" # #INSTALLER_ENV="/etc/mailwolt/installer.env" #APP_ENV="/var/www/mailwolt/.env" #REDIS_CLI="$(command -v redis-cli || true)" #SYSTEMCTL="$(command -v systemctl || true)" #RSPAMD_SERVICE="rspamd" # #if [ -r "$INSTALLER_ENV" ]; then . "$INSTALLER_ENV"; fi #if [ -z "${REDIS_PASSWORD}" ] && [ -r "$APP_ENV" ]; then # REDIS_PASSWORD="$(grep -E '^REDIS_PASSWORD=' "$APP_ENV" | head -n1 | cut -d= -f2- || true)" #fi # #if [ -n "$REDIS_CLI" ]; then # echo "[INFO] Prüfe Redis Verbindung..." # if [ -n "${REDIS_PASSWORD}" ]; then # if ! "$REDIS_CLI" -h "$REDIS_HOST" -p "$REDIS_PORT" -a "$REDIS_PASSWORD" ping | grep -q '^PONG$'; then # echo "[WARN] Redis antwortet nicht oder Passwort falsch!" # else # echo "[OK] Redis antwortet (auth ok)." # fi # else # if ! "$REDIS_CLI" -h "$REDIS_HOST" -p "$REDIS_PORT" ping | grep -q '^PONG$'; then # echo "[WARN] Redis antwortet nicht (ohne Passwort)." # else # echo "[OK] Redis antwortet (kein Passwort)." # fi # fi #else # echo "[WARN] redis-cli nicht gefunden – überspringe Test." #fi # #echo "[INFO] Prüfe Rspamd Socket & Verzeichnis..." #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 # #echo "[INFO] Starte Rspamd neu..." #if [ -n "$SYSTEMCTL" ]; then # "$SYSTEMCTL" restart "$RSPAMD_SERVICE" # echo "[OK] Rspamd erfolgreich neu gestartet." #else # echo "[ERROR] systemctl nicht gefunden – kein Neustart möglich." # exit 1 #fi # #echo "[INFO] Healthcheck (Port 11334)..." #sleep 3 #if ss -tln | grep -q ':11334'; then # echo "[OK] Rspamd Controller läuft auf Port 11334." #else # echo "[WARN] Rspamd Controller Port 11334 nicht erreichbar." #fi # #echo "[DONE] Mailwolt Rspamd-Heal abgeschlossen." #exit 0 #EOSH #chmod 0755 /usr/local/sbin/mailwolt-rspamd-heal.sh # ## WoltGuard Wrapper + Unit #cat >/usr/local/bin/woltguard <<'EOSH' ##!/usr/bin/env bash #set -euo pipefail #case "${1:-status}" in # start) systemctl enable --now monit ;; # stop) systemctl stop monit ;; # status) monit summary || systemctl status monit || true ;; # heal) monit reload || true; sleep 1; monit restart all || true ;; # monitor) monit monitor all || true ;; # unmonitor) monit unmonitor all || true ;; # *) echo "Usage: woltguard {start|stop|status|heal|monitor|unmonitor}"; exit 2;; #esac #EOSH #chmod 0755 /usr/local/bin/woltguard # #cat >/etc/systemd/system/woltguard.service <<'EOF' #[Unit] #Description=WoltGuard – Self-Healing Monitor for MailWolt #After=network.target #[Service] #Type=oneshot #ExecStart=/usr/local/bin/woltguard start #ExecStop=/usr/local/bin/woltguard stop #RemainAfterExit=yes #[Install] #WantedBy=multi-user.target #EOF #systemctl daemon-reload #systemctl enable --now woltguard # ## Monit Basis + include #sed -i 's/^set daemon .*/set daemon 30/' /etc/monit/monitrc || true #grep -q 'include /etc/monit/conf.d/*' /etc/monit/monitrc || echo 'include /etc/monit/conf.d/*' >>/etc/monit/monitrc #install -d -m 0755 /etc/monit/conf.d # ## Checks #cat >/etc/monit/conf.d/postfix.conf <<'EOF' #check process postfix with pidfile /var/spool/postfix/pid/master.pid # start program = "/bin/systemctl start postfix" # stop program = "/bin/systemctl stop postfix" # if failed port 25 protocol smtp then restart # if failed port 465 type tcpssl then restart # if failed port 587 type tcp then restart # if 5 restarts within 5 cycles then alert #EOF # #cat >/etc/monit/conf.d/dovecot.conf <<'EOF' #check process dovecot with pidfile /run/dovecot/master.pid # start program = "/bin/systemctl start dovecot" # stop program = "/bin/systemctl stop dovecot" # if failed port 993 type tcpssl for 2 cycles then restart # if failed port 24 protocol lmtp for 2 cycles then restart # if 5 restarts within 5 cycles then alert #EOF # #cat >/etc/monit/conf.d/nginx.conf <<'EOF' #check process nginx with pidfile /run/nginx.pid # start program = "/bin/systemctl start nginx" # stop program = "/bin/systemctl stop nginx" # if failed port 80 type tcp then restart # if failed port 443 type tcpssl then restart # if 5 restarts within 5 cycles then alert #EOF # #cat >/etc/monit/conf.d/redis.conf <<'EOF' #check process redis with pidfile /run/redis/redis-server.pid # start program = "/bin/systemctl start redis-server" # stop program = "/bin/systemctl stop redis-server" # 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/mailwolt-redis-ping.sh" # if status != 0 for 2 cycles then exec "/bin/systemctl restart redis-server" #EOF # #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/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 # #cat >/etc/monit/conf.d/opendkim.conf <<'EOF' #check process opendkim with pidfile /run/opendkim/opendkim.pid # start program = "/bin/systemctl start opendkim" # stop program = "/bin/systemctl stop opendkim" # if failed host 127.0.0.1 port 8891 type tcp for 2 cycles then restart # if 5 restarts within 5 cycles then alert #EOF # ## optional: OpenDMARC #if [[ "$OPENDMARC_ENABLE" = "1" ]]; then # cat >/etc/monit/conf.d/opendmarc.conf <<'EOF' #check process opendmarc with pidfile /run/opendmarc/opendmarc.pid # start program = "/bin/systemctl start opendmarc" # stop program = "/bin/systemctl stop opendmarc" # if 5 restarts within 5 cycles then alert #EOF #else # rm -f /etc/monit/conf.d/opendmarc.conf || true #fi # ## optional: ClamAV #if [[ "$CLAMAV_ENABLE" = "1" ]]; then # cat >/etc/monit/conf.d/clamav.conf <<'EOF' #check process clamd with pidfile /run/clamav/clamd.pid # start program = "/bin/systemctl start clamav-daemon" # stop program = "/bin/systemctl stop clamav-daemon" # if failed unixsocket /run/clamav/clamd.ctl then restart # if 5 restarts within 5 cycles then alert #EOF #else # rm -f /etc/monit/conf.d/clamav.conf || true #fi # ## optional: Fail2Ban #if [[ "$FAIL2BAN_ENABLE" = "1" ]]; then # cat >/etc/monit/conf.d/fail2ban.conf <<'EOF' #check process fail2ban with pidfile /run/fail2ban/fail2ban.pid # start program = "/bin/systemctl start fail2ban" # stop program = "/bin/systemctl stop fail2ban" # if 5 restarts within 5 cycles then alert #EOF #else # rm -f /etc/monit/conf.d/fail2ban.conf || true #fi # #monit -t #systemctl reload monit || systemctl restart monit #systemctl status monit --no-pager || true #log "[✓] WoltGuard aktiv."