1. Die optimierte Nginx-Direktive (In ISPConfig einfügen)

[!INFO] Admin Bereich nur per Tailscale IP erlaubt

client_max_body_size 64M;

# 1. Security Headers & SSL Options
add_header Strict-Transport-Security "max-age=63072000; includeSubDomains; preload" always;
add_header Content-Security-Policy "default-src 'self'; script-src 'self' 'unsafe-inline' 'unsafe-eval'; object-src 'none'; style-src 'self' 'unsafe-inline'; img-src 'self' data:; font-src 'self' data: https://gstatic.com; frame-ancestors 'self'; form-action 'self'; base-uri 'self';" always;
add_header X-Content-Type-Options "nosniff" always;
add_header Referrer-Policy "strict-origin-when-cross-origin" always;

ssl_ciphers 'ECDHE-ECDSA-AES128-GCM-SHA256:ECDHE-RSA-AES128-GCM-SHA256:ECDHE-ECDSA-AES256-GCM-SHA384:ECDHE-RSA-AES256-GCM-SHA384:ECDHE-ECDSA-CHACHA20-POLY1305:ECDHE-RSA-CHACHA20-POLY1305';
ssl_prefer_server_ciphers on;

# Deaktiviert SHA224 für TLS 1.2 Signatur-Handshakes (Internet.nl Warnung)
ssl_conf_command SignatureAlgorithms ECDSA+SHA256:ECDSA+SHA384:ECDSA+SHA512:rsa_pss_rsae_sha256:rsa_pss_rsae_sha384:rsa_pss_rsae_sha512:RSA+SHA256:RSA+SHA384:RSA+SHA512;

# 2. Tailscale Restriction for Admin Area (inkl. Adminer)
set $block_unauthorized_admin 0;

if ($uri ~* "^/(admin)") {
    set $block_unauthorized_admin 1;
}

if ($remote_addr ~ "^100\.(6[4-9]|[7-9][0-9]|1[0-1][0-9]|12[0-7])\.") {
    set $block_unauthorized_admin 
0;
}

if ($block_unauthorized_admin = 1) {
    return 403;
}

# 3. Grav Access Control

# Allow .well-known (für security.txt & Let's Encrypt)
location ^~ /.well-known/ {
    try_files $uri =404;
}

# Allow-Regeln für Grav Assets/Media
location ~* ^/user/accounts/[^/]+/[^/]+\.(jpe?g|png|gif|webp|avif|bmp|ico)$ { 
    try_files $uri =404; 
}

location ~* ^/user/data/.*\.(jpe?g|png|gif|webp|avif|bmp|ico|mp4|webm|ogg|ogv|mov|mp3|wav|m4a|flac|pdf)$ { 
    try_files $uri =404; 
}

# Blockieren von Scripten in Asset-/Upload-Ordnern
location ~* ^/(images|assets|cache|media|logs|tmp)/.*\.(php[0-9]?|phar|phtml|phtm|phps|pl|py|cgi|sh|bat)$ { 
    return 403; 
}

# Blockieren von sensiblen Verzeichnissen
location ~* ^/(backup|tmp|logs|\.git|cache|bin|tests)/ { 
    return 403; 
}

location ~* ^/user/(accounts|config|env|data)/ { 
    return 403; 
}

location ~* ^/(system|vendor)/.*\.(txt|xml|md|html|htm|shtml|shtm|json|yaml|yml|php[0-9]?|phar|phtml|pl|py|cgi|twig|sh|bat)$ { 
    return 403; 
}

location ~* ^/user/.*\.(txt|md|json|yaml|yml|php[0-9]?|phar|phtml|pl|py|cgi|twig|sh|bat)$ { 
    return 403; 
}

# Sensitive root files
location ~* /(LICENSE\.txt|composer\.lock|composer\.json|nginx\.conf|web\.config|htaccess\.txt|\.htaccess|\.env) { 
    return 403; 
}

# 4. Grav Routing
location / {
    try_files $uri $uri/ /index.php?$query_string;
}

2. security.txt Datei anlegen

Erstelle im Webroot deiner Domain den Ordner .well-known und darin die Datei security.txt:

  • Pfad: /var/www/deine-domain.de/web/.well-known/security.txt

  • Inhalt (Beispiel):

    Contact: mailto:security@deine-domain.de
    Expires: 2027-12-31T23:59:59.000Z
    Preferred-Languages: de, en