Infomaniak VPS „new static site“ Skript

KomponenteFunktion
nginx (gw/nginx:cache-purge)HTTP/2 via nginx-proxy, gzip, 30 Tage Browser-Cache für statische Assets, FastCGI-Cache für PHP-Output (60 min)
PHP-FPM (gw/php:static-mail)PHP 8.3-Alpine + OPcache + msmtp als sendmail-Ersatz
HTTPSautomatisch via acme-companion (LetsEncrypt)
fail2ban-Schutzgreift auch hier (gleiche Log-Pfade), die WP-Filter matchen halt nichts — kein Schaden

/mnt/data/new-static-site.sh

Wait – noch üpberarbeiten, viel zu viel!

Bash
#!/bin/bash
# Provisioniert eine schlanke Static-Site (mit optionalem PHP) unter
# /mnt/data/sites/<name>.
#
# Stack: nginx (gw/nginx:cache-purge) + PHP-FPM (gw/php:static).
# Zweck: vorwiegend HTML/CSS/JS. PHP läuft mit, falls du mal ein
# Formular (z.B. via PHPMailer + SMTP) brauchst — kein FastCGI-Cache,
# kein msmtp, keine Mail-Magic im Image.
#
# SMTP-Creds (wenn angegeben) werden NUR in .credentials notiert —
# du übernimmst sie selber in dein PHPMailer-Setup im PHP-Code.
#
# Erzeugt:
#   /mnt/data/sites/<name>/             docker-compose, .credentials (chmod 600)
#   /mnt/data/sites/<name>/public/      Web-Root (HTML/CSS/JS/PHP)
#   /mnt/data/sites/<name>/config/      nginx.conf, php.ini
#   /mnt/data/logs/<name>/nginx/        access.log + error.log

set -euo pipefail

read -p "Site-Name (nur a-z 0-9 -, z.B. landing-x): " SITE_NAME
read -p "Domain (z.B. landing.ch): " DOMAIN
echo
echo "SMTP für Formulare via PHPMailer (leer lassen = keine SMTP-Notiz):"
read -p "  SMTP-Host: " SMTP_HOST
SMTP_PORT="" SMTP_USER="" SMTP_PASS="" SMTP_FROM=""
if [[ -n "$SMTP_HOST" ]]; then
    read -p "  SMTP-Port [587]: " SMTP_PORT;  SMTP_PORT=${SMTP_PORT:-587}
    read -p "  SMTP-User: " SMTP_USER
    read -rsp "  SMTP-Pass: " SMTP_PASS; echo
    read -p "  Absender (From): " SMTP_FROM
fi

[[ -z "$SITE_NAME" || -z "$DOMAIN" ]]          && { echo "❌ Site-Name + Domain Pflicht"; exit 1; }
[[ ! "$SITE_NAME" =~ ^[a-z0-9-]+$ ]]           && { echo "❌ Site-Name: nur a-z 0-9 -"; exit 1; }
[[ ! "$DOMAIN" =~ ^[a-z0-9.-]+\.[a-z]{2,}$ ]]  && { echo "❌ Domain ungültig"; exit 1; }

SITE_DIR="/mnt/data/sites/$SITE_NAME"
[[ -e "$SITE_DIR" ]] && { echo "❌ $SITE_DIR existiert bereits"; exit 1; }

cleanup() {
    echo ""
    echo "❌ Fehler — räume auf..."
    if [[ -f "$SITE_DIR/docker-compose.yml" ]]; then
        (cd "$SITE_DIR" && docker compose down -v 2>/dev/null) || true
    fi
    rm -rf "$SITE_DIR"
    echo "Cleanup fertig."
    exit 1
}
trap cleanup ERR INT TERM

mkdir -p "$SITE_DIR/public" "$SITE_DIR/config"
mkdir -p "/mnt/data/logs/$SITE_NAME/nginx"

cat > "$SITE_DIR/public/index.html" << EOF
<!doctype html>
<html lang="de"><head>
<meta charset="utf-8"><meta name="viewport" content="width=device-width,initial-scale=1">
<title>$DOMAIN</title></head>
<body><h1>$DOMAIN</h1><p>Static site is up.</p></body></html>
EOF

