Architekturübersicht¶
KanjiIQ folgt einer Multi-Container-Pod-Architektur, die auf Kubernetes bereitgestellt wird. Frontend und Backend laufen als separate Container innerhalb desselben Pods und kommunizieren über localhost.
Systemdiagramm¶
graph TB
subgraph Internet
U[User Browser]
end
subgraph Hetzner["Hetzner k3s Cluster"]
subgraph NS["Namespace: jlpt-kanji"]
T[Traefik Ingress Controller]
subgraph Pod["Application Pod (x2 replicas)"]
FE[Flutter Web<br/>Nginx :80]
BE[Dart Frog API<br/>:8080]
end
PG[(PostgreSQL 15<br/>PVC)]
subgraph Middleware["Traefik Middlewares"]
RL[Rate Limiting]
SH[Security Headers]
end
end
CM[cert-manager<br/>Let's Encrypt]
end
U -->|HTTPS| T
T --> Middleware
Middleware -->|kanjiiq.com| FE
Middleware -->|api.kanjiiq.com| BE
FE -->|/api/ proxy| BE
BE --> PG
CM -->|TLS Certificates| T
Domain-Architektur¶
| Domain | Dienst | Zweck |
|---|---|---|
kanjiiq.com |
Frontend (Nginx) | Flutter Web Anwendung |
www.kanjiiq.com |
Frontend (Nginx) | Weiterleitung zur Hauptdomain |
api.kanjiiq.com |
Backend (Dart Frog) | REST API |
admin.kanjiiq.com |
Backend (Dart Frog) | Admin-Dashboard API |
docs.kanjiiq.app |
Docs (Nginx) | Diese Dokumentationsseite |
Multi-Container-Pod-Design¶
Die Anwendung läuft als einzelnes Kubernetes Deployment mit 2 Replikaten, die jeweils zwei Container enthalten:
# Simplified view of k8s/05-deployment.yaml
spec:
replicas: 2
template:
spec:
containers:
- name: backend # Dart Frog API on :8080
- name: frontend # Nginx serving Flutter Web on :80
Warum ein Multi-Container-Pod?
- Das Frontend-Nginx leitet
/api/-Anfragen anlocalhost:8080(das Backend) weiter und vermeidet so Cross-Origin-Probleme - Beide Container skalieren gemeinsam — jedes Replikat ist eine vollständige, eigenständige Einheit
- Vereinfachtes Netzwerk: Die Frontend-zu-Backend-Kommunikation bleibt innerhalb des Pods
Komponentenübersicht¶
Frontend¶
- Framework: Flutter Web mit Material Design 3
- Bereitstellung: Nginx Alpine (non-root, UID 1000)
- Zustandsverwaltung: Provider
- Routing: GoRouter
- Offline-Unterstützung: Lokaler SQLite-Cache mit Hintergrundsynchronisation
Backend¶
- Framework: Dart Frog 1.1.0
- Authentifizierung: JWT (für Admin-Endpunkte)
- Sicherheit: Mehrschichtiger Middleware-Stack (IP-Blockierung, Pfaderkennung, Ratenbegrenzung)
- Übersetzung: OpenAI API für dynamische Inhaltsübersetzung
Datenbank¶
- Engine: PostgreSQL 15
- Speicher: Kubernetes PersistentVolumeClaim (10Gi)
- Schema: JSONB-Spalten für mehrsprachige Inhaltsspeicherung
- Primärschlüssel: UUID
Infrastruktur¶
- Cluster: k3s auf Hetzner Dedicated Server
- Ingress: Traefik mit automatischem HTTPS
- TLS: cert-manager mit Let's Encrypt
- CI/CD: Forgejo Actions (selbst gehostet)
- Registry: Forgejo Container Registry
Sicherheitsschichten¶
KanjiIQ implementiert Tiefenverteidigung mit mehreren Sicherheitsschichten:
graph LR
R[Request] --> L1[Traefik<br/>Rate Limiting]
L1 --> L2[Traefik<br/>Security Headers]
L2 --> L3[App: IP<br/>Blocklist Check]
L3 --> L4[App: Malicious<br/>Path Detection]
L4 --> L5[App: SQL Injection<br/>Detection]
L5 --> L6[App: Regional<br/>Analytics]
L6 --> H[Request Handler]
- Infrastrukturebene (Traefik): Ratenbegrenzung (100 Req/Min öffentlich, 50 Req/Min Admin) und Sicherheitsheader (HSTS, X-Frame-Options, CSP)
- Anwendungsebene (Dart Frog Middleware): IP-Blockliste, Erkennung bösartiger Pfade (.env, .php, Konfigurationsdateien), SQL-Injection-Muster, Verhinderung von Pfadtraversierung
- Analyseebene: Regionale Anfrageverfolgung mit automatischer Blockierung nach 3 verdächtigen Anfragen innerhalb von 24 Stunden
Siehe Backend-Architektur für Details zum Middleware-Stack.