Dovecot Systax Problem
parent
06263461a3
commit
4b9a142712
|
|
@ -12,11 +12,10 @@ apt-get update -y
|
|||
apt-get -y -o Dpkg::Options::="--force-confdef" \
|
||||
-o Dpkg::Options::="--force-confold" install \
|
||||
postfix postfix-mysql dovecot-core dovecot-imapd dovecot-pop3d dovecot-lmtpd dovecot-mysql \
|
||||
mariadb-server mariadb-client redis-server \
|
||||
rspamd opendkim opendkim-tools \
|
||||
nginx php php-fpm php-cli php-mbstring php-xml php-curl php-zip php-mysql php-redis php-gd \
|
||||
unzip curl composer git certbot python3-certbot-nginx \
|
||||
ca-certificates rsyslog sudo openssl monit acl netcat-openbsd
|
||||
mariadb-server mariadb-client redis-server rspamd opendkim opendkim-tools opendmarc clamav \
|
||||
clamav-daemon nginx php php-fpm php-cli php-mbstring php-xml php-curl php-zip php-mysql \
|
||||
php-redis php-gd unzip curl composer git certbot python3-certbot-nginx fail2ban ca-certificates \
|
||||
rsyslog sudo openssl monit acl netcat-openbsd
|
||||
|
||||
# <<< Apache konsequent entfernen >>>
|
||||
systemctl disable --now apache2 >/dev/null 2>&1 || true
|
||||
|
|
|
|||
|
|
@ -35,6 +35,29 @@ fi
|
|||
/usr/sbin/postconf -e "smtp_tls_security_level = may"
|
||||
/usr/sbin/postconf -e "smtp_tls_loglevel = 1"
|
||||
|
||||
# ++ HÄRTUNG: DH-Parameter + ECDHE bevorzugen ++
|
||||
DH_FILE="/etc/ssl/private/dhparams.pem"
|
||||
if [[ ! -s "$DH_FILE" ]]; then
|
||||
openssl dhparam -out "$DH_FILE" 4096
|
||||
chmod 600 "$DH_FILE"
|
||||
chown root:root "$DH_FILE"
|
||||
fi
|
||||
/usr/sbin/postconf -e "smtpd_tls_dh1024_param_file = ${DH_FILE}"
|
||||
/usr/sbin/postconf -e "smtpd_tls_eecdh_grade = strong"
|
||||
/usr/sbin/postconf -e "tls_preempt_cipherlist = yes"
|
||||
|
||||
# Nur moderne TLS-Versionen (auch für ausgehendes SMTP)
|
||||
# (überschreibt die älteren Zeilen oben)
|
||||
/usr/sbin/postconf -e "smtpd_tls_protocols = !SSLv2,!SSLv3,!TLSv1,!TLSv1.1"
|
||||
/usr/sbin/postconf -e "smtpd_tls_mandatory_protocols = !SSLv2,!SSLv3,!TLSv1,!TLSv1.1"
|
||||
/usr/sbin/postconf -e "smtp_tls_protocols = !SSLv2,!SSLv3,!TLSv1,!TLSv1.1"
|
||||
|
||||
# Hohe Cipher, alte raus
|
||||
/usr/sbin/postconf -e "smtpd_tls_ciphers = high"
|
||||
/usr/sbin/postconf -e "smtp_tls_ciphers = high"
|
||||
/usr/sbin/postconf -e "smtpd_tls_exclude_ciphers = aNULL,eNULL,MD5,RC4,DES,3DES"
|
||||
/usr/sbin/postconf -e "smtp_tls_exclude_ciphers = aNULL,eNULL,MD5,RC4,DES,3DES"
|
||||
|
||||
# --- SMTP Sicherheit ----------------------------------------------------------
|
||||
/usr/sbin/postconf -e "disable_vrfy_command = yes"
|
||||
/usr/sbin/postconf -e "smtpd_helo_required = yes"
|
||||
|
|
@ -106,4 +129,4 @@ chmod 640 /etc/postfix/sql/mysql-virtual-alias-maps.cf
|
|||
/usr/sbin/postconf -e "virtual_transport = lmtp:unix:private/dovecot-lmtp"
|
||||
|
||||
# --- Dienst aktivieren & neu laden --------------------------------------------
|
||||
systemctl enable postfix >/dev/null 2>&1 || true
|
||||
#systemctl enable postfix >/dev/null 2>&1 || true
|
||||
|
|
|
|||
|
|
@ -168,6 +168,10 @@ else
|
|||
fi
|
||||
grep -q '^ssl_min_protocol' "$DOVECOT_SSL_CONF" || echo "ssl_min_protocol = TLSv1.2" >> "$DOVECOT_SSL_CONF"
|
||||
|
||||
# Starke Cipher + DH-Params für DHE-Fallback
|
||||
grep -q '^ssl_prefer_server_ciphers' "$DOVECOT_SSL_CONF" || echo "ssl_prefer_server_ciphers = yes" >> "$DOVECOT_SSL_CONF"
|
||||
grep -q '^ssl_dh' "$DOVECOT_SSL_CONF" || echo "ssl_dh = </etc/ssl/private/dhparams.pem" >> "$DOVECOT_SSL_CONF"
|
||||
|
||||
# Postfix-Socket-Verzeichnis sicherstellen
|
||||
mkdir -p /var/spool/postfix/private
|
||||
chown root:root /var/spool/postfix
|
||||
|
|
@ -176,124 +180,4 @@ chown postfix:postfix /var/spool/postfix/private
|
|||
chmod 0755 /var/spool/postfix/private
|
||||
|
||||
# Nur aktivieren – Start/Reload später
|
||||
systemctl enable dovecot >/dev/null 2>&1 || true
|
||||
|
||||
##!/usr/bin/env bash
|
||||
#set -euo pipefail
|
||||
#source ./lib.sh
|
||||
#
|
||||
#MAIL_SSL_DIR="/etc/ssl/mail"
|
||||
#MAIL_CERT="${MAIL_SSL_DIR}/fullchain.pem"
|
||||
#MAIL_KEY="${MAIL_SSL_DIR}/privkey.pem"
|
||||
#
|
||||
#log "Dovecot konfigurieren …"
|
||||
#
|
||||
## Hauptdatei
|
||||
#cat > /etc/dovecot/dovecot.conf <<'CONF'
|
||||
#!include_try /etc/dovecot/conf.d/*.conf
|
||||
#CONF
|
||||
#
|
||||
## Mail-Location & Namespace
|
||||
#cat > /etc/dovecot/conf.d/10-mail.conf <<'CONF'
|
||||
#protocols = imap pop3 lmtp
|
||||
#mail_location = maildir:/var/mail/vhosts/%d/%n
|
||||
#
|
||||
#namespace inbox {
|
||||
# inbox = yes
|
||||
#}
|
||||
#
|
||||
#mail_privileged_group = mail
|
||||
#first_valid_uid = 109
|
||||
#last_valid_uid = 109
|
||||
#CONF
|
||||
#
|
||||
## Auth
|
||||
#cat > /etc/dovecot/conf.d/10-auth.conf <<'CONF'
|
||||
#disable_plaintext_auth = yes
|
||||
#auth_mechanisms = plain login
|
||||
#!include_try auth-sql.conf.ext
|
||||
#CONF
|
||||
#
|
||||
## SQL-Anbindung
|
||||
#cat > /etc/dovecot/dovecot-sql.conf.ext <<CONF
|
||||
#driver = mysql
|
||||
#connect = host=127.0.0.1 dbname=${DB_NAME} user=${DB_USER} password=${DB_PASS}
|
||||
#default_pass_scheme = BLF-CRYPT
|
||||
#password_query = SELECT email AS user, password_hash AS password FROM mail_users WHERE email = '%u' AND is_active = 1 LIMIT 1;
|
||||
#CONF
|
||||
#chown root:dovecot /etc/dovecot/dovecot-sql.conf.ext
|
||||
#chmod 640 /etc/dovecot/dovecot-sql.conf.ext
|
||||
#
|
||||
## Auth-SQL Einbindung
|
||||
#cat > /etc/dovecot/conf.d/auth-sql.conf.ext <<'CONF'
|
||||
#passdb {
|
||||
# driver = sql
|
||||
# args = /etc/dovecot/dovecot-sql.conf.ext
|
||||
#}
|
||||
#userdb {
|
||||
# driver = static
|
||||
# args = uid=vmail gid=mail home=/var/mail/vhosts/%d/%n
|
||||
#}
|
||||
#CONF
|
||||
#chown root:dovecot /etc/dovecot/conf.d/auth-sql.conf.ext
|
||||
#chmod 640 /etc/dovecot/conf.d/auth-sql.conf.ext
|
||||
#
|
||||
## Master-Services (LMTP + AUTH + Listener)
|
||||
#cat > /etc/dovecot/conf.d/10-master.conf <<'CONF'
|
||||
#service lmtp {
|
||||
# unix_listener /var/spool/postfix/private/dovecot-lmtp {
|
||||
# mode = 0600
|
||||
# user = postfix
|
||||
# group = postfix
|
||||
# }
|
||||
#}
|
||||
#service auth {
|
||||
# unix_listener /var/spool/postfix/private/auth {
|
||||
# mode = 0660
|
||||
# user = postfix
|
||||
# group = postfix
|
||||
# }
|
||||
#}
|
||||
#service imap-login {
|
||||
# inet_listener imap {
|
||||
# port = 143
|
||||
# }
|
||||
# inet_listener imaps {
|
||||
# port = 993
|
||||
# ssl = yes
|
||||
# }
|
||||
#}
|
||||
#service pop3-login {
|
||||
# inet_listener pop3 {
|
||||
# port = 110
|
||||
# }
|
||||
# inet_listener pop3s {
|
||||
# port = 995
|
||||
# ssl = yes
|
||||
# }
|
||||
#}
|
||||
#CONF
|
||||
#
|
||||
## SSL – stabile Mail-Pfade
|
||||
#DOVECOT_SSL_CONF="/etc/dovecot/conf.d/10-ssl.conf"
|
||||
#grep -q '^ssl\s*=' "$DOVECOT_SSL_CONF" 2>/dev/null || echo "ssl = required" >> "$DOVECOT_SSL_CONF"
|
||||
#if grep -q '^\s*ssl_cert\s*=' "$DOVECOT_SSL_CONF"; then
|
||||
# sed -i "s|^\s*ssl_cert\s*=.*|ssl_cert = <${MAIL_CERT}|" "$DOVECOT_SSL_CONF"
|
||||
#else
|
||||
# echo "ssl_cert = <${MAIL_CERT}" >> "$DOVECOT_SSL_CONF"
|
||||
#fi
|
||||
#if grep -q '^\s*ssl_key\s*=' "$DOVECOT_SSL_CONF"; then
|
||||
# sed -i "s|^\s*ssl_key\s*=.*|ssl_key = <${MAIL_KEY}|" "$DOVECOT_SSL_CONF"
|
||||
#else
|
||||
# echo "ssl_key = <${MAIL_KEY}" >> "$DOVECOT_SSL_CONF"
|
||||
#fi
|
||||
#
|
||||
## Postfix-Socket-Verzeichnis sicherstellen
|
||||
#mkdir -p /var/spool/postfix/private
|
||||
#chown root:root /var/spool/postfix
|
||||
#chmod 0755 /var/spool/postfix
|
||||
#chown postfix:postfix /var/spool/postfix/private
|
||||
#chmod 0755 /var/spool/postfix/private
|
||||
#
|
||||
## Nur aktivieren – Start/Reload erst nach App/DB in 90-services.sh
|
||||
#systemctl enable dovecot >/dev/null 2>&1 || true
|
||||
|
|
@ -21,7 +21,7 @@ RSPAMD_CONTROLLER_PASSWORD="${RSPAMD_CONTROLLER_PASSWORD:-admin}"
|
|||
# ──────────────────────────────────────────────────────────────
|
||||
# Rspamd (Controller + Milter)
|
||||
# ──────────────────────────────────────────────────────────────
|
||||
install -d -m 0755 /etc/rspamd/local.d
|
||||
install -d -m 0750 /etc/rspamd/local.d
|
||||
|
||||
if command -v rspamadm >/dev/null 2>&1; then
|
||||
RSPAMD_HASH="$(rspamadm pw -p "${RSPAMD_CONTROLLER_PASSWORD}")"
|
||||
|
|
@ -30,32 +30,94 @@ else
|
|||
fi
|
||||
|
||||
cat >/etc/rspamd/local.d/worker-controller.inc <<CONF
|
||||
password = "${RSPAMD_HASH}";
|
||||
bind_socket = "127.0.0.1:11334";
|
||||
worker "controller" {
|
||||
bind_socket = "127.0.0.1:11334";
|
||||
password = "${RSPAMD_HASH}";
|
||||
}
|
||||
CONF
|
||||
|
||||
cat >/etc/rspamd/local.d/worker-normal.inc <<'CONF'
|
||||
bind_socket = "127.0.0.1:11332";
|
||||
#cat >/etc/rspamd/local.d/worker-normal.inc <<'CONF'
|
||||
#worker "normal" {
|
||||
# bind_socket = "127.0.0.1:11333";
|
||||
#}
|
||||
#CONF
|
||||
|
||||
cat >/etc/rspamd/local.d/worker-proxy.inc <<'CONF'
|
||||
worker "proxy" {
|
||||
bind_socket = "127.0.0.1:11333";
|
||||
milter = yes;
|
||||
timeout = 120s;
|
||||
upstream "local" {
|
||||
default = yes;
|
||||
self_scan = yes;
|
||||
}
|
||||
}
|
||||
CONF
|
||||
|
||||
|
||||
cat >/etc/rspamd/local.d/milter_headers.conf <<'CONF'
|
||||
use = ["authentication-results"];
|
||||
header = "Authentication-Results";
|
||||
CONF
|
||||
|
||||
# ──────────────────────────────────────────────────────────────
|
||||
# Rspamd Redis-Konfiguration
|
||||
# ──────────────────────────────────────────────────────────────
|
||||
log "Rspamd Redis konfigurieren …"
|
||||
|
||||
: "${REDIS_PASS:=}"
|
||||
|
||||
cat >/etc/rspamd/local.d/redis.conf <<CONF
|
||||
servers = "127.0.0.1:6379";
|
||||
${REDIS_PASS:+password = "${REDIS_PASS}";}
|
||||
db = 0;
|
||||
CONF
|
||||
|
||||
# Eigentümer und Rechte setzen
|
||||
chown root:_rspamd /etc/rspamd/local.d /etc/rspamd/local.d/redis.conf
|
||||
chmod 750 /etc/rspamd/local.d
|
||||
chmod 640 /etc/rspamd/local.d/redis.conf
|
||||
|
||||
# Testweise prüfen, ob Redis erreichbar ist (nicht kritisch)
|
||||
if command -v redis-cli >/dev/null 2>&1; then
|
||||
if [[ -n "${REDIS_PASS}" ]]; then
|
||||
if redis-cli -h 127.0.0.1 -p 6379 -a "${REDIS_PASS}" ping >/dev/null 2>&1; then
|
||||
log "[✓] Redis erreichbar und Passwort akzeptiert."
|
||||
else
|
||||
log "[!] Warnung: Redis antwortet nicht oder Passwort falsch."
|
||||
fi
|
||||
else
|
||||
if redis-cli -h 127.0.0.1 -p 6379 ping >/dev/null 2>&1; then
|
||||
log "[✓] Redis erreichbar (ohne Passwort)."
|
||||
else
|
||||
log "[!] Warnung: Redis antwortet nicht."
|
||||
fi
|
||||
fi
|
||||
fi
|
||||
|
||||
systemctl enable --now rspamd || true
|
||||
|
||||
# ──────────────────────────────────────────────────────────────
|
||||
# OpenDKIM – nur wenn DKIM_ENABLE=1
|
||||
# ──────────────────────────────────────────────────────────────
|
||||
|
||||
if [[ "${DKIM_ENABLE}" != "1" ]]; then
|
||||
log "DKIM_ENABLE=0 → OpenDKIM wird übersprungen."
|
||||
/usr/sbin/postconf -e "smtpd_milters = inet:127.0.0.1:11332"
|
||||
/usr/sbin/postconf -e "non_smtpd_milters = inet:127.0.0.1:11332"
|
||||
systemctl reload postfix || true
|
||||
/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"
|
||||
/usr/sbin/postconf -e "non_smtpd_milters = inet:127.0.0.1:11333"
|
||||
exit 0
|
||||
fi
|
||||
|
||||
#if [[ "${DKIM_ENABLE}" != "1" ]]; then
|
||||
# log "DKIM_ENABLE=0 → OpenDKIM wird übersprungen."
|
||||
# /usr/sbin/postconf -e "smtpd_milters = inet:127.0.0.1:11332"
|
||||
# /usr/sbin/postconf -e "non_smtpd_milters = inet:127.0.0.1:11332"
|
||||
# systemctl reload postfix || true
|
||||
# exit 0
|
||||
#fi
|
||||
|
||||
install -d -m 0755 /etc/opendkim
|
||||
install -d -m 0750 /etc/opendkim/keys
|
||||
chown -R opendkim:opendkim /etc/opendkim
|
||||
|
|
@ -241,10 +303,23 @@ visudo -cf /etc/sudoers.d/mailwolt-dkim >/dev/null
|
|||
|
||||
# ── Dienst + Postfix-Milter aktivieren ─────────────────────────
|
||||
systemctl daemon-reload
|
||||
systemctl enable --now opendkim || true
|
||||
systemctl enable opendkim || true
|
||||
|
||||
/usr/sbin/postconf -e "smtpd_milters = inet:127.0.0.1:11332, inet:127.0.0.1:8891"
|
||||
/usr/sbin/postconf -e "non_smtpd_milters = inet:127.0.0.1:11332, inet:127.0.0.1:8891"
|
||||
systemctl reload postfix || 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
|
||||
|
||||
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
|
||||
|
||||
#/usr/sbin/postconf -e "smtpd_milters = inet:127.0.0.1:11332, inet:127.0.0.1:8891"
|
||||
#/usr/sbin/postconf -e "non_smtpd_milters = inet:127.0.0.1:11332, inet:127.0.0.1:8891"
|
||||
|
||||
log "[✓] Rspamd + OpenDKIM eingerichtet (läuft; signiert, sobald Keys vorhanden sind)."
|
||||
|
|
|
|||
|
|
@ -0,0 +1,65 @@
|
|||
#!/usr/bin/env bash
|
||||
set -euo pipefail
|
||||
source ./lib.sh
|
||||
|
||||
log "OpenDMARC installieren/konfigurieren …"
|
||||
|
||||
# Flags laden
|
||||
set +u
|
||||
[ -r /etc/mailwolt/installer.env ] && . /etc/mailwolt/installer.env
|
||||
set -u
|
||||
OPENDMARC_ENABLE="${OPENDMARC_ENABLE:-1}"
|
||||
|
||||
# Paket sicherstellen
|
||||
if ! dpkg -s opendmarc >/dev/null 2>&1; then
|
||||
apt-get update -qq
|
||||
apt-get install -y opendmarc
|
||||
fi
|
||||
|
||||
# Config-Verzeichnisse
|
||||
install -d -m 0755 /etc/opendmarc
|
||||
install -d -m 0755 /run/opendmarc
|
||||
|
||||
# IgnoreHosts
|
||||
cat >/etc/opendmarc/ignore.hosts <<'EOF'
|
||||
127.0.0.1
|
||||
::1
|
||||
localhost
|
||||
EOF
|
||||
chmod 0644 /etc/opendmarc/ignore.hosts
|
||||
|
||||
# Hauptkonfiguration
|
||||
cat >/etc/opendmarc.conf <<'EOF'
|
||||
AuthservID mailwolt
|
||||
TrustedAuthservIDs mailwolt
|
||||
IgnoreHosts /etc/opendmarc/ignore.hosts
|
||||
Syslog true
|
||||
SoftwareHeader true
|
||||
Socket local:/run/opendmarc/opendmarc.sock
|
||||
RejectFailures false
|
||||
EOF
|
||||
chmod 0644 /etc/opendmarc.conf
|
||||
|
||||
# systemd Drop-in für RuntimeDirectory (robust nach Reboot)
|
||||
install -d -m 0755 /etc/systemd/system/opendmarc.service.d
|
||||
cat >/etc/systemd/system/opendmarc.service.d/override.conf <<'EOF'
|
||||
[Service]
|
||||
RuntimeDirectory=opendmarc
|
||||
RuntimeDirectoryMode=0755
|
||||
EOF
|
||||
|
||||
systemctl daemon-reload
|
||||
|
||||
# Dienst nach Flag
|
||||
if [[ "$OPENDMARC_ENABLE" = "1" ]]; then
|
||||
systemctl enable --now opendmarc
|
||||
else
|
||||
systemctl disable --now opendmarc || true
|
||||
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
|
||||
|
||||
log "[✓] OpenDMARC (ENABLE=${OPENDMARC_ENABLE}) bereit."
|
||||
|
|
@ -0,0 +1,59 @@
|
|||
#!/usr/bin/env bash
|
||||
set -euo pipefail
|
||||
source ./lib.sh
|
||||
|
||||
log "ClamAV (clamav-daemon) installieren/konfigurieren …"
|
||||
|
||||
# Flags laden
|
||||
set +u
|
||||
[ -r /etc/mailwolt/installer.env ] && . /etc/mailwolt/installer.env
|
||||
set -u
|
||||
CLAMAV_ENABLE="${CLAMAV_ENABLE:-0}"
|
||||
|
||||
# Pakete
|
||||
if ! dpkg -s clamav-daemon >/dev/null 2>&1; then
|
||||
apt-get update -qq
|
||||
apt-get install -y clamav clamav-daemon
|
||||
fi
|
||||
|
||||
# Signaturen aktualisieren (erst Freshclam starten)
|
||||
systemctl stop clamav-freshclam 2>/dev/null || true
|
||||
freshclam || true
|
||||
systemctl start clamav-freshclam || true
|
||||
|
||||
# clamd LocalSocket setzen
|
||||
sed -i 's|^#\?LocalSocket .*|LocalSocket /run/clamav/clamd.ctl|' /etc/clamav/clamd.conf || true
|
||||
install -d -m 0755 /run/clamav
|
||||
chown clamav:clamav /run/clamav
|
||||
|
||||
# Dienst nach Flag
|
||||
if [[ "$CLAMAV_ENABLE" = "1" ]]; then
|
||||
systemctl enable --now clamav-daemon
|
||||
else
|
||||
systemctl disable --now clamav-daemon || true
|
||||
fi
|
||||
|
||||
# Rspamd-Integration (nur wenn aktiv)
|
||||
AV_CONF="/etc/rspamd/local.d/antivirus.conf"
|
||||
if [[ "$CLAMAV_ENABLE" = "1" ]]; then
|
||||
cat >"$AV_CONF" <<'EOF'
|
||||
clamav {
|
||||
symbol = "CLAM_VIRUS";
|
||||
type = "clamav";
|
||||
servers = "/run/clamav/clamd.ctl";
|
||||
scan_mime_parts = true;
|
||||
scan_text_mime = true;
|
||||
max_size = 50mb;
|
||||
log_clean = false;
|
||||
action = "reject";
|
||||
}
|
||||
EOF
|
||||
chown root:_rspamd "$AV_CONF" || true
|
||||
chmod 0640 "$AV_CONF" || true
|
||||
systemctl reload rspamd || systemctl restart rspamd
|
||||
else
|
||||
rm -f "$AV_CONF" || true
|
||||
systemctl reload rspamd || true
|
||||
fi
|
||||
|
||||
log "[✓] ClamAV (ENABLE=${CLAMAV_ENABLE}) konfiguriert."
|
||||
|
|
@ -0,0 +1,69 @@
|
|||
#!/usr/bin/env bash
|
||||
set -euo pipefail
|
||||
source ./lib.sh
|
||||
|
||||
log "Fail2Ban installieren/konfigurieren …"
|
||||
|
||||
# Flags laden
|
||||
set +u
|
||||
[ -r /etc/mailwolt/installer.env ] && . /etc/mailwolt/installer.env
|
||||
set -u
|
||||
FAIL2BAN_ENABLE="${FAIL2BAN_ENABLE:-1}"
|
||||
|
||||
# Paket
|
||||
if ! dpkg -s fail2ban >/dev/null 2>&1; then
|
||||
apt-get update -qq
|
||||
apt-get install -y fail2ban
|
||||
fi
|
||||
|
||||
install -d -m 0755 /etc/fail2ban/jail.d
|
||||
|
||||
# Basis-Jails (praxisnah)
|
||||
cat >/etc/fail2ban/jail.d/mailwolt.conf <<'EOF'
|
||||
[DEFAULT]
|
||||
bantime = 1h
|
||||
findtime = 10m
|
||||
maxretry = 5
|
||||
backend = auto
|
||||
|
||||
[sshd]
|
||||
enabled = true
|
||||
port = ssh
|
||||
logpath = /var/log/auth.log
|
||||
|
||||
[postfix]
|
||||
enabled = true
|
||||
logpath = /var/log/mail.log
|
||||
port = smtp,ssmtp,submission,465
|
||||
|
||||
[dovecot]
|
||||
enabled = true
|
||||
logpath = /var/log/mail.log
|
||||
port = pop3,pop3s,imap,imaps,submission,465,587,993
|
||||
|
||||
# Optional: Rspamd-Controller-Auth (nur wenn Passwort/Basic-Auth genutzt wird)
|
||||
[rspamd-controller]
|
||||
enabled = true
|
||||
port = 11334
|
||||
filter = rspamd
|
||||
logpath = /var/log/rspamd/rspamd.log
|
||||
maxretry = 5
|
||||
EOF
|
||||
|
||||
# einfacher Filter für Rspamd-Controller
|
||||
if [ ! -f /etc/fail2ban/filter.d/rspamd.conf ]; then
|
||||
cat >/etc/fail2ban/filter.d/rspamd.conf <<'EOF'
|
||||
[Definition]
|
||||
failregex = .*Authentication failed for user.* from <HOST>
|
||||
ignoreregex =
|
||||
EOF
|
||||
fi
|
||||
|
||||
# Dienst nach Flag
|
||||
if [[ "$FAIL2BAN_ENABLE" = "1" ]]; then
|
||||
systemctl enable --now fail2ban
|
||||
else
|
||||
systemctl disable --now fail2ban || true
|
||||
fi
|
||||
|
||||
log "[✓] Fail2Ban (ENABLE=${FAIL2BAN_ENABLE}) bereit."
|
||||
|
|
@ -63,11 +63,6 @@ if [[ "${BASE_DOMAIN}" != "example.com" ]]; then
|
|||
issue "${WEBMAIL_HOST:-}"
|
||||
issue "${MAIL_HOSTNAME:-}"
|
||||
|
||||
# Falls der Deploy-Wrapper gerade erst installiert wurde:
|
||||
# if [[ -x /usr/local/sbin/mw-deploy.sh ]]; then
|
||||
# /usr/local/sbin/mw-deploy.sh || true
|
||||
# fi
|
||||
|
||||
# Nginx nur neu laden, wenn aktiv
|
||||
if systemctl is-active --quiet nginx; then
|
||||
systemctl reload nginx || true
|
||||
|
|
@ -75,238 +70,3 @@ if [[ "${BASE_DOMAIN}" != "example.com" ]]; then
|
|||
else
|
||||
echo "[i] BASE_DOMAIN=example.com – LE wird übersprungen."
|
||||
fi
|
||||
|
||||
|
||||
##!/usr/bin/env bash
|
||||
#set -euo pipefail
|
||||
#source ./lib.sh
|
||||
#
|
||||
#ACME_WEBROOT="/var/www/letsencrypt"
|
||||
#install -d -m 0755 "${ACME_WEBROOT}/.well-known/acme-challenge"
|
||||
#
|
||||
#CERTBOT_EXTRA=()
|
||||
#LE_STAGING="${LE_STAGING:-0}" # 1 = Let's Encrypt Staging aktivieren
|
||||
#[[ "$LE_STAGING" = "1" ]] && CERTBOT_EXTRA+=(--test-cert)
|
||||
#
|
||||
#resolve_ok() {
|
||||
# local host="$1"
|
||||
# local pats=()
|
||||
# [[ -n "${SERVER_PUBLIC_IPV4:-}" ]] && pats+=("${SERVER_PUBLIC_IPV4//./\\.}")
|
||||
# [[ -n "${SERVER_PUBLIC_IPV6:-}" ]] && pats+=("${SERVER_PUBLIC_IPV6//:/\\:}")
|
||||
# # Wenn gar nichts bekannt ist, lieber nicht blockieren:
|
||||
# [[ ${#pats[@]} -eq 0 ]] && return 0
|
||||
# getent ahosts "$host" | awk '{print $1}' | sort -u \
|
||||
# | grep -Eq "^($(IFS='|'; echo "${pats[*]}"))$"
|
||||
#}
|
||||
#
|
||||
#probe_http() {
|
||||
# local host="$1"
|
||||
# echo test > "${ACME_WEBROOT}/.well-known/acme-challenge/_probe"
|
||||
# curl -fsS --max-time 5 -4 "http://${host}/.well-known/acme-challenge/_probe" >/dev/null \
|
||||
# || curl -fsS --max-time 5 -6 "http://${host}/.well-known/acme-challenge/_probe" >/dev/null
|
||||
#}
|
||||
#
|
||||
#issue() {
|
||||
# local host="$1"
|
||||
# echo "[i] Versuche LE für ${host} …"
|
||||
# resolve_ok "$host" || { echo "[!] DNS zeigt (noch) nicht hierher – skip ${host}"; return 0; }
|
||||
#
|
||||
# if ! probe_http "$host"; then
|
||||
# echo "[!] ACME-HTTP-Check für ${host} fehlgeschlagen (Port 80/IPv6/Firewall/Nginx prüfen)."
|
||||
# fi
|
||||
#
|
||||
# # MX: Key beibehalten (TLSA 3 1 1 bleibt stabil)
|
||||
# EXTRA_ARGS=()
|
||||
# [[ "$host" == "$MAIL_HOSTNAME" ]] && EXTRA_ARGS+=(--reuse-key)
|
||||
#
|
||||
# certbot certonly --agree-tos -m "${LE_EMAIL:-admin@${BASE_DOMAIN}}" \
|
||||
# --non-interactive --webroot -w "$ACME_WEBROOT" -d "$host" \
|
||||
# "${EXTRA_ARGS[@]}" "${CERTBOT_EXTRA[@]}" || true
|
||||
#}
|
||||
#
|
||||
#if [[ "$BASE_DOMAIN" != "example.com" ]]; then
|
||||
# issue "$UI_HOST"
|
||||
# issue "$WEBMAIL_HOST"
|
||||
# issue "$MAIL_HOSTNAME"
|
||||
#
|
||||
#run-parts /etc/letsencrypt/renewal-hooks/deploy || true
|
||||
#systemctl reload nginx || true
|
||||
#
|
||||
## # TLSA direkt einmal schreiben (Hook macht es bei Renewals sowieso)
|
||||
## MX_CERT="/etc/letsencrypt/live/${MAIL_HOSTNAME}/fullchain.pem"
|
||||
## if [[ -s "$MX_CERT" ]]; then
|
||||
## HASH="$(openssl x509 -in "$MX_CERT" -noout -pubkey \
|
||||
## | openssl pkey -pubin -outform DER \
|
||||
## | openssl dgst -sha256 | sed 's/^.*= //')"
|
||||
## TLSA_LINE="_25._tcp.${MAIL_HOSTNAME}. IN TLSA 3 1 1 ${HASH}"
|
||||
## install -d -m 0755 /etc/mailwolt/dns
|
||||
## echo "${TLSA_LINE}" > "/etc/mailwolt/dns/${MAIL_HOSTNAME}.tlsa.txt"
|
||||
## echo "[TLSA] ${TLSA_LINE}"
|
||||
## fi
|
||||
#else
|
||||
# echo "[i] BASE_DOMAIN=example.com – LE wird übersprungen."
|
||||
#fi
|
||||
|
||||
|
||||
##!/usr/bin/env bash
|
||||
#set -euo pipefail
|
||||
#source ./lib.sh
|
||||
#
|
||||
#ACME_WEBROOT="/var/www/letsencrypt"
|
||||
#install -d -m 0755 "${ACME_WEBROOT}/.well-known/acme-challenge"
|
||||
#
|
||||
## Let's Encrypt: Staging optional (für Tests)
|
||||
#CERTBOT_EXTRA=()
|
||||
#LE_STAGING="${LE_STAGING:-0}"
|
||||
#[[ "$LE_STAGING" = "1" ]] && CERTBOT_EXTRA+=(--test-cert)
|
||||
#
|
||||
## Einheitliche LE-E-Mail mit Fallback
|
||||
#LE_MAIL="${LE_EMAIL:-admin@${BASE_DOMAIN}}"
|
||||
#
|
||||
## DNS zeigt auf diese Kiste?
|
||||
#resolve_ok() {
|
||||
# local host="$1"
|
||||
# local pats=()
|
||||
# [[ -n "${SERVER_PUBLIC_IPV4:-}" ]] && pats+=("${SERVER_PUBLIC_IPV4//./\\.}")
|
||||
# [[ -n "${SERVER_PUBLIC_IPV6:-}" ]] && pats+=("${SERVER_PUBLIC_IPV6//:/\\:}")
|
||||
# [[ ${#pats[@]} -eq 0 ]] && return 0
|
||||
# getent ahosts "$host" | awk '{print $1}' | sort -u \
|
||||
# | grep -Eq "^($(IFS='|'; echo "${pats[*]}"))$"
|
||||
#}
|
||||
#
|
||||
## HTTP-01 erreichbar?
|
||||
#probe_http() {
|
||||
# local host="$1"
|
||||
# echo test > "${ACME_WEBROOT}/.well-known/acme-challenge/_probe"
|
||||
# curl -fsS --max-time 5 -4 "http://${host}/.well-known/acme-challenge/_probe" >/dev/null \
|
||||
# || curl -fsS --max-time 5 -6 "http://${host}/.well-known/acme-challenge/_probe" >/dev/null
|
||||
#}
|
||||
#
|
||||
## Ein Zertifikat ausstellen
|
||||
#issue() {
|
||||
# local host="$1"
|
||||
# [[ -z "$host" ]] && return 0
|
||||
#
|
||||
# echo "[i] Versuche LE für ${host} …"
|
||||
#
|
||||
# if ! resolve_ok "$host"; then
|
||||
# echo "[!] DNS zeigt (noch) nicht hierher – überspringe: ${host}"
|
||||
# return 0
|
||||
# fi
|
||||
#
|
||||
# if ! probe_http "$host"; then
|
||||
# echo "[!] ACME-HTTP-Check für ${host} fehlgeschlagen (Port 80/IPv6/Firewall/Nginx prüfen)."
|
||||
# fi
|
||||
#
|
||||
# EXTRA_ARGS=()
|
||||
# # MX: Key wiederverwenden → stabiler TLSA-Hash (3 1 1)
|
||||
# [[ "${host}" == "${MAIL_HOSTNAME}" ]] && EXTRA_ARGS+=(--reuse-key)
|
||||
#
|
||||
#certbot certonly \
|
||||
# --agree-tos -m "${LE_MAIL}" --non-interactive \
|
||||
# --webroot -w "${ACME_WEBROOT}" -d "${host}" \
|
||||
# "${EXTRA_ARGS[@]}" "${CERTBOT_EXTRA[@]}" || true
|
||||
#}
|
||||
#
|
||||
## ------------------- Hauptlauf -------------------
|
||||
#if [[ "${BASE_DOMAIN}" != "example.com" ]]; then
|
||||
# issue "${UI_HOST:-}"
|
||||
# issue "${WEBMAIL_HOST:-}"
|
||||
# issue "${MAIL_HOSTNAME:-}"
|
||||
#
|
||||
# # Falls Deploy-Hook erst JETZT angelegt wurde: einmal manuell ausführen
|
||||
# if [[ -x /usr/local/sbin/mw-deploy.sh ]]; then
|
||||
# /usr/local/sbin/mw-deploy.sh || true
|
||||
# fi
|
||||
#
|
||||
# # Nginx nur neu laden, wenn aktiv
|
||||
# if systemctl is-active --quiet nginx; then
|
||||
# systemctl reload nginx || true
|
||||
# fi
|
||||
#else
|
||||
# echo "[i] BASE_DOMAIN=example.com – LE wird übersprungen."
|
||||
#fi
|
||||
|
||||
##!/usr/bin/env bash
|
||||
#set -euo pipefail
|
||||
#source ./lib.sh
|
||||
#
|
||||
#ACME_WEBROOT="/var/www/letsencrypt"
|
||||
#install -d -m 0755 "${ACME_WEBROOT}/.well-known/acme-challenge"
|
||||
#
|
||||
## Let's Encrypt: Staging optional aktivieren (keine echten Zertifikate)
|
||||
#CERTBOT_EXTRA=()
|
||||
#LE_STAGING="${LE_STAGING:-0}" # 1 = Staging
|
||||
#[[ "$LE_STAGING" = "1" ]] && CERTBOT_EXTRA+=(--test-cert)
|
||||
#
|
||||
## Einheitliche LE-E-Mail mit Fallback
|
||||
#LE_MAIL="${LE_EMAIL:-admin@${BASE_DOMAIN}}"
|
||||
#
|
||||
## DNS-Auflösung gegen unsere bekannte(n) IP(s) prüfen (nur als Warnsignal)
|
||||
#resolve_ok() {
|
||||
# local host="$1"
|
||||
# local pats=()
|
||||
# [[ -n "${SERVER_PUBLIC_IPV4:-}" ]] && pats+=("${SERVER_PUBLIC_IPV4//./\\.}")
|
||||
# [[ -n "${SERVER_PUBLIC_IPV6:-}" ]] && pats+=("${SERVER_PUBLIC_IPV6//:/\\:}")
|
||||
# [[ ${#pats[@]} -eq 0 ]] && return 0
|
||||
# getent ahosts "$host" | awk '{print $1}' | sort -u \
|
||||
# | grep -Eq "^($(IFS='|'; echo "${pats[*]}"))$"
|
||||
#}
|
||||
#
|
||||
## HTTP-01 Erreichbarkeit schnell antesten (IPv4/IPv6)
|
||||
#probe_http() {
|
||||
# local host="$1"
|
||||
# echo test > "${ACME_WEBROOT}/.well-known/acme-challenge/_probe"
|
||||
# curl -fsS --max-time 5 -4 "http://${host}/.well-known/acme-challenge/_probe" >/dev/null \
|
||||
# || curl -fsS --max-time 5 -6 "http://${host}/.well-known/acme-challenge/_probe" >/dev/null
|
||||
#}
|
||||
#
|
||||
## Ein Zertifikat für einen Host ausstellen
|
||||
#issue() {
|
||||
# local host="$1"
|
||||
# [[ -z "$host" ]] && return 0
|
||||
#
|
||||
# echo "[i] Versuche LE für ${host} …"
|
||||
#
|
||||
# if ! resolve_ok "$host"; then
|
||||
# echo "[!] DNS zeigt (noch) nicht hierher – überspringe: ${host}"
|
||||
# return 0
|
||||
# fi
|
||||
#
|
||||
# if ! probe_http "$host"; then
|
||||
# echo "[!] ACME-HTTP-Check für ${host} fehlgeschlagen (Port 80/IPv6/Firewall/Nginx prüfen)."
|
||||
# # wir versuchen es trotzdem – Certbot meldet sich, falls es scheitert
|
||||
# fi
|
||||
#
|
||||
# # Für MX den Key wiederverwenden (stabiler TLSA-Hash 3 1 1)
|
||||
# EXTRA_ARGS=()
|
||||
# [[ "${host}" == "${MAIL_HOSTNAME}" ]] && EXTRA_ARGS+=(--reuse-key)
|
||||
#
|
||||
# certbot certonly \
|
||||
# --agree-tos -m "${LE_MAIL}" --non-interactive \
|
||||
# --webroot -w "${ACME_WEBROOT}" -d "${host}" \
|
||||
# --deploy-hook /usr/local/sbin/mw-deploy.sh \
|
||||
# "${EXTRA_ARGS[@]}" "${CERTBOT_EXTRA[@]}" || true
|
||||
#}
|
||||
#
|
||||
## -----------------------------------------------------------------------------
|
||||
## Hauptlauf
|
||||
## -----------------------------------------------------------------------------
|
||||
#if [[ "${BASE_DOMAIN}" != "example.com" ]]; then
|
||||
# issue "${UI_HOST:-}"
|
||||
# issue "${WEBMAIL_HOST:-}"
|
||||
# issue "${MAIL_HOSTNAME:-}"
|
||||
#
|
||||
# # Der Deploy-Hook hat Symlinks bereits gesetzt und nginx ggf. neu geladen.
|
||||
# # Optional trotzdem manuell ausführen (harmlos, hilft bei exotischen Setups):
|
||||
# if [[ -d /etc/letsencrypt/renewal-hooks/deploy ]]; then
|
||||
# run-parts /etc/letsencrypt/renewal-hooks/deploy || true
|
||||
# fi
|
||||
# if systemctl is-active --quiet nginx; then
|
||||
# systemctl reload nginx || true
|
||||
# fi
|
||||
#else
|
||||
# echo "[i] BASE_DOMAIN=example.com – LE-Ausstellung wird übersprungen."
|
||||
#fi
|
||||
#
|
||||
|
||||
|
|
|
|||
|
|
@ -236,7 +236,7 @@ if [[ "${DKIM_ENABLE}" = "1" && -n "${SYSMAIL_DOMAIN}" ]]; then
|
|||
rm -f "$TMP_TXT" || true
|
||||
|
||||
# 3) OpenDKIM neu laden
|
||||
systemctl reload opendkim || systemctl restart opendkim || true
|
||||
touch /run/mailwolt.need-opendkim-reload || true
|
||||
else
|
||||
log "DKIM übersprungen (DKIM_ENABLE=${DKIM_ENABLE}, SYSMAIL_DOMAIN='${SYSMAIL_DOMAIN}')."
|
||||
fi
|
||||
|
|
@ -262,5 +262,5 @@ chown -R "$APP_USER":"$APP_GROUP" "$APP_DIR"
|
|||
chmod -R u=rwX,g=rwX,o=rX "$APP_DIR"
|
||||
install -d -m 0775 -o "$APP_USER" -g "$APP_GROUP" "$APP_DIR/storage" "$APP_DIR/bootstrap/cache"
|
||||
|
||||
relink_and_reload
|
||||
systemctl restart php*-fpm || true
|
||||
#relink_and_reload
|
||||
#systemctl restart php*-fpm || true
|
||||
|
|
|
|||
|
|
@ -94,14 +94,28 @@ fi
|
|||
systemctl enable --now ${APP_USER}-schedule
|
||||
systemctl enable --now ${APP_USER}-queue
|
||||
|
||||
# Webstack
|
||||
systemctl reload nginx || true
|
||||
systemctl restart php*-fpm || true
|
||||
# Mail-Dienste starten
|
||||
systemctl enable --now rspamd opendkim postfix dovecot || true
|
||||
|
||||
# Mail-Dienste JETZT starten (damit 25/465/587 offen sind)
|
||||
systemctl enable --now rspamd opendkim || true
|
||||
systemctl enable --now postfix
|
||||
systemctl enable --now dovecot
|
||||
# PHP-FPM: Unit erkennen, enable + (re)load
|
||||
enable_and_touch_php_fpm() {
|
||||
for u in php8.3-fpm php8.2-fpm php8.1-fpm php8.0-fpm php7.4-fpm php-fpm; do
|
||||
if systemctl list-unit-files | grep -q "^${u}\.service"; then
|
||||
systemctl enable --now "$u" || true
|
||||
systemctl reload "$u" || systemctl restart "$u" || true
|
||||
echo "[i] PHP-FPM unit: $u"
|
||||
return 0
|
||||
fi
|
||||
done
|
||||
echo "[!] Keine passende php-fpm Unit gefunden."
|
||||
}
|
||||
enable_and_touch_php_fpm
|
||||
|
||||
# Falls in 80-app.sh DKIM installiert wurde: jetzt einmal reloaden
|
||||
if [[ -e /run/mailwolt.need-opendkim-reload ]]; then
|
||||
systemctl reload opendkim || true
|
||||
rm -f /run/mailwolt.need-opendkim-reload || true
|
||||
fi
|
||||
|
||||
# Falls DB-Migration schon durch: einmal reload
|
||||
db_ready(){ mysql -u"${DB_USER}" -p"${DB_PASS}" -h 127.0.0.1 -D "${DB_NAME}" -e "SHOW TABLES LIKE 'migrations'\G" >/dev/null 2>&1; }
|
||||
|
|
|
|||
|
|
@ -40,4 +40,8 @@ chmod 600 /etc/monit/monitrc
|
|||
monit -t && systemctl enable --now monit
|
||||
monit reload || true
|
||||
|
||||
log "[✓] Monit konfiguriert und gestartet"
|
||||
log "[✓] Monit konfiguriert und gestartet"
|
||||
|
||||
# ── mailwolt-update ins System kopieren ─────────────────────────────
|
||||
install -m 0750 -o root -g root scripts/update.sh /usr/local/sbin/mailwolt-update
|
||||
log "[✓] mailwolt-update installiert → ausführbar via 'sudo mailwolt-update'"
|
||||
|
|
@ -0,0 +1,175 @@
|
|||
#!/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/mw-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/mw-redis-ping.sh
|
||||
|
||||
cat >/usr/local/sbin/mw-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
|
||||
|
||||
# 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 failed program "/usr/local/sbin/mw-redis-ping.sh" for 2 cycles then restart
|
||||
if 5 restarts within 5 cycles then alert
|
||||
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/mw-rspamd-heal.sh"
|
||||
if failed port 11334 for 2 cycles then exec "/usr/local/sbin/mw-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 does not exist file "/run/opendkim/opendkim.pid" 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
|
||||
woltguard status || true
|
||||
log "[✓] WoltGuard aktiv."
|
||||
|
|
@ -4,130 +4,134 @@ source ./lib.sh
|
|||
|
||||
log "MOTD installieren …"
|
||||
install -d /usr/local/bin
|
||||
|
||||
cat >/usr/local/bin/mw-motd <<'SH'
|
||||
#!/usr/bin/env bash
|
||||
# bewusst KEIN "set -e"; MOTD soll nie hart abbrechen
|
||||
# MOTD – MailWolt
|
||||
# bewusst KEIN "set -e" und KEIN pipefail; MOTD darf nie hart abbrechen
|
||||
set -u
|
||||
|
||||
# Farben
|
||||
NC="\033[0m"; CY="\033[1;36m"; GR="\033[1;32m"; YE="\033[1;33m"; RD="\033[1;31m"; GY="\033[0;90m"; WH="\033[1;37m"
|
||||
# ---------- Farben ----------
|
||||
NC="\033[0m"; WH="\033[1;37m"; CY="\033[1;36m"; GY="\033[0;90m"
|
||||
GR="\033[1;32m"; YE="\033[1;33m"; RD="\033[1;31m"
|
||||
|
||||
# Installer-Variablen (optional)
|
||||
UI_HOST=""; WEBMAIL_HOST=""; MAIL_HOSTNAME=""; LE_EMAIL=""; PROXY_MODE=""; NPM_IP=""
|
||||
# ---------- Breite / Zentrierung ----------
|
||||
W=110
|
||||
term_cols=$(tput cols 2>/dev/null || echo $W)
|
||||
[ "$term_cols" -gt "$W" ] && pad=$(( (term_cols - W)/2 )) || pad=0
|
||||
sp(){ [ "$1" -gt 0 ] && printf "%${1}s" " " || true; }
|
||||
center() { local s="$1"; local n=$(( (W - ${#s})/2 )); sp $((pad+n)); printf "%s\n" "$s"; }
|
||||
rule(){ sp "$pad"; printf "%0.s=" $(seq 1 "$W"); printf "\n"; }
|
||||
title(){ sp "$pad"; local t="$1"; local lf=$(( (W - ${#t} - 2)/2 )); local rf=$(( W - ${#t} - 2 - lf )); \
|
||||
printf "%s" "$(printf '─%.0s' $(seq 1 $lf))"; printf " %s " "$t"; printf "%s\n" "$(printf '─%.0s' $(seq 1 $rf))"; }
|
||||
kv(){ sp "$pad"; printf "%-12s: %s\n" "$1" "$2"; }
|
||||
|
||||
# ---------- Installer-/App-Variablen ----------
|
||||
UI_HOST=""; WEBMAIL_HOST=""; MAIL_HOSTNAME=""
|
||||
[ -r /etc/mailwolt/installer.env ] && . /etc/mailwolt/installer.env || true
|
||||
# Aus .env (falls vorhanden)
|
||||
if [ -r /var/www/mailwolt/.env ]; then
|
||||
LE_EMAIL="${LE_EMAIL:-$(grep -E '^LE_EMAIL=' /var/www/mailwolt/.env 2>/dev/null | sed 's/^LE_EMAIL=//')}"
|
||||
PROXY_MODE="${PROXY_MODE:-$(grep -E '^PROXY_MODE=' /var/www/mailwolt/.env 2>/dev/null | sed 's/^PROXY_MODE=//')}"
|
||||
NPM_IP="${NPM_IP:-$(grep -E '^NPM_IP=' /var/www/mailwolt/.env 2>/dev/null | sed 's/^NPM_IP=//')}"
|
||||
fi
|
||||
|
||||
# Header
|
||||
printf "${CY}"
|
||||
cat <<'ASCII'
|
||||
:::: :::: ::: ::::::::::: ::: ::: ::: :::::::: ::: :::::::::::
|
||||
+:+:+: :+:+:+ :+: :+: :+: :+: :+: :+: :+: :+: :+: :+:
|
||||
+:+ +:+:+ +:+ +:+ +:+ +:+ +:+ +:+ +:+ +:+ +:+ +:+ +:+
|
||||
+#+ +:+ +#+ +#++:++#++: +#+ +#+ +#+ +:+ +#+ +#+ +:+ +#+ +#+
|
||||
+#+ +#+ +#+ +#+ +#+ +#+ +#+ +#+#+ +#+ +#+ +#+ +#+ +#+
|
||||
#+# #+# #+# #+# #+# #+# #+#+# #+#+# #+# #+# #+# #+#
|
||||
### ### ### ### ########### ########## ### ### ######## ########## ###
|
||||
ASCII
|
||||
printf "${NC}\n"
|
||||
# ---------- Systemdaten ----------
|
||||
now="$(date '+%Y-%m-%d %H:%M:%S %Z' 2>/dev/null || echo '-')"
|
||||
upt="$(uptime -p 2>/dev/null || echo '-')"
|
||||
cores="$(nproc 2>/dev/null || echo 1)"
|
||||
load_raw="$(awk '{printf "%s / %s / %s",$1,$2,$3}' /proc/loadavg 2>/dev/null || echo '0.00 / 0.00 / 0.00')"
|
||||
load1="$(awk '{print $1}' /proc/loadavg 2>/dev/null || echo 0)"
|
||||
|
||||
# Safe-Helfer (niemals Script killen)
|
||||
grab() { eval "$1" 2>/dev/null || true; }
|
||||
line() { printf "${GY}%-7s:${NC} %s\n" "$1" "$2"; }
|
||||
# RAM/SWAP
|
||||
mem_total="$(awk '/MemTotal/ {print int($2/1024)}' /proc/meminfo 2>/dev/null || echo 0)"
|
||||
mem_avail="$(awk '/MemAvailable/ {print int($2/1024)}' /proc/meminfo 2>/dev/null || echo 0)"
|
||||
mem_used=$(( mem_total - mem_avail ))
|
||||
swap_total="$(awk '/SwapTotal/ {print int($2/1024)}' /proc/meminfo 2>/dev/null || echo 0)"
|
||||
swap_free="$(awk '/SwapFree/ {print int($2/1024)}' /proc/meminfo 2>/dev/null || echo 0)"
|
||||
swap_used=$(( swap_total - swap_free ))
|
||||
|
||||
# Systemdaten
|
||||
now="$(date '+%Y-%m-%d %H:%M:%S %Z' 2>/dev/null || echo -n '-')"
|
||||
fqdn="$(hostname -f 2>/dev/null || hostname 2>/dev/null || echo -n '-')"
|
||||
ip_int="$(hostname -I 2>/dev/null | awk '{print $1}' 2>/dev/null || true)"
|
||||
ip_ext="$(curl -fsS --max-time 1 https://ifconfig.me 2>/dev/null || true)"
|
||||
upt="$(uptime -p 2>/dev/null || echo -n '-')"
|
||||
cores="$(nproc 2>/dev/null || echo -n '-')"
|
||||
load="$(awk '{print $1" / "$2" / "$3}' /proc/loadavg 2>/dev/null || echo -n '-')"
|
||||
|
||||
# RAM/SWAP (MiB)
|
||||
mem_total="$(awk '/MemTotal/ {print int($2/1024)}' /proc/meminfo 2>/dev/null || echo -n '-')"
|
||||
mem_avail="$(awk '/MemAvailable/ {print int($2/1024)}' /proc/meminfo 2>/dev/null || echo -n '0')"
|
||||
mem_used=$(( ${mem_total:-0}-${mem_avail:-0} ))
|
||||
swap_total="$(awk '/SwapTotal/ {print int($2/1024)}' /proc/meminfo 2>/dev/null || echo -n '-')"
|
||||
swap_free="$(awk '/SwapFree/ {print int($2/1024)}' /proc/meminfo 2>/dev/null || echo -n '0')"
|
||||
swap_used=$(( ${swap_total:-0}-${swap_free:-0} ))
|
||||
pct(){ local u="$1" t="$2"; [ "$t" -gt 0 ] || { echo 0; return; }; awk -v u="$u" -v t="$t" 'BEGIN{printf "%d",(u*100)/t}' ; }
|
||||
ram_pct=$(pct "$mem_used" "$mem_total")
|
||||
swap_pct=$(pct "$swap_used" "$swap_total")
|
||||
|
||||
# Disks
|
||||
disk_line(){ df -hP "$1" 2>/dev/null | awk 'NR==2{printf "%s/%s (%s used)", $3,$2,$5}'; }
|
||||
disk_root="$(disk_line /)"
|
||||
disk_var="$(disk_line /var)"
|
||||
df_line(){ df -hP "$1" 2>/dev/null | awk 'NR==2{printf "%s / %s (%s)",$3,$2,$5}'; }
|
||||
df_pct(){ df -P "$1" 2>/dev/null | awk 'NR==2{gsub("%","",$5);print $5+0}'; }
|
||||
disk_root="$(df_line /)"; pct_root="$(df_pct /)"
|
||||
disk_var="$(df_line /var 2>/dev/null)"; [ -n "$disk_var" ] || disk_var="-"
|
||||
pct_var="$(df_pct /var 2>/dev/null)"; [ -n "$pct_var" ] || pct_var=0
|
||||
|
||||
svc_state(){
|
||||
local unit="$1"
|
||||
if systemctl is-active --quiet "$unit"; then
|
||||
printf "${GR}OK${NC}"
|
||||
else
|
||||
printf "${RD}FAIL${NC}"
|
||||
# IPs (int/ext)
|
||||
ipv4_int="$(hostname -I 2>/dev/null | awk '{for(i=1;i<=NF;i++) if($i!~/:/){print $i;exit}}')"
|
||||
ipv6_int="$(hostname -I 2>/dev/null | awk '{for(i=1;i<=NF;i++) if($i~/:/){print $i;exit}}')"
|
||||
ipv4_ext="$(curl -4fsS --max-time 1 https://ifconfig.me 2>/dev/null || true)"
|
||||
ipv6_ext="$(curl -6fsS --max-time 1 https://ifconfig.me 2>/dev/null || true)"
|
||||
|
||||
# ---------- Status-Farben ----------
|
||||
mark(){ # value thresholdY thresholdR
|
||||
local v="$1" y="$2" r="$3"
|
||||
if [ "$v" -ge "$r" ]; then printf "${RD}[HIGH]${NC}"
|
||||
elif [ "$v" -ge "$y" ]; then printf "${YE}[WARN]${NC}"
|
||||
else printf "${GR}[OK]${NC}"
|
||||
fi
|
||||
}
|
||||
# Load/CPU-Schwellen (pro Core)
|
||||
load_pct=$(awk -v l="$load1" -v c="$cores" 'BEGIN{if(c<1)c=1; printf "%d", (l/c)*100}')
|
||||
m_load="$(mark "$load_pct" 70 100)"
|
||||
m_ram="$(mark "$ram_pct" 75 90)"
|
||||
m_swap="$(mark "$swap_pct" 10 50)"
|
||||
m_root="$(mark "$pct_root" 75 90)"
|
||||
m_var="$(mark "$pct_var" 75 90)"
|
||||
|
||||
# Ausgabe
|
||||
printf "${CY}Information as of:${NC} ${YE}%s${NC}\n" "$now"
|
||||
line "FQDN" "$fqdn"
|
||||
if [ -n "$ip_ext" ]; then
|
||||
printf "${GY}%-7s:${NC} %s ${GY}(ext:${NC} %s${GY})${NC}\n" "IP" "${ip_int:--}" "$ip_ext"
|
||||
else
|
||||
line "IP" "${ip_int:--}"
|
||||
fi
|
||||
line "Uptime" "$upt"
|
||||
printf "${GY}%-7s:${NC} %s cores, load %s (1/5/15)\n" "CPU" "$cores" "$load"
|
||||
printf "${GY}%-7s:${NC} %s MiB used / %s MiB total\n" "RAM" "$mem_used" "$mem_total"
|
||||
printf "${GY}%-7s:${NC} %s MiB used / %s MiB total\n" "SWAP" "$swap_used" "$swap_total"
|
||||
line "Disk /" "${disk_root:-'-'}"
|
||||
line "Disk/var" "${disk_var:-'-'}"
|
||||
# ---------- Header ----------
|
||||
rule
|
||||
center ""
|
||||
center ":::: :::: ::: ::::::::::: ::: ::: ::: :::::::: ::: :::::::::::"
|
||||
center ":+:+:+ :+:+:+ :+: :+: :+: :+: :+: :+: :+: :+: :+: :+: "
|
||||
center ":+: +:+:+ +:+ +:+ +:+ +:+ +:+ +:+ +:+ +:+ +:+ +:+ +:+ "
|
||||
center "+#+ +:+ +#+ +#++:++#++: +#+ +#+ +#+ +:+ +#+ +#+ +:+ +#+ +#+ "
|
||||
center "+#+ +#+ +#+ +#+ +#+ +#+ +#+ +#+#+ +#+ +#+ +#+ +#+ +#+ "
|
||||
center "#+# #+# #+# #+# #+# #+# #+#+# #+#+# #+# #+# #+# #+# "
|
||||
center "### ### ### ### ########### ########## ### ### ######## ########## ### "
|
||||
center ""
|
||||
rule
|
||||
|
||||
# App/Installer Infos
|
||||
[ -n "${LE_EMAIL:-}" ] && line "LE Mail" "$LE_EMAIL"
|
||||
[ -n "${UI_HOST:-}" ] && line "UI" "$UI_HOST"
|
||||
[ -n "${WEBMAIL_HOST:-}" ] && line "Webmail" "$WEBMAIL_HOST"
|
||||
[ -n "${MAIL_HOSTNAME:-}" ]&& line "MX" "$MAIL_HOSTNAME"
|
||||
if [ -n "${PROXY_MODE:-}" ]; then
|
||||
if [ "$PROXY_MODE" = "1" ]; then
|
||||
line "Proxy" "ja (NPM: ${NPM_IP:-unbekannt})"
|
||||
elif [ "$PROXY_MODE" = "dev" ]; then
|
||||
line "Proxy" "Entwicklungsmodus"
|
||||
else
|
||||
line "Proxy" "nein"
|
||||
fi
|
||||
fi
|
||||
# ---------- System ----------
|
||||
kv "Date / Time" "${YE}${now}${NC}"
|
||||
sp "$pad"; printf "%-12s: int %-40s ext %s\n" "IPv4" "${ipv4_int:--}" "${ipv4_ext:--}"
|
||||
sp "$pad"; printf "%-12s: int %-40s ext %s\n" "IPv6" "${ipv6_int:--}" "${ipv6_ext:--}"
|
||||
kv "Uptime" "$upt"
|
||||
sp "$pad"; printf "%-12s: %s cores, load %s %b\n" "CPU" "$cores" "$load_raw" "$m_load"
|
||||
sp "$pad"; printf "%-12s: %s MiB / %s MiB (%d%%) %b %-5s %s MiB / %s MiB (%d%%) %b\n" \
|
||||
"RAM" "$mem_used" "$mem_total" "$ram_pct" "$m_ram" "SWAP:" "$swap_used" "$swap_total" "$swap_pct" "$m_swap"
|
||||
sp "$pad"; printf "%-12s: / %s %b %-5s %s %b\n" \
|
||||
"Disk" "$disk_root" "$m_root" "/var:" "$disk_var" "$m_var"
|
||||
echo
|
||||
|
||||
# Services
|
||||
printf "${WH}\nServices:${NC}\n"
|
||||
printf " nginx … %b\n" "$(svc_state nginx)"
|
||||
printf " mariadb … %b\n" "$(svc_state mariadb)"
|
||||
printf " redis-server … %b\n" "$(svc_state redis-server)"
|
||||
printf " postfix … %b\n" "$(svc_state postfix)"
|
||||
printf " dovecot … %b\n" "$(svc_state dovecot)"
|
||||
printf " mailwolt-ws … %b\n" "$(svc_state mailwolt-ws)"
|
||||
printf " mailwolt-queue … %b\n" "$(svc_state mailwolt-queue)"
|
||||
printf " mailwolt-schedule … %b\n" "$(svc_state mailwolt-schedule)"
|
||||
# ---------- Domains ----------
|
||||
title "Domains"
|
||||
[ -n "${UI_HOST:-}" ] && kv "UI" "${UI_HOST}"
|
||||
[ -n "${WEBMAIL_HOST:-}" ] && kv "Webmail" "${WEBMAIL_HOST}"
|
||||
[ -n "${MAIL_HOSTNAME:-}" ]&& kv "MX" "${MAIL_HOSTNAME}"
|
||||
echo
|
||||
|
||||
# Zertifikatskurzinfo (nur wenn vorhanden)
|
||||
show_cert_exp(){
|
||||
local name="$1" path="$2"
|
||||
if [ -r "$path" ]; then
|
||||
local exp
|
||||
exp="$(openssl x509 -in "$path" -noout -enddate 2>/dev/null | sed 's/notAfter=//')"
|
||||
[ -n "$exp" ] && printf "${GY}%s cert:${NC} expires %s\n" "$name" "$exp"
|
||||
fi
|
||||
}
|
||||
show_cert_exp "UI" "/etc/ssl/ui/fullchain.pem"
|
||||
show_cert_exp "Webmail" "/etc/ssl/webmail/fullchain.pem"
|
||||
show_cert_exp "MX" "/etc/ssl/mail/fullchain.pem"
|
||||
# ---------- Services (4 Spalten, bündig) ----------
|
||||
title "Services"
|
||||
svc_state(){ systemctl is-active --quiet "$1" && printf "${GR}[OK]${NC}" || printf "${RD}[FAIL]${NC}"; }
|
||||
SVC=( nginx mariadb redis-server postfix dovecot rspamd opendkim opendmarc clamav-daemon fail2ban mailwolt-ws mailwolt-queue mailwolt-schedule )
|
||||
|
||||
i=0; line=""
|
||||
for s in "${SVC[@]}"; do
|
||||
st="$(svc_state "$s")"
|
||||
seg="$(printf "%-18s %-7s" "$s" "$st")"
|
||||
line="$line$seg"
|
||||
i=$((i+1))
|
||||
if [ $((i%4)) -eq 0 ]; then sp "$pad"; echo "$line"; line=""; else line="$line "; fi
|
||||
done
|
||||
[ -n "$line" ] && { sp "$pad"; echo "$line"; }
|
||||
echo
|
||||
|
||||
exit 0
|
||||
SH
|
||||
|
||||
chmod 755 /usr/local/bin/mw-motd
|
||||
|
||||
# update-motd Hook
|
||||
if [[ -d /etc/update-motd.d ]]; then
|
||||
cat >/etc/update-motd.d/10-mailwolt <<'SH'
|
||||
#!/usr/bin/env bash
|
||||
|
|
@ -136,47 +140,21 @@ SH
|
|||
chmod +x /etc/update-motd.d/10-mailwolt
|
||||
[[ -f /etc/update-motd.d/50-motd-news ]] && chmod -x /etc/update-motd.d/50-motd-news || true
|
||||
else
|
||||
# Fallback für Systeme ohne dynamic MOTD
|
||||
cat >/etc/profile.d/10-mailwolt-motd.sh <<'SH'
|
||||
case "$-" in *i*) /usr/local/bin/mw-motd ;; esac
|
||||
SH
|
||||
fi
|
||||
|
||||
: > /etc/motd 2>/dev/null || true
|
||||
log "[✓] MOTD installiert."
|
||||
|
||||
|
||||
|
||||
#cat >/usr/local/bin/mw-motd <<'SH'
|
||||
##!/usr/bin/env bash
|
||||
#set -euo pipefail
|
||||
#NC="\033[0m"; CY="\033[1;36m"; GR="\033[1;32m"; YE="\033[1;33m"; RD="\033[1;31m"; GY="\033[0;90m"
|
||||
#printf "\033[1;36m"
|
||||
#cat <<'ASCII'
|
||||
#:::: :::: ::: ::::::::::: ::: ::: ::: :::::::: ::: :::::::::::
|
||||
#+:+:+: :+:+:+ :+: :+: :+: :+: :+: :+: :+: :+: :+: :+:
|
||||
#+:+ +:+:+ +:+ +:+ +:+ +:+ +:+ +:+ +:+ +:+ +:+ +:+ +:+
|
||||
#+#+ +:+ +#+ +#++:++#++: +#+ +#+ +#+ +:+ +#+ +#+ +:+ +#+ +#+
|
||||
#+#+ +#+ +#+ +#+ +#+ +#+ +#+ +#+#+ +#+ +#+ +#+ +#+ +#+
|
||||
##+# #+# #+# #+# #+# #+# #+#+# #+#+# #+# #+# #+# #+#
|
||||
#### ### ### ### ########### ########## ### ### ######## ########## ###
|
||||
#ASCII
|
||||
#printf "\033[0m\n"
|
||||
#now="$(date '+%Y-%m-%d %H:%M:%S %Z')"
|
||||
#fqdn="$(hostname -f 2>/dev/null || hostname)"
|
||||
#ip_int="$(hostname -I 2>/dev/null | awk '{print $1}')"
|
||||
#ip_ext=""; command -v curl >/dev/null 2>&1 && ip_ext="$(curl -s --max-time 1 https://ifconfig.me || true)"
|
||||
#upt="$(uptime -p 2>/dev/null || true)"
|
||||
#cores="$(nproc 2>/dev/null || echo -n '?')"
|
||||
#load="$(awk '{print $1" / "$2" / "$3}' /proc/loadavg 2>/dev/null)"
|
||||
#svc(){ systemctl is-active --quiet "$1" && echo -e "${GR}OK${NC}" || echo -e "${RD}FAIL${NC}"; }
|
||||
#printf "${CY}Information as of:${NC} ${YE}%s${NC}\n" "$now"
|
||||
#printf "${GY}FQDN :${NC} %s\n" "$fqdn"
|
||||
#if [ -n "$ip_ext" ]; then printf "${GY}IP :${NC} %s ${GY}(ext:${NC} %s${GY})${NC}\n" "${ip_int:-?}" "$ip_ext"; else printf "${GY}IP :${NC} %s\n" "${ip_int:-?}"; fi
|
||||
#printf "${GY}Uptime :${NC} %s\n" "${upt:-?}"
|
||||
#printf "${GY}Cores :${NC} %s\n" "$cores"
|
||||
#printf "${GY}Load :${NC} %s (1/5/15)\n" "${load:-?}"
|
||||
#printf "${GY}Svc :${NC} postfix: $(svc postfix) dovecot: $(svc dovecot) nginx: $(svc nginx) mariadb: $(svc mariadb) redis: $(svc redis)\n"
|
||||
#SH
|
||||
#chmod +x /usr/local/bin/mw-motd
|
||||
|
||||
#source ./lib.sh
|
||||
#
|
||||
#log "MOTD installieren …"
|
||||
#install -d /usr/local/bin
|
||||
#cat >/usr/local/bin/mw-motd <<'SH'
|
||||
##!/usr/bin/env bash
|
||||
## bewusst KEIN "set -e"; MOTD soll nie hart abbrechen
|
||||
|
|
@ -198,6 +176,9 @@ fi
|
|||
## Header
|
||||
#printf "${CY}"
|
||||
#cat <<'ASCII'
|
||||
#
|
||||
#==========================================================================================
|
||||
#
|
||||
#:::: :::: ::: ::::::::::: ::: ::: ::: :::::::: ::: :::::::::::
|
||||
#+:+:+: :+:+:+ :+: :+: :+: :+: :+: :+: :+: :+: :+: :+:
|
||||
#+:+ +:+:+ +:+ +:+ +:+ +:+ +:+ +:+ +:+ +:+ +:+ +:+ +:+
|
||||
|
|
@ -205,6 +186,9 @@ fi
|
|||
#+#+ +#+ +#+ +#+ +#+ +#+ +#+ +#+#+ +#+ +#+ +#+ +#+ +#+
|
||||
##+# #+# #+# #+# #+# #+# #+#+# #+#+# #+# #+# #+# #+#
|
||||
#### ### ### ### ########### ########## ### ### ######## ########## ###
|
||||
#
|
||||
#==========================================================================================
|
||||
#
|
||||
#ASCII
|
||||
#printf "${NC}\n"
|
||||
#
|
||||
|
|
@ -299,4 +283,177 @@ fi
|
|||
#
|
||||
#exit 0
|
||||
#SH
|
||||
#chmod 755 /usr/local/bin/mw-motd
|
||||
#chmod 755 /usr/local/bin/mw-motd
|
||||
#
|
||||
#if [[ -d /etc/update-motd.d ]]; then
|
||||
# cat >/etc/update-motd.d/10-mailwolt <<'SH'
|
||||
##!/usr/bin/env bash
|
||||
#/usr/local/bin/mw-motd
|
||||
#SH
|
||||
# chmod +x /etc/update-motd.d/10-mailwolt
|
||||
# [[ -f /etc/update-motd.d/50-motd-news ]] && chmod -x /etc/update-motd.d/50-motd-news || true
|
||||
#else
|
||||
# cat >/etc/profile.d/10-mailwolt-motd.sh <<'SH'
|
||||
#case "$-" in *i*) /usr/local/bin/mw-motd ;; esac
|
||||
#SH
|
||||
#fi
|
||||
#: > /etc/motd 2>/dev/null || true
|
||||
#
|
||||
#
|
||||
#
|
||||
##cat >/usr/local/bin/mw-motd <<'SH'
|
||||
###!/usr/bin/env bash
|
||||
##set -euo pipefail
|
||||
##NC="\033[0m"; CY="\033[1;36m"; GR="\033[1;32m"; YE="\033[1;33m"; RD="\033[1;31m"; GY="\033[0;90m"
|
||||
##printf "\033[1;36m"
|
||||
##cat <<'ASCII'
|
||||
##:::: :::: ::: ::::::::::: ::: ::: ::: :::::::: ::: :::::::::::
|
||||
##+:+:+: :+:+:+ :+: :+: :+: :+: :+: :+: :+: :+: :+: :+:
|
||||
##+:+ +:+:+ +:+ +:+ +:+ +:+ +:+ +:+ +:+ +:+ +:+ +:+ +:+
|
||||
##+#+ +:+ +#+ +#++:++#++: +#+ +#+ +#+ +:+ +#+ +#+ +:+ +#+ +#+
|
||||
##+#+ +#+ +#+ +#+ +#+ +#+ +#+ +#+#+ +#+ +#+ +#+ +#+ +#+
|
||||
###+# #+# #+# #+# #+# #+# #+#+# #+#+# #+# #+# #+# #+#
|
||||
##### ### ### ### ########### ########## ### ### ######## ########## ###
|
||||
##ASCII
|
||||
##printf "\033[0m\n"
|
||||
##now="$(date '+%Y-%m-%d %H:%M:%S %Z')"
|
||||
##fqdn="$(hostname -f 2>/dev/null || hostname)"
|
||||
##ip_int="$(hostname -I 2>/dev/null | awk '{print $1}')"
|
||||
##ip_ext=""; command -v curl >/dev/null 2>&1 && ip_ext="$(curl -s --max-time 1 https://ifconfig.me || true)"
|
||||
##upt="$(uptime -p 2>/dev/null || true)"
|
||||
##cores="$(nproc 2>/dev/null || echo -n '?')"
|
||||
##load="$(awk '{print $1" / "$2" / "$3}' /proc/loadavg 2>/dev/null)"
|
||||
##svc(){ systemctl is-active --quiet "$1" && echo -e "${GR}OK${NC}" || echo -e "${RD}FAIL${NC}"; }
|
||||
##printf "${CY}Information as of:${NC} ${YE}%s${NC}\n" "$now"
|
||||
##printf "${GY}FQDN :${NC} %s\n" "$fqdn"
|
||||
##if [ -n "$ip_ext" ]; then printf "${GY}IP :${NC} %s ${GY}(ext:${NC} %s${GY})${NC}\n" "${ip_int:-?}" "$ip_ext"; else printf "${GY}IP :${NC} %s\n" "${ip_int:-?}"; fi
|
||||
##printf "${GY}Uptime :${NC} %s\n" "${upt:-?}"
|
||||
##printf "${GY}Cores :${NC} %s\n" "$cores"
|
||||
##printf "${GY}Load :${NC} %s (1/5/15)\n" "${load:-?}"
|
||||
##printf "${GY}Svc :${NC} postfix: $(svc postfix) dovecot: $(svc dovecot) nginx: $(svc nginx) mariadb: $(svc mariadb) redis: $(svc redis)\n"
|
||||
##SH
|
||||
##chmod +x /usr/local/bin/mw-motd
|
||||
#
|
||||
##cat >/usr/local/bin/mw-motd <<'SH'
|
||||
###!/usr/bin/env bash
|
||||
### bewusst KEIN "set -e"; MOTD soll nie hart abbrechen
|
||||
##set -u
|
||||
##
|
||||
### Farben
|
||||
##NC="\033[0m"; CY="\033[1;36m"; GR="\033[1;32m"; YE="\033[1;33m"; RD="\033[1;31m"; GY="\033[0;90m"; WH="\033[1;37m"
|
||||
##
|
||||
### Installer-Variablen (optional)
|
||||
##UI_HOST=""; WEBMAIL_HOST=""; MAIL_HOSTNAME=""; LE_EMAIL=""; PROXY_MODE=""; NPM_IP=""
|
||||
##[ -r /etc/mailwolt/installer.env ] && . /etc/mailwolt/installer.env || true
|
||||
### Aus .env (falls vorhanden)
|
||||
##if [ -r /var/www/mailwolt/.env ]; then
|
||||
## LE_EMAIL="${LE_EMAIL:-$(grep -E '^LE_EMAIL=' /var/www/mailwolt/.env 2>/dev/null | sed 's/^LE_EMAIL=//')}"
|
||||
## PROXY_MODE="${PROXY_MODE:-$(grep -E '^PROXY_MODE=' /var/www/mailwolt/.env 2>/dev/null | sed 's/^PROXY_MODE=//')}"
|
||||
## NPM_IP="${NPM_IP:-$(grep -E '^NPM_IP=' /var/www/mailwolt/.env 2>/dev/null | sed 's/^NPM_IP=//')}"
|
||||
##fi
|
||||
##
|
||||
### Header
|
||||
##printf "${CY}"
|
||||
##cat <<'ASCII'
|
||||
##:::: :::: ::: ::::::::::: ::: ::: ::: :::::::: ::: :::::::::::
|
||||
##+:+:+: :+:+:+ :+: :+: :+: :+: :+: :+: :+: :+: :+: :+:
|
||||
##+:+ +:+:+ +:+ +:+ +:+ +:+ +:+ +:+ +:+ +:+ +:+ +:+ +:+
|
||||
##+#+ +:+ +#+ +#++:++#++: +#+ +#+ +#+ +:+ +#+ +#+ +:+ +#+ +#+
|
||||
##+#+ +#+ +#+ +#+ +#+ +#+ +#+ +#+#+ +#+ +#+ +#+ +#+ +#+
|
||||
###+# #+# #+# #+# #+# #+# #+#+# #+#+# #+# #+# #+# #+#
|
||||
##### ### ### ### ########### ########## ### ### ######## ########## ###
|
||||
##ASCII
|
||||
##printf "${NC}\n"
|
||||
##
|
||||
### Safe-Helfer (niemals Script killen)
|
||||
##grab() { eval "$1" 2>/dev/null || true; }
|
||||
##line() { printf "${GY}%-7s:${NC} %s\n" "$1" "$2"; }
|
||||
##
|
||||
### Systemdaten
|
||||
##now="$(date '+%Y-%m-%d %H:%M:%S %Z' 2>/dev/null || echo -n '-')"
|
||||
##fqdn="$(hostname -f 2>/dev/null || hostname 2>/dev/null || echo -n '-')"
|
||||
##ip_int="$(hostname -I 2>/dev/null | awk '{print $1}' 2>/dev/null || true)"
|
||||
##ip_ext="$(curl -fsS --max-time 1 https://ifconfig.me 2>/dev/null || true)"
|
||||
##upt="$(uptime -p 2>/dev/null || echo -n '-')"
|
||||
##cores="$(nproc 2>/dev/null || echo -n '-')"
|
||||
##load="$(awk '{print $1" / "$2" / "$3}' /proc/loadavg 2>/dev/null || echo -n '-')"
|
||||
##
|
||||
### RAM/SWAP (MiB)
|
||||
##mem_total="$(awk '/MemTotal/ {print int($2/1024)}' /proc/meminfo 2>/dev/null || echo -n '-')"
|
||||
##mem_avail="$(awk '/MemAvailable/ {print int($2/1024)}' /proc/meminfo 2>/dev/null || echo -n '0')"
|
||||
##mem_used=$(( ${mem_total:-0}-${mem_avail:-0} ))
|
||||
##swap_total="$(awk '/SwapTotal/ {print int($2/1024)}' /proc/meminfo 2>/dev/null || echo -n '-')"
|
||||
##swap_free="$(awk '/SwapFree/ {print int($2/1024)}' /proc/meminfo 2>/dev/null || echo -n '0')"
|
||||
##swap_used=$(( ${swap_total:-0}-${swap_free:-0} ))
|
||||
##
|
||||
### Disks
|
||||
##disk_line(){ df -hP "$1" 2>/dev/null | awk 'NR==2{printf "%s/%s (%s used)", $3,$2,$5}'; }
|
||||
##disk_root="$(disk_line /)"
|
||||
##disk_var="$(disk_line /var)"
|
||||
##
|
||||
##svc_state(){
|
||||
## local unit="$1"
|
||||
## if systemctl is-active --quiet "$unit"; then
|
||||
## printf "${GR}OK${NC}"
|
||||
## else
|
||||
## printf "${RD}FAIL${NC}"
|
||||
## fi
|
||||
##}
|
||||
##
|
||||
### Ausgabe
|
||||
##printf "${CY}Information as of:${NC} ${YE}%s${NC}\n" "$now"
|
||||
##line "FQDN" "$fqdn"
|
||||
##if [ -n "$ip_ext" ]; then
|
||||
## printf "${GY}%-7s:${NC} %s ${GY}(ext:${NC} %s${GY})${NC}\n" "IP" "${ip_int:--}" "$ip_ext"
|
||||
##else
|
||||
## line "IP" "${ip_int:--}"
|
||||
##fi
|
||||
##line "Uptime" "$upt"
|
||||
##printf "${GY}%-7s:${NC} %s cores, load %s (1/5/15)\n" "CPU" "$cores" "$load"
|
||||
##printf "${GY}%-7s:${NC} %s MiB used / %s MiB total\n" "RAM" "$mem_used" "$mem_total"
|
||||
##printf "${GY}%-7s:${NC} %s MiB used / %s MiB total\n" "SWAP" "$swap_used" "$swap_total"
|
||||
##line "Disk /" "${disk_root:-'-'}"
|
||||
##line "Disk/var" "${disk_var:-'-'}"
|
||||
##
|
||||
### App/Installer Infos
|
||||
##[ -n "${LE_EMAIL:-}" ] && line "LE Mail" "$LE_EMAIL"
|
||||
##[ -n "${UI_HOST:-}" ] && line "UI" "$UI_HOST"
|
||||
##[ -n "${WEBMAIL_HOST:-}" ] && line "Webmail" "$WEBMAIL_HOST"
|
||||
##[ -n "${MAIL_HOSTNAME:-}" ]&& line "MX" "$MAIL_HOSTNAME"
|
||||
##if [ -n "${PROXY_MODE:-}" ]; then
|
||||
## if [ "$PROXY_MODE" = "1" ]; then
|
||||
## line "Proxy" "ja (NPM: ${NPM_IP:-unbekannt})"
|
||||
## elif [ "$PROXY_MODE" = "dev" ]; then
|
||||
## line "Proxy" "Entwicklungsmodus"
|
||||
## else
|
||||
## line "Proxy" "nein"
|
||||
## fi
|
||||
##fi
|
||||
##
|
||||
### Services
|
||||
##printf "${WH}\nServices:${NC}\n"
|
||||
##printf " nginx … %b\n" "$(svc_state nginx)"
|
||||
##printf " mariadb … %b\n" "$(svc_state mariadb)"
|
||||
##printf " redis-server … %b\n" "$(svc_state redis-server)"
|
||||
##printf " postfix … %b\n" "$(svc_state postfix)"
|
||||
##printf " dovecot … %b\n" "$(svc_state dovecot)"
|
||||
##printf " mailwolt-ws … %b\n" "$(svc_state mailwolt-ws)"
|
||||
##printf " mailwolt-queue … %b\n" "$(svc_state mailwolt-queue)"
|
||||
##printf " mailwolt-schedule … %b\n" "$(svc_state mailwolt-schedule)"
|
||||
##
|
||||
### Zertifikatskurzinfo (nur wenn vorhanden)
|
||||
##show_cert_exp(){
|
||||
## local name="$1" path="$2"
|
||||
## if [ -r "$path" ]; then
|
||||
## local exp
|
||||
## exp="$(openssl x509 -in "$path" -noout -enddate 2>/dev/null | sed 's/notAfter=//')"
|
||||
## [ -n "$exp" ] && printf "${GY}%s cert:${NC} expires %s\n" "$name" "$exp"
|
||||
## fi
|
||||
##}
|
||||
##show_cert_exp "UI" "/etc/ssl/ui/fullchain.pem"
|
||||
##show_cert_exp "Webmail" "/etc/ssl/webmail/fullchain.pem"
|
||||
##show_cert_exp "MX" "/etc/ssl/mail/fullchain.pem"
|
||||
##
|
||||
##exit 0
|
||||
##SH
|
||||
##chmod 755 /usr/local/bin/mw-motd
|
||||
|
|
@ -1,11 +1,13 @@
|
|||
#!/usr/bin/env bash
|
||||
set -euo pipefail
|
||||
|
||||
# --- Flags / Modi ---
|
||||
# ──────────────────────────────────────────────────────────────
|
||||
# MailWolt – Interaktiver Bootstrap (whiptail + Fallback)
|
||||
# ──────────────────────────────────────────────────────────────
|
||||
|
||||
DEV_MODE=0
|
||||
PROXY_MODE=0
|
||||
NPM_IP=""
|
||||
|
||||
while [[ $# -gt 0 ]]; do
|
||||
case "$1" in
|
||||
-dev) DEV_MODE=1 ;;
|
||||
|
|
@ -15,12 +17,11 @@ while [[ $# -gt 0 ]]; do
|
|||
done
|
||||
|
||||
APP_ENV="${APP_ENV:-$([[ $DEV_MODE -eq 1 ]] && echo local || echo production)}"
|
||||
APP_DEBUG="${APP_DEBUG:-$([[ $DEV_MODE -eq 1 ]] && echo true || echo false)}"
|
||||
APP_DEBUG="${APP_DEBUG:-$([[ $DEV_MODE -eq 1 ]] && echo true || echo false)}"
|
||||
export DEV_MODE PROXY_MODE NPM_IP APP_ENV APP_DEBUG
|
||||
|
||||
DB_PASS="${DB_PASS:-$(openssl rand -hex 16)}"
|
||||
REDIS_PASS="${REDIS_PASS:-$(openssl rand -hex 16)}"
|
||||
|
||||
export DB_PASS REDIS_PASS
|
||||
|
||||
cd "$(dirname "$0")"
|
||||
|
|
@ -28,7 +29,7 @@ source ./lib.sh
|
|||
require_root
|
||||
header
|
||||
|
||||
# ── Defaults ────────────────────────────────────────────────────────────────
|
||||
# ── Defaults ──────────────────────────────────────────────────
|
||||
APP_NAME="${APP_NAME:-MailWolt}"
|
||||
APP_USER="${APP_USER:-mailwolt}"
|
||||
APP_GROUP="${APP_GROUP:-www-data}"
|
||||
|
|
@ -50,49 +51,109 @@ DEFAULT_LOCALE="$(guess_locale_from_tz "$DEFAULT_TZ")"
|
|||
|
||||
echo -e "${GREY}Erkannte IP (v4): ${SERVER_PUBLIC_IPV4} v6: ${SERVER_PUBLIC_IPV6:-–}${NC}"
|
||||
|
||||
# ── FQDNs abfragen ───────────────────────────────────────────────────────────
|
||||
read -r -p "Mailserver FQDN (MX, z.B. mx.domain.tld) [Enter=${MTA_SUB}.${BASE_DOMAIN}]: " MTA_FQDN
|
||||
read -r -p "UI / Admin-Panel FQDN (z.B. ui.domain.tld) [Enter=${UI_SUB}.${BASE_DOMAIN}]: " UI_FQDN
|
||||
read -r -p "Webmail FQDN (z.B. webmail.domain.tld) [Enter=${WEBMAIL_SUB}.${BASE_DOMAIN}]: " WEBMAIL_FQDN
|
||||
# ── Helpers ───────────────────────────────────────────────────
|
||||
have_whiptail(){ command -v whiptail >/dev/null 2>&1; }
|
||||
valid_fqdn(){
|
||||
[[ "$1" =~ ^([a-z0-9]([-a-z0-9]*[a-z0-9])?\.)+[a-z]{2,}$ ]]
|
||||
}
|
||||
ask_tty_domain(){
|
||||
local label="$1" example="$2" def="$3" outvar="$4" inp
|
||||
echo -e "${CYAN}${label}${NC}"
|
||||
echo -e " z.B. ${YELLOW}${example}${NC}"
|
||||
echo -e " Default: ${GREY}${def}${NC}"
|
||||
read -r -p " Eingabe (Enter=Default): " inp || true
|
||||
inp="${inp:-$def}"
|
||||
if ! valid_fqdn "$inp"; then
|
||||
echo -e "${YELLOW}[!] Ungültiger FQDN, nehme Default: ${def}${NC}"
|
||||
inp="$def"
|
||||
fi
|
||||
eval "$outvar='$inp'"
|
||||
}
|
||||
|
||||
# Defaults, wenn Enter gedrückt
|
||||
MTA_FQDN="${MTA_FQDN:-${MTA_SUB}.${BASE_DOMAIN}}"
|
||||
UI_FQDN="${UI_FQDN:-${UI_SUB}.${BASE_DOMAIN}}"
|
||||
WEBMAIL_FQDN="${WEBMAIL_FQDN:-${WEBMAIL_SUB}.${BASE_DOMAIN}}"
|
||||
# ── Interaktive Eingaben (whiptail oder Fallback) ─────────────
|
||||
MTA_DEFAULT="${MTA_SUB}.${BASE_DOMAIN}"
|
||||
UI_DEFAULT="${UI_SUB}.${BASE_DOMAIN}"
|
||||
WEBMAIL_DEFAULT="${WEBMAIL_SUB}.${BASE_DOMAIN}"
|
||||
|
||||
CLAMAV_ENABLE=1
|
||||
OPENDMARC_ENABLE=1
|
||||
FAIL2BAN_ENABLE=1
|
||||
|
||||
if have_whiptail; then
|
||||
TITLE="MailWolt Setup"
|
||||
|
||||
MTA_FQDN="$(whiptail --title "$TITLE" --inputbox "Mailserver-FQDN (MX)\nBeispiel: mx.domain.tld" 11 70 "$MTA_DEFAULT" 3>&1 1>&2 2>&3)" || exit 1
|
||||
valid_fqdn "$MTA_FQDN" || MTA_FQDN="$MTA_DEFAULT"
|
||||
|
||||
UI_FQDN="$(whiptail --title "$TITLE" --inputbox "UI / Admin-Panel FQDN\nBeispiel: ui.domain.tld" 11 70 "$UI_DEFAULT" 3>&1 1>&2 2>&3)" || exit 1
|
||||
valid_fqdn "$UI_FQDN" || UI_FQDN="$UI_DEFAULT"
|
||||
|
||||
WEBMAIL_FQDN="$(whiptail --title "$TITLE" --inputbox "Webmail FQDN\nBeispiel: webmail.domain.tld" 11 70 "$WEBMAIL_DEFAULT" 3>&1 1>&2 2>&3)" || exit 1
|
||||
valid_fqdn "$WEBMAIL_FQDN" || WEBMAIL_FQDN="$WEBMAIL_DEFAULT"
|
||||
|
||||
CHOICES="$(whiptail --title "$TITLE" --checklist "Optionale Dienste aktivieren" 15 70 6 \
|
||||
"ClamAV" "Virenscan (clamd/clamav-daemon)" ON \
|
||||
"OpenDMARC" "DMARC-Auswertung" ON \
|
||||
"Fail2Ban" "Brute-Force-Schutz" ON \
|
||||
3>&1 1>&2 2>&3)" || true
|
||||
|
||||
CLAMAV_ENABLE=0; [[ "$CHOICES" == *"ClamAV"* ]] && CLAMAV_ENABLE=1
|
||||
OPENDMARC_ENABLE=0; [[ "$CHOICES" == *"OpenDMARC"* ]] && OPENDMARC_ENABLE=1
|
||||
FAIL2BAN_ENABLE=0; [[ "$CHOICES" == *"Fail2Ban"* ]] && FAIL2BAN_ENABLE=1
|
||||
|
||||
whiptail --title "$TITLE" --msgbox "Zusammenfassung:
|
||||
|
||||
MX : $MTA_FQDN
|
||||
UI : $UI_FQDN
|
||||
Webmail : $WEBMAIL_FQDN
|
||||
|
||||
ClamAV : $([[ $CLAMAV_ENABLE -eq 1 ]] && echo Aktiv || echo Deaktiv)
|
||||
OpenDMARC : $([[ $OPENDMARC_ENABLE -eq 1 ]] && echo Aktiv || echo Deaktiv)
|
||||
Fail2Ban : $([[ $FAIL2BAN_ENABLE -eq 1 ]] && echo Aktiv || echo Deaktiv)
|
||||
" 16 70
|
||||
|
||||
else
|
||||
echo -e "${GREY}[i] whiptail nicht gefunden – nutze TTY-Prompts.${NC}\n"
|
||||
ask_tty_domain "Mailserver-FQDN (MX)" "mx.domain.tld" "$MTA_DEFAULT" MTA_FQDN
|
||||
ask_tty_domain "UI / Admin-Panel FQDN" "ui.domain.tld" "$UI_DEFAULT" UI_FQDN
|
||||
ask_tty_domain "Webmail FQDN" "webmail.domain.tld" "$WEBMAIL_DEFAULT" WEBMAIL_FQDN
|
||||
|
||||
read -r -p "ClamAV aktivieren? (1/0, Enter=1): " CLAMAV_ENABLE; CLAMAV_ENABLE="${CLAMAV_ENABLE:-1}"
|
||||
read -r -p "OpenDMARC aktivieren? (1/0, Enter=1): " OPENDMARC_ENABLE; OPENDMARC_ENABLE="${OPENDMARC_ENABLE:-1}"
|
||||
read -r -p "Fail2Ban aktivieren? (1/0, Enter=1): " FAIL2BAN_ENABLE; FAIL2BAN_ENABLE="${FAIL2BAN_ENABLE:-1}"
|
||||
fi
|
||||
|
||||
# ── Defaults/Kompatibilität ──────────────────────────────────
|
||||
MTA_FQDN="${MTA_FQDN:-${MTA_DEFAULT}}"
|
||||
UI_FQDN="${UI_FQDN:-${UI_DEFAULT}}"
|
||||
WEBMAIL_FQDN="${WEBMAIL_FQDN:-${WEBMAIL_DEFAULT}}"
|
||||
DKIM_ENABLE="${DKIM_ENABLE:-1}"
|
||||
DKIM_SELECTOR="${DKIM_SELECTOR:-mwl1}"
|
||||
DKIM_GENERATE="${DKIM_GENERATE:-1}"
|
||||
|
||||
# BASE_DOMAIN und Sub-Labels aus MTA/UI/WEBMAIL ableiten (robust)
|
||||
if [[ "$MTA_FQDN" =~ ^([^.]+)\.(.+)$ ]]; then
|
||||
MTA_SUB="${BASH_REMATCH[1]}"
|
||||
BASE_DOMAIN="${BASH_REMATCH[2]}"
|
||||
fi
|
||||
if [[ "$UI_FQDN" =~ ^([^.]+)\.(.+)$ ]]; then
|
||||
UI_SUB="${BASH_REMATCH[1]}"
|
||||
fi
|
||||
if [[ "$WEBMAIL_FQDN" =~ ^([^.]+)\.(.+)$ ]]; then
|
||||
WEBMAIL_SUB="${BASH_REMATCH[1]}"
|
||||
fi
|
||||
# BASE_DOMAIN/Subs aus FQDNs ableiten
|
||||
if [[ "$MTA_FQDN" =~ ^([^.]+)\.(.+)$ ]]; then MTA_SUB="${BASH_REMATCH[1]}"; BASE_DOMAIN="${BASH_REMATCH[2]}"; fi
|
||||
if [[ "$UI_FQDN" =~ ^([^.]+)\.(.+)$ ]]; then UI_SUB="${BASH_REMATCH[1]}"; fi
|
||||
if [[ "$WEBMAIL_FQDN" =~ ^([^.]+)\.(.+)$ ]]; then WEBMAIL_SUB="${BASH_REMATCH[1]}"; fi
|
||||
|
||||
SYSMAIL_SUB="${SYSMAIL_SUB:-sysmail}"
|
||||
SYSMAIL_DOMAIN="${SYSMAIL_SUB}.${BASE_DOMAIN}"
|
||||
# Kanonische Host-Variablen (NIE wieder zusammenbauen – nimm die FQDNs)
|
||||
|
||||
MAIL_HOSTNAME="${MTA_FQDN}"
|
||||
UI_HOST="${UI_FQDN}"
|
||||
WEBMAIL_HOST="${WEBMAIL_FQDN}"
|
||||
|
||||
# Zeitzone/Locale sinnvoll setzen (könntest du auch noch abfragen)
|
||||
APP_TZ="${APP_TZ:-$DEFAULT_TZ}"
|
||||
APP_LOCALE="${APP_LOCALE:-$DEFAULT_LOCALE}"
|
||||
|
||||
# ── Variablen exportieren ───────────────────────────────────────────────────
|
||||
# ── Export & persist ─────────────────────────────────────────
|
||||
export APP_NAME APP_USER APP_GROUP APP_USER_PREFIX APP_DIR
|
||||
export BASE_DOMAIN UI_SUB WEBMAIL_SUB MTA_SUB
|
||||
export SYSMAIL_SUB SYSMAIL_DOMAIN DKIM_ENABLE DKIM_SELECTOR DKIM_GENERATE
|
||||
export UI_HOST WEBMAIL_HOST MAIL_HOSTNAME
|
||||
export DB_NAME DB_USER
|
||||
export SERVER_PUBLIC_IPV4 SERVER_PUBLIC_IPV6 APP_TZ APP_LOCALE
|
||||
export CLAMAV_ENABLE OPENDMARC_ENABLE FAIL2BAN_ENABLE
|
||||
|
||||
install -d -m 0755 /etc/mailwolt
|
||||
cat >/etc/mailwolt/installer.env <<EOF
|
||||
|
|
@ -116,15 +177,350 @@ DB_HOST=127.0.0.1
|
|||
DB_NAME=${DB_NAME}
|
||||
DB_USER=${DB_USER}
|
||||
DB_PASS=${DB_PASS}
|
||||
REDIS_PASS=${REDIS_PASS}
|
||||
|
||||
SERVER_PUBLIC_IPV4=${SERVER_PUBLIC_IPV4}
|
||||
SERVER_PUBLIC_IPV6=${SERVER_PUBLIC_IPV6}
|
||||
APP_ENV=${APP_ENV}
|
||||
EOF
|
||||
|
||||
# ── Sequenz ────────────────────────────────────────────────────────────────
|
||||
for STEP in 10-provision 20-ssl 21-le-deploy-hook 22-dkim-helper 30-db 40-postfix 50-dovecot 60-rspamd-opendkim 70-nginx 75-le-issue 80-app 90-services 95-monit 98-motd 99-summary
|
||||
CLAMAV_ENABLE=${CLAMAV_ENABLE}
|
||||
OPENDMARC_ENABLE=${OPENDMARC_ENABLE}
|
||||
FAIL2BAN_ENABLE=${FAIL2BAN_ENABLE}
|
||||
EOF
|
||||
chmod 600 /etc/mailwolt/installer.env
|
||||
|
||||
# ── Installer-Sequenz ────────────────────────────────────────
|
||||
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 \
|
||||
70-nginx 75-le-issue 80-app 90-services 95-woltguard 98-motd 99-summary
|
||||
do
|
||||
log ">>> Running ${STEP}.sh"
|
||||
bash "./${STEP}.sh"
|
||||
done
|
||||
done
|
||||
|
||||
##!/usr/bin/env bash
|
||||
#set -euo pipefail
|
||||
#
|
||||
## --- Flags / Modi ---
|
||||
#DEV_MODE=0
|
||||
#PROXY_MODE=0
|
||||
#NPM_IP=""
|
||||
#
|
||||
#while [[ $# -gt 0 ]]; do
|
||||
# case "$1" in
|
||||
# -dev) DEV_MODE=1 ;;
|
||||
# -proxy) PROXY_MODE=1; NPM_IP="${2:-}"; shift ;;
|
||||
# esac
|
||||
# shift
|
||||
#done
|
||||
#
|
||||
#APP_ENV="${APP_ENV:-$([[ $DEV_MODE -eq 1 ]] && echo local || echo production)}"
|
||||
#APP_DEBUG="${APP_DEBUG:-$([[ $DEV_MODE -eq 1 ]] && echo true || echo false)}"
|
||||
#export DEV_MODE PROXY_MODE NPM_IP APP_ENV APP_DEBUG
|
||||
#
|
||||
#DB_PASS="${DB_PASS:-$(openssl rand -hex 16)}"
|
||||
#REDIS_PASS="${REDIS_PASS:-$(openssl rand -hex 16)}"
|
||||
#
|
||||
#export DB_PASS REDIS_PASS
|
||||
#
|
||||
#cd "$(dirname "$0")"
|
||||
#source ./lib.sh
|
||||
#require_root
|
||||
#header
|
||||
#
|
||||
## ── Defaults ────────────────────────────────────────────────────────────────
|
||||
#APP_NAME="${APP_NAME:-MailWolt}"
|
||||
#APP_USER="${APP_USER:-mailwolt}"
|
||||
#APP_GROUP="${APP_GROUP:-www-data}"
|
||||
#APP_USER_PREFIX="${APP_USER_PREFIX:-mw}"
|
||||
#APP_DIR="${APP_DIR:-/var/www/${APP_USER}}"
|
||||
#
|
||||
#BASE_DOMAIN="${BASE_DOMAIN:-example.com}"
|
||||
#UI_SUB="${UI_SUB:-ui}"
|
||||
#WEBMAIL_SUB="${WEBMAIL_SUB:-webmail}"
|
||||
#MTA_SUB="${MTA_SUB:-mx}"
|
||||
#
|
||||
#DB_NAME="${DB_NAME:-${APP_USER}}"
|
||||
#DB_USER="${DB_USER:-${APP_USER}}"
|
||||
#
|
||||
#SERVER_PUBLIC_IPV4="$(detect_ip)"
|
||||
#SERVER_PUBLIC_IPV6="$(detect_ipv6)"
|
||||
#DEFAULT_TZ="$(detect_timezone)"
|
||||
#DEFAULT_LOCALE="$(guess_locale_from_tz "$DEFAULT_TZ")"
|
||||
#
|
||||
#echo -e "${GREY}Erkannte IP (v4): ${SERVER_PUBLIC_IPV4} v6: ${SERVER_PUBLIC_IPV6:-–}${NC}"
|
||||
#
|
||||
## ── Schöne, farbige Abfragen ────────────────────────────────────────────────
|
||||
#echo -e "${CYAN}"
|
||||
#echo "──────────────────────────────────────────────"
|
||||
#echo -e " 📧 MailWolt Setup – Domain Konfiguration"
|
||||
#echo "──────────────────────────────────────────────"
|
||||
#echo -e "${NC}"
|
||||
#
|
||||
#MTA_DEFAULT="${MTA_SUB}.${BASE_DOMAIN}"
|
||||
#UI_DEFAULT="${UI_SUB}.${BASE_DOMAIN}"
|
||||
#WEBMAIL_DEFAULT="${WEBMAIL_SUB}.${BASE_DOMAIN}"
|
||||
#
|
||||
#ask_domain() {
|
||||
# local __outvar="$1" label="$2" example="$3" defval="$4" input=""
|
||||
# echo -e "${GREEN}[?]${NC} ${label}"
|
||||
# echo -e " z.B. ${YELLOW}${example}${NC}"
|
||||
# echo -e " Default: ${CYAN}${defval}${NC}"
|
||||
# echo -ne " → Eingabe: ${CYAN}"
|
||||
# read -r input
|
||||
# echo -e "${NC}"
|
||||
# if [[ -z "$input" ]]; then
|
||||
# eval "$__outvar='$defval'"
|
||||
# else
|
||||
# eval "$__outvar='$input'"
|
||||
# fi
|
||||
#}
|
||||
#
|
||||
#ask_toggle() {
|
||||
# local __outvar="$1" label="$2" defval="${3:-1}" input=""
|
||||
# echo -ne "${GREEN}[?]${NC} ${label} (${CYAN}1${NC}=Ja / ${YELLOW}0${NC}=Nein) [Enter=${defval}]: "
|
||||
# read -r input
|
||||
# input="${input:-$defval}"
|
||||
# case "$input" in
|
||||
# 1|0) ;;
|
||||
# *) echo -e "${YELLOW}Ungültig, nehme Default=${defval}.${NC}"; input="$defval" ;;
|
||||
# esac
|
||||
# eval "$__outvar='$input'"
|
||||
#}
|
||||
#
|
||||
#ask_domain "MTA_FQDN" "Mailserver-FQDN (MX)" "mx.domain.tld" "$MTA_DEFAULT"
|
||||
#ask_domain "UI_FQDN" "UI / Admin-Panel" "ui.domain.tld" "$UI_DEFAULT"
|
||||
#ask_domain "WEBMAIL_FQDN" "Webmail-FQDN" "webmail.domain.tld" "$WEBMAIL_DEFAULT"
|
||||
#
|
||||
#echo -e "${CYAN}"
|
||||
#echo "──────────────────────────────────────────────"
|
||||
#echo -e " 🛡 Optionale Dienste"
|
||||
#echo "──────────────────────────────────────────────"
|
||||
#echo -e "${NC}"
|
||||
#
|
||||
#ask_toggle "CLAMAV_ENABLE" "ClamAV Virenscan aktivieren?" 1
|
||||
#ask_toggle "OPENDMARC_ENABLE" "OpenDMARC auswerten?" 1
|
||||
#ask_toggle "FAIL2BAN_ENABLE" "Fail2Ban aktivieren?" 1
|
||||
#echo
|
||||
#
|
||||
## Defaults, wenn Enter gedrückt (Abwärtskompatibilität)
|
||||
#MTA_FQDN="${MTA_FQDN:-${MTA_SUB}.${BASE_DOMAIN}}"
|
||||
#UI_FQDN="${UI_FQDN:-${UI_SUB}.${BASE_DOMAIN}}"
|
||||
#WEBMAIL_FQDN="${WEBMAIL_FQDN:-${WEBMAIL_SUB}.${BASE_DOMAIN}}"
|
||||
#DKIM_ENABLE="${DKIM_ENABLE:-1}"
|
||||
#DKIM_SELECTOR="${DKIM_SELECTOR:-mwl1}"
|
||||
#DKIM_GENERATE="${DKIM_GENERATE:-1}"
|
||||
#
|
||||
## BASE_DOMAIN und Sub-Labels aus MTA/UI/WEBMAIL ableiten (robust)
|
||||
#if [[ "$MTA_FQDN" =~ ^([^.]+)\.(.+)$ ]]; then
|
||||
# MTA_SUB="${BASH_REMATCH[1]}"
|
||||
# BASE_DOMAIN="${BASH_REMATCH[2]}"
|
||||
#fi
|
||||
#if [[ "$UI_FQDN" =~ ^([^.]+)\.(.+)$ ]]; then
|
||||
# UI_SUB="${BASH_REMATCH[1]}"
|
||||
#fi
|
||||
#if [[ "$WEBMAIL_FQDN" =~ ^([^.]+)\.(.+)$ ]]; then
|
||||
# WEBMAIL_SUB="${BASH_REMATCH[1]}"
|
||||
#fi
|
||||
#
|
||||
#SYSMAIL_SUB="${SYSMAIL_SUB:-sysmail}"
|
||||
#SYSMAIL_DOMAIN="${SYSMAIL_SUB}.${BASE_DOMAIN}"
|
||||
## Kanonische Host-Variablen (NIE wieder zusammenbauen – nimm die FQDNs)
|
||||
#MAIL_HOSTNAME="${MTA_FQDN}"
|
||||
#UI_HOST="${UI_FQDN}"
|
||||
#WEBMAIL_HOST="${WEBMAIL_FQDN}"
|
||||
#
|
||||
## Zeitzone/Locale sinnvoll setzen
|
||||
#APP_TZ="${APP_TZ:-$DEFAULT_TZ}"
|
||||
#APP_LOCALE="${APP_LOCALE:-$DEFAULT_LOCALE}"
|
||||
#
|
||||
## ── Variablen exportieren ───────────────────────────────────────────────────
|
||||
#export APP_NAME APP_USER APP_GROUP APP_USER_PREFIX APP_DIR
|
||||
#export BASE_DOMAIN UI_SUB WEBMAIL_SUB MTA_SUB
|
||||
#export SYSMAIL_SUB SYSMAIL_DOMAIN DKIM_ENABLE DKIM_SELECTOR DKIM_GENERATE
|
||||
#export UI_HOST WEBMAIL_HOST MAIL_HOSTNAME
|
||||
#export DB_NAME DB_USER
|
||||
#export SERVER_PUBLIC_IPV4 SERVER_PUBLIC_IPV6 APP_TZ APP_LOCALE
|
||||
#export CLAMAV_ENABLE OPENDMARC_ENABLE FAIL2BAN_ENABLE
|
||||
#
|
||||
#install -d -m 0755 /etc/mailwolt
|
||||
#cat >/etc/mailwolt/installer.env <<EOF
|
||||
#BASE_DOMAIN=${BASE_DOMAIN}
|
||||
#MTA_SUB=${MTA_SUB}
|
||||
#UI_SUB=${UI_SUB}
|
||||
#WEBMAIL_SUB=${WEBMAIL_SUB}
|
||||
#
|
||||
#MAIL_HOSTNAME=${MAIL_HOSTNAME}
|
||||
#UI_HOST=${UI_HOST}
|
||||
#WEBMAIL_HOST=${WEBMAIL_HOST}
|
||||
#
|
||||
#SYSMAIL_SUB=${SYSMAIL_SUB}
|
||||
#SYSMAIL_DOMAIN=${SYSMAIL_DOMAIN}
|
||||
#
|
||||
#DKIM_ENABLE=${DKIM_ENABLE}
|
||||
#DKIM_SELECTOR=${DKIM_SELECTOR}
|
||||
#DKIM_GENERATE=${DKIM_GENERATE}
|
||||
#
|
||||
#DB_HOST=127.0.0.1
|
||||
#DB_NAME=${DB_NAME}
|
||||
#DB_USER=${DB_USER}
|
||||
#DB_PASS=${DB_PASS}
|
||||
#REDIS_PASS=${REDIS_PASS}
|
||||
#
|
||||
#SERVER_PUBLIC_IPV4=${SERVER_PUBLIC_IPV4}
|
||||
#SERVER_PUBLIC_IPV6=${SERVER_PUBLIC_IPV6}
|
||||
#APP_ENV=${APP_ENV}
|
||||
#
|
||||
#CLAMAV_ENABLE=${CLAMAV_ENABLE}
|
||||
#OPENDMARC_ENABLE=${OPENDMARC_ENABLE}
|
||||
#FAIL2BAN_ENABLE=${FAIL2BAN_ENABLE}
|
||||
#EOF
|
||||
#
|
||||
#chmod 600 /etc/mailwolt/installer.env
|
||||
#
|
||||
## ── Sequenz ────────────────────────────────────────────────────────────────
|
||||
#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 70-nginx 75-le-issue 80-app 90-services 95-woltguard 98-motd 99-summary
|
||||
#do
|
||||
# log ">>> Running ${STEP}.sh"
|
||||
# bash "./${STEP}.sh"
|
||||
#done
|
||||
###!/usr/bin/env bash
|
||||
##set -euo pipefail
|
||||
##
|
||||
### --- Flags / Modi ---
|
||||
##DEV_MODE=0
|
||||
##PROXY_MODE=0
|
||||
##NPM_IP=""
|
||||
##
|
||||
##while [[ $# -gt 0 ]]; do
|
||||
## case "$1" in
|
||||
## -dev) DEV_MODE=1 ;;
|
||||
## -proxy) PROXY_MODE=1; NPM_IP="${2:-}"; shift ;;
|
||||
## esac
|
||||
## shift
|
||||
##done
|
||||
##
|
||||
##APP_ENV="${APP_ENV:-$([[ $DEV_MODE -eq 1 ]] && echo local || echo production)}"
|
||||
##APP_DEBUG="${APP_DEBUG:-$([[ $DEV_MODE -eq 1 ]] && echo true || echo false)}"
|
||||
##export DEV_MODE PROXY_MODE NPM_IP APP_ENV APP_DEBUG
|
||||
##
|
||||
##DB_PASS="${DB_PASS:-$(openssl rand -hex 16)}"
|
||||
##REDIS_PASS="${REDIS_PASS:-$(openssl rand -hex 16)}"
|
||||
##
|
||||
##export DB_PASS REDIS_PASS
|
||||
##
|
||||
##cd "$(dirname "$0")"
|
||||
##source ./lib.sh
|
||||
##require_root
|
||||
##header
|
||||
##
|
||||
### ── Defaults ────────────────────────────────────────────────────────────────
|
||||
##APP_NAME="${APP_NAME:-MailWolt}"
|
||||
##APP_USER="${APP_USER:-mailwolt}"
|
||||
##APP_GROUP="${APP_GROUP:-www-data}"
|
||||
##APP_USER_PREFIX="${APP_USER_PREFIX:-mw}"
|
||||
##APP_DIR="${APP_DIR:-/var/www/${APP_USER}}"
|
||||
##
|
||||
##BASE_DOMAIN="${BASE_DOMAIN:-example.com}"
|
||||
##UI_SUB="${UI_SUB:-ui}"
|
||||
##WEBMAIL_SUB="${WEBMAIL_SUB:-webmail}"
|
||||
##MTA_SUB="${MTA_SUB:-mx}"
|
||||
##
|
||||
##DB_NAME="${DB_NAME:-${APP_USER}}"
|
||||
##DB_USER="${DB_USER:-${APP_USER}}"
|
||||
##
|
||||
##SERVER_PUBLIC_IPV4="$(detect_ip)"
|
||||
##SERVER_PUBLIC_IPV6="$(detect_ipv6)"
|
||||
##DEFAULT_TZ="$(detect_timezone)"
|
||||
##DEFAULT_LOCALE="$(guess_locale_from_tz "$DEFAULT_TZ")"
|
||||
##
|
||||
##echo -e "${GREY}Erkannte IP (v4): ${SERVER_PUBLIC_IPV4} v6: ${SERVER_PUBLIC_IPV6:-–}${NC}"
|
||||
##
|
||||
### ── FQDNs abfragen ───────────────────────────────────────────────────────────
|
||||
##read -r -p "Mailserver FQDN (MX, z.B. mx.domain.tld) [Enter=${MTA_SUB}.${BASE_DOMAIN}]: " MTA_FQDN
|
||||
##read -r -p "UI / Admin-Panel FQDN (z.B. ui.domain.tld) [Enter=${UI_SUB}.${BASE_DOMAIN}]: " UI_FQDN
|
||||
##read -r -p "Webmail FQDN (z.B. webmail.domain.tld) [Enter=${WEBMAIL_SUB}.${BASE_DOMAIN}]: " WEBMAIL_FQDN
|
||||
##
|
||||
### Defaults, wenn Enter gedrückt
|
||||
##MTA_FQDN="${MTA_FQDN:-${MTA_SUB}.${BASE_DOMAIN}}"
|
||||
##UI_FQDN="${UI_FQDN:-${UI_SUB}.${BASE_DOMAIN}}"
|
||||
##WEBMAIL_FQDN="${WEBMAIL_FQDN:-${WEBMAIL_SUB}.${BASE_DOMAIN}}"
|
||||
##DKIM_ENABLE="${DKIM_ENABLE:-1}"
|
||||
##DKIM_SELECTOR="${DKIM_SELECTOR:-mwl1}"
|
||||
##DKIM_GENERATE="${DKIM_GENERATE:-1}"
|
||||
##
|
||||
### BASE_DOMAIN und Sub-Labels aus MTA/UI/WEBMAIL ableiten (robust)
|
||||
##if [[ "$MTA_FQDN" =~ ^([^.]+)\.(.+)$ ]]; then
|
||||
## MTA_SUB="${BASH_REMATCH[1]}"
|
||||
## BASE_DOMAIN="${BASH_REMATCH[2]}"
|
||||
##fi
|
||||
##if [[ "$UI_FQDN" =~ ^([^.]+)\.(.+)$ ]]; then
|
||||
## UI_SUB="${BASH_REMATCH[1]}"
|
||||
##fi
|
||||
##if [[ "$WEBMAIL_FQDN" =~ ^([^.]+)\.(.+)$ ]]; then
|
||||
## WEBMAIL_SUB="${BASH_REMATCH[1]}"
|
||||
##fi
|
||||
##
|
||||
##SYSMAIL_SUB="${SYSMAIL_SUB:-sysmail}"
|
||||
##SYSMAIL_DOMAIN="${SYSMAIL_SUB}.${BASE_DOMAIN}"
|
||||
### Kanonische Host-Variablen (NIE wieder zusammenbauen – nimm die FQDNs)
|
||||
##MAIL_HOSTNAME="${MTA_FQDN}"
|
||||
##UI_HOST="${UI_FQDN}"
|
||||
##WEBMAIL_HOST="${WEBMAIL_FQDN}"
|
||||
##
|
||||
### Zeitzone/Locale sinnvoll setzen (könntest du auch noch abfragen)
|
||||
##APP_TZ="${APP_TZ:-$DEFAULT_TZ}"
|
||||
##APP_LOCALE="${APP_LOCALE:-$DEFAULT_LOCALE}"
|
||||
##
|
||||
### ── Variablen exportieren ───────────────────────────────────────────────────
|
||||
##export APP_NAME APP_USER APP_GROUP APP_USER_PREFIX APP_DIR
|
||||
##export BASE_DOMAIN UI_SUB WEBMAIL_SUB MTA_SUB
|
||||
##export SYSMAIL_SUB SYSMAIL_DOMAIN DKIM_ENABLE DKIM_SELECTOR DKIM_GENERATE
|
||||
##export UI_HOST WEBMAIL_HOST MAIL_HOSTNAME
|
||||
##export DB_NAME DB_USER
|
||||
##export SERVER_PUBLIC_IPV4 SERVER_PUBLIC_IPV6 APP_TZ APP_LOCALE
|
||||
##
|
||||
##install -d -m 0755 /etc/mailwolt
|
||||
##cat >/etc/mailwolt/installer.env <<EOF
|
||||
##BASE_DOMAIN=${BASE_DOMAIN}
|
||||
##MTA_SUB=${MTA_SUB}
|
||||
##UI_SUB=${UI_SUB}
|
||||
##WEBMAIL_SUB=${WEBMAIL_SUB}
|
||||
##
|
||||
##MAIL_HOSTNAME=${MAIL_HOSTNAME}
|
||||
##UI_HOST=${UI_HOST}
|
||||
##WEBMAIL_HOST=${WEBMAIL_HOST}
|
||||
##
|
||||
##SYSMAIL_SUB=${SYSMAIL_SUB}
|
||||
##SYSMAIL_DOMAIN=${SYSMAIL_DOMAIN}
|
||||
##
|
||||
##DKIM_ENABLE=${DKIM_ENABLE}
|
||||
##DKIM_SELECTOR=${DKIM_SELECTOR}
|
||||
##DKIM_GENERATE=${DKIM_GENERATE}
|
||||
##
|
||||
##DB_HOST=127.0.0.1
|
||||
##DB_NAME=${DB_NAME}
|
||||
##DB_USER=${DB_USER}
|
||||
##DB_PASS=${DB_PASS}
|
||||
##REDIS_PASS=${REDIS_PASS}
|
||||
##
|
||||
##SERVER_PUBLIC_IPV4=${SERVER_PUBLIC_IPV4}
|
||||
##SERVER_PUBLIC_IPV6=${SERVER_PUBLIC_IPV6}
|
||||
##APP_ENV=${APP_ENV}
|
||||
##
|
||||
##CLAMAV_ENABLE=1
|
||||
##OPENDMARC_ENABLE=1
|
||||
##FAIL2BAN_ENABLE=1
|
||||
##EOF
|
||||
##
|
||||
##chmod 600 /etc/mailwolt/installer.env
|
||||
##
|
||||
### ── Sequenz ────────────────────────────────────────────────────────────────
|
||||
##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 70-nginx 75-le-issue 80-app 90-services 95-woltguard 98-motd 99-summary
|
||||
##do
|
||||
## log ">>> Running ${STEP}.sh"
|
||||
## bash "./${STEP}.sh"
|
||||
##done
|
||||
|
|
@ -0,0 +1,300 @@
|
|||
#!/usr/bin/env bash
|
||||
set -euo pipefail
|
||||
|
||||
# -------- Konfiguration --------
|
||||
APP_USER="mailwolt"
|
||||
APP_DIR="/var/www/mailwolt"
|
||||
BRANCH="${BRANCH:-main}" # nur relevant bei UPDATE_MODE=branch
|
||||
MODE="${UPDATE_MODE:-tags}" # tags | branch
|
||||
|
||||
# -------- Helper --------
|
||||
as_app(){ sudo -u "$APP_USER" -H bash -lc "$*"; }
|
||||
restart_if_exists(){ local u="$1"; systemctl list-unit-files | grep -q "^${u}\.service" && systemctl restart "$u" || true; }
|
||||
reload_if_active(){ local u="$1"; systemctl is-active --quiet "$u" && systemctl reload "$u" || true; }
|
||||
restart_php_fpm(){
|
||||
for u in php8.3-fpm php8.2-fpm php8.1-fpm php-fpm; do
|
||||
if systemctl list-unit-files | grep -q "^${u}\.service"; then
|
||||
systemctl restart "$u"
|
||||
return 0
|
||||
fi
|
||||
done
|
||||
}
|
||||
|
||||
# -------- Guards --------
|
||||
[[ "$(id -u)" -eq 0 ]] || { echo "[!] Bitte als root ausführen"; exit 1; }
|
||||
[[ -d "$APP_DIR/.git" ]] || { echo "[!] $APP_DIR scheint kein Git-Repo zu sein"; exit 1; }
|
||||
|
||||
echo "[i] Prüfe Repository …"
|
||||
OLD_REV="$(as_app "cd ${APP_DIR} && git rev-parse HEAD")"
|
||||
NEW_REV="$OLD_REV"
|
||||
|
||||
if [[ "$MODE" = "tags" ]]; then
|
||||
# Auf neuesten Release-Tag wechseln (semantisch sortiert)
|
||||
LATEST_TAG="$(as_app "cd ${APP_DIR} && git fetch --tags --quiet origin && git tag --list | sort -V | tail -n1")"
|
||||
if [[ -z "$LATEST_TAG" ]]; then
|
||||
echo "[!] Keine Tags gefunden – falle auf origin/${BRANCH} zurück"
|
||||
as_app "cd ${APP_DIR} && git fetch --quiet origin ${BRANCH} && git checkout -q ${BRANCH} && git pull --ff-only origin ${BRANCH}"
|
||||
else
|
||||
TARGET_REV="$(as_app "cd ${APP_DIR} && git rev-list -n1 ${LATEST_TAG}")"
|
||||
if [[ "$TARGET_REV" = "$OLD_REV" ]]; then
|
||||
echo "[✓] Bereits auf neuestem Release (${LATEST_TAG}) – nichts zu tun."
|
||||
exit 0
|
||||
fi
|
||||
echo "[i] Checkout auf Release ${LATEST_TAG} (${TARGET_REV:0:7}) …"
|
||||
as_app "cd ${APP_DIR} && git checkout -q ${LATEST_TAG}"
|
||||
fi
|
||||
NEW_REV="$(as_app "cd ${APP_DIR} && git rev-parse HEAD")"
|
||||
else
|
||||
# Rolling: branch folgen
|
||||
as_app "cd ${APP_DIR} && git fetch --quiet origin ${BRANCH}"
|
||||
BEHIND="$(as_app "cd ${APP_DIR} && git rev-list --count HEAD..origin/${BRANCH} || echo 0")"
|
||||
if [[ "$BEHIND" -eq 0 ]]; then
|
||||
echo "[✓] Branch origin/${BRANCH} ist bereits aktuell – nichts zu tun."
|
||||
exit 0
|
||||
fi
|
||||
echo "[i] Es gibt ${BEHIND} neue Commit(s) – ziehe Änderungen …"
|
||||
as_app "cd ${APP_DIR} && git checkout -q ${BRANCH} && git pull --ff-only origin ${BRANCH}"
|
||||
NEW_REV="$(as_app "cd ${APP_DIR} && git rev-parse HEAD")"
|
||||
fi
|
||||
|
||||
# -------- Änderungstypen ermitteln --------
|
||||
CHANGED_FILES="$(as_app "cd ${APP_DIR} && git diff --name-only ${OLD_REV}..${NEW_REV}")"
|
||||
|
||||
NEED_COMPOSER=0
|
||||
NEED_MIGRATIONS=0
|
||||
NEED_FRONTEND=0
|
||||
NEED_PHP_RESTART=0
|
||||
|
||||
echo "$CHANGED_FILES" | grep -qE '(^|/)composer\.(json|lock)$' && NEED_COMPOSER=1
|
||||
echo "$CHANGED_FILES" | grep -qE '^database/migrations/' && NEED_MIGRATIONS=1
|
||||
echo "$CHANGED_FILES" | grep -qE '^(package(-lock)?\.json|vite\.config|resources/|public/.*\.(js|css))' && NEED_FRONTEND=1
|
||||
echo "$CHANGED_FILES" | grep -qE '^(app/|routes/|config/|resources/views/)' && NEED_PHP_RESTART=1
|
||||
|
||||
echo "[i] Zusammenfassung:"
|
||||
echo " Composer : $([[ $NEED_COMPOSER -eq 1 ]] && echo JA || echo nein)"
|
||||
echo " Migrations : $([[ $NEED_MIGRATIONS -eq 1 ]] && echo JA || echo nein)"
|
||||
echo " Frontend : $([[ $NEED_FRONTEND -eq 1 ]] && echo JA || echo nein)"
|
||||
echo " PHP restart : $([[ $NEED_PHP_RESTART -eq 1 ]] && echo JA || echo nein)"
|
||||
|
||||
# Wenn gar nichts relevantes geändert wurde → sauber beenden
|
||||
if [[ $NEED_COMPOSER -eq 0 && $NEED_MIGRATIONS -eq 0 && $NEED_FRONTEND -eq 0 && $NEED_PHP_RESTART -eq 0 ]]; then
|
||||
echo "[✓] Code-Stand aktualisiert, aber keine Build/Runtime-Änderungen – keine Neustarts nötig."
|
||||
# Build-Info trotzdem aktualisieren
|
||||
INST_VER="$(as_app "cd ${APP_DIR} && (cat VERSION 2>/dev/null || echo dev)")"
|
||||
printf "version=%s\nrev=%s\nupdated=%s\n" "$INST_VER" "$NEW_REV" "$(date -Is)" > /etc/mailwolt/build.info || true
|
||||
exit 0
|
||||
fi
|
||||
|
||||
# -------- Gezielter Build/Deploy --------
|
||||
if [[ $NEED_COMPOSER -eq 1 ]]; then
|
||||
echo "[i] Composer …"
|
||||
as_app "cd ${APP_DIR} && composer install --no-interaction --prefer-dist --optimize-autoloader"
|
||||
fi
|
||||
|
||||
if [[ $NEED_MIGRATIONS -eq 1 ]]; then
|
||||
echo "[i] DB-Migrationen …"
|
||||
as_app "cd ${APP_DIR} && php artisan migrate --force"
|
||||
fi
|
||||
|
||||
if [[ $NEED_PHP_RESTART -eq 1 || $NEED_COMPOSER -eq 1 || $NEED_MIGRATIONS -eq 1 ]]; then
|
||||
echo "[i] Cache/Optimierungen …"
|
||||
as_app "cd ${APP_DIR} && php artisan config:cache && php artisan route:cache || true"
|
||||
as_app "cd ${APP_DIR} && php artisan queue:restart || true"
|
||||
as_app "cd ${APP_DIR} && php artisan optimize:clear || true"
|
||||
fi
|
||||
|
||||
if [[ $NEED_FRONTEND -eq 1 ]]; then
|
||||
echo "[i] Frontend build …"
|
||||
as_app "cd ${APP_DIR} && (npm ci --no-audit --no-fund || npm install)"
|
||||
as_app "cd ${APP_DIR} && npm run build"
|
||||
fi
|
||||
|
||||
# -------- Dienste nur wenn nötig --------
|
||||
echo "[i] Dienste neu laden/neustarten (gezielt) …"
|
||||
if [[ $NEED_PHP_RESTART -eq 1 || $NEED_COMPOSER -eq 1 || $NEED_MIGRATIONS -eq 1 ]]; then
|
||||
restart_php_fpm
|
||||
restart_if_exists "${APP_USER}-queue"
|
||||
restart_if_exists "${APP_USER}-schedule"
|
||||
restart_if_exists "${APP_USER}-ws"
|
||||
fi
|
||||
if [[ $NEED_FRONTEND -eq 1 || $NEED_PHP_RESTART -eq 1 ]]; then
|
||||
reload_if_active nginx
|
||||
fi
|
||||
|
||||
# -------- Build-Info ablegen --------
|
||||
INST_VER="$(as_app "cd ${APP_DIR} && (cat VERSION 2>/dev/null || echo dev)")"
|
||||
printf "version=%s\nrev=%s\nupdated=%s\n" "$INST_VER" "$NEW_REV" "$(date -Is)" > /etc/mailwolt/build.info || true
|
||||
|
||||
echo "[✓] Update abgeschlossen: ${OLD_REV:0:7} → ${NEW_REV:0:7} (Version: ${INST_VER})"
|
||||
|
||||
##!/usr/bin/env bash
|
||||
#set -euo pipefail
|
||||
#
|
||||
#APP_USER="mailwolt"
|
||||
#APP_DIR="/var/www/mailwolt"
|
||||
#BRANCH="${BRANCH:-main}" # bei Bedarf anpassen
|
||||
#
|
||||
#as_app(){ sudo -u "$APP_USER" -H bash -lc "$*"; }
|
||||
#
|
||||
#restart_if_exists(){ local u="$1"; systemctl list-unit-files | grep -q "^${u}\.service" && systemctl restart "$u" || true; }
|
||||
#reload_if_active(){ local u="$1"; systemctl is-active --quiet "$u" && systemctl reload "$u" || true; }
|
||||
#
|
||||
#restart_php_fpm(){
|
||||
# for u in php8.3-fpm php8.2-fpm php8.1-fpm php-fpm; do
|
||||
# systemctl list-unit-files | grep -q "^${u}\.service" && { systemctl restart "$u"; return 0; }
|
||||
# done
|
||||
# return 0
|
||||
#}
|
||||
#
|
||||
#[[ "$(id -u)" -eq 0 ]] || { echo "[!] Bitte als root ausführen"; exit 1; }
|
||||
#
|
||||
##!/usr/bin/env bash
|
||||
#set -euo pipefail
|
||||
#APP_USER="mailwolt"
|
||||
#APP_DIR="/var/www/mailwolt"
|
||||
#MODE="${UPDATE_MODE:-tags}"
|
||||
#
|
||||
#as_app(){ sudo -u "$APP_USER" -H bash -lc "$*"; }
|
||||
#
|
||||
## --- Ab hier wie gehabt ---
|
||||
#echo "[i] Prüfe Repository …"
|
||||
#if [[ "$MODE" = "tags" ]]; then
|
||||
# LATEST_TAG="$(as_app "cd ${APP_DIR} && git fetch --tags --quiet origin && git tag --list | sort -V | tail -n1")"
|
||||
# if [[ -n "$LATEST_TAG" ]]; then
|
||||
# OLD_REV="$(as_app "cd ${APP_DIR} && git rev-parse HEAD")"
|
||||
# echo "[i] Checkout auf neuesten Release: ${LATEST_TAG}"
|
||||
# as_app "cd ${APP_DIR} && git checkout -q ${LATEST_TAG}"
|
||||
# NEW_REV="$(as_app "cd ${APP_DIR} && git rev-parse HEAD")"
|
||||
# else
|
||||
# echo "[!] Keine Tags gefunden, falle auf origin/main zurück"
|
||||
# as_app "cd ${APP_DIR} && git pull --ff-only origin main"
|
||||
# fi
|
||||
#else
|
||||
# as_app "cd ${APP_DIR} && git fetch --quiet origin main && git pull --ff-only origin main"
|
||||
#fi
|
||||
#
|
||||
#echo "[i] Prüfe Repository …"
|
||||
#OLD_REV="$(as_app "cd ${APP_DIR} && git rev-parse HEAD")"
|
||||
#as_app "cd ${APP_DIR} && git fetch --tags --quiet origin ${BRANCH}"
|
||||
#BEHIND="$(as_app "cd ${APP_DIR} && git rev-list --count HEAD..origin/${BRANCH} || echo 0")"
|
||||
#
|
||||
#if [[ "${BEHIND}" -eq 0 ]]; then
|
||||
# echo "[✓] Bereits aktuell – nichts zu tun."
|
||||
# exit 0
|
||||
#fi
|
||||
#
|
||||
#echo "[i] Es gibt ${BEHIND} neue Commit(s) – ziehe Änderungen …"
|
||||
#as_app "cd ${APP_DIR} && git pull --ff-only origin ${BRANCH}"
|
||||
#NEW_REV="$(as_app "cd ${APP_DIR} && git rev-parse HEAD")"
|
||||
#
|
||||
## Welche Bereiche haben sich geändert?
|
||||
#CHANGED_FILES="$(as_app "cd ${APP_DIR} && git diff --name-only ${OLD_REV}..${NEW_REV}")"
|
||||
#
|
||||
#NEED_COMPOSER=0
|
||||
#NEED_MIGRATIONS=0
|
||||
#NEED_FRONTEND=0
|
||||
#NEED_PHP_RESTART=0
|
||||
#
|
||||
#if echo "$CHANGED_FILES" | grep -qE '^(composer\.json|composer\.lock)'; then
|
||||
# NEED_COMPOSER=1
|
||||
#fi
|
||||
#if echo "$CHANGED_FILES" | grep -qE '^database/migrations/'; then
|
||||
# NEED_MIGRATIONS=1
|
||||
#fi
|
||||
#if echo "$CHANGED_FILES" | grep -qE '^(package(-lock)?\.json|vite\.config\.|resources/|public/.*\.(js|css))'; then
|
||||
# NEED_FRONTEND=1
|
||||
#fi
|
||||
## PHP-Code/Views/Config geändert?
|
||||
#if echo "$CHANGED_FILES" | grep -qE '^(app/|routes/|config/|resources/views/)'; then
|
||||
# NEED_PHP_RESTART=1
|
||||
#fi
|
||||
#
|
||||
#echo "[i] Zusammenfassung:"
|
||||
#echo " Composer : $([[ $NEED_COMPOSER -eq 1 ]] && echo JA || echo nein)"
|
||||
#echo " Migrations : $([[ $NEED_MIGRATIONS -eq 1 ]] && echo JA || echo nein)"
|
||||
#echo " Frontend : $([[ $NEED_FRONTEND -eq 1 ]] && echo JA || echo nein)"
|
||||
#echo " PHP restart : $([[ $NEED_PHP_RESTART -eq 1 ]] && echo JA || echo nein)"
|
||||
#
|
||||
#echo "[i] Führe Build/Deploy (gezielt) aus …"
|
||||
#if [[ $NEED_COMPOSER -eq 1 ]]; then
|
||||
# as_app "cd ${APP_DIR} && composer install --no-interaction --prefer-dist --optimize-autoloader"
|
||||
#fi
|
||||
#
|
||||
#if [[ $NEED_MIGRATIONS -eq 1 ]]; then
|
||||
# as_app "cd ${APP_DIR} && php artisan migrate --force"
|
||||
#fi
|
||||
#
|
||||
## Cache & Queue nur wenn relevant
|
||||
#if [[ $NEED_PHP_RESTART -eq 1 || $NEED_COMPOSER -eq 1 || $NEED_MIGRATIONS -eq 1 ]]; then
|
||||
# as_app "cd ${APP_DIR} && php artisan config:cache && php artisan route:cache || true"
|
||||
# as_app "cd ${APP_DIR} && php artisan queue:restart || true"
|
||||
# as_app "cd ${APP_DIR} && php artisan optimize:clear || true"
|
||||
#fi
|
||||
#
|
||||
#if [[ $NEED_FRONTEND -eq 1 ]]; then
|
||||
# as_app "cd ${APP_DIR} && (npm ci --no-audit --no-fund || npm install)"
|
||||
# as_app "cd ${APP_DIR} && npm run build"
|
||||
#fi
|
||||
#
|
||||
## Dienste nur neu laden/starten wenn nötig
|
||||
#ANY_RUNTIME_CHANGE=0
|
||||
#[[ $NEED_COMPOSER -eq 1 || $NEED_MIGRATIONS -eq 1 || $NEED_FRONTEND -eq 1 || $NEED_PHP_RESTART -eq 1 ]] && ANY_RUNTIME_CHANGE=1
|
||||
#
|
||||
#if [[ $ANY_RUNTIME_CHANGE -eq 1 ]]; then
|
||||
# echo "[i] Dienste neu laden/neustarten (gezielt) …"
|
||||
# if [[ $NEED_PHP_RESTART -eq 1 || $NEED_COMPOSER -eq 1 || $NEED_MIGRATIONS -eq 1 ]]; then
|
||||
# restart_php_fpm
|
||||
# restart_if_exists "${APP_USER}-queue"
|
||||
# restart_if_exists "${APP_USER}-schedule"
|
||||
# restart_if_exists "${APP_USER}-ws"
|
||||
# fi
|
||||
# # Webserver nur bei Assets/Views/Config
|
||||
# if [[ $NEED_FRONTEND -eq 1 || $NEED_PHP_RESTART -eq 1 ]]; then
|
||||
# reload_if_active nginx
|
||||
# fi
|
||||
#else
|
||||
# echo "[i] Nichts zum Updaten."
|
||||
#fi
|
||||
#
|
||||
#echo "[✓] Update auf ${NEW_REV:0:7} abgeschlossen."
|
||||
|
||||
##!/usr/bin/env bash
|
||||
#set -euo pipefail
|
||||
#
|
||||
#APP_USER="mailwolt"
|
||||
#APP_DIR="/var/www/mailwolt"
|
||||
#
|
||||
#as_app(){ sudo -u "$APP_USER" -H bash -lc "$*"; }
|
||||
#
|
||||
#restart_if_exists(){ local u="$1"; systemctl list-unit-files | grep -q "^${u}\.service" && systemctl restart "$u" || true; }
|
||||
#reload_if_active(){ local u="$1"; systemctl is-active --quiet "$u" && systemctl reload "$u" || true; }
|
||||
#
|
||||
#restart_php_fpm(){
|
||||
# for u in php8.3-fpm php8.2-fpm php8.1-fpm php-fpm; do
|
||||
# systemctl list-unit-files | grep -q "^${u}\.service" && { systemctl restart "$u"; return 0; }
|
||||
# done
|
||||
# return 0
|
||||
#}
|
||||
#
|
||||
#[[ "$(id -u)" -eq 0 ]] || { echo "[!] Bitte als root ausführen"; exit 1; }
|
||||
#
|
||||
#echo "[i] Code-Update & Build als ${APP_USER} …"
|
||||
#as_app "cd ${APP_DIR} && git pull --ff-only"
|
||||
#as_app "cd ${APP_DIR} && composer install --no-interaction --prefer-dist --optimize-autoloader"
|
||||
#as_app "cd ${APP_DIR} && php artisan migrate --force"
|
||||
#as_app "cd ${APP_DIR} && php artisan config:cache && php artisan route:cache || true && php artisan queue:restart || true && php artisan optimize:clear"
|
||||
#as_app "cd ${APP_DIR} && (npm ci --no-audit --no-fund || npm install)"
|
||||
#as_app "cd ${APP_DIR} && npm run build"
|
||||
#
|
||||
#echo "[i] Dienste neu laden/neustarten …"
|
||||
#restart_php_fpm
|
||||
#restart_if_exists "${APP_USER}-queue"
|
||||
#restart_if_exists "${APP_USER}-schedule"
|
||||
#restart_if_exists "${APP_USER}-ws"
|
||||
#reload_if_active nginx
|
||||
#reload_if_active opendkim
|
||||
#reload_if_active postfix
|
||||
#reload_if_active dovecot
|
||||
#reload_if_active rspamd
|
||||
#
|
||||
#echo "[✓] Update abgeschlossen."
|
||||
|
|
@ -0,0 +1,33 @@
|
|||
#!/usr/bin/env bash
|
||||
set -euo pipefail
|
||||
|
||||
MSG=""
|
||||
BRANCH="$(git rev-parse --abbrev-ref HEAD 2>/dev/null || echo main)"
|
||||
REMOTE="${REMOTE:-origin}"
|
||||
|
||||
usage(){ echo "Usage: $0 -m \"commit message\" [-b branch]"; exit 1; }
|
||||
|
||||
while getopts ":m:b:" opt; do
|
||||
case "$opt" in
|
||||
m) MSG="$OPTARG" ;;
|
||||
b) BRANCH="$OPTARG" ;;
|
||||
*) usage ;;
|
||||
esac
|
||||
done
|
||||
shift $((OPTIND-1))
|
||||
|
||||
[[ -n "$MSG" ]] || usage
|
||||
git rev-parse --git-dir >/dev/null 2>&1 || { echo "[x] kein Git-Repo"; exit 1; }
|
||||
|
||||
echo "[i] Add/Commit → $BRANCH"
|
||||
git add -A
|
||||
# Kein Commit, wenn nichts geändert ist
|
||||
if ! git diff --cached --quiet; then
|
||||
git commit -m "$MSG"
|
||||
else
|
||||
echo "[i] Nichts zu committen (Index leer) – pushe nur."
|
||||
fi
|
||||
|
||||
echo "[i] Push → $REMOTE/$BRANCH"
|
||||
git push "$REMOTE" "$BRANCH"
|
||||
echo "[✓] Done."
|
||||
|
|
@ -0,0 +1,80 @@
|
|||
#!/usr/bin/env bash
|
||||
set -euo pipefail
|
||||
|
||||
REMOTE="${REMOTE:-origin}"
|
||||
BRANCH="${BRANCH:-main}"
|
||||
ALLOW_DIRTY=0
|
||||
VERSION=""
|
||||
MSG=""
|
||||
|
||||
usage(){
|
||||
echo "Usage: $0 <X.Y.Z> [-m \"release notes\"] [-b branch] [--allow-dirty]"
|
||||
exit 1
|
||||
}
|
||||
|
||||
# Args
|
||||
[[ $# -ge 1 ]] || usage
|
||||
VERSION="$1"; shift || true
|
||||
[[ "$VERSION" =~ ^[0-9]+\.[0-9]+\.[0-9]+$ ]] || { echo "[x] Ungültige Version: $VERSION (erwarte SemVer X.Y.Z)"; exit 1; }
|
||||
|
||||
while [[ $# -gt 0 ]]; do
|
||||
case "$1" in
|
||||
-m) MSG="$2"; shift 2 ;;
|
||||
-b) BRANCH="$2"; shift 2 ;;
|
||||
--allow-dirty) ALLOW_DIRTY=1; shift ;;
|
||||
*) usage ;;
|
||||
esac
|
||||
done
|
||||
|
||||
git rev-parse --git-dir >/dev/null 2>&1 || { echo "[x] kein Git-Repo"; exit 1; }
|
||||
|
||||
# Clean tree?
|
||||
if [[ $ALLOW_DIRTY -eq 0 ]]; then
|
||||
if ! git diff --quiet || ! git diff --cached --quiet; then
|
||||
echo "[x] Arbeitsbaum nicht sauber. Committe oder nutze --allow-dirty."
|
||||
exit 1
|
||||
fi
|
||||
fi
|
||||
|
||||
# Aktuellen Stand holen
|
||||
git fetch --quiet "$REMOTE" --tags
|
||||
# Branch check-out/sync
|
||||
git checkout -q "$BRANCH"
|
||||
git pull --ff-only "$REMOTE" "$BRANCH"
|
||||
|
||||
TAG="v${VERSION}"
|
||||
if git rev-parse -q --verify "refs/tags/${TAG}" >/dev/null; then
|
||||
echo "[x] Tag ${TAG} existiert bereits."
|
||||
exit 1
|
||||
fi
|
||||
|
||||
LAST_TAG="$(git describe --tags --abbrev=0 2>/dev/null || true)"
|
||||
if [[ -n "$LAST_TAG" ]]; then
|
||||
CHANGELOG="$(git log --pretty=format:'- %s (%h)' "${LAST_TAG}..HEAD" || true)"
|
||||
else
|
||||
CHANGELOG="$(git log --pretty=format:'- %s (%h)' || true)"
|
||||
fi
|
||||
[[ -n "$CHANGELOG" ]] || CHANGELOG="- initial release content"
|
||||
|
||||
# VERSION bumpen
|
||||
echo -n "$VERSION" > VERSION
|
||||
git add VERSION
|
||||
git commit -m "chore(release): v${VERSION}"
|
||||
|
||||
# Tag-Message bauen
|
||||
if [[ -z "$MSG" ]]; then
|
||||
read -r -d '' MSG <<EOF || true
|
||||
MailWolt v${VERSION}
|
||||
|
||||
Changes since ${LAST_TAG:-repo start}:
|
||||
${CHANGELOG}
|
||||
EOF
|
||||
fi
|
||||
|
||||
git tag -a "$TAG" -m "$MSG"
|
||||
|
||||
# Push commit + tag
|
||||
git push "$REMOTE" "$BRANCH"
|
||||
git push "$REMOTE" "$TAG"
|
||||
|
||||
echo "[✓] Release ${TAG} erstellt & gepusht."
|
||||
Loading…
Reference in New Issue