mailwolt-installer/scripts/70-nginx.sh

544 lines
16 KiB
Bash
Raw Blame History

This file contains ambiguous Unicode characters!

This file contains ambiguous Unicode characters that may be confused with others in your current locale. If your use case is intentional and legitimate, you can safely ignore this warning. Use the Escape button to highlight these characters.

#!/usr/bin/env bash
set -euo pipefail
source ./lib.sh
log "Nginx konfigurieren …"
# ── Flags/Umgebung (vom Bootstrap gesetzt; hier Fallbacks) ────────────────
DEV_MODE="${DEV_MODE:-0}" # 1 = DEV (Vite-Proxy aktiv), 0 = PROD
PROXY_MODE="${PROXY_MODE:-0}" # 1 = NPM/Proxy davor, Backend spricht nur HTTP:80
NPM_IP="${NPM_IP:-}" # z.B. 10.10.20.20
# Erwartet vom Bootstrap/Installer exportiert:
: "${UI_HOST:?UI_HOST fehlt}"
: "${WEBMAIL_HOST:?WEBMAIL_HOST fehlt}"
: "${APP_DIR:?APP_DIR fehlt}"
ACME_ROOT="/var/www/letsencrypt"
install -d -m 0755 "$ACME_ROOT"
# Default-Sites entfernen (verhindert doppelten default_server)
rm -f /etc/nginx/sites-enabled/default /etc/nginx/sites-available/default || true
# HTTP/2-Unterstützung erkennen
NGINX_HTTP2_SUFFIX=""
if nginx -V 2>&1 | grep -q http_v2; then
NGINX_HTTP2_SUFFIX=" http2"
fi
# PHP-FPM Socket/TCP finden → fastcgi_pass bauen
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 "unix:${s}"; return; }
done
[[ -S "/run/php/php-fpm.sock" ]] && { echo "unix:/run/php/php-fpm.sock"; return; }
echo "127.0.0.1:9000"
}
PHP_FPM_TARGET="$(detect_php_fpm_sock)"
if [[ "$PHP_FPM_TARGET" == unix:* ]]; then
FASTCGI_PASS="fastcgi_pass ${PHP_FPM_TARGET};"
else
FASTCGI_PASS="fastcgi_pass ${PHP_FPM_TARGET};"
fi
# ── Builder 1: HTTP-only (Proxy-Mode: TLS endet im NPM) ───────────────────
# $1=host, $2=outfile
build_site_http_only(){
local host="$1" outfile="$2"
cat > "$outfile" <<CONF
# --- ${host} : HTTP (kein Redirect, kein TLS; läuft hinter Reverse-Proxy) ---
server {
listen 80;
listen [::]:80;
server_name ${host};
# ACME HTTP-01 (optional; meist übernimmt das der Proxy)
location ^~ /.well-known/acme-challenge/ {
root ${ACME_ROOT};
allow all;
}
root ${APP_DIR}/public;
index index.php index.html;
access_log /var/log/nginx/${host}_access.log;
error_log /var/log/nginx/${host}_error.log;
client_max_body_size 25m;
location / { try_files \$uri \$uri/ /index.php?\$query_string; }
location ~ \.php\$ {
include snippets/fastcgi-php.conf;
${FASTCGI_PASS}
}
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 (Backend intern HTTP)
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/;
}
CONF
if [[ "${DEV_MODE}" = "1" ]]; then
cat >> "$outfile" <<'CONF'
# DEV: Vite-Proxy (HMR)
location ^~ /@vite/ { proxy_pass http://127.0.0.1:5173/@vite/; proxy_set_header Host $host; }
location ^~ /node_modules/ { proxy_pass http://127.0.0.1:5173/node_modules/; proxy_set_header Host $host; }
location ^~ /resources/ { proxy_pass http://127.0.0.1:5173/resources/; proxy_set_header Host $host; }
CONF
fi
echo "}" >> "$outfile"
}
# ── Builder 2: 80→443 Redirect + 443/TLS (Live-Server) ────────────────────
# $1=host, $2=cert_dir (/etc/ssl/ui | /etc/ssl/webmail), $3=outfile
build_site_tls(){
local host="$1" cert_dir="$2" outfile="$3"
local cert="${cert_dir}/fullchain.pem"
local key="${cert_dir}/privkey.pem"
cat > "$outfile" <<CONF
# --- ${host} : HTTP (ACME + Redirect) ---
server {
listen 80;
listen [::]:80;
server_name ${host};
location ^~ /.well-known/acme-challenge/ {
root ${ACME_ROOT};
allow all;
}
return 301 https://\$host\$request_uri;
}
# --- ${host} : HTTPS ---
server {
listen 443 ssl${NGINX_HTTP2_SUFFIX};
listen [::]:443 ssl${NGINX_HTTP2_SUFFIX};
server_name ${host};
ssl_certificate ${cert};
ssl_certificate_key ${key};
ssl_protocols TLSv1.2 TLSv1.3;
root ${APP_DIR}/public;
index index.php index.html;
access_log /var/log/nginx/${host}_ssl_access.log;
error_log /var/log/nginx/${host}_ssl_error.log;
client_max_body_size 25m;
location / { try_files \$uri \$uri/ /index.php?\$query_string; }
location ~ \.php\$ {
include snippets/fastcgi-php.conf;
${FASTCGI_PASS}
}
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/;
}
CONF
if [[ "${DEV_MODE}" = "1" ]]; then
cat >> "$outfile" <<'CONF'
# DEV: Vite-Proxy
location ^~ /@vite/ { proxy_pass http://127.0.0.1:5173/@vite/; proxy_set_header Host $host; proxy_set_header X-Forwarded-Proto https; }
location ^~ /node_modules/ { proxy_pass http://127.0.0.1:5173/node_modules/; proxy_set_header Host $host; proxy_set_header X-Forwarded-Proto https; }
location ^~ /resources/ { proxy_pass http://127.0.0.1:5173/resources/; proxy_set_header Host $host; proxy_set_header X-Forwarded-Proto https; }
CONF
fi
echo "}" >> "$outfile"
}
# ── Sites erzeugen ─────────────────────────────────────────────────────────
UI_SITE="/etc/nginx/sites-available/ui-mailwolt.conf"
WEBMAIL_SITE="/etc/nginx/sites-available/webmail-mailwolt.conf"
if [[ "${PROXY_MODE}" -eq 1 ]]; then
# Hinter NPM/Proxy: Backend nur HTTP:80 (keine Redirects, kein 443)
build_site_http_only "$UI_HOST" "$UI_SITE"
build_site_http_only "$WEBMAIL_HOST" "$WEBMAIL_SITE"
else
# Live-Server: 80→443 + TLS vHosts
build_site_tls "$UI_HOST" "/etc/ssl/ui" "$UI_SITE"
build_site_tls "$WEBMAIL_HOST" "/etc/ssl/webmail" "$WEBMAIL_SITE"
fi
ln -sf "$UI_SITE" "/etc/nginx/sites-enabled/ui-mailwolt.conf"
ln -sf "$WEBMAIL_SITE" "/etc/nginx/sites-enabled/webmail-mailwolt.conf"
# ── Real-IP nur, wenn Proxy davor ──────────────────────────────────────────
if [[ "${PROXY_MODE}" -eq 1 && -n "${NPM_IP}" ]]; then
cat > /etc/nginx/conf.d/realip.conf <<NGX
real_ip_header X-Forwarded-For;
set_real_ip_from ${NPM_IP};
real_ip_recursive on;
NGX
else
rm -f /etc/nginx/conf.d/realip.conf || true
fi
# ── Test & reload ──────────────────────────────────────────────────────────
if nginx -t; then
systemctl enable --now nginx >/dev/null 2>&1 || true
systemctl reload nginx || true
else
die "nginx -t fehlgeschlagen siehe /var/log/nginx/*.log"
fi
#---
##!/usr/bin/env bash
#set -euo pipefail
#source ./lib.sh
#
#log "Nginx konfigurieren …"
#
## Flags/Umgebung (kommen idealerweise aus bootstrap; hier Fallbacks)
#DEV_MODE="${DEV_MODE:-0}" # 1 = DEV (Vite-Proxy aktiv), 0 = PROD
#PROXY_MODE="${PROXY_MODE:-0}" # 1 = NPM/Proxy davor
#NPM_IP="${NPM_IP:-}" # z.B. 10.10.20.20
#
## Erwartet gesetzt: UI_HOST, WEBMAIL_HOST, APP_DIR
#: "${UI_HOST:?UI_HOST fehlt}"
#: "${WEBMAIL_HOST:?WEBMAIL_HOST fehlt}"
#: "${APP_DIR:?APP_DIR fehlt}"
#
#ACME_ROOT="/var/www/letsencrypt"
#install -d -m 0755 "$ACME_ROOT"
#
## Default-Sites konsequent entfernen (verhindert doppelten default_server)
#rm -f /etc/nginx/sites-enabled/default /etc/nginx/sites-available/default || true
#
## HTTP/2 prüfen
#NGINX_HTTP2_SUFFIX=""
#if nginx -V 2>&1 | grep -q http_v2; then
# NGINX_HTTP2_SUFFIX=" http2"
#fi
#
## PHP-FPM Socket oder TCP ermitteln und fastcgi_pass bauen
#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 "unix:${s}"; return; }
# done
# [[ -S "/run/php/php-fpm.sock" ]] && { echo "unix:/run/php/php-fpm.sock"; return; }
# echo "127.0.0.1:9000"
#}
#PHP_FPM_TARGET="$(detect_php_fpm_sock)"
#if [[ "$PHP_FPM_TARGET" == unix:* ]]; then
# FASTCGI_PASS="fastcgi_pass ${PHP_FPM_TARGET};"
#else
# FASTCGI_PASS="fastcgi_pass ${PHP_FPM_TARGET};"
#fi
#
## Helper zum Bauen einer Site
## $1=host, $2=cert_dir (/etc/ssl/ui oder /etc/ssl/webmail), $3=outfile
#build_site(){
# local host="$1" cert_dir="$2" outfile="$3"
# local cert="${cert_dir}/fullchain.pem"
# local key="${cert_dir}/privkey.pem"
#
# cat > "$outfile" <<CONF
## --- ${host} : HTTP (ACME + Redirect) ---
#server {
# listen 80;
# listen [::]:80;
# server_name ${host};
#
# # ACME HTTP-01
# location ^~ /.well-known/acme-challenge/ {
# root ${ACME_ROOT};
# allow all;
# }
#
# return 301 https://\$host\$request_uri;
#}
#
## --- ${host} : HTTPS ---
#server {
# listen 443 ssl${NGINX_HTTP2_SUFFIX};
# listen [::]:443 ssl${NGINX_HTTP2_SUFFIX};
# server_name ${host};
#
# ssl_certificate ${cert};
# ssl_certificate_key ${key};
# ssl_protocols TLSv1.2 TLSv1.3;
#
# root ${APP_DIR}/public;
# index index.php index.html;
#
# access_log /var/log/nginx/${host}_ssl_access.log;
# error_log /var/log/nginx/${host}_ssl_error.log;
#
# client_max_body_size 25m;
#
# location / { try_files \$uri \$uri/ /index.php?\$query_string; }
#
# location ~ \.php\$ {
# include snippets/fastcgi-php.conf;
# ${FASTCGI_PASS}
# }
#
# 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/;
# }
#CONF
#
# if [[ "$DEV_MODE" = "1" ]]; then
# cat >> "$outfile" <<'CONF'
# # DEV: Vite-Proxy
# location ^~ /@vite/ { proxy_pass http://127.0.0.1:5173/@vite/; proxy_set_header Host $host; proxy_set_header X-Forwarded-Proto https; }
# location ^~ /node_modules/ { proxy_pass http://127.0.0.1:5173/node_modules/; proxy_set_header Host $host; proxy_set_header X-Forwarded-Proto https; }
# location ^~ /resources/ { proxy_pass http://127.0.0.1:5173/resources/; proxy_set_header Host $host; proxy_set_header X-Forwarded-Proto https; }
#CONF
# fi
#
# echo "}" >> "$outfile"
#}
#
## Sites erzeugen
#UI_SITE="/etc/nginx/sites-available/ui-mailwolt.conf"
#WEBMAIL_SITE="/etc/nginx/sites-available/webmail-mailwolt.conf"
#
#build_site "$UI_HOST" "/etc/ssl/ui" "$UI_SITE"
#build_site "$WEBMAIL_HOST" "/etc/ssl/webmail" "$WEBMAIL_SITE"
#
#ln -sf "$UI_SITE" "/etc/nginx/sites-enabled/ui-mailwolt.conf"
#ln -sf "$WEBMAIL_SITE" "/etc/nginx/sites-enabled/webmail-mailwolt.conf"
#
## Real-IP nur, wenn Proxy davor
#if [[ "$PROXY_MODE" -eq 1 && -n "$NPM_IP" ]]; then
# cat > /etc/nginx/conf.d/realip.conf <<NGX
#real_ip_header X-Forwarded-For;
#set_real_ip_from ${NPM_IP};
#real_ip_recursive on;
#NGX
#else
# rm -f /etc/nginx/conf.d/realip.conf || true
#fi
#
## Test & reload
#if nginx -t; then
# systemctl enable --now nginx >/dev/null 2>&1 || true
# systemctl reload nginx || true
#else
# die "nginx -t fehlgeschlagen siehe /var/log/nginx/*.log"
#fi
#---
##!/usr/bin/env bash
#set -euo pipefail
#source ./lib.sh
#
#log "Nginx konfigurieren …"
#
#ROOT_DIR="$(cd "$(dirname "${BASH_SOURCE[0]}")/.." && pwd)"
#
#NGINX_SITE="/etc/nginx/sites-available/${APP_USER}.conf"
#NGINX_SITE_LINK="/etc/nginx/sites-enabled/${APP_USER}.conf"
#ACME_ROOT="/var/www/letsencrypt"
#install -d -m 0755 "$ACME_ROOT"
#
## Default-Sites konsequent entfernen (verhindert doppelten default_server)
#rm -f /etc/nginx/sites-enabled/default /etc/nginx/sites-available/default || true
#
## HTTP/2 prüfen
#NGINX_HTTP2_SUFFIX=""
#if nginx -V 2>&1 | grep -q http_v2; then
# NGINX_HTTP2_SUFFIX=" http2"
#fi
#
## PHP-FPM Socket oder TCP ermitteln und fastcgi_pass bauen
#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 "unix:${s}"; return; }
# done
# [[ -S "/run/php/php-fpm.sock" ]] && { echo "unix:/run/php/php-fpm.sock"; return; }
# echo "127.0.0.1:9000"
#}
#PHP_FPM_TARGET="$(detect_php_fpm_sock)"
#if [[ "$PHP_FPM_TARGET" == unix:* ]]; then
# FASTCGI_PASS="fastcgi_pass ${PHP_FPM_TARGET};" # << keep the unix: prefix!
#else
# FASTCGI_PASS="fastcgi_pass ${PHP_FPM_TARGET};"
#fi
#
## Prüfen, ob UI-Zert vorhanden ist
#UI_CERT="/etc/ssl/ui/fullchain.pem"
#UI_KEY="/etc/ssl/ui/privkey.pem"
#SSL_ENABLED=0
#[[ -s "$UI_CERT" && -s "$UI_KEY" ]] && SSL_ENABLED=1
#
#TPL="${ROOT_DIR}/config/nginx/site.conf.tmpl"
#[[ -f "$TPL" ]] || die "Nginx-Template fehlt: $TPL"
#render="$(cat "$TPL")"
#
## --------- Bausteine, die in das Template eingesetzt werden ---------
#
## (A) HTTP-Body, wenn KEIN SSL → App direkt über Port 80
#HTTP_BODY_APP="$(cat <<'HTTP'
# root ${APP_DIR}/public;
# index index.php index.html;
#
# access_log /var/log/nginx/${APP_USER}_access.log;
# error_log /var/log/nginx/${APP_USER}_error.log;
#
# client_max_body_size 25m;
#
# location / { try_files $uri $uri/ /index.php?$query_string; }
# location ~ \.php$ {
# include snippets/fastcgi-php.conf;
# __FASTCGI_PASS__
# }
# location ^~ /livewire/ { try_files $uri /index.php?$query_string; }
# location ~* \.(jpg|jpeg|png|gif|css|js|ico|svg)$ { expires 30d; access_log off; }
#HTTP
#)"
#
## (B) HTTP-Body, wenn SSL → nur Redirect auf 443
#HTTP_BODY_REDIRECT='return 301 https://$host$request_uri;'
#
## (C) kompletter SSL-Serverblock (wird nur eingefügt, wenn SSL aktiv)
#SSL_BLOCK="$(cat <<'SSL'
#server {
# listen 443 ssl${NGINX_HTTP2_SUFFIX};
# listen [::]:443 ssl${NGINX_HTTP2_SUFFIX};
# server_name _;
#
# ssl_certificate ${UI_CERT};
# ssl_certificate_key ${UI_KEY};
# ssl_protocols TLSv1.2 TLSv1.3;
#
# root ${APP_DIR}/public;
# index index.php index.html;
#
# access_log /var/log/nginx/${APP_USER}_ssl_access.log;
# error_log /var/log/nginx/${APP_USER}_ssl_error.log;
#
# client_max_body_size 25m;
#
# location / { try_files $uri $uri/ /index.php?$query_string; }
# location ~ \.php$ {
# include snippets/fastcgi-php.conf;
# __FASTCGI_PASS__
# }
# 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/;
# }
#}
#SSL
#)"
#
## --------- Platzhalter ersetzen ---------
#if [[ $SSL_ENABLED -eq 1 ]]; then
# render="${render/__HTTP_BODY__/$HTTP_BODY_REDIRECT}"
# render="${render/__SSL_SERVER_BLOCK__/$SSL_BLOCK}"
#else
# render="${render/__HTTP_BODY__/$HTTP_BODY_APP}"
# # HTTPS-Block komplett entfernen
# render="${render/__SSL_SERVER_BLOCK__/}"
#fi
#
## Variablen & __FASTCGI_PASS__ im fertigen Render ersetzen
#render="$(echo "$render" \
# | sed "s|\${APP_DIR}|${APP_DIR}|g; s|\${APP_USER}|${APP_USER}|g; \
# s|\${UI_CERT}|${UI_CERT}|g; s|\${UI_KEY}|${UI_KEY}|g; \
# s|\${NGINX_HTTP2_SUFFIX}|${NGINX_HTTP2_SUFFIX}|g; \
# s|__FASTCGI_PASS__|${FASTCGI_PASS}|g")"
#
## Schreiben/aktivieren
#echo "$render" > "$NGINX_SITE"
#ln -sf "$NGINX_SITE" "$NGINX_SITE_LINK"
#
## Test & reload
#if nginx -t; then
# systemctl enable --now nginx >/dev/null 2>&1 || true
# systemctl reload nginx || true
#else
# die "nginx -t fehlgeschlagen siehe /var/log/nginx/*.log"
#fi