Some checks failed
CI / Unit & Component Tests (pull_request) Successful in 5m45s
CI / OCR Service Tests (pull_request) Successful in 36s
CI / Backend Unit Tests (pull_request) Failing after 23m49s
CI / fail2ban Regex (pull_request) Successful in 2m13s
CI / Compose Bucket Idempotency (pull_request) Successful in 1m46s
Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
53 lines
4.9 KiB
Plaintext
53 lines
4.9 KiB
Plaintext
@startuml
|
|
!include <C4/C4_Container>
|
|
|
|
title Container Diagram: Familienarchiv
|
|
|
|
Person(user, "User", "Admin or family member")
|
|
System_Ext(mail, "Email Service", "SMTP server. Delivers notification and password-reset emails.")
|
|
|
|
Container(caddy, "Reverse Proxy", "Caddy 2 (host-installed)", "TLS termination (auto Let's Encrypt). Routes /api/* to backend:8080, everything else to frontend:3000. Responds 404 on /actuator/* and adds HSTS, X-Content-Type-Options, Referrer-Policy headers.")
|
|
|
|
System_Boundary(archiv, "Familienarchiv (Docker Compose)") {
|
|
Container(frontend, "Web Frontend", "SvelteKit / Node adapter / port 3000", "Server-side rendered UI. Handles auth session cookies, document search and viewer, transcription editor, annotation layer, family tree (Stammbaum), stories (Geschichten), activity feed (Chronik), enrichment workflow, and admin panel.")
|
|
Container(backend, "API Backend", "Spring Boot 4 / Java 21 / Jetty / port 8080", "REST API. Implements document management, search, user auth, file upload/download, transcription, OCR orchestration, and SSE notifications. Trusts X-Forwarded-* headers from Caddy.")
|
|
Container(ocr, "OCR Service", "Python FastAPI / port 8000", "Handwritten text recognition (HTR) and OCR microservice. Single-node by design — see ADR-001. Reachable only on the internal Docker network; no external port exposed.")
|
|
ContainerDb(db, "Relational Database", "PostgreSQL 16", "Stores document metadata, persons, users, permission groups, tags, transcription blocks, audit log, and Spring Session data.")
|
|
ContainerDb(storage, "Object Storage", "MinIO (S3-compatible)", "Stores the actual document files (PDFs, scans). Backend uses a bucket-scoped service account (archiv-app), not MinIO root.")
|
|
Container(mc, "Bucket / Service-Account Init", "MinIO Client (mc)", "One-shot container on startup. Idempotent: creates the archive bucket, the archiv-app service account, and attaches the readwrite policy.")
|
|
}
|
|
|
|
System_Boundary(observability, "Observability Stack (docker-compose.observability.yml)") {
|
|
Container(prometheus, "Prometheus", "prom/prometheus:v3.4.0", "Scrapes metrics from backend management port 8081 (/actuator/prometheus), node-exporter, and cAdvisor. Retention: 30 days.")
|
|
Container(node_exporter, "Node Exporter", "prom/node-exporter:v1.9.0", "Host-level CPU, memory, disk, and network metrics.")
|
|
Container(cadvisor, "cAdvisor", "gcr.io/cadvisor/cadvisor:v0.52.1", "Per-container resource metrics.")
|
|
Container(loki, "Loki", "grafana/loki:3.4.2", "Stores log streams from all containers.")
|
|
Container(promtail, "Promtail", "grafana/promtail:3.4.2", "Ships Docker container logs to Loki via Docker SD.")
|
|
Container(tempo, "Tempo", "grafana/tempo:2.7.2", "Distributed trace storage. OTLP gRPC receiver on port 4317 (archiv-net). Grafana queries traces on port 3200 (obs-net). All ports internal only.")
|
|
Container(grafana, "Grafana", "grafana/grafana-oss:11.6.1", "Unified observability UI — dashboards, logs, traces. Datasources (Prometheus, Loki, Tempo) and three dashboards are auto-provisioned.")
|
|
Container(glitchtip, "GlitchTip", "glitchtip/glitchtip:v4", "Sentry-compatible error tracker — web process. Receives frontend + backend error events, groups by fingerprint, provides issue UI with stack traces.")
|
|
Container(obs_glitchtip_worker, "GlitchTip Worker", "glitchtip/glitchtip:v4", "Celery + beat worker — async event ingestion, notifications, cleanup.")
|
|
Container(obs_redis, "Redis", "redis:7-alpine", "Celery task queue for GlitchTip async workers.")
|
|
}
|
|
|
|
Rel(user, caddy, "HTTPS", "TLS 1.2/1.3")
|
|
Rel(caddy, frontend, "Reverse proxies non-/api requests", "HTTP / loopback:3000")
|
|
Rel(caddy, backend, "Reverse proxies /api/*", "HTTP / loopback:8080")
|
|
Rel(frontend, backend, "API requests with Basic Auth token", "HTTP / REST / JSON")
|
|
Rel(backend, user, "SSE notifications (server-sent events)", "HTTP / SSE — fronted by Caddy")
|
|
Rel(backend, db, "Reads and writes metadata and sessions", "JDBC / SQL")
|
|
Rel(backend, storage, "Uploads and streams document files using archiv-app service account", "HTTP / S3 API (AWS SDK v2)")
|
|
Rel(backend, ocr, "OCR job requests with presigned MinIO URL", "HTTP / REST / JSON")
|
|
Rel(backend, mail, "Sends notification and password-reset emails (optional)", "SMTP")
|
|
Rel(ocr, storage, "Fetches PDF via presigned URL", "HTTP / S3 presigned")
|
|
Rel(mc, storage, "Bootstraps bucket + service account on startup", "MinIO Client CLI")
|
|
Rel(promtail, loki, "Pushes log streams", "HTTP/Loki push API")
|
|
Rel(backend, tempo, "Sends distributed traces via OTLP", "gRPC / OTLP / port 4317 (archiv-net)")
|
|
Rel(grafana, prometheus, "Queries metrics", "HTTP 9090")
|
|
Rel(grafana, loki, "Queries logs", "HTTP 3100")
|
|
Rel(grafana, tempo, "Queries traces", "HTTP 3200")
|
|
Rel(glitchtip, db, "Stores error events in glitchtip DB", "PostgreSQL / archiv-net")
|
|
Rel(obs_glitchtip_worker, obs_redis, "Processes Celery tasks", "Redis / obs-net")
|
|
|
|
@enduml
|