Remove istaller form Laravel
parent
8bd603733f
commit
2e59e65eb6
|
|
@ -1,64 +0,0 @@
|
|||
server {
|
||||
listen 80 default_server;
|
||||
listen [::]:80 default_server;
|
||||
|
||||
# ACME
|
||||
location ^~ /.well-known/acme-challenge/ {
|
||||
root /var/www/letsencrypt;
|
||||
allow all;
|
||||
}
|
||||
|
||||
# Wenn SSL da: redirect auf 443, sonst direkt App
|
||||
{% if ssl %}
|
||||
return 301 https://$host$request_uri;
|
||||
{% endif %}
|
||||
}
|
||||
|
||||
server {
|
||||
listen 443 ssl${NGINX_HTTP2_SUFFIX};
|
||||
listen [::]:443 ssl${NGINX_HTTP2_SUFFIX};
|
||||
|
||||
ssl_certificate ${UI_CERT};
|
||||
ssl_certificate_key ${UI_KEY};
|
||||
ssl_protocols TLSv1.2 TLSv1.3;
|
||||
|
||||
server_name _;
|
||||
|
||||
root ${APP_DIR}/public;
|
||||
index index.php index.html;
|
||||
|
||||
access_log /var/log/nginx/app_ssl_access.log;
|
||||
error_log /var/log/nginx/app_ssl_error.log;
|
||||
|
||||
client_max_body_size 25m;
|
||||
|
||||
location / { try_files $uri $uri/ /index.php?$query_string; }
|
||||
location ~ \.php$ {
|
||||
include snippets/fastcgi-php.conf;
|
||||
# Der pass (unix vs tcp) wird vom System gesetzt; Debian snippet kümmert sich
|
||||
fastcgi_pass unix:/run/php/php-fpm.sock;
|
||||
try_files $uri =404;
|
||||
}
|
||||
location ^~ /livewire/ { try_files $uri /index.php?$query_string; }
|
||||
location ~* \.(jpg|jpeg|png|gif|css|js|ico|svg)$ { expires 30d; access_log off; }
|
||||
|
||||
# WebSocket: Laravel Reverb
|
||||
location /ws/ {
|
||||
proxy_http_version 1.1;
|
||||
proxy_set_header Upgrade $http_upgrade;
|
||||
proxy_set_header Connection "Upgrade";
|
||||
proxy_set_header Host $host;
|
||||
proxy_read_timeout 60s;
|
||||
proxy_send_timeout 60s;
|
||||
proxy_pass http://127.0.0.1:8080/;
|
||||
}
|
||||
|
||||
# Reverb HTTP API
|
||||
location /apps/ {
|
||||
proxy_http_version 1.1;
|
||||
proxy_set_header Host $host;
|
||||
proxy_read_timeout 60s;
|
||||
proxy_send_timeout 60s;
|
||||
proxy_pass http://127.0.0.1:8080/apps/;
|
||||
}
|
||||
}
|
||||
|
|
@ -1,61 +0,0 @@
|
|||
#!/usr/bin/env bash
|
||||
set -euo pipefail
|
||||
source ./lib.sh
|
||||
|
||||
log "Paketquellen aktualisieren…"
|
||||
export DEBIAN_FRONTEND=noninteractive
|
||||
apt-get update -y
|
||||
|
||||
# MariaDB include-Workaround
|
||||
mkdir -p /etc/mysql /etc/mysql/mariadb.conf.d
|
||||
[[ -f /etc/mysql/mariadb.cnf ]] || echo '!include /etc/mysql/mariadb.conf.d/*.cnf' > /etc/mysql/mariadb.cnf
|
||||
|
||||
log "Pakete installieren… (das dauert etwas)"
|
||||
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 \
|
||||
fail2ban \
|
||||
ca-certificates rsyslog sudo openssl netcat-openbsd monit acl
|
||||
|
||||
# HTTP/2 prüfen
|
||||
NGINX_HTTP2_SUPPORTED=0
|
||||
if nginx -V 2>&1 | grep -q http_v2; then
|
||||
NGINX_HTTP2_SUPPORTED=1; log "Nginx: HTTP/2 verfügbar."
|
||||
else
|
||||
warn "Nginx http_v2 fehlt – versuche nginx-full…"
|
||||
apt-get install -y nginx-full || true; systemctl restart nginx || true
|
||||
nginx -V 2>&1 | grep -q http_v2 && NGINX_HTTP2_SUPPORTED=1 || warn "HTTP/2 weiterhin nicht verfügbar."
|
||||
fi
|
||||
export NGINX_HTTP2_SUFFIX=$([[ "$NGINX_HTTP2_SUPPORTED" = "1" ]] && echo " http2" || echo "")
|
||||
|
||||
# Verzeichnisse / User
|
||||
log "Verzeichnisse & Benutzer…"
|
||||
mkdir -p /etc/postfix/sql /etc/dovecot/conf.d /etc/rspamd/local.d /var/mail/vhosts
|
||||
id vmail >/dev/null 2>&1 || adduser --system --group --home /var/mail vmail
|
||||
chown -R vmail:vmail /var/mail
|
||||
|
||||
id "$APP_USER" >/dev/null 2>&1 || adduser --disabled-password --gecos "" "$APP_USER"
|
||||
usermod -a -G "$APP_GROUP" "$APP_USER"
|
||||
|
||||
# Redis absichern
|
||||
log "Redis absichern…"
|
||||
REDIS_CONF="/etc/redis/redis.conf"
|
||||
REDIS_PASS="${REDIS_PASS:-$(openssl rand -hex 16)}"
|
||||
sed -i 's/^\s*#\?\s*bind .*/bind 127.0.0.1/' "$REDIS_CONF"
|
||||
sed -i 's/^\s*#\?\s*protected-mode .*/protected-mode yes/' "$REDIS_CONF"
|
||||
if grep -qE '^\s*#?\s*requirepass ' "$REDIS_CONF"; then
|
||||
sed -i "s/^\s*#\?\s*requirepass .*/requirepass ${REDIS_PASS}/" "$REDIS_CONF"
|
||||
else
|
||||
printf "\nrequirepass %s\n" "${REDIS_PASS}" >> "$REDIS_CONF"
|
||||
fi
|
||||
systemctl enable --now redis-server
|
||||
systemctl restart redis-server
|
||||
|
|
@ -1,92 +0,0 @@
|
|||
#!/usr/bin/env bash
|
||||
set -euo pipefail
|
||||
source ./lib.sh
|
||||
|
||||
# Stabile Pfade
|
||||
MAIL_SSL_DIR="/etc/ssl/mail"
|
||||
UI_SSL_DIR="/etc/ssl/ui"
|
||||
WEBMAIL_SSL_DIR="/etc/ssl/webmail"
|
||||
|
||||
ensure_dir root root 0755 "$MAIL_SSL_DIR"
|
||||
ensure_dir root root 0755 "$UI_SSL_DIR"
|
||||
ensure_dir root root 0755 "$WEBMAIL_SSL_DIR"
|
||||
ensure_dir root root 0755 "/var/www/letsencrypt"
|
||||
|
||||
# Self-signed Quick-Gen (wenn kein LE kommt)
|
||||
self_signed(){
|
||||
local dir="$1"
|
||||
local cert="${dir}/fullchain.pem" key="${dir}/privkey.pem"
|
||||
[[ -s "$cert" && -s "$key" ]] && return 0
|
||||
log "Self-signed für $dir …"
|
||||
openssl req -x509 -newkey rsa:2048 -sha256 -days 825 -nodes \
|
||||
-subj "/CN=${SERVER_PUBLIC_IPV4}/O=${APP_NAME}/C=DE" \
|
||||
-keyout "$key" -out "$cert" >/dev/null 2>&1
|
||||
chmod 600 "$key"; chmod 644 "$cert"
|
||||
}
|
||||
|
||||
self_signed "$MAIL_SSL_DIR"
|
||||
self_signed "$UI_SSL_DIR"
|
||||
self_signed "$WEBMAIL_SSL_DIR"
|
||||
|
||||
issue_cert(){
|
||||
local host="$1"
|
||||
if resolve_ok "$host"; then
|
||||
log "LE für $host …"
|
||||
certbot certonly --agree-tos -m "${LE_EMAIL}" \
|
||||
--non-interactive --webroot -w /var/www/letsencrypt -d "$host" \
|
||||
|| warn "LE fehlgeschlagen für $host – Self-signed bleibt aktiv."
|
||||
else
|
||||
warn "DNS zeigt nicht auf diese IP: $host – LE wird übersprungen."
|
||||
fi
|
||||
}
|
||||
|
||||
link_if_present(){
|
||||
local host="$1" target_dir="$2"
|
||||
local base="/etc/letsencrypt/live/$host"
|
||||
if [[ -f "$base/fullchain.pem" && -f "$base/privkey.pem" ]]; then
|
||||
ln -sf "$base/fullchain.pem" "$target_dir/fullchain.pem"
|
||||
ln -sf "$base/privkey.pem" "$target_dir/privkey.pem"
|
||||
log "TLS verlinkt: $target_dir -> $base"
|
||||
fi
|
||||
}
|
||||
|
||||
# Echte Domain? Dann versuchen
|
||||
if [[ "$BASE_DOMAIN" != "example.com" ]]; then
|
||||
issue_cert "$UI_HOST"
|
||||
issue_cert "$WEBMAIL_HOST"
|
||||
issue_cert "$MAIL_HOSTNAME"
|
||||
|
||||
link_if_present "$UI_HOST" "$UI_SSL_DIR"
|
||||
link_if_present "$WEBMAIL_HOST" "$WEBMAIL_SSL_DIR"
|
||||
link_if_present "$MAIL_HOSTNAME" "$MAIL_SSL_DIR"
|
||||
else
|
||||
warn "BASE_DOMAIN=example.com – bleibe bei Self-signed."
|
||||
fi
|
||||
|
||||
# LE-Deploy-Hook (Symlinks aktuell halten)
|
||||
install -d /etc/letsencrypt/renewal-hooks/deploy
|
||||
cat >/etc/letsencrypt/renewal-hooks/deploy/50-mailwolt-symlinks.sh <<'HOOK'
|
||||
#!/usr/bin/env bash
|
||||
set -euo pipefail
|
||||
UI_SSL_DIR="/etc/ssl/ui"
|
||||
WEBMAIL_SSL_DIR="/etc/ssl/webmail"
|
||||
MAIL_SSL_DIR="/etc/ssl/mail"
|
||||
UI_HOST="${UI_HOST}"
|
||||
WEBMAIL_HOST="${WEBMAIL_HOST}"
|
||||
MX_HOST="${MAIL_HOSTNAME}"
|
||||
|
||||
link_if() {
|
||||
local le_base="/etc/letsencrypt/live/$1" target_dir="$2"
|
||||
if [[ -f "$le_base/fullchain.pem" && -f "$le_base/privkey.pem" ]]; then
|
||||
install -d -m 0755 "$target_dir"
|
||||
ln -sf "$le_base/fullchain.pem" "$target_dir/fullchain.pem"
|
||||
ln -sf "$le_base/privkey.pem" "$target_dir/privkey.pem"
|
||||
echo "[+] Linked $target_dir -> $le_base"
|
||||
fi
|
||||
}
|
||||
link_if "$UI_HOST" "$UI_SSL_DIR"
|
||||
link_if "$WEBMAIL_HOST" "$WEBMAIL_SSL_DIR"
|
||||
link_if "$MX_HOST" "$MAIL_SSL_DIR"
|
||||
systemctl reload nginx || true
|
||||
HOOK
|
||||
chmod +x /etc/letsencrypt/renewal-hooks/deploy/50-mailwolt-symlinks.sh
|
||||
|
|
@ -1,23 +0,0 @@
|
|||
#!/usr/bin/env bash
|
||||
set -euo pipefail
|
||||
source ./lib.sh
|
||||
|
||||
DB_NAME="${DB_NAME:-${APP_USER}}"
|
||||
DB_USER="${DB_USER:-${APP_USER}}"
|
||||
DB_PASS="${DB_PASS:-$(openssl rand -hex 16)}"
|
||||
|
||||
log "MariaDB vorbereiten…"
|
||||
systemctl enable --now mariadb
|
||||
|
||||
mysql -uroot <<SQL
|
||||
CREATE DATABASE IF NOT EXISTS ${DB_NAME} CHARACTER SET utf8mb4 COLLATE utf8mb4_unicode_ci;
|
||||
CREATE USER IF NOT EXISTS '${DB_USER}'@'localhost';
|
||||
CREATE USER IF NOT EXISTS '${DB_USER}'@'127.0.0.1';
|
||||
ALTER USER '${DB_USER}'@'localhost' IDENTIFIED BY '${DB_PASS}';
|
||||
ALTER USER '${DB_USER}'@'127.0.0.1' IDENTIFIED BY '${DB_PASS}';
|
||||
GRANT ALL PRIVILEGES ON ${DB_NAME}.* TO '${DB_USER}'@'localhost';
|
||||
GRANT ALL PRIVILEGES ON ${DB_NAME}.* TO '${DB_USER}'@'127.0.0.1';
|
||||
FLUSH PRIVILEGES;
|
||||
SQL
|
||||
|
||||
export DB_NAME DB_USER DB_PASS
|
||||
|
|
@ -1,67 +0,0 @@
|
|||
#!/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 "Postfix konfigurieren…"
|
||||
postconf -e "myhostname = ${MAIL_HOSTNAME}"
|
||||
postconf -e "myorigin = \$myhostname"
|
||||
postconf -e "mydestination = "
|
||||
postconf -e "inet_interfaces = all"
|
||||
postconf -e "inet_protocols = ipv4"
|
||||
postconf -e "smtpd_banner = \$myhostname ESMTP"
|
||||
|
||||
postconf -e "smtpd_tls_cert_file=${MAIL_CERT}"
|
||||
postconf -e "smtpd_tls_key_file=${MAIL_KEY}"
|
||||
postconf -e "smtpd_tls_security_level = may"
|
||||
postconf -e "smtp_tls_security_level = may"
|
||||
postconf -e "smtpd_tls_received_header = yes"
|
||||
postconf -e "smtpd_tls_protocols=!SSLv2,!SSLv3"
|
||||
postconf -e "smtpd_tls_mandatory_protocols=!SSLv2,!SSLv3"
|
||||
postconf -e "smtpd_tls_loglevel=1"
|
||||
postconf -e "smtp_tls_loglevel=1"
|
||||
|
||||
postconf -e "disable_vrfy_command = yes"
|
||||
postconf -e "smtpd_helo_required = yes"
|
||||
|
||||
postconf -e "milter_default_action = accept"
|
||||
postconf -e "milter_protocol = 6"
|
||||
postconf -e "smtpd_milters = inet:127.0.0.1:11332, inet:127.0.0.1:8891"
|
||||
postconf -e "non_smtpd_milters = inet:127.0.0.1:11332, inet:127.0.0.1:8891"
|
||||
|
||||
postconf -e "smtpd_sasl_type = dovecot"
|
||||
postconf -e "smtpd_sasl_path = private/auth"
|
||||
postconf -e "smtpd_sasl_auth_enable = yes"
|
||||
postconf -e "smtpd_sasl_security_options = noanonymous"
|
||||
|
||||
postconf -e "smtpd_recipient_restrictions = permit_mynetworks, permit_sasl_authenticated, reject_unauth_destination"
|
||||
postconf -e "smtpd_relay_restrictions = permit_mynetworks, reject_unauth_destination"
|
||||
|
||||
postconf -M "smtp/inet=smtp inet n - n - - smtpd -o smtpd_peername_lookup=no -o smtpd_timeout=30s"
|
||||
postconf -M "submission/inet=submission inet n - n - - smtpd -o syslog_name=postfix/submission -o smtpd_peername_lookup=no -o smtpd_tls_security_level=encrypt -o smtpd_tls_auth_only=yes -o smtpd_sasl_auth_enable=yes -o smtpd_relay_restrictions=permit_sasl_authenticated,reject -o smtpd_recipient_restrictions=permit_sasl_authenticated,reject"
|
||||
postconf -M "smtps/inet=smtps inet n - n - - smtpd -o syslog_name=postfix/smtps -o smtpd_peername_lookup=no -o smtpd_tls_wrappermode=yes -o smtpd_tls_auth_only=yes -o smtpd_sasl_auth_enable=yes -o smtpd_relay_restrictions=permit_sasl_authenticated,reject -o smtpd_recipient_restrictions=permit_sasl_authenticated,reject"
|
||||
|
||||
install -d -o root -g postfix -m 750 /etc/postfix/sql
|
||||
|
||||
cat > /etc/postfix/sql/mysql-virtual-mailbox-maps.cf <<CONF
|
||||
hosts = 127.0.0.1
|
||||
user = ${DB_USER}
|
||||
password = ${DB_PASS}
|
||||
dbname = ${DB_NAME}
|
||||
query = SELECT 1 FROM mail_users u JOIN domains d ON d.id = u.domain_id WHERE u.email = '%s' AND u.is_active = 1 AND d.is_active = 1 LIMIT 1;
|
||||
CONF
|
||||
chown root:postfix /etc/postfix/sql/mysql-virtual-mailbox-maps.cf; chmod 640 /etc/postfix/sql/mysql-virtual-mailbox-maps.cf
|
||||
|
||||
cat > /etc/postfix/sql/mysql-virtual-alias-maps.cf <<CONF
|
||||
hosts = 127.0.0.1
|
||||
user = ${DB_USER}
|
||||
password = ${DB_PASS}
|
||||
dbname = ${DB_NAME}
|
||||
query = SELECT destination FROM mail_aliases a JOIN domains d ON d.id = a.domain_id WHERE a.source = '%s' AND a.is_active = 1 AND d.is_active = 1 LIMIT 1;
|
||||
CONF
|
||||
chown root:postfix /etc/postfix/sql/mysql-virtual-alias-maps.cf; chmod 640 /etc/postfix/sql/mysql-virtual-alias-maps.cf
|
||||
|
||||
systemctl enable postfix >/dev/null 2>&1 || true
|
||||
|
|
@ -1,94 +0,0 @@
|
|||
#!/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…"
|
||||
|
||||
cat > /etc/dovecot/dovecot.conf <<'CONF'
|
||||
!include_try /etc/dovecot/conf.d/*.conf
|
||||
CONF
|
||||
|
||||
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
|
||||
CONF
|
||||
|
||||
cat > /etc/dovecot/conf.d/10-auth.conf <<'CONF'
|
||||
disable_plaintext_auth = yes
|
||||
auth_mechanisms = plain login
|
||||
!include_try auth-sql.conf.ext
|
||||
CONF
|
||||
|
||||
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
|
||||
|
||||
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=vmail 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
|
||||
|
||||
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
|
||||
|
||||
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
|
||||
|
||||
mkdir -p /var/spool/postfix/private
|
||||
chown postfix:postfix /var/spool/postfix /var/spool/postfix/private
|
||||
chmod 0755 /var/spool/postfix /var/spool/postfix/private
|
||||
|
||||
systemctl enable dovecot >/dev/null 2>&1 || true
|
||||
|
|
@ -1,26 +0,0 @@
|
|||
#!/usr/bin/env bash
|
||||
set -euo pipefail
|
||||
source ./lib.sh
|
||||
|
||||
log "Rspamd + OpenDKIM aktivieren…"
|
||||
|
||||
cat > /etc/rspamd/local.d/worker-controller.inc <<'CONF'
|
||||
password = "admin";
|
||||
bind_socket = "127.0.0.1:11334";
|
||||
CONF
|
||||
systemctl enable --now rspamd || true
|
||||
|
||||
cat > /etc/opendkim.conf <<'CONF'
|
||||
Syslog yes
|
||||
UMask 002
|
||||
Mode sv
|
||||
Socket inet:8891@127.0.0.1
|
||||
Canonicalization relaxed/simple
|
||||
On-BadSignature accept
|
||||
On-Default accept
|
||||
On-KeyNotFound accept
|
||||
On-NoSignature accept
|
||||
LogWhy yes
|
||||
OversignHeaders From
|
||||
CONF
|
||||
systemctl enable --now opendkim || true
|
||||
|
|
@ -1,26 +0,0 @@
|
|||
#!/usr/bin/env bash
|
||||
set -euo pipefail
|
||||
source ./lib.sh
|
||||
|
||||
NGINX_SITE="/etc/nginx/sites-available/${APP_USER}.conf"
|
||||
NGINX_SITE_LINK="/etc/nginx/sites-enabled/${APP_USER}.conf"
|
||||
TEMPLATE="$(cd .. && pwd)/config/nginx/site.conf.tmpl"
|
||||
|
||||
# Platzhalter für Template
|
||||
export APP_DIR
|
||||
export UI_SSL_DIR="/etc/ssl/ui"
|
||||
export UI_CERT="${UI_SSL_DIR}/fullchain.pem"
|
||||
export UI_KEY="${UI_SSL_DIR}/privkey.pem"
|
||||
export NGINX_HTTP2_SUFFIX
|
||||
|
||||
# Template -> Site
|
||||
log "Nginx konfigurieren…"
|
||||
envsubst '$APP_DIR $UI_CERT $UI_KEY $NGINX_HTTP2_SUFFIX' < "$TEMPLATE" > "$NGINX_SITE"
|
||||
|
||||
ln -sf "$NGINX_SITE" "$NGINX_SITE_LINK"
|
||||
if nginx -t; then
|
||||
systemctl enable --now nginx
|
||||
systemctl reload nginx || true
|
||||
else
|
||||
die "Nginx-Konfiguration fehlerhaft – /var/log/nginx prüfen."
|
||||
fi
|
||||
|
|
@ -1,139 +0,0 @@
|
|||
#!/usr/bin/env bash
|
||||
set -euo pipefail
|
||||
source ./lib.sh
|
||||
|
||||
log "Laravel bereitstellen…"
|
||||
mkdir -p "$(dirname "$APP_DIR")"; chown -R "$APP_USER":"$APP_GROUP" "$(dirname "$APP_DIR")"
|
||||
|
||||
if [[ ! -d "${APP_DIR}/.git" ]]; then
|
||||
sudo -u "$APP_USER" -H bash -lc "git clone --depth=1 -b ${GIT_BRANCH} ${GIT_REPO} ${APP_DIR}"
|
||||
else
|
||||
sudo -u "$APP_USER" -H bash -lc "
|
||||
set -e
|
||||
cd ${APP_DIR}
|
||||
git fetch --depth=1 origin ${GIT_BRANCH} || true
|
||||
git checkout ${GIT_BRANCH} 2>/dev/null || git checkout -B ${GIT_BRANCH}
|
||||
if git merge-base --is-ancestor HEAD origin/${GIT_BRANCH}; then git pull --ff-only; else git reset --hard origin/${GIT_BRANCH}; git clean -fd; fi
|
||||
"
|
||||
fi
|
||||
|
||||
if [[ -f "${APP_DIR}/composer.json" ]]; then
|
||||
sudo -u "$APP_USER" -H bash -lc "cd ${APP_DIR} && composer install --no-interaction --prefer-dist --no-dev"
|
||||
fi
|
||||
|
||||
# .env
|
||||
ENV_FILE="${APP_DIR}/.env"
|
||||
sudo -u "$APP_USER" -H bash -lc "cd ${APP_DIR} && cp -n .env.example .env || true"
|
||||
grep -q '^APP_KEY=' "${ENV_FILE}" || sudo -u "$APP_USER" -H bash -lc "cd ${APP_DIR} && php artisan key:generate --force || true"
|
||||
|
||||
upsert_env(){
|
||||
local k="$1" v="$2"
|
||||
local ek ev; ek="$(printf '%s' "$k" | sed -e 's/[.[\*^$(){}+?|/]/\\&/g')"; ev="$(printf '%s' "$v" | sed -e 's/[&/]/\\&/g')"
|
||||
if grep -qE "^[#[:space:]]*${ek}=" "$ENV_FILE"; then
|
||||
sed -Ei "s|^[#[:space:]]*${ek}=.*|${k}=${ev}|g" "$ENV_FILE"
|
||||
else
|
||||
printf '%s=%s\n' "$k" "$v" >> "$ENV_FILE"
|
||||
fi
|
||||
}
|
||||
|
||||
# APP_URL/Host
|
||||
APP_HOST_VAL="$SERVER_PUBLIC_IPV4"
|
||||
UI_LE_CERT="/etc/letsencrypt/live/${UI_HOST}/fullchain.pem"
|
||||
UI_LE_KEY="/etc/letsencrypt/live/${UI_HOST}/privkey.pem"
|
||||
if [[ "$BASE_DOMAIN" != "example.com" && -n "$UI_HOST" ]] && ( resolve_ok "$UI_HOST" || [[ -f "$UI_LE_CERT" && -f "$UI_LE_KEY" ]] ); then
|
||||
APP_HOST_VAL="$UI_HOST"
|
||||
fi
|
||||
if [[ "$APP_HOST_VAL" = "$UI_HOST" && -f "$UI_LE_CERT" && -f "$UI_LE_KEY" ]]; then
|
||||
APP_URL_VAL="https://${UI_HOST}"
|
||||
else
|
||||
if [[ -f "/etc/ssl/ui/fullchain.pem" && -f "/etc/ssl/ui/privkey.pem" ]]; then
|
||||
APP_URL_VAL="https://${SERVER_PUBLIC_IPV4}"
|
||||
else
|
||||
APP_URL_VAL="http://${SERVER_PUBLIC_IPV4}"
|
||||
fi
|
||||
fi
|
||||
|
||||
# .env schreiben
|
||||
upsert_env APP_URL "${APP_URL_VAL}"
|
||||
upsert_env APP_HOST "${APP_HOST_VAL}"
|
||||
upsert_env APP_NAME "${APP_NAME}"
|
||||
upsert_env APP_ENV "${APP_ENV}"
|
||||
upsert_env APP_DEBUG "${APP_DEBUG}"
|
||||
upsert_env APP_LOCALE "de"
|
||||
upsert_env APP_FALLBACK_LOCALE "en"
|
||||
|
||||
upsert_env SERVER_PUBLIC_IPV4 "${SERVER_PUBLIC_IPV4}"
|
||||
upsert_env SERVER_PUBLIC_IPV6 "${SERVER_PUBLIC_IPV6:-}"
|
||||
|
||||
upsert_env BASE_DOMAIN "${BASE_DOMAIN}"
|
||||
upsert_env UI_SUB "${UI_SUB}"
|
||||
upsert_env WEBMAIL_SUB "${WEBMAIL_SUB}"
|
||||
upsert_env SYSTEM_SUB "${SYSTEM_SUB}"
|
||||
upsert_env MTA_SUB "${MTA_SUB}"
|
||||
upsert_env LE_EMAIL "${LE_EMAIL}"
|
||||
|
||||
upsert_env DB_CONNECTION "mysql"
|
||||
upsert_env DB_HOST "127.0.0.1"
|
||||
upsert_env DB_PORT "3306"
|
||||
upsert_env DB_DATABASE "${DB_NAME}"
|
||||
upsert_env DB_USERNAME "${DB_USER}"
|
||||
upsert_env DB_PASSWORD "${DB_PASS}"
|
||||
|
||||
upsert_env CACHE_SETTINGS_STORE "redis"
|
||||
upsert_env CACHE_STORE "redis"
|
||||
upsert_env CACHE_DRIVER "redis"
|
||||
upsert_env CACHE_PREFIX "${APP_USER_PREFIX}_cache:"
|
||||
upsert_env SESSION_DRIVER "redis"
|
||||
upsert_env SESSION_SECURE_COOKIE "true"
|
||||
upsert_env SESSION_SAMESITE "lax"
|
||||
upsert_env REDIS_CLIENT "phpredis"
|
||||
upsert_env REDIS_HOST "127.0.0.1"
|
||||
upsert_env REDIS_PORT "6379"
|
||||
upsert_env REDIS_PASSWORD "${REDIS_PASS}"
|
||||
upsert_env REDIS_DB "0"
|
||||
upsert_env REDIS_CACHE_DB "1"
|
||||
upsert_env REDIS_CACHE_CONNECTION "cache"
|
||||
upsert_env REDIS_CACHE_LOCK_CONNECTION "default"
|
||||
|
||||
# Reverb / Queue (wie bei dir)
|
||||
upsert_env BROADCAST_DRIVER "reverb"
|
||||
upsert_env QUEUE_CONNECTION "redis"
|
||||
upsert_env LOG_CHANNEL "daily"
|
||||
upsert_env REVERB_APP_ID "${APP_USER_PREFIX}"
|
||||
upsert_env REVERB_APP_KEY "${APP_USER_PREFIX}_$(openssl rand -hex 16)"
|
||||
upsert_env REVERB_APP_SECRET "${APP_USER_PREFIX}_$(openssl rand -hex 32)"
|
||||
upsert_env REVERB_HOST "\${APP_HOST}"
|
||||
upsert_env REVERB_PORT "443"
|
||||
upsert_env REVERB_SCHEME "https"
|
||||
upsert_env REVERB_PATH "/ws"
|
||||
upsert_env REVERB_SCALING_ENABLED "true"
|
||||
upsert_env REVERB_SCALING_CHANNEL "reverb"
|
||||
upsert_env VITE_REVERB_APP_KEY "\${REVERB_APP_KEY}"
|
||||
upsert_env VITE_REVERB_HOST "\${REVERB_HOST}"
|
||||
upsert_env VITE_REVERB_PORT "\${REVERB_PORT}"
|
||||
upsert_env VITE_REVERB_SCHEME "\${REVERB_SCHEME}"
|
||||
upsert_env VITE_REVERB_PATH "\${REVERB_PATH}"
|
||||
upsert_env REVERB_SERVER_APP_KEY "\${REVERB_APP_KEY}"
|
||||
upsert_env REVERB_SERVER_HOST "127.0.0.1"
|
||||
upsert_env REVERB_SERVER_PORT "8080"
|
||||
upsert_env REVERB_SERVER_PATH ""
|
||||
upsert_env REVERB_SERVER_SCHEME "http"
|
||||
|
||||
# Optimize + Migrate + Seed
|
||||
sudo -u "$APP_USER" -H bash -lc "cd ${APP_DIR} && php artisan optimize:clear && php artisan config:cache"
|
||||
sudo systemctl restart php*-fpm || true
|
||||
|
||||
sudo -u "$APP_USER" -H bash -lc "
|
||||
set -e
|
||||
cd ${APP_DIR}
|
||||
php artisan optimize:clear
|
||||
php artisan migrate --force
|
||||
php artisan config:cache
|
||||
php artisan optimize:clear
|
||||
"
|
||||
|
||||
if [[ "$BASE_DOMAIN" != "example.com" ]]; then
|
||||
sudo -u "$APP_USER" -H bash -lc "cd ${APP_DIR} && php artisan db:seed --class=SystemDomainSeeder --no-interaction || true"
|
||||
else
|
||||
echo "[i] BASE_DOMAIN=example.com – Seeder übersprungen."
|
||||
fi
|
||||
|
|
@ -1,105 +0,0 @@
|
|||
#!/usr/bin/env bash
|
||||
set -euo pipefail
|
||||
source ./lib.sh
|
||||
|
||||
log "systemd Units (Reverb/Schedule/Queue)…"
|
||||
|
||||
cat > /etc/systemd/system/${APP_USER}-ws.service <<EOF
|
||||
[Unit]
|
||||
Description=${APP_NAME} WebSocket Backend
|
||||
After=network-online.target
|
||||
Wants=network-online.target
|
||||
[Service]
|
||||
Type=simple
|
||||
Environment=NODE_ENV=production WS_PORT=8080
|
||||
User=${APP_USER}
|
||||
Group=${APP_GROUP}
|
||||
WorkingDirectory=${APP_DIR}
|
||||
ExecStartPre=/usr/bin/bash -lc 'test -f .env'
|
||||
ExecStartPre=/usr/bin/bash -lc 'test -d vendor'
|
||||
ExecStart=/usr/bin/php artisan reverb:start --host=127.0.0.1 --port=8080 --no-interaction
|
||||
Restart=always
|
||||
RestartSec=2
|
||||
StandardOutput=append:/var/log/${APP_USER}-ws.log
|
||||
StandardError=append:/var/log/${APP_USER}-ws.log
|
||||
KillSignal=SIGINT
|
||||
TimeoutStopSec=15
|
||||
[Install]
|
||||
WantedBy=multi-user.target
|
||||
EOF
|
||||
|
||||
cat > /etc/systemd/system/${APP_USER}-schedule.service <<EOF
|
||||
[Unit]
|
||||
Description=${APP_NAME} Laravel Scheduler
|
||||
After=network-online.target
|
||||
Wants=network-online.target
|
||||
[Service]
|
||||
Type=simple
|
||||
User=${APP_USER}
|
||||
Group=${APP_GROUP}
|
||||
WorkingDirectory=${APP_DIR}
|
||||
ExecStartPre=/usr/bin/bash -lc 'test -f .env'
|
||||
ExecStartPre=/usr/bin/bash -lc 'test -d vendor'
|
||||
ExecStart=/usr/bin/php artisan schedule:work
|
||||
Restart=always
|
||||
RestartSec=2
|
||||
StandardOutput=append:/var/log/${APP_USER}-schedule.log
|
||||
StandardError=append:/var/log/${APP_USER}-schedule.log
|
||||
KillSignal=SIGINT
|
||||
TimeoutStopSec=15
|
||||
[Install]
|
||||
WantedBy=multi-user.target
|
||||
EOF
|
||||
|
||||
cat > /etc/systemd/system/${APP_USER}-queue.service <<EOF
|
||||
[Unit]
|
||||
Description=${APP_NAME} Queue Worker
|
||||
After=network-online.target
|
||||
Wants=network-online.target
|
||||
[Service]
|
||||
Type=simple
|
||||
User=${APP_USER}
|
||||
Group=${APP_GROUP}
|
||||
WorkingDirectory=${APP_DIR}
|
||||
ExecStartPre=/usr/bin/bash -lc 'test -f .env'
|
||||
ExecStartPre=/usr/bin/bash -lc 'test -d vendor'
|
||||
ExecStart=/usr/bin/php artisan queue:work --queue=default,notify --tries=1
|
||||
Restart=always
|
||||
RestartSec=2
|
||||
StandardOutput=append:/var/log/${APP_USER}-queue.log
|
||||
StandardError=append:/var/log/${APP_USER}-queue.log
|
||||
KillSignal=SIGINT
|
||||
TimeoutStopSec=15
|
||||
[Install]
|
||||
WantedBy=multi-user.target
|
||||
EOF
|
||||
|
||||
chown root:root /etc/systemd/system/${APP_USER}-*.service
|
||||
chmod 644 /etc/systemd/system/${APP_USER}-*.service
|
||||
touch /var/log/${APP_USER}-ws.log /var/log/${APP_USER}-schedule.log /var/log/${APP_USER}-queue.log
|
||||
chown ${APP_USER}:${APP_GROUP} /var/log/${APP_USER}-*.log
|
||||
chmod 664 /var/log/${APP_USER}-*.log
|
||||
|
||||
systemctl daemon-reload
|
||||
|
||||
# Reverb optional: nur starten, wenn Artisan-Command existiert
|
||||
if sudo -u "$APP_USER" -H bash -lc "cd ${APP_DIR} && php artisan list --no-ansi | grep -qE '(^| )reverb:start( |$)'"; then
|
||||
systemctl enable --now ${APP_USER}-ws
|
||||
else
|
||||
systemctl disable --now ${APP_USER}-ws >/dev/null 2>&1 || true
|
||||
fi
|
||||
systemctl enable --now ${APP_USER}-schedule
|
||||
systemctl enable --now ${APP_USER}-queue
|
||||
|
||||
systemctl reload nginx || true
|
||||
systemctl restart php*-fpm || true
|
||||
|
||||
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
|
||||
}
|
||||
if db_ready; then
|
||||
systemctl reload postfix || true
|
||||
systemctl reload dovecot || true
|
||||
else
|
||||
echo "[i] DB noch nicht migriert – überspringe Postfix/Dovecot reload."
|
||||
fi
|
||||
|
|
@ -1,62 +0,0 @@
|
|||
#!/usr/bin/env bash
|
||||
set -euo pipefail
|
||||
source ./lib.sh
|
||||
|
||||
log "Monit konfigurieren…"
|
||||
cat > /etc/monit/monitrc <<'EOF'
|
||||
set daemon 60
|
||||
set logfile syslog facility log_daemon
|
||||
|
||||
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 tcp ssl then restart
|
||||
if failed port 587 type tcp then restart
|
||||
|
||||
check process dovecot with pidfile /var/run/dovecot/master.pid
|
||||
start program = "/bin/systemctl start dovecot"
|
||||
stop program = "/bin/systemctl stop dovecot"
|
||||
if failed port 143 type tcp then restart
|
||||
if failed port 993 type tcp ssl then restart
|
||||
if failed port 110 type tcp then restart
|
||||
if failed port 995 type tcp ssl then restart
|
||||
|
||||
check process mariadb with pidfile /var/run/mysqld/mysqld.pid
|
||||
start program = "/bin/systemctl start mariadb"
|
||||
stop program = "/bin/systemctl stop mariadb"
|
||||
if failed port 3306 type tcp then restart
|
||||
|
||||
check process redis-server with pidfile /run/redis/redis-server.pid
|
||||
start program = "/bin/systemctl start redis-server"
|
||||
stop program = "/bin/systemctl stop redis-server"
|
||||
if failed port 6379 type tcp then restart
|
||||
|
||||
check process rspamd with pidfile /run/rspamd/rspamd.pid
|
||||
start program = "/bin/systemctl start rspamd"
|
||||
stop program = "/bin/systemctl stop rspamd"
|
||||
if failed port 11332 type tcp then restart
|
||||
|
||||
check process opendkim with pidfile /run/opendkim/opendkim.pid
|
||||
start program = "/bin/systemctl start opendkim"
|
||||
stop program = "/bin/systemctl stop opendkim"
|
||||
if failed port 8891 type tcp then restart
|
||||
|
||||
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 tcp ssl then restart
|
||||
|
||||
# Reverb WebSocket
|
||||
check process mailwolt-ws matching "reverb:start"
|
||||
start program = "/bin/systemctl start mailwolt-ws"
|
||||
stop program = "/bin/systemctl stop mailwolt-ws"
|
||||
if failed host 127.0.0.1 port 8080 type tcp for 2 cycles then restart
|
||||
if 5 restarts within 5 cycles then timeout
|
||||
EOF
|
||||
|
||||
chmod 600 /etc/monit/monitrc
|
||||
monit -t && systemctl enable --now monit
|
||||
monit reload
|
||||
monit summary || true
|
||||
|
|
@ -1,56 +0,0 @@
|
|||
#!/usr/bin/env bash
|
||||
set -euo pipefail
|
||||
|
||||
install -d /usr/local/bin
|
||||
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 '?')"
|
||||
mhz="$(LC_ALL=C lscpu 2>/dev/null | awk -F: '/MHz/{gsub(/ /,"",$2); printf("%.0f MHz",$2); exit}')"
|
||||
load="$(awk '{print $1" / "$2" / "$3}' /proc/loadavg 2>/dev/null)"
|
||||
mem_total="$(awk '/MemTotal/{printf "%.2f GB",$2/1024/1024}' /proc/meminfo)"
|
||||
mem_free="$(awk '/MemAvailable/{printf "%.2f GB",$2/1024/1024}' /proc/meminfo)"
|
||||
svc_status(){ 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}(external:${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}Core(s) :${NC} %s core(s) at ${CY}%s${NC}\n" "$cores" "${mhz:-?}"
|
||||
printf "${GY}Load :${NC} %s (1 / 5 / 15)\n" "${load:-?}"
|
||||
printf "${GY}Memory :${NC} ${RD}%s${NC} ${GY}(free)${NC} / ${CY}%s${NC} ${GY}(total)${NC}\n" "${mem_free:-?}" "${mem_total:-?}"
|
||||
echo
|
||||
printf "${GY}Services :${NC} postfix: $(svc_status postfix) dovecot: $(svc_status dovecot) nginx: $(svc_status nginx) mariadb: $(svc_status mariadb) redis: $(svc_status redis)\n"
|
||||
SH
|
||||
chmod +x /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
|
||||
[[ -f /etc/update-motd.d/80-livepatch ]] && chmod -x /etc/update-motd.d/80-livepatch || 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
|
||||
|
|
@ -1,49 +0,0 @@
|
|||
#!/usr/bin/env bash
|
||||
set -euo pipefail
|
||||
source ./lib.sh
|
||||
|
||||
ok(){ echo -e " [${GREEN}OK${NC}]"; }
|
||||
fail(){ echo -e " [${RED}FAIL${NC}]"; }
|
||||
|
||||
echo "[+] Quick-Healthchecks…"
|
||||
printf " • MariaDB … " ; mysqladmin ping --silent >/dev/null 2>&1 && ok || fail
|
||||
printf " • Redis … " ; if command -v redis-cli >/dev/null 2>&1; then
|
||||
if [[ -n "${REDIS_PASS:-}" && "${REDIS_PASS}" != "null" ]]; then redis-cli -a "${REDIS_PASS}" ping 2>/dev/null | grep -q PONG && ok || fail
|
||||
else redis-cli ping 2>/dev/null | grep -q PONG && ok || fail; fi
|
||||
else fail; fi
|
||||
|
||||
# PHP-FPM
|
||||
detect_php_fpm_sock(){
|
||||
for v in 8.3 8.2 8.1 8.0 7.4; do s="/run/php/php${v}-fpm.sock"; [[ -S "$s" ]] && { echo "$s"; return; }; done
|
||||
[[ -S "/run/php/php-fpm.sock" ]] && { echo "/run/php/php-fpm.sock"; return; }
|
||||
echo "127.0.0.1:9000"
|
||||
}
|
||||
PHP_FPM_SOCK="$(detect_php_fpm_sock)"
|
||||
printf " • PHP-FPM … " ; if [[ "$PHP_FPM_SOCK" == 127.0.0.1:9000 ]]; then ss -ltn | grep -q ":9000 " && ok || fail; else [[ -S "$PHP_FPM_SOCK" ]] && ok || fail; fi
|
||||
|
||||
# App HTTP
|
||||
printf " • App … " ; if command -v curl >/dev/null 2>&1; then
|
||||
if [[ -f "/etc/ssl/ui/fullchain.pem" && -f "/etc/ssl/ui/privkey.pem" ]]; then curl -skI "https://127.0.0.1" >/dev/null 2>&1 && ok || fail; else curl -sI "http://127.0.0.1" >/dev/null 2>&1 && ok || fail; fi
|
||||
else echo -e " ${GREY}(curl fehlt)${NC}"; fi
|
||||
|
||||
check_port(){ local label="$1" cmd="$2"; printf " • %-5s … " "$label"; timeout 8s bash -lc "$cmd" >/dev/null 2>&1 && ok || fail; }
|
||||
check_port "25" 'printf "QUIT\r\n" | nc -w 3 127.0.0.1 25'
|
||||
check_port "465" 'printf "QUIT\r\n" | openssl s_client -connect 127.0.0.1:465 -quiet -ign_eof'
|
||||
check_port "587" 'printf "EHLO x\r\nSTARTTLS\r\nQUIT\r\n" | openssl s_client -starttls smtp -connect 127.0.0.1:587 -quiet -ign_eof'
|
||||
check_port "110" 'printf "QUIT\r\n" | nc -w 3 127.0.0.1 110'
|
||||
check_port "995" 'printf "QUIT\r\n" | openssl s_client -connect 127.0.0.1:995 -quiet -ign_eof'
|
||||
check_port "143" 'printf ". LOGOUT\r\n" | nc -w 3 127.0.0.1 143'
|
||||
check_port "993" 'printf ". LOGOUT\r\n" | openssl s_client -connect 127.0.0.1:993 -quiet -ign_eof'
|
||||
|
||||
# Abschluss
|
||||
echo -e "
|
||||
${GREEN}${BAR}${NC}
|
||||
${GREEN} ✔ ${APP_NAME} Bootstrap abgeschlossen${NC}
|
||||
${GREEN}${BAR}${NC}
|
||||
Aufruf UI: ${CYAN}$( [[ -f /etc/ssl/ui/fullchain.pem ]] && echo https || echo http )://${SERVER_PUBLIC_IPV4}${NC}
|
||||
UI Host bevorzugt: ${GREY}${UI_HOST}${NC}
|
||||
Mail-Host: ${GREY}${MAIL_HOSTNAME}${NC}
|
||||
Nginx Site: ${GREY}/etc/nginx/sites-available/${APP_USER}.conf${NC}
|
||||
TLS (stabile Pfade): ${GREY}/etc/ssl/{ui,webmail,mail}/{fullchain.pem,privkey.pem}${NC}
|
||||
${GREEN}${BAR}${NC}
|
||||
"
|
||||
|
|
@ -1,63 +0,0 @@
|
|||
#!/usr/bin/env bash
|
||||
set -euo pipefail
|
||||
cd "$(dirname "$0")"
|
||||
source ./lib.sh
|
||||
|
||||
require_root
|
||||
header
|
||||
|
||||
# ── Pflicht: Mailserver-FQDN ──────────────────────────────────────────────
|
||||
MAIL_FQDN="${MAIL_FQDN:-}"
|
||||
if [[ -z "${MAIL_FQDN}" ]]; then
|
||||
read -r -p "Mailserver FQDN (z.B. mx.example.com): " MAIL_FQDN
|
||||
fi
|
||||
[[ "$MAIL_FQDN" == *.* ]] || die "MAIL_FQDN (z.B. mx.example.com) ist Pflicht."
|
||||
|
||||
# Ableitungen
|
||||
MTA_SUB="${MAIL_FQDN%%.*}"
|
||||
BASE_DOMAIN="${MAIL_FQDN#*.}"
|
||||
UI_SUB="${UI_SUB:-ui}"
|
||||
WEBMAIL_SUB="${WEBMAIL_SUB:-webmail}"
|
||||
SYSTEM_SUB="${SYSTEM_SUB:-system}" # kommt aus Seeder (App), hier nur Derivate
|
||||
|
||||
export APP_NAME="${APP_NAME:-MailWolt}"
|
||||
export APP_ENV="${APP_ENV:-production}"
|
||||
export APP_DEBUG="${APP_DEBUG:-false}"
|
||||
|
||||
export BASE_DOMAIN UI_SUB WEBMAIL_SUB MTA_SUB SYSTEM_SUB
|
||||
export UI_HOST="${UI_SUB}.${BASE_DOMAIN}"
|
||||
export WEBMAIL_HOST="${WEBMAIL_SUB}.${BASE_DOMAIN}"
|
||||
export MAIL_HOSTNAME="${MAIL_FQDN}"
|
||||
export SYSTEM_HOSTNAME="${SYSTEM_SUB}.${BASE_DOMAIN}"
|
||||
|
||||
export SERVER_PUBLIC_IPV4="$(detect_ip)"
|
||||
export SERVER_PUBLIC_IPV6="$(detect_ipv6)"
|
||||
|
||||
# Zeitzone/Locale heuristisch (kannst du später per UI anpassen)
|
||||
export APP_TZ="$(detect_timezone)"
|
||||
export APP_LOCALE="$(guess_locale_from_tz "$APP_TZ")"
|
||||
|
||||
# LE-Kontakt
|
||||
export LE_EMAIL="${LE_EMAIL:-admin@${BASE_DOMAIN}}"
|
||||
|
||||
# Repo/Branch (für 80-app.sh)
|
||||
export GIT_REPO="${GIT_REPO:-https://git.nexlab.at/boban/mailwolt.git}"
|
||||
export GIT_BRANCH="${GIT_BRANCH:-main}"
|
||||
export APP_USER="${APP_USER:-mailwolt}"
|
||||
export APP_GROUP="${APP_GROUP:-www-data}"
|
||||
export APP_DIR="/var/www/${APP_USER}"
|
||||
export APP_USER_PREFIX="${APP_USER_PREFIX:-mw}"
|
||||
|
||||
# Run modules
|
||||
./10-provision.sh
|
||||
./20-ssl.sh
|
||||
./30-db.sh
|
||||
./40-postfix.sh
|
||||
./50-dovecot.sh
|
||||
./60-rspamd-opendkim.sh
|
||||
./70-nginx.sh
|
||||
./80-app.sh
|
||||
./90-services.sh
|
||||
./95-monit.sh
|
||||
./98-motd.sh
|
||||
./99-summary.sh
|
||||
|
|
@ -1,77 +0,0 @@
|
|||
#!/usr/bin/env bash
|
||||
set -euo pipefail
|
||||
|
||||
# ── Styling ────────────────────────────────────────────────────────────────
|
||||
GREEN="$(printf '\033[1;32m')"; YELLOW="$(printf '\033[1;33m')"
|
||||
RED="$(printf '\033[1;31m')"; CYAN="$(printf '\033[1;36m')"
|
||||
GREY="$(printf '\033[0;90m')"; NC="$(printf '\033[0m')"
|
||||
BAR="──────────────────────────────────────────────────────────────────────────────"
|
||||
|
||||
header(){ echo -e "${CYAN}${BAR}${NC}
|
||||
${CYAN} 888b d888 d8b 888 888 888 888 888 ${NC}
|
||||
${CYAN} 8888b d8888 Y8P 888 888 o 888 888 888 ${NC}
|
||||
${CYAN} 88888b.d88888 888 888 d8b 888 888 888 ${NC}
|
||||
${CYAN} 888Y88888P888 8888b. 888 888 888 d888b 888 .d88b. 888 888888 ${NC}
|
||||
${CYAN} 888 Y888P 888 '88b 888 888 888d88888b888 d88''88b 888 888 ${NC}
|
||||
${CYAN} 888 Y8P 888 .d888888 888 888 88888P Y88888 888 888 888 888 ${NC}
|
||||
${CYAN} 888 ' 888 888 888 888 888 8888P Y8888 Y88..88P 888 Y88b. ${NC}
|
||||
${CYAN} 888 888 'Y888888 888 888 888P Y888 'Y88P' 888 'Y888 ${NC}
|
||||
${CYAN}${BAR}${NC}\n"; }
|
||||
|
||||
log(){ echo -e "${GREEN}[+]${NC} $*"; }
|
||||
warn(){ echo -e "${YELLOW}[!]${NC} $*"; }
|
||||
err(){ echo -e "${RED}[x]${NC} $*"; }
|
||||
die(){ err "$*"; exit 1; }
|
||||
require_root(){ [[ "$(id -u)" -eq 0 ]] || die "Bitte als root ausführen."; }
|
||||
|
||||
detect_ip(){
|
||||
local ip
|
||||
ip="$(ip -4 route get 1.1.1.1 2>/dev/null | awk '{for(i=1;i<=NF;i++) if($i=="src"){print $(i+1); exit}}')" || true
|
||||
[[ -n "${ip:-}" ]] || ip="$(hostname -I 2>/dev/null | awk '{print $1}')"
|
||||
[[ -n "${ip:-}" ]] || die "Konnte Server-IP nicht ermitteln."
|
||||
echo "$ip"
|
||||
}
|
||||
|
||||
detect_ipv6(){
|
||||
local ip6
|
||||
ip6="$(ip -6 addr show scope global 2>/dev/null | awk '/inet6/{print $2}' | cut -d/ -f1 | head -n1)" || true
|
||||
[[ -n "${ip6:-}" ]] || ip6="$(hostname -I 2>/dev/null | awk '{for(i=1;i<=NF;i++) if($i ~ /:/){print $i; exit}}')" || true
|
||||
echo "${ip6:-}"
|
||||
}
|
||||
|
||||
detect_timezone(){
|
||||
if command -v timedatectl >/dev/null 2>&1; then
|
||||
tz="$(timedatectl show -p Timezone --value 2>/dev/null | tr -d '[:space:]')" || true
|
||||
[[ -n "${tz:-}" && "$tz" == */* ]] && { echo "$tz"; return; }
|
||||
fi
|
||||
if [[ -r /etc/timezone ]]; then
|
||||
tz="$(sed -n '1p' /etc/timezone | tr -d '[:space:]')" || true
|
||||
[[ -n "${tz:-}" && "$tz" == */* ]] && { echo "$tz"; return; }
|
||||
fi
|
||||
if [[ -L /etc/localtime ]]; then
|
||||
target="$(readlink -f /etc/localtime 2>/dev/null || true)"
|
||||
target="${target#/usr/share/zoneinfo/}"
|
||||
[[ "$target" == */* ]] && { echo "$target"; return; }
|
||||
fi
|
||||
if command -v curl >/dev/null 2>&1; then
|
||||
tz="$(curl -fsSL --max-time 3 https://ipapi.co/timezone 2>/dev/null || true)"
|
||||
[[ -n "${tz:-}" && "$tz" == */* ]] && { echo "$tz"; return; }
|
||||
fi
|
||||
echo "UTC"
|
||||
}
|
||||
|
||||
guess_locale_from_tz(){
|
||||
local tz="${1:-UTC}"
|
||||
case "$tz" in
|
||||
Europe/Berlin|Europe/Vienna|Europe/Zurich|Europe/Luxembourg|Europe/Brussels|Europe/Amsterdam) echo "de";;
|
||||
*) echo "en";;
|
||||
esac
|
||||
}
|
||||
|
||||
resolve_ok(){
|
||||
local host="$1" ip="${SERVER_PUBLIC_IPV4:-}"
|
||||
[[ -n "$ip" ]] || return 1
|
||||
getent ahosts "$host" | awk '{print $1}' | sort -u | grep -q -F "$ip"
|
||||
}
|
||||
|
||||
ensure_dir(){ install -d -m "${3:-0755}" -o "${1:-root}" -g "${2:-root}" "${4}"; }
|
||||
Loading…
Reference in New Issue