cat > "$SITE_DIR/config/php.ini" << 'PHPEOF'
upload_max_filesize = 32M
post_max_size = 32M
max_execution_time = 60
memory_limit = 128M

opcache.enable = 1
opcache.memory_consumption = 64
opcache.max_accelerated_files = 4000
opcache.revalidate_freq = 2
opcache.validate_timestamps = 1
PHPEOF

cat > "$SITE_DIR/config/nginx.conf" << 'NGINXEOF'
server {
    listen 80;
    root /var/www/html;
    index index.html index.php;

    access_log /var/log/nginx/access.log;
    error_log  /var/log/nginx/error.log;

    set_real_ip_from 10.0.0.0/8;
    set_real_ip_from 172.16.0.0/12;
    set_real_ip_from 192.168.0.0/16;
    real_ip_header X-Forwarded-For;
    real_ip_recursive on;

    gzip on;
    gzip_vary on;
    gzip_min_length 1024;
    gzip_types text/plain text/css text/xml application/javascript application/json image/svg+xml;

    location ~ /\. { deny all; }

    # nginx vererbt add_header NICHT in Child-locations mit eigenen add_header
    # — Snippet pro location includen.

    location ~* \.(jpg|jpeg|png|gif|webp|avif|svg|ico|css|js|woff|woff2|ttf|otf|eot)$ {
        include /etc/nginx/snippets/security-headers.conf;
        add_header Cache-Control "public, no-transform" always;
        expires 30d;
        access_log off;
        try_files $uri =404;
    }

    location / {
        include /etc/nginx/snippets/security-headers.conf;
        try_files $uri $uri/ /index.php?$args =404;
    }

    location ~ \.php$ {
        include /etc/nginx/snippets/security-headers.conf;
        try_files $uri =404;
        fastcgi_pass php:9000;
        fastcgi_index index.php;
        include fastcgi_params;
        fastcgi_param SCRIPT_FILENAME $document_root$fastcgi_script_name;
    }
}
NGINXEOF

cat > "$SITE_DIR/docker-compose.yml" << EOF
services:
  php:
    image: gw/php:static
    container_name: ${SITE_NAME}-php
    restart: unless-stopped
    volumes:
      - ./public:/var/www/html
      - ./config/php.ini:/usr/local/etc/php/conf.d/custom.ini:ro
    networks:
      - internal

  nginx:
    image: gw/nginx:cache-purge
    container_name: ${SITE_NAME}-nginx
    restart: unless-stopped
    command: sh -c "umask 002 && exec nginx -g 'daemon off;'"
    environment:
      VIRTUAL_HOST: ${DOMAIN}
      LETSENCRYPT_HOST: ${DOMAIN}
    volumes:
      - ./public:/var/www/html:ro
      - ./config/nginx.conf:/etc/nginx/conf.d/default.conf:ro
      - /mnt/data/logs/${SITE_NAME}/nginx:/var/log/nginx
    networks:
      - internal
      - nginx-proxy_default
    depends_on:
      - php

networks:
  internal:
  nginx-proxy_default:
    external: true
EOF

cd "$SITE_DIR"
docker compose up -d

if [[ -n "$SMTP_HOST" ]]; then
    cat > "$SITE_DIR/.credentials" << EOF
Site:        $SITE_NAME
Domain:      https://$DOMAIN

SMTP (für PHPMailer im PHP-Code zu verwenden):
  Host:      $SMTP_HOST
  Port:      $SMTP_PORT
  User:      $SMTP_USER
  Pass:      $SMTP_PASS
  From:      $SMTP_FROM
EOF
    chmod 600 "$SITE_DIR/.credentials"
fi

trap - ERR INT TERM

echo ""
echo "✅ Static-Site erstellt!"
echo "   URL:         https://$DOMAIN"
echo "   Web-Root:    $SITE_DIR/public/  (HTML, CSS, JS, PHP hier ablegen)"
if [[ -n "$SMTP_HOST" ]]; then
    echo "   SMTP-Notiz:  $SITE_DIR/.credentials  (chmod 600)"
    echo "                — Werte selber in dein PHPMailer-Setup übernehmen."
fi
echo ""