# Nginx-Konfiguration für TimeClock v3 # Datei speichern unter: /etc/nginx/sites-available/stechuhr3.tsschulz.de # # Installation: # sudo cp nginx.conf /etc/nginx/sites-available/stechuhr3.tsschulz.de # sudo ln -s /etc/nginx/sites-available/stechuhr3.tsschulz.de /etc/nginx/sites-enabled/ # sudo nginx -t # sudo systemctl reload nginx # HTTP Server - Redirect zu HTTPS server { listen 80; listen [::]:80; server_name stechuhr3.tsschulz.de; # Let's Encrypt ACME Challenge location /.well-known/acme-challenge/ { root /var/www/certbot; } # Alle anderen Requests zu HTTPS umleiten location / { return 301 https://$server_name$request_uri; } } # HTTPS Server - Hauptkonfiguration server { listen 443 ssl http2; listen [::]:443 ssl http2; server_name stechuhr3.tsschulz.de; # ================================================================= # SSL-Konfiguration (wird von Certbot automatisch verwaltet) # ================================================================= ssl_certificate /etc/letsencrypt/live/stechuhr3.tsschulz.de/fullchain.pem; ssl_certificate_key /etc/letsencrypt/live/stechuhr3.tsschulz.de/privkey.pem; # SSL-Protokolle und Ciphers ssl_protocols TLSv1.2 TLSv1.3; ssl_prefer_server_ciphers on; 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:DHE-RSA-AES128-GCM-SHA256:DHE-RSA-AES256-GCM-SHA384'; # SSL-Session-Cache ssl_session_cache shared:SSL:10m; ssl_session_timeout 10m; ssl_session_tickets off; # OCSP Stapling ssl_stapling on; ssl_stapling_verify on; ssl_trusted_certificate /etc/letsencrypt/live/stechuhr3.tsschulz.de/chain.pem; resolver 8.8.8.8 8.8.4.4 valid=300s; resolver_timeout 5s; # ================================================================= # Frontend (Vue.js SPA) # ================================================================= root /var/www/timeclock/frontend/dist; index index.html; # ================================================================= # Logging # ================================================================= access_log /var/log/nginx/stechuhr3.access.log; error_log /var/log/nginx/stechuhr3.error.log warn; # ================================================================= # Gzip Compression # ================================================================= gzip on; gzip_vary on; gzip_proxied any; gzip_comp_level 6; gzip_min_length 1024; gzip_types text/plain text/css text/xml text/javascript application/javascript application/x-javascript application/json application/xml application/xml+rss application/rss+xml application/atom+xml image/svg+xml font/ttf font/woff font/woff2; # ================================================================= # Security Headers # ================================================================= # X-Frame-Options: Schutz vor Clickjacking add_header X-Frame-Options "SAMEORIGIN" always; # X-Content-Type-Options: Verhindert MIME-Type Sniffing add_header X-Content-Type-Options "nosniff" always; # X-XSS-Protection: XSS-Schutz für ältere Browser add_header X-XSS-Protection "1; mode=block" always; # Referrer-Policy: Kontrolliert Referrer-Informationen add_header Referrer-Policy "strict-origin-when-cross-origin" always; # Permissions-Policy: Kontrolliert Browser-Features add_header Permissions-Policy "geolocation=(), microphone=(), camera=()" always; # Content-Security-Policy (angepasst für Vue.js) # Kann bei Bedarf verschärft werden add_header Content-Security-Policy "default-src 'self'; script-src 'self' 'unsafe-inline' 'unsafe-eval'; style-src 'self' 'unsafe-inline'; img-src 'self' data: https:; font-src 'self' data:; connect-src 'self' https://stechuhr3.tsschulz.de;" always; # Strict-Transport-Security (HSTS) add_header Strict-Transport-Security "max-age=31536000; includeSubDomains; preload" always; # ================================================================= # API Reverse Proxy zum Backend # ================================================================= location /api { # Proxy Pass zum Backend auf localhost:3010 proxy_pass http://localhost:3010; # HTTP Version proxy_http_version 1.1; # WebSocket Support (falls später benötigt) proxy_set_header Upgrade $http_upgrade; proxy_set_header Connection 'upgrade'; # Standard Proxy Headers proxy_set_header Host $host; proxy_set_header X-Real-IP $remote_addr; proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for; proxy_set_header X-Forwarded-Proto $scheme; proxy_set_header X-Forwarded-Host $server_name; # Cache Bypass proxy_cache_bypass $http_upgrade; # Timeouts proxy_connect_timeout 60s; proxy_send_timeout 60s; proxy_read_timeout 60s; # Buffer-Einstellungen proxy_buffering on; proxy_buffer_size 4k; proxy_buffers 8 4k; proxy_busy_buffers_size 8k; # Fehlerbehandlung proxy_next_upstream error timeout invalid_header http_500 http_502 http_503; proxy_next_upstream_tries 2; } # ================================================================= # Statische Assets mit langem Cache # ================================================================= location ~* \.(js|css|png|jpg|jpeg|gif|ico|svg|webp|avif)$ { expires 1y; add_header Cache-Control "public, immutable"; access_log off; } # Font-Dateien mit langem Cache location ~* \.(woff|woff2|ttf|eot)$ { expires 1y; add_header Cache-Control "public, immutable"; add_header Access-Control-Allow-Origin "*"; access_log off; } # ================================================================= # SPA Fallback - alle anderen Requests zu index.html # ================================================================= location / { try_files $uri $uri/ /index.html; # Cache-Control für HTML-Dateien (kein Cache) add_header Cache-Control "no-cache, no-store, must-revalidate"; add_header Pragma "no-cache"; add_header Expires "0"; } # ================================================================= # Spezielle Dateien # ================================================================= # robots.txt und sitemap.xml location ~* ^/(robots\.txt|sitemap\.xml)$ { root /var/www/timeclock/frontend/dist; access_log off; } # favicon.ico location = /favicon.ico { root /var/www/timeclock/frontend/dist; access_log off; log_not_found off; } # ================================================================= # Sicherheit: Verstecke sensible Dateien # ================================================================= # Blockiere Zugriff auf .git, .env, etc. location ~ /\. { deny all; access_log off; log_not_found off; } # Blockiere Zugriff auf Backup-Dateien location ~ ~$ { deny all; access_log off; log_not_found off; } # ================================================================= # Limits und Rate Limiting (optional) # ================================================================= # Client Body Size Limit (z.B. für File-Uploads) client_max_body_size 10M; # Client Body Timeout client_body_timeout 30s; # Client Header Timeout client_header_timeout 30s; # Send Timeout send_timeout 30s; # Rate Limiting für API (optional) # Kommentare entfernen und in nginx.conf http-Block hinzufügen: # limit_req_zone $binary_remote_addr zone=api_limit:10m rate=10r/s; # location /api { # limit_req zone=api_limit burst=20 nodelay; # ... rest der Konfiguration # } } # ================================================================= # OPTIONAL: Rate Limiting Zone (in /etc/nginx/nginx.conf http-Block) # ================================================================= # Uncomment und in die Haupt-nginx.conf einfügen, falls gewünscht: # # http { # ... # # # Rate Limiting Zones # limit_req_zone $binary_remote_addr zone=general_limit:10m rate=30r/s; # limit_req_zone $binary_remote_addr zone=api_limit:10m rate=10r/s; # limit_req_zone $binary_remote_addr zone=login_limit:10m rate=5r/m; # # # Connection Limiting # limit_conn_zone $binary_remote_addr zone=conn_limit:10m; # # ... # }