From d41a132fbb71831aec8db8ee03fe5c4b5a260b58 Mon Sep 17 00:00:00 2001 From: boksbc Date: Fri, 17 Oct 2025 23:31:51 +0200 Subject: [PATCH] Laudende Default seite entfernen --- scripts/21-le-deploy-hook.sh | 238 +++++++++++++++++++++------ scripts/60-rspamd-opendkim.sh | 293 +++++++++++++++++++++++++++++----- scripts/80-app.sh | 36 ++--- scripts/99-summary.sh | 25 ++- scripts/bootstrap.sh | 4 +- 5 files changed, 482 insertions(+), 114 deletions(-) diff --git a/scripts/21-le-deploy-hook.sh b/scripts/21-le-deploy-hook.sh index 57bfb3a..c3f5702 100644 --- a/scripts/21-le-deploy-hook.sh +++ b/scripts/21-le-deploy-hook.sh @@ -2,7 +2,9 @@ set -euo pipefail source ./lib.sh -# Persistente Installer-Variablen (werden vom Wrapper gelesen) +# ------------------------------------------------------------------- +# 1) Persistente Installer-Variablen für Deploy-Hook/Wrapper ablegen +# ------------------------------------------------------------------- install -d -m 0755 /etc/mailwolt cat >/etc/mailwolt/installer.env </usr/local/sbin/mw-deploy.sh <<'WRAP' -#!/usr/bin/env bash -set -euo pipefail +#!/bin/sh +# POSIX-safe Certbot deploy-hook (ohne bashisms) +set -eu -# Installer-Variablen laden -set +u -[ -r /etc/mailwolt/installer.env ] && . /etc/mailwolt/installer.env -set -u +# Installer-ENV laden (liefert UI_HOST/WEBMAIL_HOST/MAIL_HOSTNAME etc.) +if [ -r /etc/mailwolt/installer.env ]; then + # shellcheck disable=SC1091 + . /etc/mailwolt/installer.env +fi UI_HOST="${UI_HOST:-}" WEBMAIL_HOST="${WEBMAIL_HOST:-}" MAIL_HOSTNAME="${MAIL_HOSTNAME:-}" +ACME_BASE="/etc/letsencrypt/live" -# --- Kopieren statt Symlinks (damit Laravel lesen kann) --------------------- copy_cert() { - local le_base="$1" target_dir="$2" - local cert="${le_base}/fullchain.pem" - local key="${le_base}/privkey.pem" + le_base="$1" # z.B. /etc/letsencrypt/live/ui.example.com + target_dir="$2" # z.B. /etc/ssl/ui - [[ -s "$cert" && -s "$key" ]] || return 0 + cert="${le_base}/fullchain.pem" + key="${le_base}/privkey.pem" - install -d -m 0755 "$target_dir" + [ -s "$cert" ] || { echo "[deploy] missing $cert"; return 1; } + [ -s "$key" ] || { echo "[deploy] missing $key"; return 1; } - # Vorhandene Symlinks entfernen, sonst kopierst du in die LE-Datei hinein - [ -L "${target_dir}/fullchain.pem" ] && rm -f "${target_dir}/fullchain.pem" - [ -L "${target_dir}/privkey.pem" ] && rm -f "${target_dir}/privkey.pem" + mkdir -p "$target_dir" - # Echte Dateien ablegen + # echte Dateien (keine Symlinks), feste Rechte install -m 0644 "$cert" "${target_dir}/fullchain.pem" install -m 0600 "$key" "${target_dir}/privkey.pem" echo "[+] Copied ${target_dir}/fullchain.pem und privkey.pem ← ${le_base}" } -# Nur Domains bearbeiten, die in diesem Lauf betroffen sind. -# Bei manchen Distros ist RENEWED_DOMAINS auf Erst-issue leer -> Fallback nutzen. -RDOMS=" ${RENEWED_DOMAINS:-} " -did_any=0 - -maybe_copy_for() { - local host="$1" dir="$2" - [[ -z "$host" ]] && return 0 - if [[ "$RDOMS" == *" ${host} "* ]]; then - copy_cert "/etc/letsencrypt/live/${host}" "${dir}" - did_any=1 +reload_services() { + kind="$1" # ui | mail + if command -v systemctl >/dev/null 2>&1; then + if [ "$kind" = "mail" ]; then + systemctl reload postfix 2>/dev/null || true + systemctl reload dovecot 2>/dev/null || true + else + systemctl reload nginx 2>/dev/null || true + fi fi } -# 1) Normalfall: nur die vom Certbot gemeldeten Hosts kopieren -maybe_copy_for "$UI_HOST" "/etc/ssl/ui" -maybe_copy_for "$WEBMAIL_HOST" "/etc/ssl/webmail" -maybe_copy_for "$MAIL_HOSTNAME" "/etc/ssl/mail" - -# 2) Fallback: Beim Erstlauf/Edge-Cases alles kopieren, was bereits existiert -if [[ "$did_any" -eq 0 ]]; then - [[ -n "$UI_HOST" && -d "/etc/letsencrypt/live/${UI_HOST}" ]] && copy_cert "/etc/letsencrypt/live/${UI_HOST}" "/etc/ssl/ui" - [[ -n "$WEBMAIL_HOST" && -d "/etc/letsencrypt/live/${WEBMAIL_HOST}" ]] && copy_cert "/etc/letsencrypt/live/${WEBMAIL_HOST}" "/etc/ssl/webmail" - [[ -n "$MAIL_HOSTNAME" && -d "/etc/letsencrypt/live/${MAIL_HOSTNAME}"]] && copy_cert "/etc/letsencrypt/live/${MAIL_HOSTNAME}"/etc/ssl/mail +# Certbot-Kontext +LINEAGE="${RENEWED_LINEAGE:-}" +HOST="" +if [ -n "$LINEAGE" ]; then + HOST="$(basename "$LINEAGE")" fi -# Optional: TLSA via Laravel (tolerant, falls App noch nicht gebaut) -if command -v php >/dev/null 2>&1 && [ -d /var/www/mailwolt ] && [ -f /var/www/mailwolt/artisan ]; then +did_any=0 + +maybe_copy_for_host() { + host="$1" + dir="$2" + [ -n "$host" ] || return 0 + + # Fall A: Certbot liefert RENEWED_DOMAINS (Space-getrennt) + if [ -n "${RENEWED_DOMAINS:-}" ]; then + case " ${RENEWED_DOMAINS} " in + *" ${host} "*) copy_cert "${ACME_BASE}/${host}" "${dir}" && did_any=1 ;; + esac + return 0 + fi + + # Fall B: Erst-issue / kein RENEWED_DOMAINS → über LINEAGE matchen + if [ -n "$HOST" ] && [ "$HOST" = "$host" ]; then + copy_cert "${ACME_BASE}/${host}" "${dir}" && did_any=1 + fi +} + +# Gezieltes Kopieren +maybe_copy_for_host "$UI_HOST" "/etc/ssl/ui" +maybe_copy_for_host "$WEBMAIL_HOST" "/etc/ssl/webmail" +maybe_copy_for_host "$MAIL_HOSTNAME" "/etc/ssl/mail" + +# Fallback (Erstlauf): kopiere vorhandene Lineages +if [ "$did_any" -eq 0 ]; then + [ -n "$UI_HOST" ] && [ -d "${ACME_BASE}/${UI_HOST}" ] && copy_cert "${ACME_BASE}/${UI_HOST}" "/etc/ssl/ui" + [ -n "$WEBMAIL_HOST" ] && [ -d "${ACME_BASE}/${WEBMAIL_HOST}" ] && copy_cert "${ACME_BASE}/${WEBMAIL_HOST}" "/etc/ssl/webmail" + [ -n "$MAIL_HOSTNAME" ] && [ -d "${ACME_BASE}/${MAIL_HOSTNAME}" ] && copy_cert "${ACME_BASE}/${MAIL_HOSTNAME}" "/etc/ssl/mail" +fi + +# TLSA-Refresh (tolerant falls App noch nicht ready) +if command -v php >/dev/null 2>&1 && [ -f /var/www/mailwolt/artisan ]; then (cd /var/www/mailwolt && php artisan dns:tlsa:refresh) || true fi -# Nginx nur neu laden, wenn aktiv -if systemctl is-active --quiet nginx; then - systemctl reload nginx || true +# Services neu laden +if [ -n "$HOST" ]; then + if [ -n "$MAIL_HOSTNAME" ] && [ "$HOST" = "$MAIL_HOSTNAME" ]; then + reload_services mail + else + reload_services ui + fi +else + reload_services ui fi + +exit 0 WRAP chmod +x /usr/local/sbin/mw-deploy.sh -# 2) Certbot-Deploy-Hook: ruft den Wrapper bei jeder erfolgreichen Ausstellung/Renew auf +# ------------------------------------------------------------------- +# 3) Certbot deploy-hook, der den Wrapper aufruft +# ------------------------------------------------------------------- install -d -m 0755 /etc/letsencrypt/renewal-hooks/deploy cat >/etc/letsencrypt/renewal-hooks/deploy/50-mailwolt-certs.sh <<'HOOK' -#!/usr/bin/env bash +#!/bin/sh exec /usr/local/sbin/mw-deploy.sh HOOK chmod +x /etc/letsencrypt/renewal-hooks/deploy/50-mailwolt-certs.sh log "[✓] MailWolt Deploy-Hook eingerichtet" +##!/usr/bin/env bash +#set -euo pipefail +#source ./lib.sh +# +## Persistente Installer-Variablen (werden vom Wrapper gelesen) +#install -d -m 0755 /etc/mailwolt +#cat >/etc/mailwolt/installer.env </usr/local/sbin/mw-deploy.sh <<'WRAP' +##!/usr/bin/env bash +#set -euo pipefail +# +## Installer-Variablen laden +#set +u +#[ -r /etc/mailwolt/installer.env ] && . /etc/mailwolt/installer.env +#set -u +# +#UI_HOST="${UI_HOST:-}" +#WEBMAIL_HOST="${WEBMAIL_HOST:-}" +#MAIL_HOSTNAME="${MAIL_HOSTNAME:-}" +# +## --- Kopieren statt Symlinks (damit Laravel lesen kann) --------------------- +#copy_cert() { +# local le_base="$1" target_dir="$2" +# local cert="${le_base}/fullchain.pem" +# local key="${le_base}/privkey.pem" +# +# [[ -s "$cert" && -s "$key" ]] || return 0 +# +# install -d -m 0755 "$target_dir" +# +# # Vorhandene Symlinks entfernen, sonst kopierst du in die LE-Datei hinein +# [ -L "${target_dir}/fullchain.pem" ] && rm -f "${target_dir}/fullchain.pem" +# [ -L "${target_dir}/privkey.pem" ] && rm -f "${target_dir}/privkey.pem" +# +# # Echte Dateien ablegen +# install -m 0644 "$cert" "${target_dir}/fullchain.pem" +# install -m 0600 "$key" "${target_dir}/privkey.pem" +# +# echo "[+] Copied ${target_dir}/fullchain.pem und privkey.pem ← ${le_base}" +#} +# +## Nur Domains bearbeiten, die in diesem Lauf betroffen sind. +## Bei manchen Distros ist RENEWED_DOMAINS auf Erst-issue leer -> Fallback nutzen. +#RDOMS=" ${RENEWED_DOMAINS:-} " +#did_any=0 +# +#maybe_copy_for() { +# local host="$1" dir="$2" +# [[ -z "$host" ]] && return 0 +# if [[ "$RDOMS" == *" ${host} "* ]]; then +# copy_cert "/etc/letsencrypt/live/${host}" "${dir}" +# did_any=1 +# fi +#} +# +## 1) Normalfall: nur die vom Certbot gemeldeten Hosts kopieren +#maybe_copy_for "$UI_HOST" "/etc/ssl/ui" +#maybe_copy_for "$WEBMAIL_HOST" "/etc/ssl/webmail" +#maybe_copy_for "$MAIL_HOSTNAME" "/etc/ssl/mail" +# +## 2) Fallback: Beim Erstlauf/Edge-Cases alles kopieren, was bereits existiert +#if [[ "$did_any" -eq 0 ]]; then +# [[ -n "$UI_HOST" && -d "/etc/letsencrypt/live/${UI_HOST}" ]] && copy_cert "/etc/letsencrypt/live/${UI_HOST}" "/etc/ssl/ui" +# [[ -n "$WEBMAIL_HOST" && -d "/etc/letsencrypt/live/${WEBMAIL_HOST}" ]] && copy_cert "/etc/letsencrypt/live/${WEBMAIL_HOST}" "/etc/ssl/webmail" +# [[ -n "$MAIL_HOSTNAME" && -d "/etc/letsencrypt/live/${MAIL_HOSTNAME}"]] && copy_cert "/etc/letsencrypt/live/${MAIL_HOSTNAME}"/etc/ssl/mail +#fi +# +## Optional: TLSA via Laravel (tolerant, falls App noch nicht gebaut) +#if command -v php >/dev/null 2>&1 && [ -d /var/www/mailwolt ] && [ -f /var/www/mailwolt/artisan ]; then +# (cd /var/www/mailwolt && php artisan dns:tlsa:refresh) || true +#fi +# +## Nginx nur neu laden, wenn aktiv +#if systemctl is-active --quiet nginx; then +# systemctl reload nginx || true +#fi +#WRAP +#chmod +x /usr/local/sbin/mw-deploy.sh +# +## 2) Certbot-Deploy-Hook: ruft den Wrapper bei jeder erfolgreichen Ausstellung/Renew auf +#install -d -m 0755 /etc/letsencrypt/renewal-hooks/deploy +#cat >/etc/letsencrypt/renewal-hooks/deploy/50-mailwolt-certs.sh <<'HOOK' +##!/usr/bin/env bash +#exec /usr/local/sbin/mw-deploy.sh +#HOOK +#chmod +x /etc/letsencrypt/renewal-hooks/deploy/50-mailwolt-certs.sh +# +#log "[✓] MailWolt Deploy-Hook eingerichtet" + ##!/usr/bin/env bash #set -euo pipefail #source ./lib.sh diff --git a/scripts/60-rspamd-opendkim.sh b/scripts/60-rspamd-opendkim.sh index bea8044..99500bd 100644 --- a/scripts/60-rspamd-opendkim.sh +++ b/scripts/60-rspamd-opendkim.sh @@ -18,6 +18,8 @@ DKIM_SELECTOR="${DKIM_SELECTOR:-mwl1}" # z.B. mwl1 DKIM_GENERATE="${DKIM_GENERATE:-1}" # 1=Key generieren, falls fehlt RSPAMD_CONTROLLER_PASSWORD="${RSPAMD_CONTROLLER_PASSWORD:-admin}" + +DKIM_GENERATE="0" # ────────────────────────────────────────────────────────────── # Rspamd (Controller + Milter) # ────────────────────────────────────────────────────────────── @@ -70,13 +72,13 @@ CONF chown opendkim:opendkim /etc/opendkim/TrustedHosts chmod 640 /etc/opendkim/TrustedHosts +# ── Key-Verzeichnis für SYSMAIL_DOMAIN vorbereiten ─────────────────────────── KEY_DIR="/etc/opendkim/keys/${SYSMAIL_DOMAIN}" KEY_PRIV="${KEY_DIR}/${DKIM_SELECTOR}.private" KEY_DNSTXT="${KEY_DIR}/${DKIM_SELECTOR}.txt" - install -d -m 0750 -o opendkim -g opendkim "${KEY_DIR}" -# Falls kein Key da: optional generieren (auf SYSMAIL_DOMAIN) +# ── Key optional generieren (damit sofort signiert werden kann) ────────────── if [[ ! -s "${KEY_PRIV}" && "${DKIM_GENERATE}" = "1" ]]; then if command -v opendkim-genkey >/dev/null 2>&1; then opendkim-genkey -b 2048 -s "${DKIM_SELECTOR}" -d "${SYSMAIL_DOMAIN}" -D "${KEY_DIR}" @@ -87,25 +89,27 @@ if [[ ! -s "${KEY_PRIV}" && "${DKIM_GENERATE}" = "1" ]]; then fi fi -# Tabellen schreiben (zeigen auf SYSMAIL_DOMAIN) -cat >/etc/opendkim/KeyTable < /etc/opendkim/KeyTable +: > /etc/opendkim/SigningTable +chown opendkim:opendkim /etc/opendkim/KeyTable /etc/opendkim/SigningTable +chmod 640 /etc/opendkim/KeyTable /etc/opendkim/SigningTable -cat >/etc/opendkim/SigningTable <> /etc/opendkim/KeyTable + echo "*@${SYSMAIL_DOMAIN} ${DKIM_SELECTOR}._domainkey.${SYSMAIL_DOMAIN}" \ + >> /etc/opendkim/SigningTable +fi -# Hauptkonfiguration +# ── Hauptkonfiguration ─────────────────────────────────────────────────────── cat >/etc/opendkim.conf <<'CONF' Syslog yes UMask 002 Mode sv Socket inet:8891@127.0.0.1 +PidFile /run/opendkim/opendkim.pid Canonicalization relaxed/simple On-BadSignature accept @@ -129,16 +133,26 @@ DNSTimeout 5 SignatureAlgorithm rsa-sha256 CONF -# Root-Helper zum nachträglichen Installieren von DKIM-Keys (aus der App) +# ── systemd Drop-in: /run/opendkim sicherstellen ───────────────────────────── +install -d -m 0755 /etc/systemd/system/opendkim.service.d +cat >/etc/systemd/system/opendkim.service.d/override.conf <<'EOF' +[Service] +RuntimeDirectory=opendkim +RuntimeDirectoryMode=0755 +EOF + +# Laufzeitverzeichnis sofort anlegen (erste Startphase im Installer) +install -d -o opendkim -g opendkim -m 0755 /run/opendkim + +# ── Root-Helper: DKIM-Keys später aus der App installieren ─────────────────── install -d -m 0750 /usr/local/sbin cat > /usr/local/sbin/mailwolt-install-dkim <<'EOSH' #!/usr/bin/env bash set -euo pipefail - -DOMAIN="$1" # z.B. sysmail.example.com ODER kunden.tld -SELECTOR="$2" # z.B. dkim / mwl1 -TMP_PRIV="$3" # private PEM (von App) -TMP_PUBTXT="${4:-}" # optional: fertiger TXT-String-Dateipfad +DOMAIN="$1" +SELECTOR="$2" +TMP_PRIV="$3" +TMP_PUBTXT="${4:-}" OKDIR="/etc/opendkim" KEYDIR="${OKDIR}/keys/${DOMAIN}" @@ -164,33 +178,236 @@ if [[ -n "${TMP_PUBTXT}" && -s "${TMP_PUBTXT}" ]]; then cp -f "${TMP_PUBTXT}" "/etc/mailwolt/dns/dkim-${DOMAIN}.txt" fi +# Dienst läuft evtl. schon – reload reicht if systemctl is-active --quiet opendkim; then systemctl reload opendkim || true fi - echo "OK" EOSH chown root:root /usr/local/sbin/mailwolt-install-dkim chmod 0750 /usr/local/sbin/mailwolt-install-dkim -KEY_DIR="/etc/opendkim/keys/${SYSMAIL_DOMAIN}" -KEY_PRIV="${KEY_DIR}/${DKIM_SELECTOR}.private" -KEY_DNSTXT="${KEY_DIR}/${DKIM_SELECTOR}.txt" +# ── Dienst + Postfix-Milter: IMMER aktivieren (signiert nur, wenn Key vorhanden) ── +systemctl daemon-reload +systemctl enable --now 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 + +log "[✓] Rspamd + OpenDKIM eingerichtet (OpenDKIM läuft; signiert, sobald Keys vorhanden sind)." + +##!/usr/bin/env bash +#set -euo pipefail +#source ./lib.sh +# +#log "Rspamd + OpenDKIM einrichten …" +# +## ────────────────────────────────────────────────────────────── +## ENV laden +## ────────────────────────────────────────────────────────────── +#set +u +#[ -r /etc/mailwolt/installer.env ] && . /etc/mailwolt/installer.env +#set -u +# +#BASE_DOMAIN="${BASE_DOMAIN:-example.com}" +#SYSMAIL_DOMAIN="${SYSMAIL_DOMAIN:-sysmail.${BASE_DOMAIN}}" # z.B. sysmail.example.com +#DKIM_ENABLE="${DKIM_ENABLE:-1}" # 1=OpenDKIM aktiv +#DKIM_SELECTOR="${DKIM_SELECTOR:-mwl1}" # z.B. mwl1 +#DKIM_GENERATE="${DKIM_GENERATE:-1}" # 1=Key generieren, falls fehlt +#RSPAMD_CONTROLLER_PASSWORD="${RSPAMD_CONTROLLER_PASSWORD:-admin}" +# +## ────────────────────────────────────────────────────────────── +## Rspamd (Controller + Milter) +## ────────────────────────────────────────────────────────────── +#install -d -m 0755 /etc/rspamd/local.d +# +#if command -v rspamadm >/dev/null 2>&1; then +# RSPAMD_HASH="$(rspamadm pw -p "${RSPAMD_CONTROLLER_PASSWORD}")" +#else +# RSPAMD_HASH="${RSPAMD_CONTROLLER_PASSWORD}" +#fi +# +#cat >/etc/rspamd/local.d/worker-controller.inc </etc/rspamd/local.d/worker-normal.inc <<'CONF' +#bind_socket = "127.0.0.1:11332"; +#CONF +# +#cat >/etc/rspamd/local.d/milter_headers.conf <<'CONF' +#use = ["authentication-results"]; +#header = "Authentication-Results"; +#CONF +# +#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 +# exit 0 +#fi +# +#install -d -m 0755 /etc/opendkim +#install -d -m 0750 /etc/opendkim/keys +#chown -R opendkim:opendkim /etc/opendkim +#chmod 750 /etc/opendkim/keys +# +## TrustedHosts +#cat >/etc/opendkim/TrustedHosts <<'CONF' +#127.0.0.1 +#::1 +#localhost +#CONF +#chown opendkim:opendkim /etc/opendkim/TrustedHosts +#chmod 640 /etc/opendkim/TrustedHosts +# +#KEY_DIR="/etc/opendkim/keys/${SYSMAIL_DOMAIN}" +#KEY_PRIV="${KEY_DIR}/${DKIM_SELECTOR}.private" +#KEY_DNSTXT="${KEY_DIR}/${DKIM_SELECTOR}.txt" +# +#install -d -m 0750 -o opendkim -g opendkim "${KEY_DIR}" +# +## Falls kein Key da: optional generieren (auf SYSMAIL_DOMAIN) +#if [[ ! -s "${KEY_PRIV}" && "${DKIM_GENERATE}" = "1" ]]; then +# if command -v opendkim-genkey >/dev/null 2>&1; then +# opendkim-genkey -b 2048 -s "${DKIM_SELECTOR}" -d "${SYSMAIL_DOMAIN}" -D "${KEY_DIR}" +# chown opendkim:opendkim "${KEY_DIR}/${DKIM_SELECTOR}.private" || true +# chmod 600 "${KEY_DIR}/${DKIM_SELECTOR}.private" || true +# else +# echo "[!] opendkim-genkey fehlt – kann DKIM-Key nicht generieren." +# fi +#fi +# +## Tabellen schreiben (zeigen auf SYSMAIL_DOMAIN) +#cat >/etc/opendkim/KeyTable </etc/opendkim/SigningTable </etc/opendkim.conf <<'CONF' +#Syslog yes +#UMask 002 +#Mode sv +#Socket inet:8891@127.0.0.1 +#PidFile /run/opendkim/opendkim.pid +#Canonicalization relaxed/simple +# +#On-BadSignature accept +#On-Default accept +#On-KeyNotFound accept +#On-NoSignature accept +# +#LogWhy yes +#OversignHeaders From +# +#KeyTable /etc/opendkim/KeyTable +#SigningTable refile:/etc/opendkim/SigningTable +#ExternalIgnoreList /etc/opendkim/TrustedHosts +#InternalHosts /etc/opendkim/TrustedHosts +# +#UserID opendkim:opendkim +#AutoRestart yes +#AutoRestartRate 10/1h +#Background yes +#DNSTimeout 5 +#SignatureAlgorithm rsa-sha256 +#CONF +# +# +## ────────────────────────────────────────────────────────────── +## systemd Drop-in: sorgt dafür, dass /run/opendkim existiert +## ────────────────────────────────────────────────────────────── +#install -d -m 0755 /etc/systemd/system/opendkim.service.d +#cat >/etc/systemd/system/opendkim.service.d/override.conf <<'EOF' +#[Service] +#RuntimeDirectory=opendkim +#RuntimeDirectoryMode=0755 +#EOF +# +## Laufzeitverzeichnis sofort anlegen (damit der Start im Installer klappt) +#install -d -o opendkim -g opendkim -m 0755 /run/opendkim +# +## Root-Helper zum nachträglichen Installieren von DKIM-Keys (aus der App) +#install -d -m 0750 /usr/local/sbin +#cat > /usr/local/sbin/mailwolt-install-dkim <<'EOSH' +##!/usr/bin/env bash +#set -euo pipefail +# +#DOMAIN="$1" # z.B. sysmail.example.com ODER kunden.tld +#SELECTOR="$2" # z.B. dkim / mwl1 +#TMP_PRIV="$3" # private PEM (von App) +#TMP_PUBTXT="${4:-}" # optional: fertiger TXT-String-Dateipfad +# +#OKDIR="/etc/opendkim" +#KEYDIR="${OKDIR}/keys/${DOMAIN}" +#KEYPRI="${KEYDIR}/${SELECTOR}.private" +# +#install -d -m 0750 -o opendkim -g opendkim "${KEYDIR}" +#install -m 0600 -o opendkim -g opendkim "${TMP_PRIV}" "${KEYPRI}" +# +#kt="${OKDIR}/KeyTable" +#st="${OKDIR}/SigningTable" +#touch "$kt" "$st" +#chown opendkim:opendkim "$kt" "$st" +#chmod 0640 "$kt" "$st" +# +#line_kt="${SELECTOR}._domainkey.${DOMAIN} ${DOMAIN}:${SELECTOR}:${KEYPRI}" +#grep -Fqx "$line_kt" "$kt" || echo "$line_kt" >> "$kt" +# +#line_st="*@${DOMAIN} ${SELECTOR}._domainkey.${DOMAIN}" +#grep -Fqx "$line_st" "$st" || echo "$line_st" >> "$st" +# +#if [[ -n "${TMP_PUBTXT}" && -s "${TMP_PUBTXT}" ]]; then +# install -d -m 0755 /etc/mailwolt/dns +# cp -f "${TMP_PUBTXT}" "/etc/mailwolt/dns/dkim-${DOMAIN}.txt" +#fi +# +#if systemctl is-active --quiet opendkim; then +# systemctl reload opendkim || true +#fi +# +#echo "OK" +#EOSH +#chown root:root /usr/local/sbin/mailwolt-install-dkim +#chmod 0750 /usr/local/sbin/mailwolt-install-dkim +# +#KEY_DIR="/etc/opendkim/keys/${SYSMAIL_DOMAIN}" +#KEY_PRIV="${KEY_DIR}/${DKIM_SELECTOR}.private" +#KEY_DNSTXT="${KEY_DIR}/${DKIM_SELECTOR}.txt" +# +# if [[ -s "${KEY_PRIV}" ]]; then +# systemctl enable opendkim >/dev/null 2>&1 || true +# if systemctl is-active --quiet opendkim; then +# systemctl reload opendkim || true +# fi +# /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 +# else +# echo "[i] Noch kein Private Key unter ${KEY_PRIV} – OpenDKIM bleibt aus." +# /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 +# fi + - if [[ -s "${KEY_PRIV}" ]]; then - systemctl enable opendkim >/dev/null 2>&1 || true - if systemctl is-active --quiet opendkim; then - systemctl reload opendkim || true - fi - /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 - else - echo "[i] Noch kein Private Key unter ${KEY_PRIV} – OpenDKIM bleibt aus." - /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 - fi # OpenDKIM nur starten, wenn Key vorhanden – sonst nur Rspamd aktiv lassen #if [[ -s "${KEY_PRIV}" ]]; then # systemctl enable --now opendkim || true diff --git a/scripts/80-app.sh b/scripts/80-app.sh index 6e7f308..08366d5 100644 --- a/scripts/80-app.sh +++ b/scripts/80-app.sh @@ -180,45 +180,31 @@ if [[ "${BASE_DOMAIN}" != "example.com" ]]; then sudo -u "$APP_USER" -H bash -lc "cd ${APP_DIR} && php artisan db:seed --class=SystemDomainSeeder --force" fi -set +u -[ -r /etc/mailwolt/installer.env ] && . /etc/mailwolt/installer.env -set -u - -# Defaults, falls was fehlt -DKIM_ENABLE="${DKIM_ENABLE:-1}" # 1=an, 0=aus +# --- DKIM für SYSMAIL_DOMAIN via App erzeugen & in OpenDKIM einhängen ------- +DKIM_ENABLE="${DKIM_ENABLE:-1}" DKIM_SELECTOR="${DKIM_SELECTOR:-mwl1}" SYSMAIL_DOMAIN="${SYSMAIL_DOMAIN:-sysmail.${BASE_DOMAIN}}" if [[ "${DKIM_ENABLE}" = "1" && -n "${SYSMAIL_DOMAIN}" ]]; then log "Erzeuge/aktualisiere DKIM für ${SYSMAIL_DOMAIN} (Selector: ${DKIM_SELECTOR}) …" - set +u - [ -r /etc/mailwolt/installer.env ] && . /etc/mailwolt/installer.env - set -u - - : "${SYSMAIL_DOMAIN:?SYSMAIL_DOMAIN fehlt}" - : "${DKIM_SELECTOR:=mwl1}" - - # sichere Temp-Dateien EIGENTÜMER = APP_USER (sonst Permission denied in PHP) TMP_PRIV="$(mktemp /tmp/dkim_priv_XXXXXX.pem)" TMP_TXT="$(mktemp /tmp/dkim_txt_XXXXXX.txt)" chown "${APP_USER}:${APP_GROUP}" "$TMP_PRIV" "$TMP_TXT" chmod 600 "$TMP_PRIV" "$TMP_TXT" - # Key mit deinem bestehenden DkimService generieren (läuft als APP_USER) sudo -u "${APP_USER}" -H bash -lc "cd ${APP_DIR} && php -r ' - require \"vendor/autoload.php\"; - \$app = require \"bootstrap/app.php\"; - \$kernel = \$app->make(Illuminate\\Contracts\\Console\\Kernel::class); \$kernel->bootstrap(); - \$domain = App\\Models\\Domain::firstOrCreate([\"domain\"=>\"${SYSMAIL_DOMAIN}\"],[\"is_active\"=>1,\"is_system\"=>1]); - \$svc = app(App\\Services\\DkimService::class); - \$res = \$svc->generateForDomain(\$domain, 2048, \"${DKIM_SELECTOR}\"); - file_put_contents(\"${TMP_PRIV}\", \$res[\"private_pem\"]); - file_put_contents(\"${TMP_TXT}\", \$res[\"dns_txt\"]); - echo \"OK\n\"; + require \"vendor/autoload.php\"; + \$app = require \"bootstrap/app.php\"; + \$kernel = \$app->make(Illuminate\\Contracts\\Console\\Kernel::class); \$kernel->bootstrap(); + \$domain = App\\Models\\Domain::firstOrCreate([\"domain\"=>\"${SYSMAIL_DOMAIN}\"],[\"is_active\"=>1,\"is_system\"=>1]); + \$svc = app(App\\Services\\DkimService::class); + \$res = \$svc->generateForDomain(\$domain, 2048, \"${DKIM_SELECTOR}\"); + file_put_contents(\"${TMP_PRIV}\", \$res[\"private_pem\"]); + file_put_contents(\"${TMP_TXT}\", \$res[\"dns_txt\"]); + echo \"OK\\n\"; '" - # Root-Helper installiert den Key in OpenDKIM (KeyTable/SigningTable) if [[ -x /usr/local/sbin/mailwolt-install-dkim ]]; then sudo /usr/local/sbin/mailwolt-install-dkim "${SYSMAIL_DOMAIN}" "${DKIM_SELECTOR}" "${TMP_PRIV}" "${TMP_TXT}" || true fi diff --git a/scripts/99-summary.sh b/scripts/99-summary.sh index e36711c..bf08778 100644 --- a/scripts/99-summary.sh +++ b/scripts/99-summary.sh @@ -65,9 +65,28 @@ UI_CERT_TARGET="$(real_target "$UI_CERT")" WEBMAIL_CERT_TARGET="$(real_target "$WEBMAIL_CERT")" MAIL_CERT_TARGET="$(real_target "$MAIL_CERT")" -UI_LE=$([[ -s "$UI_CERT" && -n "$UI_CERT_TARGET" && is_le_path "$UI_CERT_TARGET" ]] && echo "LE" || echo "self-signed/none") -WEBMAIL_LE=$([[ -s "$WEBMAIL_CERT" && -n "$WEBMAIL_CERT_TARGET" && is_le_path "$WEBMAIL_CERT_TARGET" ]] && echo "LE" || echo "self-signed/none") -MAIL_LE=$([[ -s "$MAIL_CERT" && -n "$MAIL_CERT_TARGET" && is_le_path "$MAIL_CERT_TARGET" ]] && echo "LE" || echo "self-signed/none") +is_le_path() { + case "$1" in + /etc/letsencrypt/live/*) return 0 ;; + *) return 1 ;; + esac +} + +# robust gegen set -u: immer ${var:-} +UI_LE="self-signed/none" +if [ -s "${UI_CERT:-}" ] && [ -n "${UI_CERT_TARGET:-}" ] && is_le_path "${UI_CERT_TARGET:-}"; then + UI_LE="LE" +fi + +WEBMAIL_LE="self-signed/none" +if [ -s "${WEBMAIL_CERT:-}" ] && [ -n "${WEBMAIL_CERT_TARGET:-}" ] && is_le_path "${WEBMAIL_CERT_TARGET:-}"; then + WEBMAIL_LE="LE" +fi + +MAIL_LE="self-signed/none" +if [ -s "${MAIL_CERT:-}" ] && [ -n "${MAIL_CERT_TARGET:-}" ] && is_le_path "${MAIL_CERT_TARGET:-}"; then + MAIL_LE="LE" +fi echo bar diff --git a/scripts/bootstrap.sh b/scripts/bootstrap.sh index 940b2ab..345c0fe 100644 --- a/scripts/bootstrap.sh +++ b/scripts/bootstrap.sh @@ -59,8 +59,6 @@ read -r -p "Webmail FQDN (z.B. webmail.domain.tld) [Enter=${WEBMAIL_SUB}. MTA_FQDN="${MTA_FQDN:-${MTA_SUB}.${BASE_DOMAIN}}" UI_FQDN="${UI_FQDN:-${UI_SUB}.${BASE_DOMAIN}}" WEBMAIL_FQDN="${WEBMAIL_FQDN:-${WEBMAIL_SUB}.${BASE_DOMAIN}}" -SYSMAIL_SUB="${SYSMAIL_SUB:-sysmail}" -SYSMAIL_DOMAIN="${SYSMAIL_SUB}.${BASE_DOMAIN}" DKIM_ENABLE="${DKIM_ENABLE:-1}" DKIM_SELECTOR="${DKIM_SELECTOR:-mwl1}" DKIM_GENERATE="${DKIM_GENERATE:-1}" @@ -77,6 +75,8 @@ 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}"