Files
timemaster/nginx.conf
T
patrickandClaude Sonnet 5 319e070ffe
Security Audit / Python Dependency Audit (push) Has been cancelled
Security Audit / Node.js Dependency Audit (push) Has been cancelled
feat(tls): optionales certbot-Setup vorbereitet (Option A)
setup-tls.sh: auf Server ausführbares, manuelles Skript für direktes
Let's-Encrypt-Zertifikat via certbot --nginx. Bleibt ungenutzt solange
der vorgeschaltete Proxy TLS+Domain übernimmt (aktueller Stand) -
nginx.conf bleibt deshalb bewusst HTTP-only, certbot würde die
443-Erweiterung selbst in /etc/nginx/ einfügen, nicht ins Repo.

Co-Authored-By: Claude Sonnet 5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01LTxkZEUdfgMxZvHPiZJ8bV
2026-08-05 19:34:25 +02:00

100 lines
4.8 KiB
Nginx Configuration File
Raw Blame History

This file contains ambiguous Unicode characters
This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.
# HTTP-only Konfiguration bewusst so, aktuell übernimmt ein vorgeschalteter
# Proxy TLS-Terminierung + Domain. Diese Datei bleibt deshalb HTTP-only.
#
# Optional (falls der Server künftig OHNE vorgeschalteten Proxy direkt mit
# eigenem Zertifikat laufen soll): ./setup-tls.sh <domain> auf dem Server
# ausführen (certbot --nginx, holt Zertifikat + fügt 443-Block automatisch in
# /etc/nginx/sites-available/timemaster ein, NICHT in dieses Repo-File).
server {
listen 80;
server_name _;
client_max_body_size 20M;
# API Backend
location /api/ {
proxy_pass http://127.0.0.1:8000;
proxy_http_version 1.1;
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_read_timeout 60s;
# Security Headers
add_header X-Content-Type-Options "nosniff" always;
add_header X-Frame-Options "DENY" always;
add_header Referrer-Policy "strict-origin-when-cross-origin" always;
add_header X-XSS-Protection "1; mode=block" always;
add_header Permissions-Policy "geolocation=(), microphone=(), camera=()" always;
add_header Content-Security-Policy "default-src 'self'; script-src 'self' 'unsafe-inline'; style-src 'self' 'unsafe-inline'; img-src 'self' data: blob:; font-src 'self' data:; connect-src 'self'; frame-ancestors 'none';" always;
}
# FastAPI Docs nur aus internem LAN erreichbar (API-Struktur sonst für
# Angreifer sichtbar). LAN-Bereich ggf. an tatsächliches Subnetz anpassen.
location /docs {
allow 192.168.1.0/24;
allow 127.0.0.1;
deny all;
proxy_pass http://127.0.0.1:8000/docs;
# Security Headers
add_header X-Content-Type-Options "nosniff" always;
add_header X-Frame-Options "DENY" always;
add_header Referrer-Policy "strict-origin-when-cross-origin" always;
add_header X-XSS-Protection "1; mode=block" always;
add_header Permissions-Policy "geolocation=(), microphone=(), camera=()" always;
add_header Content-Security-Policy "default-src 'self'; script-src 'self' 'unsafe-inline'; style-src 'self' 'unsafe-inline'; img-src 'self' data: blob:; font-src 'self' data:; connect-src 'self'; frame-ancestors 'none';" always;
}
location /openapi.json {
allow 192.168.1.0/24;
allow 127.0.0.1;
deny all;
proxy_pass http://127.0.0.1:8000/openapi.json;
# Security Headers
add_header X-Content-Type-Options "nosniff" always;
add_header X-Frame-Options "DENY" always;
add_header Referrer-Policy "strict-origin-when-cross-origin" always;
add_header X-XSS-Protection "1; mode=block" always;
add_header Permissions-Policy "geolocation=(), microphone=(), camera=()" always;
add_header Content-Security-Policy "default-src 'self'; script-src 'self' 'unsafe-inline'; style-src 'self' 'unsafe-inline'; img-src 'self' data: blob:; font-src 'self' data:; connect-src 'self'; frame-ancestors 'none';" always;
}
# React Frontend (statische Dateien)
# HINWEIS: nginx-Regel: add_header in einem location-Block ueberschreibt
# alle add_header-Direktiven des parent server-Blocks. Daher Security-Header
# in jede location wiederholen.
location / {
root /opt/timemaster/frontend/dist;
index index.html;
try_files $uri $uri/ /index.html;
expires 1d;
add_header Cache-Control "public, must-revalidate";
add_header X-Content-Type-Options "nosniff" always;
add_header X-Frame-Options "DENY" always;
add_header Referrer-Policy "strict-origin-when-cross-origin" always;
add_header X-XSS-Protection "1; mode=block" always;
add_header Permissions-Policy "geolocation=(), microphone=(), camera=()" always;
add_header Content-Security-Policy "default-src 'self'; script-src 'self' 'unsafe-inline'; style-src 'self' 'unsafe-inline'; img-src 'self' data: blob:; font-src 'self' data:; connect-src 'self'; frame-ancestors 'none';" always;
}
# Uploads / Static Files
location /static/ {
alias /opt/timemaster/backend/static/;
expires 7d;
add_header X-Content-Type-Options "nosniff" always;
add_header X-Frame-Options "DENY" always;
add_header Referrer-Policy "strict-origin-when-cross-origin" always;
add_header X-XSS-Protection "1; mode=block" always;
add_header Permissions-Policy "geolocation=(), microphone=(), camera=()" always;
add_header Content-Security-Policy "default-src 'self'; script-src 'self' 'unsafe-inline'; style-src 'self' 'unsafe-inline'; img-src 'self' data: blob:; font-src 'self' data:; connect-src 'self'; frame-ancestors 'none';" always;
}
}