First Commit with complete Setup coded by Claude 4.7 Opus

This commit is contained in:
Tronax 2026-05-13 19:05:40 +02:00
commit bf1d37de77
19 changed files with 4544 additions and 0 deletions

50
nginx/certs/README.md Normal file
View file

@ -0,0 +1,50 @@
# TLS-Zertifikate
Dieses Verzeichnis ist für deine eigenen TLS-Zertifikate gedacht.
## Selbstsigniertes Zertifikat (Standard)
Wenn dieses Verzeichnis **leer** ist, generiert CardSync beim ersten Start
automatisch ein selbstsigniertes Zertifikat (10 Jahre gültig) für die Hostnamen:
- `cardsync.local`
- `localhost`
- `127.0.0.1`
Browser zeigen dabei eine Sicherheitswarnung, die du einmalig akzeptieren musst.
## Eigenes Zertifikat verwenden (Wildcard, Let's Encrypt, etc.)
Lege deine Dateien hier ab — **exakt mit diesen Namen**:
```
nginx/certs/cert.pem ← Public Cert (inkl. Intermediate-Chain bei CA-Certs)
nginx/certs/key.pem ← Private Key (unverschlüsselt)
```
Falls dein Provider die Datei anders nennt:
| Datei vom Provider | → umbenennen zu |
|-------------------------------------|-----------------|
| `fullchain.pem` (Let's Encrypt) | `cert.pem` |
| `privkey.pem` (Let's Encrypt) | `key.pem` |
| `cert.crt` + `bundle.crt` | zusammenfügen zu `cert.pem` (cert zuerst, dann bundle) |
| `*.pfx` (Windows) | siehe Konvertierung unten |
## PFX/P12 nach PEM konvertieren
Falls du nur eine `.pfx`-Datei hast (typisch bei Windows-Wildcard-Certs):
```bash
# Cert extrahieren
openssl pkcs12 -in dein-zertifikat.pfx -clcerts -nokeys -out cert.pem
# Key extrahieren (entschlüsselt)
openssl pkcs12 -in dein-zertifikat.pfx -nocerts -nodes -out key.pem
```
## Nach Cert-Tausch
```bash
docker compose restart frontend
```
Das ist alles — CardSync übernimmt das neue Zertifikat automatisch.

44
nginx/entrypoint.sh Executable file
View file

@ -0,0 +1,44 @@
#!/bin/sh
# CardSync Nginx Entrypoint
# Generiert ein selbstsigniertes Zertifikat falls noch keins vorhanden ist.
# Eigene Zertifikate können einfach in ./nginx/certs/ als cert.pem + key.pem
# abgelegt werden — diese werden dann verwendet.
set -e
CERT_DIR="/etc/nginx/certs"
CERT_FILE="$CERT_DIR/cert.pem"
KEY_FILE="$CERT_DIR/key.pem"
mkdir -p "$CERT_DIR"
if [ ! -f "$CERT_FILE" ] || [ ! -f "$KEY_FILE" ]; then
echo "==> Kein TLS-Zertifikat gefunden — generiere selbstsigniertes Cert..."
# OpenSSL ist im nginx:alpine Image bereits vorhanden
openssl req -x509 -nodes -newkey rsa:2048 \
-keyout "$KEY_FILE" \
-out "$CERT_FILE" \
-days 3650 \
-subj "/CN=cardsync.local/O=CardSync/C=DE" \
-addext "subjectAltName=DNS:cardsync.local,DNS:localhost,IP:127.0.0.1" \
2>/dev/null
chmod 644 "$CERT_FILE"
chmod 600 "$KEY_FILE"
echo "==> Selbstsigniertes Zertifikat erstellt (gültig 10 Jahre)"
echo " Cert: $CERT_FILE"
echo " Key: $KEY_FILE"
echo ""
echo " Um ein eigenes Zertifikat zu verwenden:"
echo " - Lege cert.pem + key.pem in ./nginx/certs/ ab"
echo " - docker compose restart frontend"
else
echo "==> Verwende vorhandenes TLS-Zertifikat aus $CERT_DIR"
# Kurze Cert-Info ausgeben
openssl x509 -in "$CERT_FILE" -noout -subject -issuer -dates 2>/dev/null || true
fi
# Nginx im Vordergrund starten (Standard-Behavior fortsetzen)
exec nginx -g "daemon off;"

58
nginx/nginx.conf Normal file
View file

@ -0,0 +1,58 @@
# Redirect HTTP HTTPS
server {
listen 80;
server_name _;
return 301 https://$host$request_uri;
}
# HTTPS
server {
listen 443 ssl;
http2 on;
server_name _;
ssl_certificate /etc/nginx/certs/cert.pem;
ssl_certificate_key /etc/nginx/certs/key.pem;
# Moderne TLS-Konfiguration (Mozilla "intermediate")
ssl_protocols TLSv1.2 TLSv1.3;
ssl_prefer_server_ciphers off;
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_session_timeout 1d;
ssl_session_cache shared:SSL:10m;
ssl_session_tickets off;
# HSTS (1 Jahr)
add_header Strict-Transport-Security "max-age=31536000; includeSubDomains" always;
# Frontend (statische Dateien)
root /usr/share/nginx/html;
index index.html;
# API zum Backend
location /api/ {
proxy_pass http://backend:8000;
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 120s;
}
location /auth/ {
proxy_pass http://backend:8000;
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;
}
location /health {
proxy_pass http://backend:8000;
}
# Frontend-Dateien
location / {
try_files $uri $uri/ /index.html;
}
}