Files
timemaster/nginx.conf
T
patrickandClaude Sonnet 5 edb727e09a
Security Audit / Python Dependency Audit (push) Has been cancelled
Security Audit / Node.js Dependency Audit (push) Has been cancelled
fix(security): python-jose CVE-2024-33663 durch pyjwt ersetzt, Deps gepinnt
- security.py/dependencies.py/auth.py: jose -> pyjwt (unmaintained,
  Algorithm-Confusion-CVE). API-kompatibel (jwt.encode/decode gleich).
- requirements.txt: alle Versionen gepinnt (waren >=, jetzt == anhand
  aktueller 137-Installation) fuer reproduzierbare Deploys.
- nginx.conf: /docs + /openapi.json nur noch aus LAN erreichbar (waren
  oeffentlich, API-Struktur-Leak).

fail2ban auf 137+164 installiert (sshd + nginx-badbots + timemaster-auth
Jails), Configs nicht im Repo (Server-only, /etc/fail2ban/).

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

99 lines
4.7 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 (SSL/HTTPS noch nicht eingerichtet)
# Sobald ein TLS-Zertifikat vorhanden ist:
# 1. Listen-Block auf 443 ssl http2 erweitern
# 2. ssl_certificate / ssl_certificate_key einkommentieren
# 3. HSTS-Header hinzufügen
# 4. HTTP->HTTPS-Redirect aktivieren
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;
}
}