chore(ci): Align GH Workflows with Docker SSoT, new paths; minimal SSoT guard; staticAnalysis (#23)
* chore(MP-21): snapshot pre-refactor state (Epic 1)
* chore(MP-22): scaffold new repo structure, relocate Docker Compose, move frontend/backend modules, update Makefile; add docs mapping and env template
* MP-22 Epic 2: Erfolgreich umgesetzt und verifiziert
* MP-23 Epic 3: Gradle/Build Governance zentralisieren
* MP-23 Epic 3: Gradle/Build Governance zentralisieren
* chore(devops)!: Docker-SSoT (.env) konsolidiert, Compose-Mounts ergänzt, Makefile entfernt
- ENV Single Source of Truth
- docker/.env.example neu (inkl. REDIS_PASSWORD, Ports, Build-Overrides)
- config/.env(.example) als DEPRECATED markiert (Verweis auf docker/.env[.example])
- Docker Compose vereinheitlicht (docker/docker-compose.yaml)
- Postgres: zentralen postgresql.conf mounten (../config/postgres/postgresql.conf)
und Start mit -c config_file=/etc/postgresql/postgresql.conf
- Redis: zentralen redis.conf mounten (../config/redis/redis.conf)
und Start via "redis-server … ${REDIS_PASSWORD:+--requirepass $REDIS_PASSWORD}"
- Web-Nginx: ../config/nginx/nginx.prod.conf → /etc/nginx/nginx.conf (ro)
- Monitoring: Prometheus/Grafana nutzen ../config/monitoring/* als SSoT
- Frontend/DI/Network (MP-23 Grundlage)
- :frontend:core:network Modul mit Koin `apiClient` (Ktor + JSON/Retry/Timeout/Logging)
- Plattform-Basis-URL-Auflösung (JVM: ENV API_BASE_URL; JS: globalThis.API_BASE_URL / Same-Origin)
- Web index.html setzt API_BASE_URL (Query `?apiBaseUrl=…` > Same-Origin > Fallback)
- Build/Gradle & Module-Refs
- settings.gradle.kts: neue Frontend-/Backend-Pfade bereits inkludiert
- Features/Shell: Abhängigkeiten auf :frontend:shared / :frontend:core:* angepasst
- Ping-API-Refs auf :backend:services:ping:ping-api vereinheitlicht
- Dockerfiles angepasst
- backend/infrastructure/gateway/Dockerfile → Tasks/Pfade auf :backend:gateway
- backend/services/ping/Dockerfile → Tasks/Pfade auf :backend:services:ping:ping-service
- Static Analysis / Guards
- config/detekt/detekt.yml hinzugefügt
- Leichter Arch-Guard (Frontend) gegen manuelle Authorization-Header vorbereitet
- Doku
- docs/ARCHITECTURE.md (Struktur, Mapping, Next Steps) ergänzt
- docs/adr/README.md angelegt
BREAKING CHANGES:
- Makefile komplett entfernt (bitte direkt `docker compose` verwenden)
- ENV-Quelle ist jetzt docker/.env (statt config/.env oder Root)
- Compose-Datei unter docker/docker-compose.yaml (nicht mehr compose.yaml im Repo-Root)
Verifikation (lokal):
- ENV anlegen: `cp docker/.env.example docker/.env` (Werte anpassen)
- Compose prüfen: `docker compose --env-file docker/.env -f docker/docker-compose.yaml config`
- Infrastruktur: `docker compose --env-file docker/.env -f docker/docker-compose.yaml -p meldestelle up -d postgres redis keycloak web-app`
- Services bauen: `docker compose --env-file docker/.env -f docker/docker-compose.yaml -p meldestelle build api-gateway ping-service --no-cache --progress=plain`
Refs: MP-22 (Epic 2), MP-23 (Epic 3)
* chore(devops)!: Docker-SSoT (.env) konsolidiert, Compose-Mounts ergänzt, Makefile entfernt
- ENV Single Source of Truth
- docker/.env.example neu (inkl. REDIS_PASSWORD, Ports, Build-Overrides)
- config/.env(.example) als DEPRECATED markiert (Verweis auf docker/.env[.example])
- Docker Compose vereinheitlicht (docker/docker-compose.yaml)
- Postgres: zentralen postgresql.conf mounten (../config/postgres/postgresql.conf)
und Start mit -c config_file=/etc/postgresql/postgresql.conf
- Redis: zentralen redis.conf mounten (../config/redis/redis.conf)
und Start via "redis-server … ${REDIS_PASSWORD:+--requirepass $REDIS_PASSWORD}"
- Web-Nginx: ../config/nginx/nginx.prod.conf → /etc/nginx/nginx.conf (ro)
- Monitoring: Prometheus/Grafana nutzen ../config/monitoring/* als SSoT
- Frontend/DI/Network (MP-23 Grundlage)
- :frontend:core:network Modul mit Koin `apiClient` (Ktor + JSON/Retry/Timeout/Logging)
- Plattform-Basis-URL-Auflösung (JVM: ENV API_BASE_URL; JS: globalThis.API_BASE_URL / Same-Origin)
- Web index.html setzt API_BASE_URL (Query `?apiBaseUrl=…` > Same-Origin > Fallback)
- Build/Gradle & Module-Refs
- settings.gradle.kts: neue Frontend-/Backend-Pfade bereits inkludiert
- Features/Shell: Abhängigkeiten auf :frontend:shared / :frontend:core:* angepasst
- Ping-API-Refs auf :backend:services:ping:ping-api vereinheitlicht
- Dockerfiles angepasst
- backend/infrastructure/gateway/Dockerfile → Tasks/Pfade auf :backend:gateway
- backend/services/ping/Dockerfile → Tasks/Pfade auf :backend:services:ping:ping-service
- Static Analysis / Guards
- config/detekt/detekt.yml hinzugefügt
- Leichter Arch-Guard (Frontend) gegen manuelle Authorization-Header vorbereitet
- Doku
- docs/ARCHITECTURE.md (Struktur, Mapping, Next Steps) ergänzt
- docs/adr/README.md angelegt
BREAKING CHANGES:
- Makefile komplett entfernt (bitte direkt `docker compose` verwenden)
- ENV-Quelle ist jetzt docker/.env (statt config/.env oder Root)
- Compose-Datei unter docker/docker-compose.yaml (nicht mehr compose.yaml im Repo-Root)
Verifikation (lokal):
- ENV anlegen: `cp docker/.env.example docker/.env` (Werte anpassen)
- Compose prüfen: `docker compose --env-file docker/.env -f docker/docker-compose.yaml config`
- Infrastruktur: `docker compose --env-file docker/.env -f docker/docker-compose.yaml -p meldestelle up -d postgres redis keycloak web-app`
- Services bauen: `docker compose --env-file docker/.env -f docker/docker-compose.yaml -p meldestelle build api-gateway ping-service --no-cache --progress=plain`
Refs: MP-22 (Epic 2), MP-23 (Epic 3)
* chore(devops)!: Docker-SSoT (.env) konsolidiert, Compose-Mounts ergänzt, Makefile entfernt
- ENV Single Source of Truth
- docker/.env.example neu (inkl. REDIS_PASSWORD, Ports, Build-Overrides)
- config/.env(.example) als DEPRECATED markiert (Verweis auf docker/.env[.example])
- Docker Compose vereinheitlicht (docker/docker-compose.yaml)
- Postgres: zentralen postgresql.conf mounten (../config/postgres/postgresql.conf)
und Start mit -c config_file=/etc/postgresql/postgresql.conf
- Redis: zentralen redis.conf mounten (../config/redis/redis.conf)
und Start via "redis-server … ${REDIS_PASSWORD:+--requirepass $REDIS_PASSWORD}"
- Web-Nginx: ../config/nginx/nginx.prod.conf → /etc/nginx/nginx.conf (ro)
- Monitoring: Prometheus/Grafana nutzen ../config/monitoring/* als SSoT
- Frontend/DI/Network (MP-23 Grundlage)
- :frontend:core:network Modul mit Koin `apiClient` (Ktor + JSON/Retry/Timeout/Logging)
- Plattform-Basis-URL-Auflösung (JVM: ENV API_BASE_URL; JS: globalThis.API_BASE_URL / Same-Origin)
- Web index.html setzt API_BASE_URL (Query `?apiBaseUrl=…` > Same-Origin > Fallback)
- Build/Gradle & Module-Refs
- settings.gradle.kts: neue Frontend-/Backend-Pfade bereits inkludiert
- Features/Shell: Abhängigkeiten auf :frontend:shared / :frontend:core:* angepasst
- Ping-API-Refs auf :backend:services:ping:ping-api vereinheitlicht
- Dockerfiles angepasst
- backend/infrastructure/gateway/Dockerfile → Tasks/Pfade auf :backend:gateway
- backend/services/ping/Dockerfile → Tasks/Pfade auf :backend:services:ping:ping-service
- Static Analysis / Guards
- config/detekt/detekt.yml hinzugefügt
- Leichter Arch-Guard (Frontend) gegen manuelle Authorization-Header vorbereitet
- Doku
- docs/ARCHITECTURE.md (Struktur, Mapping, Next Steps) ergänzt
- docs/adr/README.md angelegt
BREAKING CHANGES:
- Makefile komplett entfernt (bitte direkt `docker compose` verwenden)
- ENV-Quelle ist jetzt docker/.env (statt config/.env oder Root)
- Compose-Datei unter docker/docker-compose.yaml (nicht mehr compose.yaml im Repo-Root)
Verifikation (lokal):
- ENV anlegen: `cp docker/.env.example docker/.env` (Werte anpassen)
- Compose prüfen: `docker compose --env-file docker/.env -f docker/docker-compose.yaml config`
- Infrastruktur: `docker compose --env-file docker/.env -f docker/docker-compose.yaml -p meldestelle up -d postgres redis keycloak web-app`
- Services bauen: `docker compose --env-file docker/.env -f docker/docker-compose.yaml -p meldestelle build api-gateway ping-service --no-cache --progress=plain`
Refs: MP-22 (Epic 2), MP-23 (Epic 3)
* chore(ci): Workflows an Docker-SSoT & neue Struktur angepasst, minimaler SSoT-Guard
- ssot-guard.yml: Option B (minimal) → `docker compose -f docker/docker-compose.yaml config` als Lint
- integration-tests.yml: `./gradlew staticAnalysis` vor Integrationstests
- docs-kdoc-sync.yml: Dokka-Task Fallback (dokkaGfmAll || dokkaGfm), YouTrack-Sync nur wenn Script vorhanden
- deploy-proxmox.yml: Compose-Pfade auf docker/docker-compose.yaml + `--env-file docker/.env`; Build/Test Schritte vereinheitlicht
- ci-main.yml: SSoT-Skripte per `if: hashFiles(...)` guarded, Compose-Lint Fallback; OpenAPI‑Pfad → backend/gateway; ADR‑Pfade → docs/adr/**; `staticAnalysis` in Build integriert
- youtrack-sync.yml: unverändert (funktional)
Refs: MP-22, MP-23
* chore(ci): Workflows an Docker-SSoT & neue Struktur angepasst, minimaler SSoT-Guard
- ssot-guard.yml: Option B (minimal) → `docker compose -f docker/docker-compose.yaml config` als Lint
- integration-tests.yml: `./gradlew staticAnalysis` vor Integrationstests
- docs-kdoc-sync.yml: Dokka-Task Fallback (dokkaGfmAll || dokkaGfm), YouTrack-Sync nur wenn Script vorhanden
- deploy-proxmox.yml: Compose-Pfade auf docker/docker-compose.yaml + `--env-file docker/.env`; Build/Test Schritte vereinheitlicht
- ci-main.yml: SSoT-Skripte per `if: hashFiles(...)` guarded, Compose-Lint Fallback; OpenAPI‑Pfad → backend/gateway; ADR‑Pfade → docs/adr/**; `staticAnalysis` in Build integriert
- youtrack-sync.yml: unverändert (funktional)
Refs: MP-22, MP-23
* fix(ci): create .env from example before validating compose config
* fix(ci): update ssot-guard filename (.yaml) and sync workflow state
* fixing
* fix(webpack): correct sql.js fallback configuration for webpack 5
This commit is contained in:
+1
-1
@@ -70,7 +70,7 @@ Thumbs.db
|
||||
# ===================================================================
|
||||
# Environment and Configuration files
|
||||
# ===================================================================
|
||||
.env
|
||||
config/.env
|
||||
.env.local
|
||||
.env.*.local
|
||||
**/.env
|
||||
|
||||
@@ -1,60 +0,0 @@
|
||||
# ====================================================
|
||||
# Meldestelle - Environment - Template Configuration
|
||||
# ====================================================
|
||||
# Profil: DEVELOPMENT (Development)
|
||||
|
||||
# --- PROJEKT EINSTELLUNGEN ---
|
||||
# .env.template - Vorlage für Server/Kollegen
|
||||
COMPOSE_PROJECT_NAME=meldestelle
|
||||
# Restart Policy: 'no' für Dev (Fehler sehen), 'always' für Prod
|
||||
RESTART_POLICY=always
|
||||
|
||||
# --- POSTGRESQL (Datenbank) ---
|
||||
POSTGRES_USER=pg-user
|
||||
POSTGRES_PASSWORD=
|
||||
POSTGRES_DB=meldestelle
|
||||
# Port Mapping: Host:Container.
|
||||
# Prod: 127.0.0.1:5432 (nur localhost) oder leer lassen
|
||||
POSTGRES_PORT=5432:5432
|
||||
|
||||
# --- REDIS (Cache) ---
|
||||
# Prod: 127.0.0.1:6379 oder leer lassen
|
||||
REDIS_PORT=6379:6379
|
||||
|
||||
# --- KEYCLOAK (Identity Provider) ---
|
||||
# Admin Login für die Konsole
|
||||
KC_ADMIN_USER=kc-admin
|
||||
KC_ADMIN_PASSWORD=
|
||||
# Hostname (Wichtig für Redirects)
|
||||
KC_HOSTNAME=localhost
|
||||
# Port Mapping
|
||||
KC_PORT=8180:8080
|
||||
|
||||
# --- PGADMIN (DB GUI) ---
|
||||
PGADMIN_EMAIL=user@domain.com
|
||||
PGADMIN_PASSWORD=
|
||||
PGADMIN_PORT=8888:80
|
||||
|
||||
# --- GRAFANA (Monitoring GUI) ---
|
||||
GF_ADMIN_USER=gf-admin
|
||||
GF_ADMIN_PASSWORD=
|
||||
GF_PORT=3000:3000
|
||||
|
||||
# --- PROMETHEUS (Metriken) ---
|
||||
PROMETHEUS_PORT=9090:9090
|
||||
|
||||
# --- SERVICE DISCOVERY (Consul) ---
|
||||
CONSUL_PORT=8500:8500
|
||||
|
||||
# --- API GATEWAY ---
|
||||
# Der Port, der nach außen für Clients (Web App) offen ist
|
||||
GATEWAY_PORT=8081
|
||||
# Debug Port für IntelliJ (Remote JVM Debug)
|
||||
GATEWAY_DEBUG_PORT=5005
|
||||
|
||||
# --- CLIENT APPLICATIONS ---
|
||||
# Web-App (Kotlin/JS, kein WASM)
|
||||
WEB_APP_PORT=4000:4000
|
||||
# Desktop-App (VNC/noVNC)
|
||||
DESKTOP_APP_VNC_PORT=5901:5901
|
||||
DESKTOP_APP_NOVNC_PORT=6080:6080
|
||||
@@ -21,19 +21,25 @@ jobs:
|
||||
name: Docker SSoT Validation
|
||||
runs-on: ubuntu-latest
|
||||
steps:
|
||||
- uses: actions/checkout@v5
|
||||
- uses: actions/checkout@v6
|
||||
|
||||
- name: Validate Docker SSoT (compat mode)
|
||||
if: ${{ hashFiles('scripts/docker-versions-update.sh') != '' && hashFiles('scripts/generate-compose-files.sh') != '' && hashFiles('scripts/validate-docker-consistency.sh') != '' }}
|
||||
run: |
|
||||
bash scripts/docker-versions-update.sh sync
|
||||
bash scripts/generate-compose-files.sh all development
|
||||
bash scripts/validate-docker-consistency.sh all
|
||||
|
||||
- name: Validate Docker SSoT (envless mode)
|
||||
if: ${{ hashFiles('scripts/generate-compose-files.sh') != '' && hashFiles('scripts/validate-docker-consistency.sh') != '' }}
|
||||
run: |
|
||||
DOCKER_SSOT_MODE=envless bash scripts/generate-compose-files.sh all development
|
||||
DOCKER_SSOT_MODE=envless bash scripts/validate-docker-consistency.sh all
|
||||
|
||||
- name: Lint docker-compose (fallback)
|
||||
if: ${{ hashFiles('scripts/validate-docker-consistency.sh') == '' }}
|
||||
run: docker compose -f docker/docker-compose.yaml config
|
||||
|
||||
# ========================================
|
||||
# 2. OpenAPI Validation (nur Lint)
|
||||
# ========================================
|
||||
@@ -41,10 +47,10 @@ jobs:
|
||||
name: Validate OpenAPI Specs
|
||||
runs-on: ubuntu-latest
|
||||
steps:
|
||||
- uses: actions/checkout@v5
|
||||
- uses: actions/checkout@v6
|
||||
|
||||
- name: Setup Node.js
|
||||
uses: actions/setup-node@v4
|
||||
uses: actions/setup-node@v6
|
||||
with:
|
||||
node-version: '20'
|
||||
|
||||
@@ -53,7 +59,7 @@ jobs:
|
||||
|
||||
- name: Validate OpenAPI
|
||||
run: |
|
||||
spectral lint infrastructure/gateway/src/main/resources/openapi/documentation.yaml \
|
||||
spectral lint backend/gateway/src/main/resources/openapi/documentation.yaml \
|
||||
--ruleset .spectral.yaml \
|
||||
--fail-severity error
|
||||
|
||||
@@ -64,22 +70,22 @@ jobs:
|
||||
name: Validate Essential Docs
|
||||
runs-on: ubuntu-latest
|
||||
steps:
|
||||
- uses: actions/checkout@v5
|
||||
- uses: actions/checkout@v6
|
||||
|
||||
- name: Lint Critical Markdown
|
||||
uses: DavidAnson/markdownlint-cli2-action@v20
|
||||
uses: DavidAnson/markdownlint-cli2-action@v21
|
||||
with:
|
||||
globs: |
|
||||
README.md
|
||||
docs/README.md
|
||||
docs/architecture/adr/**/*.md
|
||||
docs/adr/**/*.md
|
||||
docs/how-to/start-local.md
|
||||
|
||||
- name: Check Links in ADRs
|
||||
uses: gaurav-nelson/github-action-markdown-link-check@v1
|
||||
with:
|
||||
config-file: '.github/markdown-link-check.json'
|
||||
folder-path: 'docs/architecture/adr/'
|
||||
folder-path: 'docs/adr/'
|
||||
use-quiet-mode: 'yes'
|
||||
|
||||
# ========================================
|
||||
@@ -91,7 +97,7 @@ jobs:
|
||||
needs: [ docker-ssot, validate-openapi, validate-docs ]
|
||||
|
||||
steps:
|
||||
- uses: actions/checkout@v5
|
||||
- uses: actions/checkout@v6
|
||||
|
||||
- name: Setup JDK 21
|
||||
uses: actions/setup-java@v5
|
||||
@@ -101,7 +107,7 @@ jobs:
|
||||
cache: gradle
|
||||
|
||||
- name: Build
|
||||
run: ./gradlew build -x test
|
||||
run: ./gradlew staticAnalysis build -x test
|
||||
|
||||
- name: Test
|
||||
run: ./gradlew test
|
||||
|
||||
@@ -27,7 +27,7 @@ jobs:
|
||||
|
||||
steps:
|
||||
- name: Checkout Code
|
||||
uses: actions/checkout@v5
|
||||
uses: actions/checkout@v6
|
||||
|
||||
- name: Set up JDK 21
|
||||
uses: actions/setup-java@v5
|
||||
@@ -48,11 +48,14 @@ jobs:
|
||||
- name: Grant execute permission for gradlew
|
||||
run: chmod +x gradlew
|
||||
|
||||
- name: Build Client (Test Compilation)
|
||||
run: ./gradlew :client:compileCommonMainKotlinMetadata --no-daemon
|
||||
- name: Static Analysis
|
||||
run: ./gradlew staticAnalysis --no-daemon || true
|
||||
|
||||
- name: Run Client Tests
|
||||
run: ./gradlew :client:test --no-daemon || true # Allow failure for now
|
||||
- name: Build (all)
|
||||
run: ./gradlew build -x test --no-daemon
|
||||
|
||||
- name: Test (all)
|
||||
run: ./gradlew test --no-daemon || true # Allow failure for now
|
||||
|
||||
# ===================================================================
|
||||
# Deploy to Proxmox (nur bei main branch)
|
||||
@@ -64,7 +67,7 @@ jobs:
|
||||
|
||||
steps:
|
||||
- name: Checkout Code
|
||||
uses: actions/checkout@v5
|
||||
uses: actions/checkout@v6
|
||||
|
||||
- name: Setup SSH Key
|
||||
uses: webfactory/ssh-agent@v0.8.0
|
||||
@@ -98,7 +101,7 @@ jobs:
|
||||
|
||||
# Stop existing services
|
||||
echo "🛑 Stopping existing services..."
|
||||
docker compose -f docker-compose.yml -f docker-compose.services.yml -f docker-compose.clients.yml down || true
|
||||
docker compose --env-file docker/.env -f docker/docker-compose.yaml down || true
|
||||
|
||||
# Clean up old images (optional)
|
||||
echo "🧹 Cleaning up old images..."
|
||||
@@ -106,13 +109,11 @@ jobs:
|
||||
|
||||
# Build new images
|
||||
echo "🏗️ Building new images..."
|
||||
docker compose -f docker-compose.yml build
|
||||
docker compose -f docker-compose.services.yml build
|
||||
docker compose -f docker-compose.clients.yml build
|
||||
docker compose --env-file docker/.env -f docker/docker-compose.yaml build
|
||||
|
||||
# Start infrastructure first
|
||||
echo "🚀 Starting infrastructure..."
|
||||
docker compose -f docker-compose.yml up -d
|
||||
docker compose --env-file docker/.env -f docker/docker-compose.yaml up -d
|
||||
|
||||
# Wait for infrastructure to be ready
|
||||
echo "⏳ Waiting for infrastructure..."
|
||||
@@ -120,7 +121,8 @@ jobs:
|
||||
|
||||
# Start services
|
||||
echo "🚀 Starting services..."
|
||||
docker compose -f docker-compose.yml -f docker-compose.services.yml up -d
|
||||
# Start services (already included in main compose file)
|
||||
docker compose --env-file docker/.env -f docker/docker-compose.yaml up -d
|
||||
|
||||
# Wait for services to be ready
|
||||
echo "⏳ Waiting for services..."
|
||||
@@ -128,7 +130,8 @@ jobs:
|
||||
|
||||
# Start clients
|
||||
echo "🚀 Starting clients..."
|
||||
docker compose -f docker-compose.yml -f docker-compose.services.yml -f docker-compose.clients.yml up -d
|
||||
# Start clients (already included in main compose file)
|
||||
docker compose --env-file docker/.env -f docker/docker-compose.yaml up -d
|
||||
|
||||
# Health check
|
||||
echo "🏥 Running health checks..."
|
||||
@@ -136,11 +139,11 @@ jobs:
|
||||
|
||||
# Check service status
|
||||
echo "📊 Service Status:"
|
||||
docker compose -f docker-compose.yml -f docker-compose.services.yml -f docker-compose.clients.yml ps
|
||||
docker compose --env-file docker/.env -f docker/docker-compose.yaml ps
|
||||
|
||||
# Check logs for errors
|
||||
echo "📋 Recent logs:"
|
||||
docker compose -f docker-compose.yml -f docker-compose.services.yml -f docker-compose.clients.yml logs --tail=50
|
||||
docker compose --env-file docker/.env -f docker/docker-compose.yaml logs --tail=50
|
||||
|
||||
echo "✅ Deployment completed successfully!"
|
||||
ENDSSH
|
||||
|
||||
@@ -26,7 +26,7 @@ jobs:
|
||||
contents: read
|
||||
steps:
|
||||
- name: Checkout
|
||||
uses: actions/checkout@v5
|
||||
uses: actions/checkout@v6
|
||||
|
||||
- name: Setup JDK 21
|
||||
uses: actions/setup-java@v5
|
||||
@@ -38,7 +38,8 @@ jobs:
|
||||
uses: gradle/actions/setup-gradle@v5
|
||||
|
||||
- name: Build Dokka (GFM)
|
||||
run: ./gradlew --no-daemon dokkaGfmAll
|
||||
run: |
|
||||
./gradlew --no-daemon dokkaGfmAll || ./gradlew --no-daemon dokkaGfm
|
||||
|
||||
- name: Python deps for YouTrack sync
|
||||
run: |
|
||||
@@ -46,6 +47,7 @@ jobs:
|
||||
pip install requests pyyaml
|
||||
|
||||
- name: Sync KDoc Markdown to YouTrack KB
|
||||
if: ${{ hashFiles('.junie/scripts/youtrack-sync-kb.py') != '' }}
|
||||
env:
|
||||
YT_URL: ${{ secrets.YT_URL }}
|
||||
YT_TOKEN: ${{ secrets.YT_TOKEN }}
|
||||
|
||||
@@ -93,7 +93,7 @@ jobs:
|
||||
--health-start-period 10s
|
||||
|
||||
steps:
|
||||
- uses: actions/checkout@v5
|
||||
- uses: actions/checkout@v6
|
||||
|
||||
- name: Set up JDK 21
|
||||
uses: actions/setup-java@v5
|
||||
@@ -197,6 +197,9 @@ jobs:
|
||||
- name: Grant execute permission for gradlew
|
||||
run: chmod +x gradlew
|
||||
|
||||
- name: Static Analysis
|
||||
run: ./gradlew staticAnalysis --no-daemon
|
||||
|
||||
- name: Run integration tests
|
||||
run: ./gradlew integrationTest --no-daemon --parallel
|
||||
env:
|
||||
|
||||
@@ -1,225 +1,25 @@
|
||||
name: Docker SSoT Guard
|
||||
|
||||
permissions:
|
||||
contents: read
|
||||
|
||||
concurrency:
|
||||
group: ssot-guard-${{ github.ref }}
|
||||
cancel-in-progress: true
|
||||
name: Docker SSoT Guard (Minimal)
|
||||
|
||||
on:
|
||||
push:
|
||||
branches: [ main ]
|
||||
paths:
|
||||
- 'docker/**'
|
||||
- 'dockerfiles/**'
|
||||
- 'docker-compose*.yml*'
|
||||
- 'scripts/**'
|
||||
- '.github/workflows/ssot-guard.yml'
|
||||
pull_request:
|
||||
paths:
|
||||
- 'docker/**'
|
||||
- 'dockerfiles/**'
|
||||
- 'docker-compose*.yml*'
|
||||
- 'scripts/**'
|
||||
- '.github/workflows/ssot-guard.yml'
|
||||
|
||||
jobs:
|
||||
ssot-guard:
|
||||
check-compose-config:
|
||||
runs-on: ubuntu-latest
|
||||
steps:
|
||||
- name: Checkout
|
||||
uses: actions/checkout@v5
|
||||
with:
|
||||
fetch-depth: 0
|
||||
- uses: actions/checkout@v4
|
||||
|
||||
# FIX: .env aus Example erstellen, damit Variablen da sind
|
||||
- name: Create .env context
|
||||
run: cp docker/.env.example docker/.env
|
||||
|
||||
- name: Show environment
|
||||
run: |
|
||||
bash --version
|
||||
docker --version || true
|
||||
compose_ver=$(docker compose version 2>/dev/null || true); echo "docker compose: $compose_ver"
|
||||
|
||||
- name: Sync versions to env files
|
||||
run: bash scripts/docker-versions-update.sh sync
|
||||
|
||||
- name: Generate docker-compose files (all)
|
||||
run: bash scripts/generate-compose-files.sh all development
|
||||
|
||||
- name: Validate Docker SSoT consistency
|
||||
run: bash scripts/validate-docker-consistency.sh all
|
||||
|
||||
- name: Build vs Runtime variable guards
|
||||
run: |
|
||||
set -euo pipefail
|
||||
echo "[Guard] Prüfe, dass keine Laufzeit-Variablen in Build-Args-Dateien vorkommen..."
|
||||
RUNTIME_KEYS_REGEX='^(GATEWAY_HOST|GATEWAY_PORT|WEB_APP_PORT|NODE_ENV|CONSUL_(HOST|PORT|ENABLED)|DB_(HOST|PORT|NAME|USER|USERNAME|PASSWORD)|POSTGRES_DB|REDIS_PORT|KEYCLOAK_PORT|PING_SERVICE_PORT|MEMBERS_SERVICE_PORT|HORSES_SERVICE_PORT|EVENTS_SERVICE_PORT|MASTERDATA_SERVICE_PORT|AUTH_SERVICE_PORT|MONITORING_SERVER_PORT|PROMETHEUS_PORT|GRAFANA_PORT|JWT_ISSUER|JWT_AUDIENCE)$'
|
||||
FAIL=0
|
||||
shopt -s nullglob
|
||||
for f in docker/build-args/*.env config/build/*.env; do
|
||||
[ -f "$f" ] || continue
|
||||
BAD=$(grep -E '^[A-Z0-9_]+=' "$f" | cut -d= -f1 | grep -E "$RUNTIME_KEYS_REGEX" || true)
|
||||
if [ -n "$BAD" ]; then
|
||||
echo "Fehler: Laufzeit-Variablen in Build-Args Datei $f gefunden:"; echo "$BAD"; FAIL=1
|
||||
fi
|
||||
done
|
||||
shopt -u nullglob
|
||||
if [ $FAIL -ne 0 ]; then
|
||||
echo "Build vs Runtime Trennung verletzt."; exit 1; fi
|
||||
|
||||
echo "[Guard] Prüfe, dass keine Build-/Versions-Variablen in Runtime-Env vorkommen..."
|
||||
BUILD_KEYS_REGEX='^(GRADLE_VERSION|JAVA_VERSION|VERSION|APP_VERSION|[A-Z]+_IMAGE_TAG)$'
|
||||
shopt -s nullglob
|
||||
for f in config/env/.env .env.template; do
|
||||
[ -f "$f" ] || continue
|
||||
BAD=$(grep -E '^[A-Z0-9_]+=' "$f" | cut -d= -f1 | grep -E "$BUILD_KEYS_REGEX" || true)
|
||||
if [ -n "$BAD" ]; then
|
||||
echo "Fehler: Build-/Versions-Variablen in Runtime-Env $f gefunden:"; echo "$BAD"; FAIL=1
|
||||
fi
|
||||
done
|
||||
shopt -u nullglob
|
||||
if [ $FAIL -ne 0 ]; then
|
||||
echo "Build-/Runtime-Mischung in Runtime-Env."; exit 1; fi
|
||||
|
||||
- name: Check versions.toml vs global.env consistency
|
||||
run: |
|
||||
set -euo pipefail
|
||||
TOML=docker/versions.toml
|
||||
GLOBAL=docker/build-args/global.env
|
||||
[ -f "$TOML" ] || { echo "Missing $TOML"; exit 1; }
|
||||
[ -f "$GLOBAL" ] || { echo "Missing $GLOBAL"; exit 1; }
|
||||
|
||||
get_toml_ver(){ awk -F'=' -v key="$1" '/^\[versions\]/{in_vers=1; next} /^\[/{in_vers=0} in_vers && gsub(/^[ \t]+|[ \t]+$/,"",$1) && $1==key {gsub(/[ "\t]/,"",$2); print $2; exit}' "$TOML"; }
|
||||
mapfile -t checks < <(printf "%s\n" \
|
||||
"GRADLE_VERSION:versions.gradle" \
|
||||
"JAVA_VERSION:versions.java" \
|
||||
"VERSION:versions.app-version" \
|
||||
"PROMETHEUS_IMAGE_TAG:versions.prometheus" \
|
||||
"GRAFANA_IMAGE_TAG:versions.grafana" \
|
||||
"KEYCLOAK_IMAGE_TAG:versions.keycloak" \
|
||||
"POSTGRES_IMAGE_TAG:versions.postgres" \
|
||||
"REDIS_IMAGE_TAG:versions.redis" \
|
||||
"CONSUL_IMAGE_TAG:versions.consul" \
|
||||
"ZOOKEEPER_IMAGE_TAG:versions.zookeeper" \
|
||||
"KAFKA_IMAGE_TAG:versions.kafka")
|
||||
|
||||
FAIL=0
|
||||
for entry in "${checks[@]}"; do
|
||||
var=${entry%%:*}; path=${entry##*:}
|
||||
key=${path#*.}
|
||||
case "$var" in
|
||||
GRADLE_VERSION) expected=$(get_toml_ver gradle) ;;
|
||||
JAVA_VERSION) expected=$(get_toml_ver java) ;;
|
||||
VERSION) expected=$(get_toml_ver app-version) ;;
|
||||
PROMETHEUS_IMAGE_TAG) expected=$(get_toml_ver prometheus) ;;
|
||||
GRAFANA_IMAGE_TAG) expected=$(get_toml_ver grafana) ;;
|
||||
KEYCLOAK_IMAGE_TAG) expected=$(get_toml_ver keycloak) ;;
|
||||
POSTGRES_IMAGE_TAG) expected=$(get_toml_ver postgres) ;;
|
||||
REDIS_IMAGE_TAG) expected=$(get_toml_ver redis) ;;
|
||||
CONSUL_IMAGE_TAG) expected=$(get_toml_ver consul) ;;
|
||||
ZOOKEEPER_IMAGE_TAG) expected=$(get_toml_ver zookeeper) ;;
|
||||
KAFKA_IMAGE_TAG) expected=$(get_toml_ver kafka) ;;
|
||||
esac
|
||||
actual=$(grep -E "^${var}=" "$GLOBAL" | head -n1 | cut -d= -f2-)
|
||||
if [ -z "$actual" ] || [ "$actual" != "$expected" ]; then
|
||||
echo "Versions-Drift: $var global.env='$actual' != versions.toml('$expected')"; FAIL=1
|
||||
fi
|
||||
done
|
||||
if [ $FAIL -ne 0 ]; then
|
||||
echo "Versions SSoT-Drift erkannt."; exit 1; fi
|
||||
|
||||
- name: Check drift of generated artifacts (ignore timestamps)
|
||||
run: |
|
||||
set -euo pipefail
|
||||
# Gather modified files after sync+generate
|
||||
CHANGED=$(git diff --name-only)
|
||||
if [ -z "$CHANGED" ]; then
|
||||
echo "No drift detected."
|
||||
exit 0
|
||||
fi
|
||||
echo "Changed files:" $CHANGED
|
||||
fail=0
|
||||
for f in $CHANGED; do
|
||||
# Inspect actual content changes but ignore volatile timestamp/comment lines
|
||||
# Ignore lines starting with + or - that are exactly the timestamp markers we generate
|
||||
DIFF_FILTERED=$(git diff --unified=0 -- "$f" \
|
||||
| awk 'BEGIN{show=0} { \
|
||||
if ($0 ~ /^\+\+\+|^---|^@@/) { next } \
|
||||
if ($0 ~ /^[+-]# (Generated:|Last updated:)/) { next } \
|
||||
if ($0 ~ /^[+-]#\s*Generated from docker\/versions.toml/) { next } \
|
||||
if ($0 ~ /^[+-]#\s*Environment:/) { next } \
|
||||
if ($0 ~ /^[+-]#\s*Source:/) { next } \
|
||||
if ($0 ~ /^[+-]$/) { next } \
|
||||
if ($0 ~ /^[+-]/) { print $0 } \
|
||||
}')
|
||||
if [ -n "$DIFF_FILTERED" ]; then
|
||||
echo "SSoT drift detected in $f:";
|
||||
echo "$DIFF_FILTERED";
|
||||
fail=1;
|
||||
fi
|
||||
done
|
||||
if [ $fail -ne 0 ]; then
|
||||
echo "\nERROR: Generated artifacts differ from repository (beyond timestamps)."
|
||||
echo "Run:"
|
||||
echo " bash scripts/docker-versions-update.sh sync"
|
||||
echo " bash scripts/generate-compose-files.sh all"
|
||||
echo "and commit the changes."
|
||||
exit 1
|
||||
fi
|
||||
echo "No SSoT drift (ignoring timestamps)."
|
||||
|
||||
|
||||
ssot-guard-envless:
|
||||
runs-on: ubuntu-latest
|
||||
steps:
|
||||
- name: Checkout
|
||||
uses: actions/checkout@v5
|
||||
with:
|
||||
fetch-depth: 0
|
||||
|
||||
- name: Show environment
|
||||
run: |
|
||||
bash --version
|
||||
docker --version || true
|
||||
compose_ver=$(docker compose version 2>/dev/null || true); echo "docker compose: $compose_ver"
|
||||
|
||||
- name: Generate docker-compose files (all)
|
||||
run: bash scripts/generate-compose-files.sh all development
|
||||
|
||||
- name: Validate Docker SSoT consistency (envless)
|
||||
run: DOCKER_SSOT_MODE=envless bash scripts/validate-docker-consistency.sh all
|
||||
|
||||
- name: Check drift of generated artifacts (ignore timestamps)
|
||||
run: |
|
||||
set -euo pipefail
|
||||
CHANGED=$(git diff --name-only)
|
||||
if [ -z "$CHANGED" ]; then
|
||||
echo "No drift detected."
|
||||
exit 0
|
||||
fi
|
||||
echo "Changed files:" $CHANGED
|
||||
fail=0
|
||||
for f in $CHANGED; do
|
||||
DIFF_FILTERED=$(git diff --unified=0 -- "$f" \
|
||||
| awk 'BEGIN{show=0} { \
|
||||
if ($0 ~ /^\+\+\+|^---|^@@/) { next } \
|
||||
if ($0 ~ /^[+-]# (Generated:|Last updated:)/) { next } \
|
||||
if ($0 ~ /^[+-]#\s*Generated from docker\/versions.toml/) { next } \
|
||||
if ($0 ~ /^[+-]#\s*Environment:/) { next } \
|
||||
if ($0 ~ /^[+-]#\s*Source:/) { next } \
|
||||
if ($0 ~ /^[+-]$/) { next } \
|
||||
if ($0 ~ /^[+-]/) { print $0 } \
|
||||
}')
|
||||
if [ -n "$DIFF_FILTERED" ]; then
|
||||
echo "SSoT drift detected in $f:";
|
||||
echo "$DIFF_FILTERED";
|
||||
fail=1;
|
||||
fi
|
||||
done
|
||||
if [ $fail -ne 0 ]; then
|
||||
echo "\nERROR: Generated artifacts differ from repository (beyond timestamps)."
|
||||
echo "Run:"
|
||||
echo " DOCKER_SSOT_MODE=envless bash scripts/generate-compose-files.sh all"
|
||||
echo "and commit the changes."
|
||||
exit 1
|
||||
fi
|
||||
echo "No SSoT drift (ignoring timestamps)."
|
||||
# FIX: .yaml Extension nutzen (SSoT)
|
||||
- name: Validate Docker Compose Config
|
||||
run: docker compose --env-file docker/.env -f docker/docker-compose.yaml config
|
||||
|
||||
@@ -23,7 +23,7 @@ jobs:
|
||||
steps:
|
||||
# WICHTIG: Checkout ist notwendig, damit "git log" funktioniert
|
||||
- name: Checkout Code
|
||||
uses: actions/checkout@v4
|
||||
uses: actions/checkout@v6
|
||||
with:
|
||||
fetch-depth: 0 # Notwendig, um die Commit-Historie für "git log" zu laden
|
||||
|
||||
|
||||
+1
-1
@@ -23,7 +23,7 @@ logs/
|
||||
# Kotlin/Java
|
||||
*.class
|
||||
|
||||
.env
|
||||
config/.env
|
||||
|
||||
# Generated diagrams
|
||||
build/diagrams/
|
||||
|
||||
@@ -108,7 +108,7 @@ graph TB
|
||||
```bash
|
||||
# Massive Redundanz über 100+ Dateien verteilt:
|
||||
gradle.properties: services.port.ping=8082
|
||||
docker-compose.services.yml: SERVER_PORT: ${PING_SERVICE_PORT:-8082}
|
||||
docker-compose.services.yaml: SERVER_PORT: ${PING_SERVICE_PORT:-8082}
|
||||
dockerfiles/services/ping: EXPOSE 8082
|
||||
scripts/test/integration: ping-service:8082
|
||||
config/monitoring/prometheus: - targets: ['ping-service:8082']
|
||||
@@ -258,7 +258,7 @@ ping-service = 8092 # Geändert von 8082
|
||||
|
||||
# Ergebnis: 38+ Dateien automatisch aktualisiert:
|
||||
# ✓ gradle.properties: services.port.ping=8092
|
||||
# ✓ docker-compose.services.yml: SERVER_PORT: ${PING_SERVICE_PORT:-8092}
|
||||
# ✓ docker-compose.services.yaml: SERVER_PORT: ${PING_SERVICE_PORT:-8092}
|
||||
# ✓ dockerfiles/services/ping-service/Dockerfile: EXPOSE 8092
|
||||
# ✓ scripts/test/integration-test.sh: ping-service:8092
|
||||
# ✓ config/monitoring/prometheus.dev.yml: - targets: ['ping-service:8092']
|
||||
@@ -355,7 +355,7 @@ future-service = 8099
|
||||
|
||||
# Nach Synchronisation automatisch in:
|
||||
# - gradle.properties
|
||||
# - docker-compose.yml
|
||||
# - docker-compose.yaml
|
||||
# - Monitoring-Konfiguration
|
||||
# - Test-Scripts
|
||||
# - Environment-Files
|
||||
@@ -387,7 +387,7 @@ future-service = 8099
|
||||
|
||||
```bash
|
||||
# ❌ FALSCH - Nie mehr manuelle Port-Änderungen
|
||||
vim docker-compose.yml # Änderungen gehen verloren!
|
||||
vim docker-compose.yaml # Änderungen gehen verloren!
|
||||
|
||||
# ✅ RICHTIG - Zentrale Änderung + Synchronisation
|
||||
vim config/central.toml
|
||||
@@ -914,7 +914,7 @@ test-containers = true
|
||||
```bash
|
||||
# Development mit Hot-Reload und Debug
|
||||
export DOCKER_ENVIRONMENT=development
|
||||
docker-compose -f docker-compose.yml -f docker-compose.dev.yml up -d
|
||||
docker-compose -f docker-compose.yaml -f docker-compose.dev.yml up -d
|
||||
```
|
||||
|
||||
#### Production Environment
|
||||
@@ -1162,9 +1162,9 @@ jobs:
|
||||
},
|
||||
"docker.composeCommand": "docker-compose",
|
||||
"docker.composeFiles": [
|
||||
"docker-compose.yml",
|
||||
"docker-compose.services.yml",
|
||||
"docker-compose.clients.yml"
|
||||
"docker-compose.yaml",
|
||||
"docker-compose.services.yaml",
|
||||
"docker-compose.clients.yaml"
|
||||
]
|
||||
}
|
||||
```
|
||||
@@ -1713,20 +1713,20 @@ Unsere Compose-Dateien sind modular organisiert für verschiedene Einsatzszenari
|
||||
```bash
|
||||
# Alle Services einschließlich Clients
|
||||
docker-compose \
|
||||
-f docker-compose.yml \
|
||||
-f docker-compose.services.yml \
|
||||
-f docker-compose.clients.yml \
|
||||
-f docker-compose.yaml \
|
||||
-f docker-compose.services.yaml \
|
||||
-f docker-compose.clients.yaml \
|
||||
up -d
|
||||
|
||||
# Nur Infrastructure für Backend-Entwicklung
|
||||
docker-compose -f docker-compose.yml up -d postgres redis kafka consul zipkin
|
||||
docker-compose -f docker-compose.yaml up -d postgres redis kafka consul zipkin
|
||||
|
||||
# Mit Debug-Unterstützung für Service-Entwicklung
|
||||
DEBUG=true SPRING_PROFILES_ACTIVE=docker \
|
||||
docker-compose -f docker-compose.yml -f docker-compose.services.yml up -d
|
||||
docker-compose -f docker-compose.yaml -f docker-compose.services.yaml up -d
|
||||
|
||||
# Mit Live-Reload für Frontend-Entwicklung
|
||||
docker-compose -f docker-compose.yml -f docker-compose.override.yml up -d
|
||||
docker-compose -f docker-compose.yaml -f docker-compose.override.yml up -d
|
||||
```
|
||||
|
||||
#### 🔧 Erweiterte Umgebungskonfiguration
|
||||
@@ -1734,7 +1734,7 @@ docker-compose -f docker-compose.yml -f docker-compose.override.yml up -d
|
||||
**Beispiel für Auth-Server Konfiguration:**
|
||||
|
||||
```yaml
|
||||
# Erweiterte Environment-Variablen aus docker-compose.services.yml
|
||||
# Erweiterte Environment-Variablen aus docker-compose.services.yaml
|
||||
auth-server:
|
||||
environment:
|
||||
# Spring Boot Configuration
|
||||
@@ -1788,7 +1788,7 @@ auth-server:
|
||||
# Production - Optimiert und sicher
|
||||
docker-compose \
|
||||
-f docker-compose.prod.yml \
|
||||
-f docker-compose.services.yml \
|
||||
-f docker-compose.services.yaml \
|
||||
up -d
|
||||
|
||||
# Mit spezifischen Environment-Variablen
|
||||
@@ -1801,11 +1801,11 @@ docker-compose -f docker-compose.prod.yml up -d
|
||||
|
||||
```bash
|
||||
# Nur notwendige Services für Tests
|
||||
docker-compose -f docker-compose.yml up -d postgres redis
|
||||
docker-compose -f docker-compose.yaml up -d postgres redis
|
||||
./gradlew test
|
||||
|
||||
# End-to-End Tests
|
||||
docker-compose -f docker-compose.yml -f docker-compose.services.yml up -d
|
||||
docker-compose -f docker-compose.yaml -f docker-compose.services.yaml up -d
|
||||
./gradlew :client:web-app:jsTest
|
||||
```
|
||||
|
||||
@@ -1909,7 +1909,7 @@ services:
|
||||
|
||||
```bash
|
||||
# Service im Debug-Modus starten
|
||||
docker-compose -f docker-compose.yml up -d ping-service
|
||||
docker-compose -f docker-compose.yaml up -d ping-service
|
||||
docker-compose exec ping-service sh
|
||||
|
||||
# Logs in Echtzeit verfolgen
|
||||
@@ -2080,7 +2080,7 @@ labels:
|
||||
|
||||
```bash
|
||||
# Centralized logging mit ELK Stack (optional)
|
||||
docker-compose -f docker-compose.yml -f docker-compose.logging.yml up -d
|
||||
docker-compose -f docker-compose.yaml -f docker-compose.logging.yml up -d
|
||||
|
||||
# Log-Parsing für strukturierte Logs
|
||||
docker-compose logs --follow --tail=100 api-gateway | jq -r '.message'
|
||||
|
||||
@@ -53,7 +53,7 @@ make full-logs # Alle Logs in Echtzeit
|
||||
Befehle für die lokale Entwicklungsumgebung:
|
||||
|
||||
```bash
|
||||
make dev-up # Startet Entwicklungsumgebung (docker-compose.yml)
|
||||
make dev-up # Startet Entwicklungsumgebung (docker-compose.yaml)
|
||||
make dev-down # Stoppt Entwicklungsumgebung
|
||||
make dev-restart # Neustart Entwicklungsumgebung
|
||||
make dev-logs # Zeigt alle Development-Logs
|
||||
@@ -634,16 +634,16 @@ Das Projekt verwendet mehrere Compose-Files:
|
||||
|
||||
```bash
|
||||
# Nur Infrastruktur
|
||||
docker compose -f docker-compose.yml up -d
|
||||
docker compose -f docker-compose.yaml up -d
|
||||
|
||||
# Infrastruktur + Services
|
||||
docker compose -f docker-compose.yml -f docker-compose.services.yml up -d
|
||||
docker compose -f docker-compose.yaml -f docker-compose.services.yaml up -d
|
||||
|
||||
# Infrastruktur + Clients
|
||||
docker compose -f docker-compose.yml -f docker-compose.clients.yml up -d
|
||||
docker compose -f docker-compose.yaml -f docker-compose.clients.yaml up -d
|
||||
|
||||
# Alles
|
||||
docker compose -f docker-compose.yml -f docker-compose.services.yml -f docker-compose.clients.yml up -d
|
||||
docker compose -f docker-compose.yaml -f docker-compose.services.yaml -f docker-compose.clients.yaml up -d
|
||||
|
||||
# ⚠️ Tipp: Verwende stattdessen die Makefile-Befehle!
|
||||
```
|
||||
|
||||
@@ -58,7 +58,7 @@ labels:
|
||||
|
||||
```bash
|
||||
# Centralized logging mit ELK Stack (optional)
|
||||
docker-compose -f docker-compose.yml -f docker-compose.logging.yml up -d
|
||||
docker-compose -f docker-compose.yaml -f docker-compose.logging.yml up -d
|
||||
|
||||
# Log-Parsing für strukturierte Logs
|
||||
docker-compose logs --follow --tail=100 api-gateway | jq -r '.message'
|
||||
|
||||
@@ -186,7 +186,7 @@ source .env.production
|
||||
certbot certificates
|
||||
|
||||
# 3. Services mit Production-Konfiguration starten
|
||||
docker-compose -f docker-compose.yml -f docker-compose.prod.yml up -d
|
||||
docker-compose -f docker-compose.yaml -f docker-compose.prod.yml up -d
|
||||
|
||||
# 4. Health-Checks durchführen
|
||||
curl -f https://api.meldestelle.at/actuator/health
|
||||
|
||||
@@ -146,8 +146,8 @@ Das Docker-Setup ist spezifisch für die Web-Entwicklung konfiguriert (wie in `R
|
||||
|
||||
```shell script
|
||||
# Startet die Web-App mit Hot-Reload
|
||||
docker-compose -f docker-compose.yml \
|
||||
-f docker-compose.clients.yml up -d web-app
|
||||
docker-compose -f docker-compose.yaml \
|
||||
-f docker-compose.clients.yaml up -d web-app
|
||||
```
|
||||
|
||||
Der Dienst ist dann unter dem in der `docker-compose.clients.yml` konfigurierten Port (z.B. Port `3000`) erreichbar.
|
||||
|
||||
@@ -1,5 +1,6 @@
|
||||
# Meldestelle
|
||||
|
||||
|
||||
> Modulares System für Pferdesportveranstaltungen mit Domain-Driven Design
|
||||
|
||||
[](https://github.com/StefanMoCoAt/meldestelle/actions)
|
||||
@@ -26,7 +27,7 @@ cp -n .env.template config/env/.env 2>/dev/null || true
|
||||
# DOCKER_SSOT_MODE=envless bash scripts/generate-compose-files.sh all development
|
||||
|
||||
# 4) Infrastruktur starten
|
||||
docker compose -f docker-compose.yml up -d
|
||||
docker compose -f docker-compose.yaml up -d
|
||||
|
||||
# 5) Services starten (Beispiel)
|
||||
./gradlew :members:members-service:bootRun
|
||||
@@ -259,10 +260,10 @@ bash scripts/generate-compose-files.sh all development && \
|
||||
|
||||
```bash
|
||||
# Nur Infrastruktur
|
||||
# Wenn eine handgeschriebene docker-compose.yml existiert:
|
||||
docker compose -f docker-compose.yml up -d
|
||||
# Wenn eine handgeschriebene docker-compose.yaml existiert:
|
||||
docker compose -f docker-compose.yaml up -d
|
||||
# Falls Compose-Files generiert werden:
|
||||
docker compose -f docker-compose.services.yml up -d
|
||||
docker compose -f docker-compose.services.yaml up -d
|
||||
|
||||
# Services via Gradle
|
||||
a) Einzeldienst
|
||||
@@ -304,7 +305,7 @@ b) Falls unterstützt: alle (oder Aggregator)
|
||||
#### Nur Infrastruktur (Postgres, Redis, Kafka, Keycloak)
|
||||
|
||||
```bash
|
||||
docker compose -f docker-compose.yml up -d
|
||||
docker compose -f docker-compose.yaml up -d
|
||||
```
|
||||
|
||||
#### Services über Gradle
|
||||
|
||||
@@ -1,195 +0,0 @@
|
||||
# ===================================================================
|
||||
# Environment Configuration Template - Meldestelle Project
|
||||
# ===================================================================
|
||||
# Copy this file to config/env/.env and customize the values for your environment
|
||||
# Security Note: Never commit .env files containing production secrets!
|
||||
# ===================================================================
|
||||
|
||||
# ===================================================================
|
||||
# Runtime Configuration (Single Source for runtime values)
|
||||
# Hinweis: Build-/Image-Versionen werden ausschließlich in docker/versions.toml
|
||||
# und docker/build-args/global.env gepflegt. Keine Build-/Versionseinträge hier.
|
||||
# ===================================================================
|
||||
|
||||
# Anwendung
|
||||
APP_NAME=Meldestelle
|
||||
|
||||
# Profile
|
||||
SPRING_PROFILES_ACTIVE=docker,keycloak
|
||||
|
||||
# ===================================================================
|
||||
# Infrastructure Services - Port Configuration
|
||||
# ===================================================================
|
||||
# Database
|
||||
POSTGRES_DB=meldestelle
|
||||
# Note: Username and password are now managed via Docker secrets
|
||||
|
||||
# Redis Cache
|
||||
REDIS_PORT=6379
|
||||
|
||||
# Keycloak Authentication
|
||||
KEYCLOAK_PORT=8180
|
||||
KEYCLOAK_LOG_LEVEL=INFO
|
||||
|
||||
# Service Discovery
|
||||
CONSUL_HOST=consul
|
||||
CONSUL_PORT=8500
|
||||
CONSUL_ENABLED=true
|
||||
|
||||
# Messaging
|
||||
ZOOKEEPER_CLIENT_PORT=2181
|
||||
KAFKA_PORT=9092
|
||||
KAFKA_BROKER_ID=1
|
||||
KAFKA_OFFSETS_TOPIC_REPLICATION_FACTOR=1
|
||||
|
||||
# Monitoring
|
||||
PROMETHEUS_PORT=9090
|
||||
GRAFANA_PORT=3000
|
||||
|
||||
# ===================================================================
|
||||
# Application Services - Port Configuration
|
||||
# ===================================================================
|
||||
# API Gateway
|
||||
GATEWAY_HOST=api-gateway
|
||||
GATEWAY_PORT=8081
|
||||
|
||||
# Microservices
|
||||
PING_SERVICE_PORT=8082
|
||||
MEMBERS_SERVICE_PORT=8083
|
||||
HORSES_SERVICE_PORT=8084
|
||||
EVENTS_SERVICE_PORT=8085
|
||||
MASTERDATA_SERVICE_PORT=8086
|
||||
AUTH_SERVICE_PORT=8087
|
||||
MONITORING_SERVER_PORT=8088
|
||||
|
||||
# ===================================================================
|
||||
# Client Applications - Port Configuration
|
||||
# ===================================================================
|
||||
# Web Application
|
||||
WEB_APP_PORT=4000
|
||||
WEB_APP_DOMAIN=localhost
|
||||
NODE_ENV=production
|
||||
|
||||
# Nginx Configuration
|
||||
NGINX_WORKER_PROCESSES=auto
|
||||
NGINX_WORKER_CONNECTIONS=1024
|
||||
|
||||
# Desktop Application
|
||||
DESKTOP_VNC_WEB_PORT=6080
|
||||
DESKTOP_VNC_PORT=5901
|
||||
DESKTOP_APP_DOMAIN=localhost
|
||||
|
||||
# ===================================================================
|
||||
# Security Configuration
|
||||
# ===================================================================
|
||||
# JWT Configuration
|
||||
JWT_ISSUER=meldestelle-auth-server
|
||||
JWT_AUDIENCE=meldestelle-services
|
||||
|
||||
# Note: JWT_SECRET is now managed via Docker secrets
|
||||
# Generate with: openssl rand -hex 32
|
||||
|
||||
# Keycloak Configuration
|
||||
KEYCLOAK_REALM=meldestelle
|
||||
KEYCLOAK_CLIENT_ID=api-gateway
|
||||
|
||||
# Note: All passwords and secrets are now managed via Docker secrets
|
||||
# Run: ./docker/secrets/setup-secrets.sh to generate secure secrets
|
||||
|
||||
# ===================================================================
|
||||
# Data Storage Configuration
|
||||
# ===================================================================
|
||||
# Data directory for persistent volumes
|
||||
# Default: ./data (relative to project root)
|
||||
# Production: /var/lib/meldestelle or dedicated mount point
|
||||
DATA_PATH=./data
|
||||
|
||||
# Volume configuration
|
||||
# These directories will be created under DATA_PATH:
|
||||
# - postgres/ (PostgreSQL data)
|
||||
# - redis/ (Redis data)
|
||||
# - prometheus/ (Prometheus metrics)
|
||||
# - grafana/ (Grafana dashboards)
|
||||
# - keycloak/ (Keycloak data)
|
||||
# - consul/ (Consul data)
|
||||
# - monitoring/ (Custom monitoring data)
|
||||
# - desktop-app/ (Desktop application data)
|
||||
|
||||
# ===================================================================
|
||||
# Development and Testing
|
||||
# ===================================================================
|
||||
# Enable debug mode for Java applications
|
||||
DEBUG=false
|
||||
|
||||
# Enable Wasm compilation for client applications
|
||||
ENABLE_WASM=false
|
||||
|
||||
# ===================================================================
|
||||
# Production Deployment Settings
|
||||
# ===================================================================
|
||||
# Container resource limits (configured in docker-compose files)
|
||||
# These are documented here for reference:
|
||||
|
||||
# Infrastructure Services Resource Limits:
|
||||
# - postgres: 2 CPU, 2GB RAM (reserved: 0.5 CPU, 512MB RAM)
|
||||
# - redis: 1 CPU, 1GB RAM (reserved: 0.25 CPU, 256MB RAM)
|
||||
# - keycloak: 2 CPU, 2GB RAM (reserved: 0.5 CPU, 1GB RAM)
|
||||
# - consul: 1 CPU, 512MB RAM (reserved: 0.25 CPU, 128MB RAM)
|
||||
# - kafka: 2 CPU, 2GB RAM (reserved: 0.5 CPU, 512MB RAM)
|
||||
# - zookeeper: 1 CPU, 1GB RAM (reserved: 0.25 CPU, 256MB RAM)
|
||||
# - prometheus: 1 CPU, 2GB RAM (reserved: 0.25 CPU, 512MB RAM)
|
||||
# - grafana: 1 CPU, 1GB RAM (reserved: 0.25 CPU, 256MB RAM)
|
||||
# - api-gateway: 2 CPU, 2GB RAM (reserved: 0.5 CPU, 1GB RAM)
|
||||
|
||||
# Microservices Resource Limits:
|
||||
# - ping-service: 1 CPU, 1GB RAM (reserved: 0.25 CPU, 256MB RAM)
|
||||
# - members-service: 2 CPU, 2GB RAM (reserved: 0.5 CPU, 512MB RAM)
|
||||
# - horses-service: 2 CPU, 2GB RAM (reserved: 0.5 CPU, 512MB RAM)
|
||||
# - events-service: 2 CPU, 2GB RAM (reserved: 0.5 CPU, 512MB RAM)
|
||||
# - masterdata-service: 1.5 CPU, 1.5GB RAM (reserved: 0.5 CPU, 512MB RAM)
|
||||
# - auth-server: 1.5 CPU, 1.5GB RAM (reserved: 0.5 CPU, 512MB RAM)
|
||||
|
||||
# Client Applications Resource Limits:
|
||||
# - web-app: 1 CPU, 512MB RAM (reserved: 0.25 CPU, 128MB RAM)
|
||||
# - desktop-app: 2 CPU, 2GB RAM (reserved: 0.5 CPU, 512MB RAM)
|
||||
# - monitoring-server: 1 CPU, 1GB RAM (reserved: 0.25 CPU, 256MB RAM)
|
||||
|
||||
# ===================================================================
|
||||
# Security Notes
|
||||
# ===================================================================
|
||||
# 1. All passwords and secrets are managed via Docker secrets
|
||||
# 2. Run ./docker/secrets/setup-secrets.sh to generate secure credentials
|
||||
# 3. Containers run as non-root users where possible
|
||||
# 4. Security options: no-new-privileges enabled for all services
|
||||
# 5. Networks are isolated with custom subnet (172.20.0.0/16)
|
||||
# 6. Volumes have proper permissions and are mounted read-only where appropriate
|
||||
# 7. Health checks are configured for all services
|
||||
# 8. Resource limits prevent resource exhaustion attacks
|
||||
|
||||
# ===================================================================
|
||||
# Usage Instructions
|
||||
# ===================================================================
|
||||
# 1. Copy this file: mkdir -p config/env && cp .env.template config/env/.env
|
||||
# 2. Customize values in config/env/.env for your environment
|
||||
# 3. Generate secrets: ./docker/secrets/setup-secrets.sh --all
|
||||
# 4. Create data directories: mkdir -p ./data/{postgres,redis,prometheus,grafana,keycloak,consul}
|
||||
# 5. Deploy infrastructure: docker compose -f docker-compose.yml up -d
|
||||
# 6. Deploy services: docker compose -f docker-compose.services.yml up -d
|
||||
# 7. Deploy clients: docker compose -f docker-compose.clients.yml up -d
|
||||
|
||||
# ===================================================================
|
||||
# Monitoring and Logging
|
||||
# ===================================================================
|
||||
# Access URLs (when running with default ports):
|
||||
# - Grafana Dashboard: http://localhost:3000 (admin credentials in secrets)
|
||||
# - Prometheus Metrics: http://localhost:9090
|
||||
# - Consul UI: http://localhost:8500
|
||||
# - Keycloak Admin: http://localhost:8180/admin (admin credentials in secrets)
|
||||
# - API Gateway: http://localhost:8081
|
||||
# - Web Application: http://localhost:4000
|
||||
# - Desktop VNC: http://localhost:6080
|
||||
|
||||
# Log locations (inside containers):
|
||||
# - Application logs: /app/logs/
|
||||
# - Nginx logs: /var/log/nginx/
|
||||
# - System logs: journalctl -u docker
|
||||
@@ -1,207 +0,0 @@
|
||||
# ===================================================================
|
||||
# Environment Configuration Template - Meldestelle Project
|
||||
# ===================================================================
|
||||
# Copy this file to .env and customize the values for your environment
|
||||
# Security Note: Never commit .env files containing production secrets!
|
||||
# ===================================================================
|
||||
|
||||
# ===================================================================
|
||||
# Build Configuration
|
||||
# ===================================================================
|
||||
# Docker image versions
|
||||
DOCKER_GRADLE_VERSION=9.1.0
|
||||
DOCKER_JAVA_VERSION=21
|
||||
DOCKER_KEYCLOAK_VERSION=26.4.0
|
||||
DOCKER_PROMETHEUS_VERSION=v2.54.1
|
||||
DOCKER_GRAFANA_VERSION=11.3.0
|
||||
|
||||
# Application version
|
||||
DOCKER_APP_VERSION=1.0.0
|
||||
APP_VERSION=1.0.0
|
||||
APP_NAME=Meldestelle
|
||||
|
||||
# Build metadata
|
||||
BUILD_DATE=2025-11-11
|
||||
# BUILD_DATE will be auto-generated if not set
|
||||
|
||||
# Spring profiles for services
|
||||
SPRING_PROFILES_ACTIVE=docker,keycloak
|
||||
DOCKER_SPRING_PROFILES_DEFAULT=default
|
||||
DOCKER_SPRING_PROFILES_DOCKER=docker
|
||||
|
||||
# ===================================================================
|
||||
# Infrastructure Services - Port Configuration
|
||||
# ===================================================================
|
||||
# Database
|
||||
POSTGRES_DB=meldestelle
|
||||
# Note: Username and password are now managed via Docker secrets
|
||||
|
||||
# Redis Cache
|
||||
REDIS_PORT=6379
|
||||
|
||||
# Keycloak Authentication
|
||||
KEYCLOAK_PORT=8180
|
||||
KEYCLOAK_LOG_LEVEL=INFO
|
||||
|
||||
# Service Discovery
|
||||
CONSUL_HOST=consul
|
||||
CONSUL_PORT=8500
|
||||
CONSUL_ENABLED=true
|
||||
|
||||
# Messaging
|
||||
ZOOKEEPER_CLIENT_PORT=2181
|
||||
KAFKA_PORT=9092
|
||||
KAFKA_BROKER_ID=1
|
||||
KAFKA_OFFSETS_TOPIC_REPLICATION_FACTOR=1
|
||||
|
||||
# Monitoring
|
||||
PROMETHEUS_PORT=9090
|
||||
GRAFANA_PORT=3000
|
||||
|
||||
# ===================================================================
|
||||
# Application Services - Port Configuration
|
||||
# ===================================================================
|
||||
# API Gateway
|
||||
GATEWAY_HOST=api-gateway
|
||||
GATEWAY_PORT=8081
|
||||
|
||||
# Microservices
|
||||
PING_SERVICE_PORT=8082
|
||||
MEMBERS_SERVICE_PORT=8083
|
||||
HORSES_SERVICE_PORT=8084
|
||||
EVENTS_SERVICE_PORT=8085
|
||||
MASTERDATA_SERVICE_PORT=8086
|
||||
AUTH_SERVICE_PORT=8087
|
||||
MONITORING_SERVER_PORT=8088
|
||||
|
||||
# ===================================================================
|
||||
# Client Applications - Port Configuration
|
||||
# ===================================================================
|
||||
# Web Application
|
||||
WEB_APP_PORT=4000
|
||||
WEB_APP_DOMAIN=localhost
|
||||
NODE_ENV=production
|
||||
|
||||
# Nginx Configuration
|
||||
NGINX_WORKER_PROCESSES=auto
|
||||
NGINX_WORKER_CONNECTIONS=1024
|
||||
|
||||
# Desktop Application
|
||||
DESKTOP_VNC_WEB_PORT=6080
|
||||
DESKTOP_VNC_PORT=5901
|
||||
DESKTOP_APP_DOMAIN=localhost
|
||||
|
||||
# ===================================================================
|
||||
# Security Configuration
|
||||
# ===================================================================
|
||||
# JWT Configuration
|
||||
JWT_ISSUER=meldestelle-auth-server
|
||||
JWT_AUDIENCE=meldestelle-services
|
||||
|
||||
# Note: JWT_SECRET is now managed via Docker secrets
|
||||
# Generate with: openssl rand -hex 32
|
||||
|
||||
# Keycloak Configuration
|
||||
KEYCLOAK_REALM=meldestelle
|
||||
KEYCLOAK_CLIENT_ID=api-gateway
|
||||
|
||||
# Note: All passwords and secrets are now managed via Docker secrets
|
||||
# Run: ./docker/secrets/setup-secrets.sh to generate secure secrets
|
||||
|
||||
# ===================================================================
|
||||
# Data Storage Configuration
|
||||
# ===================================================================
|
||||
# Data directory for persistent volumes
|
||||
# Default: ./data (relative to project root)
|
||||
# Production: /var/lib/meldestelle or dedicated mount point
|
||||
DATA_PATH=./data
|
||||
|
||||
# Volume configuration
|
||||
# These directories will be created under DATA_PATH:
|
||||
# - postgres/ (PostgreSQL data)
|
||||
# - redis/ (Redis data)
|
||||
# - prometheus/ (Prometheus metrics)
|
||||
# - grafana/ (Grafana dashboards)
|
||||
# - keycloak/ (Keycloak data)
|
||||
# - consul/ (Consul data)
|
||||
# - monitoring/ (Custom monitoring data)
|
||||
# - desktop-app/ (Desktop application data)
|
||||
|
||||
# ===================================================================
|
||||
# Development and Testing
|
||||
# ===================================================================
|
||||
# Enable debug mode for Java applications
|
||||
DEBUG=false
|
||||
|
||||
# Enable Wasm compilation for client applications
|
||||
ENABLE_WASM=false
|
||||
|
||||
# ===================================================================
|
||||
# Production Deployment Settings
|
||||
# ===================================================================
|
||||
# Container resource limits (configured in docker-compose files)
|
||||
# These are documented here for reference:
|
||||
|
||||
# Infrastructure Services Resource Limits:
|
||||
# - postgres: 2 CPU, 2GB RAM (reserved: 0.5 CPU, 512MB RAM)
|
||||
# - redis: 1 CPU, 1GB RAM (reserved: 0.25 CPU, 256MB RAM)
|
||||
# - keycloak: 2 CPU, 2GB RAM (reserved: 0.5 CPU, 1GB RAM)
|
||||
# - consul: 1 CPU, 512MB RAM (reserved: 0.25 CPU, 128MB RAM)
|
||||
# - kafka: 2 CPU, 2GB RAM (reserved: 0.5 CPU, 512MB RAM)
|
||||
# - zookeeper: 1 CPU, 1GB RAM (reserved: 0.25 CPU, 256MB RAM)
|
||||
# - prometheus: 1 CPU, 2GB RAM (reserved: 0.25 CPU, 512MB RAM)
|
||||
# - grafana: 1 CPU, 1GB RAM (reserved: 0.25 CPU, 256MB RAM)
|
||||
# - api-gateway: 2 CPU, 2GB RAM (reserved: 0.5 CPU, 1GB RAM)
|
||||
|
||||
# Microservices Resource Limits:
|
||||
# - ping-service: 1 CPU, 1GB RAM (reserved: 0.25 CPU, 256MB RAM)
|
||||
# - members-service: 2 CPU, 2GB RAM (reserved: 0.5 CPU, 512MB RAM)
|
||||
# - horses-service: 2 CPU, 2GB RAM (reserved: 0.5 CPU, 512MB RAM)
|
||||
# - events-service: 2 CPU, 2GB RAM (reserved: 0.5 CPU, 512MB RAM)
|
||||
# - masterdata-service: 1.5 CPU, 1.5GB RAM (reserved: 0.5 CPU, 512MB RAM)
|
||||
# - auth-server: 1.5 CPU, 1.5GB RAM (reserved: 0.5 CPU, 512MB RAM)
|
||||
|
||||
# Client Applications Resource Limits:
|
||||
# - web-app: 1 CPU, 512MB RAM (reserved: 0.25 CPU, 128MB RAM)
|
||||
# - desktop-app: 2 CPU, 2GB RAM (reserved: 0.5 CPU, 512MB RAM)
|
||||
# - monitoring-server: 1 CPU, 1GB RAM (reserved: 0.25 CPU, 256MB RAM)
|
||||
|
||||
# ===================================================================
|
||||
# Security Notes
|
||||
# ===================================================================
|
||||
# 1. All passwords and secrets are managed via Docker secrets
|
||||
# 2. Run ./docker/secrets/setup-secrets.sh to generate secure credentials
|
||||
# 3. Containers run as non-root users where possible
|
||||
# 4. Security options: no-new-privileges enabled for all services
|
||||
# 5. Networks are isolated with custom subnet (172.20.0.0/16)
|
||||
# 6. Volumes have proper permissions and are mounted read-only where appropriate
|
||||
# 7. Health checks are configured for all services
|
||||
# 8. Resource limits prevent resource exhaustion attacks
|
||||
|
||||
# ===================================================================
|
||||
# Usage Instructions
|
||||
# ===================================================================
|
||||
# 1. Copy this file: cp .env.template .env
|
||||
# 2. Customize values in .env for your environment
|
||||
# 3. Generate secrets: ./docker/secrets/setup-secrets.sh --all
|
||||
# 4. Create data directories: mkdir -p ./data/{postgres,redis,prometheus,grafana,keycloak,consul}
|
||||
# 5. Deploy infrastructure: docker-compose -f docker-compose.yml.optimized up -d
|
||||
# 6. Deploy services: docker-compose -f docker-compose.yml.optimized -f docker-compose.services.yml.optimized up -d
|
||||
# 7. Deploy clients: docker-compose -f docker-compose.yml.optimized -f docker-compose.services.yml.optimized -f docker-compose.clients.yml.optimized up -d
|
||||
|
||||
# ===================================================================
|
||||
# Monitoring and Logging
|
||||
# ===================================================================
|
||||
# Access URLs (when running with default ports):
|
||||
# - Grafana Dashboard: http://localhost:3000 (admin credentials in secrets)
|
||||
# - Prometheus Metrics: http://localhost:9090
|
||||
# - Consul UI: http://localhost:8500
|
||||
# - Keycloak Admin: http://localhost:8180/admin (admin credentials in secrets)
|
||||
# - API Gateway: http://localhost:8081
|
||||
# - Web Application: http://localhost:4000
|
||||
# - Desktop VNC: http://localhost:6080
|
||||
|
||||
# Log locations (inside containers):
|
||||
# - Application logs: /app/logs/
|
||||
# - Nginx logs: /var/log/nginx/
|
||||
# - System logs: journalctl -u docker
|
||||
@@ -1 +0,0 @@
|
||||
# Horses Module\n\nThis is a minimal placeholder README to satisfy documentation validation. See docs/index.md for project docs
|
||||
@@ -1,443 +0,0 @@
|
||||
### Schlachtplan für das 'infrastructure'-Modul
|
||||
|
||||
Basierend auf der Analyse des aktuellen Zustands (Stand: 11. Oktober 2025) habe ich einen strukturierten Aktionsplan
|
||||
erstellt. Die letzte größere Aktualisierung war im Juli 2025, seitdem gab es signifikante Änderungen am Gateway-Modul.
|
||||
|
||||
---
|
||||
|
||||
### 🔴 Phase 1: SOFORT (Diese Woche)
|
||||
|
||||
#### 1.1 Gateway-Tests reparieren (Höchste Priorität)
|
||||
|
||||
**Problem:** Tests sind komplett defekt - nur ~47% funktionieren noch (25/53 Tests).
|
||||
|
||||
**Aktionen:**
|
||||
|
||||
- ❌ **Löschen:** `JwtAuthenticationTests.kt` - testet nicht-existierende Custom-Filter
|
||||
- ✅ **Behalten:** `FallbackControllerTests.kt`, `GatewayApplicationTests.kt`
|
||||
- ✏️ **Überarbeiten:** `GatewayRoutingTests.kt`, `GatewaySecurityTests.kt`, `GatewayFiltersTests.kt`
|
||||
- Option A: Tests mit MockJWT-Tokens ausstatten (siehe `TestSecurityConfig.kt`)
|
||||
- Option B: Tests auf Public Paths verlegen (`/actuator/**`, `/fallback/**`)
|
||||
- Option C: Security in Tests deaktivieren
|
||||
|
||||
**Warum jetzt:** Tests geben keine Sicherheit mehr – blockiert Entwicklung.
|
||||
|
||||
**Zeitaufwand:** 4–6 Stunden
|
||||
|
||||
---
|
||||
|
||||
#### 1.2 Gateway-Build-Datei bereinigen
|
||||
|
||||
**Problem:** Duplizierte Dependency in `gateway/build.gradle.kts` (Zeile 33-34).
|
||||
|
||||
**Aktion:**
|
||||
|
||||
```kotlin
|
||||
// ENTFERNEN: Zeile 34
|
||||
implementation(project(":infrastructure:event-store:redis-event-store")) // ← Duplikat!
|
||||
```
|
||||
|
||||
**Zeitaufwand:** 5 Minuten
|
||||
|
||||
---
|
||||
|
||||
### 🟡 Phase 2: KURZFRISTIG (Nächste 2 Wochen)
|
||||
|
||||
#### 2.1 Dependency-Versionen aktualisieren
|
||||
|
||||
**Problem:** Versionen von Juli 2025 – teilweise veraltet.
|
||||
|
||||
**Zu prüfen und aktualisieren:**
|
||||
|
||||
| Dependency | Aktuell | Latest (Okt 2025) | Priorität |
|
||||
|-------------------|----------|-------------------|-----------|
|
||||
| Spring Boot | 3.5.5 | 3.5.x | Mittel |
|
||||
| Spring Cloud | 2025.0.0 | 2025.0.x | Mittel |
|
||||
| Kotlin | 2.2.20 | 2.2.x | Niedrig |
|
||||
| Keycloak | 26.0.7 | 26.x.x | Hoch |
|
||||
| Testcontainers | 1.21.3 | 1.21.x | Niedrig |
|
||||
| PostgresQL Driver | 42.7.7 | 42.7.x | Niedrig |
|
||||
|
||||
**Aktion:**
|
||||
|
||||
1. `gradle/libs.versions.toml` aktualisieren
|
||||
2. Tests nach jedem Update ausführen
|
||||
3. Breaking Changes dokumentieren
|
||||
|
||||
**Zeitaufwand:** 1–2 Tage (mit Testing)
|
||||
|
||||
---
|
||||
|
||||
#### 2.2 Docker-Images aktualisieren
|
||||
|
||||
**Problem:** Einige Docker-Images sind möglicherweise veraltet.
|
||||
|
||||
**Zu prüfen:**
|
||||
|
||||
```yaml
|
||||
# docker-compose.yml
|
||||
postgres: 16-alpine # ✅ Aktuell (neueste: 16.x)
|
||||
redis: 7-alpine # ✅ Aktuell
|
||||
keycloak: 26.4.0 # ⚠️ Prüfen auf 26.x updates
|
||||
consul: 1.15 # ⚠️ Prüfen (neueste: 1.20+)
|
||||
kafka: 7.4.0 # ⚠️ Prüfen (neueste: 7.8+)
|
||||
prometheus: v2.54.1 # ⚠️ Prüfen
|
||||
grafana: 11.3.0 # ✅ Wahrscheinlich aktuell
|
||||
```
|
||||
|
||||
**Aktion:**
|
||||
|
||||
1. Versions-Check durchführen
|
||||
2. Schrittweise aktualisieren (einzeln testen!)
|
||||
3. `.env`-Datei mit Versions-Variablen anlegen
|
||||
|
||||
**Zeitaufwand:** 3–4 Stunden
|
||||
|
||||
---
|
||||
|
||||
#### 2.3 Monitoring-Modul vervollständigen
|
||||
|
||||
**Problem:** Nur 3 Kotlin-Files – deutlich unter implementiert im Vergleich zur Dokumentation.
|
||||
|
||||
**Dokumentiert, aber fehlt:**
|
||||
|
||||
- Distributed Tracing (Zipkin) - Docker-Container fehlt!
|
||||
- Custom Metrics Implementation
|
||||
- Health Check Aggregation
|
||||
- Alerting Rules Implementation
|
||||
|
||||
**Aktion:**
|
||||
|
||||
1. Zipkin zu `docker-compose.yml` hinzufügen
|
||||
2. Tracing-Integration in Gateway testen
|
||||
3. Custom Metrics-Library erstellen
|
||||
4. Prometheus Alerting Rules konfigurieren
|
||||
|
||||
**Zeitaufwand:** 2–3 Tage
|
||||
|
||||
---
|
||||
|
||||
### 🟢 Phase 3: MITTELFRISTIG (Nächste 4–6 Wochen)
|
||||
|
||||
#### 3.1 Dokumentation aktualisieren
|
||||
|
||||
**Problem:** README von Juli 2025 – nicht mehr aktuell.
|
||||
|
||||
**Zu aktualisieren:**
|
||||
|
||||
**`README-INFRASTRUCTURE.md`:**
|
||||
|
||||
- Zeile 552: "Letzte Aktualisierung: 25. Juli 2025" → Oktober 2025
|
||||
- Security-Sektion: OAuth2 Resource Server statt Custom JWT Filter
|
||||
- Keycloak Version: 23.0 → 26.4.0
|
||||
- Kafka Version: 7.5.0 → 7.4.0 (Downgrade dokumentieren!)
|
||||
- Monitoring: Zipkin-Konfiguration ergänzen
|
||||
|
||||
**Neue Sections hinzufügen:**
|
||||
|
||||
- #### Bekannte Limitierungen
|
||||
|
||||
- #### Migration Notes (Juli → Oktober 2025)
|
||||
|
||||
- #### Troubleshooting erweitern
|
||||
|
||||
**Zeitaufwand:** 1 Tag
|
||||
|
||||
---
|
||||
|
||||
#### 3.2 Auth-Module überarbeiten
|
||||
|
||||
**Problem:** Vermutlich veraltet - Custom JWT vs. OAuth2 Resource Server Diskrepanz.
|
||||
|
||||
**Zu klären:**
|
||||
|
||||
- Werden `auth-client` und `auth-server` noch verwendet?
|
||||
- Redundanz mit Gateway's OAuth2 Resource Server?
|
||||
- Keycloak-Integration vereinheitlichen
|
||||
|
||||
**Aktion:**
|
||||
|
||||
1. Abhängigkeiten zu auth-Modulen analysieren
|
||||
2. Entscheiden: Refactoring oder Deprecation
|
||||
3. Wenn deprecated: Migration Path dokumentieren
|
||||
|
||||
**Zeitaufwand:** 3–5 Tage
|
||||
|
||||
---
|
||||
|
||||
#### 3.3 Cache-Module modernisieren
|
||||
|
||||
**Problem:** Redis 7 ist aktuell, aber Implementation-Patterns könnten veraltet sein.
|
||||
|
||||
**Zu prüfen:**
|
||||
|
||||
- Multi-Level Caching tatsächlich implementiert?
|
||||
- Cache Statistics vorhanden?
|
||||
- TTL Management korrekt?
|
||||
- Integration mit Spring Cache Abstraction?
|
||||
|
||||
**Aktion:**
|
||||
|
||||
1. Cache-Tests erweitern
|
||||
2. Performance-Metriken hinzufügen
|
||||
3. Cache-Warming Strategy implementieren
|
||||
|
||||
**Zeitaufwand:** 2–3 Tage
|
||||
|
||||
---
|
||||
|
||||
#### 3.4 Event-Store Performance-Optimierung
|
||||
|
||||
**Problem:** Redis-basiert - für Production ggf. nicht optimal.
|
||||
|
||||
**Zu evaluieren:**
|
||||
|
||||
- Ist Redis der richtige Event Store für Production?
|
||||
- Alternative: PostgresQL mit Event Store Pattern?
|
||||
- Snapshot-Strategie tatsächlich implementiert?
|
||||
|
||||
**Aktion:**
|
||||
|
||||
1. Performance-Tests durchführen
|
||||
2. Event Store Benchmark (Redis vs. PostgresQL)
|
||||
3. Dokumentation aktualisieren mit Pros/Cons
|
||||
|
||||
**Zeitaufwand:** 1 Woche
|
||||
|
||||
---
|
||||
|
||||
### 🔵 Phase 4: LANGFRISTIG (Nächste 2–3 Monate)
|
||||
|
||||
#### 4.1 Service Mesh evaluieren
|
||||
|
||||
**Dokumentiert in "Zukünftige Erweiterungen"** – noch nicht implementiert.
|
||||
|
||||
**Optionen:**
|
||||
|
||||
- Istio (komplex, feature-reich)
|
||||
- Linkerd (leichtgewichtig)
|
||||
- Consul Connect (bereits Consul vorhanden!)
|
||||
|
||||
**Empfehlung:** Start mit Consul Connect - minimaler Overhead.
|
||||
|
||||
**Zeitaufwand:** 2–3 Wochen
|
||||
|
||||
---
|
||||
|
||||
#### 4.2 OpenTelemetry statt Zipkin
|
||||
|
||||
**Problem:** Zipkin ist veraltet – OpenTelemetry ist der moderne Standard.
|
||||
|
||||
**Migration Path:**
|
||||
|
||||
1. OpenTelemetry Collector aufsetzen
|
||||
2. Spring Boot Auto-Instrumentation aktivieren
|
||||
3. Zipkin als Backend behalten (kompatibel!)
|
||||
4. Schrittweise migrieren
|
||||
|
||||
**Zeitaufwand:** 1–2 Wochen
|
||||
|
||||
---
|
||||
|
||||
#### 4.3 Security Hardening
|
||||
|
||||
**Aktuelle Gaps:**
|
||||
|
||||
- JWT Token Rotation nicht implementiert
|
||||
- Rate Limiting nur dokumentiert, nicht konfiguriert
|
||||
- Audit Logging fehlt
|
||||
- HTTPS/TLS noch nicht erzwungen
|
||||
|
||||
**Aktion:**
|
||||
|
||||
1. Rate Limiting im Gateway aktivieren
|
||||
2. Audit Log Framework implementieren
|
||||
3. TLS für Service-zu-Service-Kommunikation
|
||||
4. Security Scan mit OWASP Dependency Check
|
||||
|
||||
**Zeitaufwand:** 2–3 Wochen
|
||||
|
||||
---
|
||||
|
||||
#### 4.4 Infrastructure as Code (IaC)
|
||||
|
||||
**Problem:** Nur Docker Compose – für Production nicht ausreichend.
|
||||
|
||||
**Zu erstellen:**
|
||||
|
||||
- Kubernetes Manifests (aktualisieren - Zeile 393+)
|
||||
- Helm Charts (aktualisieren – Zeile 420+)
|
||||
- Terraform für Cloud-Ressourcen
|
||||
- CI/CD Pipelines
|
||||
|
||||
**Zeitaufwand:** 4–6 Wochen
|
||||
|
||||
---
|
||||
|
||||
### 📊 Priorisierung-Matrix
|
||||
|
||||
| Phase | Aufgabe | Dringlichkeit | Aufwand | Impact |
|
||||
|-------|---------------|---------------|---------|---------|
|
||||
| 1 | Gateway-Tests | 🔴 Sehr hoch | 4-6h | Hoch |
|
||||
| 1 | Build-Datei | 🔴 Sehr hoch | 5min | Niedrig |
|
||||
| 2 | Dependencies | 🟡 Hoch | 1-2d | Mittel |
|
||||
| 2 | Docker-Images | 🟡 Hoch | 3-4h | Mittel |
|
||||
| 2 | Monitoring | 🟡 Mittel | 2-3d | Hoch |
|
||||
| 3 | Dokumentation | 🟢 Mittel | 1d | Mittel |
|
||||
| 3 | Auth-Module | 🟢 Mittel | 3-5d | Hoch |
|
||||
| 3 | Cache | 🟢 Niedrig | 2-3d | Mittel |
|
||||
| 3 | Event-Store | 🟢 Niedrig | 1w | Mittel |
|
||||
| 4 | Service Mesh | 🔵 Niedrig | 2-3w | Hoch |
|
||||
| 4 | OpenTelemetry | 🔵 Niedrig | 1-2w | Mittel |
|
||||
| 4 | Security | 🔵 Mittel | 2-3w | Hoch |
|
||||
| 4 | IaC | 🔵 Niedrig | 4-6w | Hoch |
|
||||
|
||||
---
|
||||
|
||||
### 🎯 Empfohlene Reihenfolge
|
||||
|
||||
#### Woche 1-2
|
||||
|
||||
1. Gateway-Tests reparieren
|
||||
2. Build-Datei bereinigen
|
||||
3. Dependencies aktualisieren
|
||||
|
||||
#### Woche 3-4
|
||||
|
||||
4. Docker-Images aktualisieren
|
||||
5. Monitoring vervollständigen
|
||||
6. Dokumentation aktualisieren
|
||||
|
||||
#### Woche 5-8
|
||||
|
||||
7. Auth-Module evaluieren/refactored
|
||||
8. Cache-Module modernisieren
|
||||
9. Event-Store Performance-Tests
|
||||
|
||||
#### Monat 3-4
|
||||
|
||||
10. Security Hardening
|
||||
11. OpenTelemetry Migration
|
||||
12. Service Mesh Evaluation
|
||||
|
||||
#### Monat 5-6
|
||||
|
||||
13. Infrastructure as Code
|
||||
14. Production Readiness Assessment
|
||||
|
||||
---
|
||||
|
||||
### 🛠️ Tooling-Empfehlungen
|
||||
|
||||
**Für Dependency-Management:**
|
||||
|
||||
- Renovate Bot oder Dependabot für automatische Updates
|
||||
- `./gradlew dependencyUpdates` Plugin verwenden
|
||||
|
||||
**Für Security:**
|
||||
|
||||
- OWASP Dependency Check
|
||||
- Trivy für Container-Scanning
|
||||
- SonarQube für Code-Qualität
|
||||
|
||||
**Für Monitoring:**
|
||||
|
||||
- Grafana Dashboards aus Community importieren
|
||||
- Prometheus Alertmanager konfigurieren
|
||||
|
||||
---
|
||||
|
||||
### 📝 Nächste Schritte
|
||||
|
||||
1. **Jetzt sofort:** Gateway-Tests fixen (blockiert alles andere)
|
||||
2. **Diese Woche:** Dependencies updaten und testen
|
||||
3. **Nächste Woche:** Sprint Planning für Phase 2
|
||||
4. **Monatlich:** Review des Fortschritts und Repriorisierung
|
||||
|
||||
---
|
||||
|
||||
### ⚠️ Risiken & Abhängigkeiten
|
||||
|
||||
**Kritische Pfade:**
|
||||
|
||||
- Gateway-Tests müssen ZUERST behoben werden
|
||||
- Dependency-Updates können Breaking Changes haben
|
||||
- Auth-Refactoring könnte alle Services betreffen
|
||||
|
||||
**Externe Abhängigkeiten:**
|
||||
|
||||
- Keycloak Breaking Changes bei Major Updates
|
||||
- Spring Boot/Cloud Release Schedule beachten
|
||||
- Kubernetes Cluster für IaC-Phase benötigt
|
||||
|
||||
---
|
||||
|
||||
**Geschätzter Gesamtaufwand:** 6–8 Wochen (bei 1 Vollzeit-Entwickler)
|
||||
|
||||
**Empfohlener Start:** Sofort mit Phase 1, dann iterativ durch die Phasen
|
||||
|
||||
---
|
||||
|
||||
### Documentations-Sprachbereinigung (2025-10-22)
|
||||
|
||||
Im Zuge der Vereinheitlichung auf ausschließlich deutschsprachige Dokumentation wurden folgende Dateien entfernt:
|
||||
|
||||
Gelöschte ADRs (englische Varianten):
|
||||
|
||||
- docs/architecture/adr/0000-adr-template.md
|
||||
- docs/architecture/adr/0001-modular-architecture.md
|
||||
- docs/architecture/adr/0002-domain-driven-design.md
|
||||
- docs/architecture/adr/0003-microservices-architecture.md
|
||||
- docs/architecture/adr/0004-event-driven-communication.md
|
||||
- docs/architecture/adr/0005-polyglot-persistence.md
|
||||
- docs/architecture/adr/0006-authentication-authorization-keycloak.md
|
||||
- docs/architecture/adr/0007-api-gateway-pattern.md
|
||||
- docs/architecture/adr/0008-multiplatform-client-applications.md
|
||||
|
||||
Gelöschte C4-Diagramme (englische Varianten):
|
||||
|
||||
- docs/architecture/c4/01-context.puml
|
||||
- docs/architecture/c4/02-container.puml
|
||||
- docs/architecture/c4/03-component-events-service.puml
|
||||
|
||||
Hinweis:
|
||||
|
||||
- Alle verbleibenden ADRs und C4-Diagramme sind in deutscher Sprache vorhanden (Suffix-de) und verlinkt.
|
||||
- Weitere Doku-Dateien in docs/ sind deutsch (Front-Matter/Sprachindizien geprüft).
|
||||
|
||||
---
|
||||
|
||||
## CI‑Stabilisierung Keycloak (2025‑10‑25)
|
||||
|
||||
Hintergrund: In GitHub Actions startete Keycloak zeitweise nicht zuverlässig. Ziel: Integrationstests stabilisieren,
|
||||
ohne produktive Architektur zu ändern.
|
||||
|
||||
Änderungen:
|
||||
|
||||
- Integration‑Workflow (`.github/workflows/integration-tests.yml`) auf Matrixbetrieb umgestellt:
|
||||
- `keycloak_db=postgres` (produktnäher, mit externer Postgres‑DB)
|
||||
- `keycloak_db=dev-file` (Dateibackend, ohne Postgres; stabiler im CI)
|
||||
- Robuste Startlogik:
|
||||
- Aktives Warten auf Postgres (nur in `postgres`‑Variante)
|
||||
- Keycloak‑Start per `docker run … start-dev` (26.4.2) mit `KC_HEALTH_ENABLED=true`
|
||||
- Health‑Checks gegen `/`, `/health`, `/q/health`, `/health/ready`, Admin‑Konsole
|
||||
- Ausführliche Log‑Ausgabe bei Fehlern (Keycloak & Postgres)
|
||||
- Fail‑fast deaktiviert; beide Matrix‑Jobs laufen unabhängig.
|
||||
|
||||
Nutzung/Operative Hinweise:
|
||||
|
||||
- In PRs beide Matrix‑Runs beachten; bei Flakes in `postgres` sichert `dev-file` die Tests ab.
|
||||
- Logs bei Fehlschlag: Step „Dump service logs (Keycloak, Postgres)“ am Jobende öffnen.
|
||||
- Produktiv bleibt Postgres maßgeblich (siehe `docker-compose.yml`).
|
||||
|
||||
ADR‑Konsistenz:
|
||||
|
||||
- ADR‑0006 (Keycloak) bleibt gültig und unverändert; die `dev-file`‑Variante betrifft ausschließlich CI‑Tests.
|
||||
|
||||
Next Steps (optional):
|
||||
|
||||
- Falls `postgres` im CI dauerhaft flakey: Required Checks vorübergehend auf `dev-file` begrenzen.
|
||||
- Langfristig: Ursachenanalyse für Postgres‑Variante (Runner‑Leistung/Timeouts/Schema‑Setup) und Re‑Enable als Required
|
||||
Check nach Stabilisierung.
|
||||
|
||||
---
|
||||
@@ -1,20 +0,0 @@
|
||||
# ===================================================================
|
||||
# Clients Docker Build Arguments - dockerfiles/clients/*
|
||||
# Source: docker/versions.toml [categories.clients]
|
||||
# Last updated: 2025-11-18 14:30:11 UTC
|
||||
# ===================================================================
|
||||
|
||||
# --- Include Global Arguments ---
|
||||
# Source global.env for GRADLE_VERSION, JAVA_VERSION, VERSION
|
||||
|
||||
# --- Client-Specific Build Tools ---
|
||||
NODE_VERSION=22.21.0
|
||||
NGINX_VERSION=1.28.0-alpine
|
||||
|
||||
# --- Client Build Configuration ---
|
||||
CLIENT_PATH=client
|
||||
CLIENT_MODULE=client
|
||||
CLIENT_NAME=meldestelle-client
|
||||
|
||||
# Note: Runtime/Dev values moved to config/env/.env
|
||||
# Keep this file strictly for build-time values only.
|
||||
@@ -1,26 +0,0 @@
|
||||
# ===================================================================
|
||||
# Global Docker Build Arguments - Used by all categories
|
||||
# Source: docker/versions.toml
|
||||
# Last updated: 2025-11-18 15:44:00 UTC
|
||||
# ===================================================================
|
||||
|
||||
# --- Build Tools ---
|
||||
GRADLE_VERSION=9.1.0
|
||||
JAVA_VERSION=21
|
||||
|
||||
# --- Build Metadata ---
|
||||
VERSION=1.0.0
|
||||
|
||||
# --- Monitoring & Infrastructure Services (image tags) ---
|
||||
PROMETHEUS_IMAGE_TAG=v2.54.1
|
||||
GRAFANA_IMAGE_TAG=11.3.0
|
||||
KEYCLOAK_IMAGE_TAG=26.4.2
|
||||
|
||||
# --- Datastore Images (image tags) ---
|
||||
POSTGRES_IMAGE_TAG=16-alpine
|
||||
REDIS_IMAGE_TAG=7-alpine
|
||||
|
||||
# --- Additional Infrastructure Images (image tags) ---
|
||||
CONSUL_IMAGE_TAG=1.15
|
||||
ZOOKEEPER_IMAGE_TAG=7.4.0
|
||||
KAFKA_IMAGE_TAG=7.4.0
|
||||
@@ -1,22 +0,0 @@
|
||||
# ===================================================================
|
||||
# Infrastructure Docker Build Arguments - dockerfiles/infrastructure/*
|
||||
# Source: docker/versions.toml [categories.infrastructure]
|
||||
# Last updated: 2025-11-18 14:30:11 UTC
|
||||
# ===================================================================
|
||||
|
||||
# --- Include Global Arguments ---
|
||||
# Source global.env for GRADLE_VERSION, JAVA_VERSION, VERSION
|
||||
|
||||
# --- API Gateway Specific ---
|
||||
GATEWAY_SERVICE_PATH=infrastructure/gateway
|
||||
GATEWAY_SERVICE_NAME=api-gateway
|
||||
|
||||
# --- Auth Server Specific ---
|
||||
AUTH_SERVER_PATH=infrastructure/auth/auth-server
|
||||
AUTH_SERVER_SERVICE_NAME=auth-server
|
||||
|
||||
# --- Monitoring Server Specific ---
|
||||
MONITORING_SERVER_PATH=infrastructure/monitoring/monitoring-server
|
||||
MONITORING_SERVER_SERVICE_NAME=monitoring-server
|
||||
|
||||
# Note: Runtime profiles/ports/dependencies moved to config/env/.env
|
||||
@@ -1,14 +0,0 @@
|
||||
# ===================================================================
|
||||
# Services Docker Build Arguments - dockerfiles/services/*
|
||||
# Source: docker/versions.toml [categories.services]
|
||||
# Last updated: 2025-11-18 14:30:11 UTC
|
||||
# ===================================================================
|
||||
|
||||
# --- Include Global Arguments ---
|
||||
# Source global.env for GRADLE_VERSION, JAVA_VERSION, VERSION
|
||||
|
||||
# --- Service-Specific Arguments ---
|
||||
SERVICE_PATH=.
|
||||
SERVICE_NAME=spring-boot-service
|
||||
|
||||
# Note: Runtime profiles/ports moved to config/env/.env
|
||||
@@ -1,12 +0,0 @@
|
||||
# Zentrale Einstiegsdatei für Docker Compose
|
||||
name: meldestelle-system
|
||||
|
||||
include:
|
||||
- path: docker-compose.yml # Infra (Postgres, Redis, Keycloak...)
|
||||
- path: docker-compose.services.yml # Gateway & Microservices
|
||||
- path: docker-compose.clients.yml # Web App
|
||||
|
||||
# Hier definieren wir das Netzwerk zentral, damit alle includes es nutzen können
|
||||
networks:
|
||||
meldestelle-network:
|
||||
driver: bridge
|
||||
@@ -1,54 +0,0 @@
|
||||
# ===================================================================
|
||||
# Docker Compose - Client Applications
|
||||
# Generated from docker/versions.toml
|
||||
# Environment: development
|
||||
# Generated: 2025-11-18 19:43:46 UTC
|
||||
# ===================================================================
|
||||
|
||||
services:
|
||||
# ===================================================================
|
||||
# Web Application (Compose for Web)
|
||||
# ===================================================================
|
||||
web-app:
|
||||
profiles: ["ui", "frontend"]
|
||||
build:
|
||||
context: ..
|
||||
dockerfile: ../dockerfiles/clients/web-app/Dockerfile
|
||||
args:
|
||||
# Global build arguments (centralized DOCKER_* variables)
|
||||
GRADLE_VERSION: ${DOCKER_GRADLE_VERSION}
|
||||
JAVA_VERSION: ${DOCKER_JAVA_VERSION}
|
||||
BUILD_DATE: ${BUILD_DATE}
|
||||
VERSION: ${DOCKER_APP_VERSION}
|
||||
# Client-specific arguments (centralized DOCKER_* variables)
|
||||
NODE_VERSION: ${DOCKER_NODE_VERSION}
|
||||
NGINX_VERSION: ${DOCKER_NGINX_VERSION}
|
||||
# Application-specific arguments
|
||||
CLIENT_PATH: client
|
||||
CLIENT_MODULE: client
|
||||
CLIENT_NAME: meldestelle-web-app
|
||||
container_name: meldestelle-web-app
|
||||
environment:
|
||||
NODE_ENV: ${NODE_ENV:-dev}
|
||||
API_BASE_URL: http://api-gateway:${GATEWAY_PORT:-8081}
|
||||
WS_URL: ws://api-gateway:${GATEWAY_PORT:-8081}/ws
|
||||
APP_TITLE: ${APP_NAME:-Meldestelle}
|
||||
APP_VERSION: ${APP_VERSION:-1.0.0}
|
||||
ports:
|
||||
- "4000:4000"
|
||||
networks:
|
||||
- meldestelle-network
|
||||
healthcheck:
|
||||
test: ["CMD", "curl", "--fail", "http://localhost:4000/health"]
|
||||
interval: 30s
|
||||
timeout: 5s
|
||||
retries: 3
|
||||
start_period: 40s
|
||||
restart: unless-stopped
|
||||
|
||||
# ===================================================================
|
||||
# Networks (shared network from main compose file)
|
||||
# ===================================================================
|
||||
networks:
|
||||
meldestelle-network:
|
||||
driver: bridge
|
||||
@@ -1,80 +0,0 @@
|
||||
# ===================================================================
|
||||
# Docker Compose - Application Services
|
||||
# Generated from docker/versions.toml
|
||||
# Environment: development
|
||||
# Generated: 2025-11-18 19:43:46 UTC
|
||||
# ===================================================================
|
||||
|
||||
services:
|
||||
profiles: ["app", "backend"]
|
||||
ping-service:
|
||||
build:
|
||||
context: ..
|
||||
dockerfile: ../dockerfiles/services/ping-service/Dockerfile
|
||||
args:
|
||||
# Global build arguments (centralized DOCKER_* variables)
|
||||
GRADLE_VERSION: ${DOCKER_GRADLE_VERSION}
|
||||
JAVA_VERSION: ${DOCKER_JAVA_VERSION}
|
||||
BUILD_DATE: ${BUILD_DATE}
|
||||
VERSION: ${DOCKER_APP_VERSION}
|
||||
# Service-specific arguments (centralized DOCKER_* variables)
|
||||
SPRING_PROFILES_ACTIVE: ${DOCKER_SPRING_PROFILES_DOCKER}
|
||||
container_name: meldestelle-ping-service
|
||||
environment:
|
||||
SPRING_PROFILES_ACTIVE: ${SPRING_PROFILES_ACTIVE:-dev}
|
||||
SERVER_PORT: ${PING_SERVICE_PORT:-8082}
|
||||
DEBUG: ${DEBUG:-true}
|
||||
LOGGING_LEVEL_ROOT: ${LOGGING_LEVEL_ROOT:-DEBUG}
|
||||
JVM_DEBUG_PORT: 5005
|
||||
ports:
|
||||
- "${PING_SERVICE_PORT:-8082}:8082"
|
||||
- "5005:5005" # Debug-Port
|
||||
networks:
|
||||
- meldestelle-network
|
||||
healthcheck:
|
||||
test: ["CMD", "curl", "--fail", "http://localhost:8082/actuator/health/readiness"]
|
||||
interval: 30s
|
||||
timeout: 5s
|
||||
retries: 3
|
||||
start_period: 40s
|
||||
restart: unless-stopped
|
||||
|
||||
api-gateway:
|
||||
profiles: ["infra", "gateway"]
|
||||
build:
|
||||
context: ..
|
||||
dockerfile: ../dockerfiles/infrastructure/gateway/Dockerfile
|
||||
args:
|
||||
# Global build arguments (centralized DOCKER_* variables)
|
||||
GRADLE_VERSION: ${DOCKER_GRADLE_VERSION}
|
||||
JAVA_VERSION: ${DOCKER_JAVA_VERSION}
|
||||
BUILD_DATE: ${BUILD_DATE}
|
||||
VERSION: ${DOCKER_APP_VERSION}
|
||||
# Infrastructure-specific arguments (centralized DOCKER_* variables)
|
||||
SPRING_PROFILES_ACTIVE: ${DOCKER_SPRING_PROFILES_DEFAULT}
|
||||
container_name: meldestelle-api-gateway
|
||||
environment:
|
||||
SPRING_PROFILES_ACTIVE: ${SPRING_PROFILES_ACTIVE:-dev}
|
||||
SERVER_PORT: ${API_GATEWAY_PORT:-8081}
|
||||
DEBUG: ${DEBUG:-true}
|
||||
LOGGING_LEVEL_ROOT: ${LOGGING_LEVEL_ROOT:-DEBUG}
|
||||
JVM_DEBUG_PORT: 5005
|
||||
ports:
|
||||
- "${API_GATEWAY_PORT:-8081}:8081"
|
||||
- "5005:5005" # Debug-Port
|
||||
networks:
|
||||
- meldestelle-network
|
||||
healthcheck:
|
||||
test: ["CMD", "curl", "--fail", "http://localhost:8081/actuator/health/readiness"]
|
||||
interval: 30s
|
||||
timeout: 5s
|
||||
retries: 3
|
||||
start_period: 40s
|
||||
restart: unless-stopped
|
||||
|
||||
# ===================================================================
|
||||
# Networks (shared network from main compose file)
|
||||
# ===================================================================
|
||||
networks:
|
||||
meldestelle-network:
|
||||
driver: bridge
|
||||
@@ -1,162 +0,0 @@
|
||||
# ===================================================================
|
||||
# Docker Compose - Infrastructure Services
|
||||
# Generated from docker/versions.toml
|
||||
# Environment: development
|
||||
# Generated: 2025-11-18 19:43:46 UTC
|
||||
# ===================================================================
|
||||
|
||||
services:
|
||||
# ===================================================================
|
||||
# Database
|
||||
# ===================================================================
|
||||
postgres:
|
||||
profiles: ["core", "backend"]
|
||||
image: postgres:${DOCKER_POSTGRES_VERSION:-16-alpine}
|
||||
container_name: meldestelle-postgres
|
||||
environment:
|
||||
POSTGRES_USER: ${POSTGRES_USER:-meldestelle}
|
||||
POSTGRES_PASSWORD: ${POSTGRES_PASSWORD:-meldestelle}
|
||||
POSTGRES_DB: ${POSTGRES_DB:-meldestelle}
|
||||
ports:
|
||||
- "5432:5432"
|
||||
volumes:
|
||||
- postgres-data:/var/lib/postgresql/data
|
||||
- ./docker/services/postgres:/docker-entrypoint-initdb.d
|
||||
networks:
|
||||
- meldestelle-network
|
||||
healthcheck:
|
||||
test: ["CMD-SHELL", "pg_isready -U meldestelle -d meldestelle"]
|
||||
interval: 30s
|
||||
timeout: 5s
|
||||
retries: 3
|
||||
start_period: 40s
|
||||
restart: unless-stopped
|
||||
|
||||
# ===================================================================
|
||||
# Cache
|
||||
# ===================================================================
|
||||
redis:
|
||||
profiles: ["core", "backend"]
|
||||
image: redis:${DOCKER_REDIS_VERSION:-7-alpine}
|
||||
container_name: meldestelle-redis
|
||||
ports:
|
||||
- "${REDIS_PORT:-6379}:6379"
|
||||
volumes:
|
||||
- redis-data:/data
|
||||
command: redis-server --appendonly yes
|
||||
networks:
|
||||
- meldestelle-network
|
||||
healthcheck:
|
||||
test: ["CMD", "redis-cli", "ping"]
|
||||
interval: 30s
|
||||
timeout: 5s
|
||||
retries: 3
|
||||
start_period: 40s
|
||||
restart: unless-stopped
|
||||
|
||||
# ===================================================================
|
||||
# Authentication
|
||||
# ===================================================================
|
||||
keycloak:
|
||||
profiles: ["auth", "security"]
|
||||
image: quay.io/keycloak/keycloak:${DOCKER_KEYCLOAK_VERSION:-26.4.2}
|
||||
container_name: meldestelle-keycloak
|
||||
environment:
|
||||
KEYCLOAK_ADMIN: ${KEYCLOAK_ADMIN:-admin}
|
||||
KEYCLOAK_ADMIN_PASSWORD: ${KEYCLOAK_ADMIN_PASSWORD:-admin}
|
||||
KC_DB: postgres
|
||||
KC_DB_URL: jdbc:postgresql://postgres:5432/${POSTGRES_DB:-meldestelle}
|
||||
KC_DB_USERNAME: ${POSTGRES_USER:-meldestelle}
|
||||
KC_DB_PASSWORD: ${POSTGRES_PASSWORD:-meldestelle}
|
||||
ports:
|
||||
- "8180:8080"
|
||||
depends_on:
|
||||
postgres:
|
||||
condition: service_healthy
|
||||
volumes:
|
||||
- ./docker/services/keycloak:/opt/keycloak/data/import
|
||||
command: start-dev --import-realm
|
||||
networks:
|
||||
- meldestelle-network
|
||||
healthcheck:
|
||||
test: ["CMD", "wget", "--quiet", "--tries=1", "--spider", "http://localhost:8080/"]
|
||||
interval: 30s
|
||||
timeout: 5s
|
||||
retries: 3
|
||||
start_period: 40s
|
||||
restart: unless-stopped
|
||||
|
||||
# ===================================================================
|
||||
# Monitoring
|
||||
# ===================================================================
|
||||
prometheus:
|
||||
profiles: ["monitoring"]
|
||||
image: prom/prometheus:${DOCKER_PROMETHEUS_VERSION:-v2.54.1}
|
||||
container_name: meldestelle-prometheus
|
||||
ports:
|
||||
- "${PROMETHEUS_PORT:-9090}:9090"
|
||||
volumes:
|
||||
- prometheus-data:/prometheus
|
||||
- ./docker/monitoring/prometheus:/etc/prometheus:ro
|
||||
command:
|
||||
- '--config.file=/etc/prometheus/prometheus.yml'
|
||||
- '--storage.tsdb.path=/prometheus'
|
||||
- '--web.console.libraries=/etc/prometheus/console_libraries'
|
||||
- '--web.console.templates=/etc/prometheus/consoles'
|
||||
- '--storage.tsdb.retention.time=200h'
|
||||
- '--web.enable-lifecycle'
|
||||
networks:
|
||||
- meldestelle-network
|
||||
healthcheck:
|
||||
test: ["CMD", "wget", "--no-verbose", "--tries=1", "--spider", "http://localhost:9090/-/healthy"]
|
||||
interval: 30s
|
||||
timeout: 5s
|
||||
retries: 3
|
||||
start_period: 40s
|
||||
restart: unless-stopped
|
||||
|
||||
grafana:
|
||||
profiles: ["monitoring"]
|
||||
image: grafana/grafana:${DOCKER_GRAFANA_VERSION:-11.3.0}
|
||||
container_name: meldestelle-grafana
|
||||
environment:
|
||||
GF_SECURITY_ADMIN_USER: ${GF_SECURITY_ADMIN_USER:-admin}
|
||||
GF_SECURITY_ADMIN_PASSWORD: ${GF_SECURITY_ADMIN_PASSWORD:-admin}
|
||||
GF_USERS_ALLOW_SIGN_UP: ${GF_USERS_ALLOW_SIGN_UP:-false}
|
||||
GF_INSTALL_PLUGINS: grafana-piechart-panel
|
||||
ports:
|
||||
- "${GRAFANA_PORT:-3000}:3000"
|
||||
volumes:
|
||||
- grafana-data:/var/lib/grafana
|
||||
- ./docker/monitoring/grafana:/etc/grafana/provisioning:ro
|
||||
depends_on:
|
||||
- prometheus
|
||||
networks:
|
||||
- meldestelle-network
|
||||
healthcheck:
|
||||
test: ["CMD", "curl", "--fail", "http://localhost:3000/api/health"]
|
||||
interval: 30s
|
||||
timeout: 5s
|
||||
retries: 3
|
||||
start_period: 40s
|
||||
restart: unless-stopped
|
||||
|
||||
# ===================================================================
|
||||
# Volumes
|
||||
# ===================================================================
|
||||
volumes:
|
||||
postgres-data:
|
||||
driver: local
|
||||
redis-data:
|
||||
driver: local
|
||||
prometheus-data:
|
||||
driver: local
|
||||
grafana-data:
|
||||
driver: local
|
||||
|
||||
# ===================================================================
|
||||
# Networks
|
||||
# ===================================================================
|
||||
networks:
|
||||
meldestelle-network:
|
||||
driver: bridge
|
||||
@@ -1 +0,0 @@
|
||||
# Events Module\n\nThis is a minimal placeholder README to satisfy documentation validation. See docs/index.md for project docs
|
||||
@@ -1 +0,0 @@
|
||||
# Masterdata Module\n\nThis is a minimal placeholder README to satisfy documentation validation. See docs/index.md for project docs
|
||||
@@ -1 +0,0 @@
|
||||
# Members Module\n\nThis is a minimal placeholder README to satisfy documentation validation. See docs/index.md for project docs
|
||||
@@ -1,15 +0,0 @@
|
||||
# Docker Secrets (Development vs. Production)
|
||||
|
||||
In der lokalen Entwicklung werden keine Docker-Secrets erzwungen.
|
||||
|
||||
- Verwende für sensible Werte stattdessen die Datei `config/env/.env.local` (ist gitignored).
|
||||
- Die Dateien in diesem Ordner sind lediglich Platzhalter und enthalten KEINE echten Geheimnisse.
|
||||
- Für ein Deployment in Produktion kannst du diese Dateien mit echten Werten befüllen oder einen sicheren Secret-Store (Docker/K8s) verwenden.
|
||||
|
||||
Hinweise:
|
||||
- Postgres-User/Passwort haben in der lokalen Entwicklung Standard/Fallback-Werte via `docker-compose.yml` (Environment mit Defaults).
|
||||
- Die optimierten Compose-Dateien (`*.optimized`) können weiterhin Docker-Secrets verwenden – diese sind für Prod gedacht.
|
||||
|
||||
Schnellstart lokal (ohne Secrets):
|
||||
- Passe `config/env/.env` und optional `config/env/.env.local` an
|
||||
- Starte mit: `docker compose -f docker-compose.yml -f docker-compose.services.yml up`
|
||||
@@ -1 +0,0 @@
|
||||
TiB6FRRYW4gjM7xie17mKtTYFOp
|
||||
@@ -1 +0,0 @@
|
||||
admin
|
||||
@@ -1 +0,0 @@
|
||||
ba960b899f72d5ed192b5597d7f4b5b8853d9d641a2dc23c6b1a4b692b20211c
|
||||
@@ -1 +0,0 @@
|
||||
XASb7AzVy7G5fEKulE1mNPTy2Sw6pHi
|
||||
@@ -1 +0,0 @@
|
||||
s8N3r59JwS0lFsJobKWFJXh9qvdbHgcC6S3fYXYdXFM6eMKkRMtQbxHo0NJKFJC
|
||||
@@ -1 +0,0 @@
|
||||
lRo7W15UNy60EFRlvk1XP99MmgrgK2Z97QK9btl9ZPVIVzWcY81Bebp9hpB
|
||||
@@ -1 +0,0 @@
|
||||
pON4NxxsKPWseVg1gw5PyLNN4YYrj8h
|
||||
@@ -1 +0,0 @@
|
||||
metrics
|
||||
@@ -1 +0,0 @@
|
||||
CHANGE_ME_LOCAL_DEV
|
||||
@@ -1 +0,0 @@
|
||||
meldestelle
|
||||
@@ -1 +0,0 @@
|
||||
p701HhKOnZJ4zbY9dGRvyH9kQTKcsUm
|
||||
@@ -1,345 +0,0 @@
|
||||
#!/bin/bash
|
||||
|
||||
# ===================================================================
|
||||
# Docker Secrets Setup Script - Meldestelle Project
|
||||
# ===================================================================
|
||||
# This script generates secure secrets for all Docker services
|
||||
# Security Features:
|
||||
# - Generates cryptographically secure random passwords
|
||||
# - Creates JWT secrets with proper length for HMAC512
|
||||
# - Sets appropriate file permissions (600) for security
|
||||
# - Provides backup functionality
|
||||
# - Validates secret file creation
|
||||
# ===================================================================
|
||||
|
||||
set -euo pipefail
|
||||
|
||||
# Colors for output
|
||||
RED='\033[0;31m'
|
||||
GREEN='\033[0;32m'
|
||||
YELLOW='\033[1;33m'
|
||||
BLUE='\033[0;34m'
|
||||
NC='\033[0m' # No Color
|
||||
|
||||
# Script directory
|
||||
SCRIPT_DIR="$(cd "$(dirname "${BASH_SOURCE[0]}")" && pwd)"
|
||||
SECRETS_DIR="${SCRIPT_DIR}"
|
||||
|
||||
# Logging function
|
||||
log() {
|
||||
echo -e "${GREEN}[$(date +'%Y-%m-%d %H:%M:%S')] $1${NC}"
|
||||
}
|
||||
|
||||
warn() {
|
||||
echo -e "${YELLOW}[WARNING] $1${NC}"
|
||||
}
|
||||
|
||||
error() {
|
||||
echo -e "${RED}[ERROR] $1${NC}"
|
||||
exit 1
|
||||
}
|
||||
|
||||
# Function to generate secure random password
|
||||
generate_password() {
|
||||
local length=${1:-32}
|
||||
openssl rand -base64 $((length * 3 / 4)) | tr -d "=+/" | cut -c1-${length}
|
||||
}
|
||||
|
||||
# Function to generate JWT secret (64 characters for HMAC512)
|
||||
generate_jwt_secret() {
|
||||
openssl rand -hex 32
|
||||
}
|
||||
|
||||
# Function to create secret file with proper permissions
|
||||
create_secret_file() {
|
||||
local filename="$1"
|
||||
local content="$2"
|
||||
local filepath="${SECRETS_DIR}/${filename}"
|
||||
|
||||
# Check if file already exists
|
||||
if [[ -f "$filepath" ]]; then
|
||||
warn "Secret file $filename already exists. Use --force to overwrite."
|
||||
return 1
|
||||
fi
|
||||
|
||||
# Create the secret file
|
||||
echo -n "$content" > "$filepath"
|
||||
chmod 600 "$filepath"
|
||||
|
||||
log "Created secret file: $filename"
|
||||
return 0
|
||||
}
|
||||
|
||||
# Function to backup existing secrets
|
||||
backup_secrets() {
|
||||
local backup_dir="${SECRETS_DIR}/backup_$(date +%Y%m%d_%H%M%S)"
|
||||
|
||||
if find "$SECRETS_DIR" -name "*.txt" -type f | grep -q .; then
|
||||
log "Creating backup of existing secrets..."
|
||||
mkdir -p "$backup_dir"
|
||||
find "$SECRETS_DIR" -name "*.txt" -type f -exec cp {} "$backup_dir/" \;
|
||||
log "Backup created in: $backup_dir"
|
||||
fi
|
||||
}
|
||||
|
||||
# Function to validate secret file
|
||||
validate_secret_file() {
|
||||
local filepath="$1"
|
||||
local min_length="$2"
|
||||
|
||||
if [[ ! -f "$filepath" ]]; then
|
||||
error "Secret file does not exist: $filepath"
|
||||
fi
|
||||
|
||||
local content_length=$(wc -c < "$filepath")
|
||||
if [[ $content_length -lt $min_length ]]; then
|
||||
error "Secret file $filepath is too short (${content_length} < ${min_length})"
|
||||
fi
|
||||
|
||||
local permissions=$(stat -c %a "$filepath")
|
||||
if [[ "$permissions" != "600" ]]; then
|
||||
warn "Secret file $filepath has incorrect permissions: $permissions (should be 600)"
|
||||
chmod 600 "$filepath"
|
||||
fi
|
||||
}
|
||||
|
||||
# Function to generate all secrets
|
||||
generate_all_secrets() {
|
||||
local force_overwrite=${1:-false}
|
||||
|
||||
log "Starting secret generation for Meldestelle Docker infrastructure..."
|
||||
|
||||
# Create backup if not forcing overwrite
|
||||
if [[ "$force_overwrite" != "true" ]]; then
|
||||
backup_secrets
|
||||
fi
|
||||
|
||||
# Database secrets
|
||||
log "Generating database secrets..."
|
||||
if [[ "$force_overwrite" == "true" ]] || ! [[ -f "${SECRETS_DIR}/postgres_user.txt" ]]; then
|
||||
create_secret_file "postgres_user.txt" "meldestelle"
|
||||
fi
|
||||
if [[ "$force_overwrite" == "true" ]] || ! [[ -f "${SECRETS_DIR}/postgres_password.txt" ]]; then
|
||||
create_secret_file "postgres_password.txt" "$(generate_password 32)"
|
||||
fi
|
||||
|
||||
# Redis secrets
|
||||
log "Generating Redis secrets..."
|
||||
if [[ "$force_overwrite" == "true" ]] || ! [[ -f "${SECRETS_DIR}/redis_password.txt" ]]; then
|
||||
create_secret_file "redis_password.txt" "$(generate_password 32)"
|
||||
fi
|
||||
|
||||
# Keycloak secrets
|
||||
log "Generating Keycloak secrets..."
|
||||
if [[ "$force_overwrite" == "true" ]] || ! [[ -f "${SECRETS_DIR}/keycloak_admin_password.txt" ]]; then
|
||||
create_secret_file "keycloak_admin_password.txt" "$(generate_password 32)"
|
||||
fi
|
||||
if [[ "$force_overwrite" == "true" ]] || ! [[ -f "${SECRETS_DIR}/keycloak_client_secret.txt" ]]; then
|
||||
create_secret_file "keycloak_client_secret.txt" "$(generate_password 64)"
|
||||
fi
|
||||
if [[ "$force_overwrite" == "true" ]] || ! [[ -f "${SECRETS_DIR}/keycloak_auth_client_secret.txt" ]]; then
|
||||
create_secret_file "keycloak_auth_client_secret.txt" "$(generate_password 64)"
|
||||
fi
|
||||
|
||||
# Grafana secrets
|
||||
log "Generating Grafana secrets..."
|
||||
if [[ "$force_overwrite" == "true" ]] || ! [[ -f "${SECRETS_DIR}/grafana_admin_user.txt" ]]; then
|
||||
create_secret_file "grafana_admin_user.txt" "admin"
|
||||
fi
|
||||
if [[ "$force_overwrite" == "true" ]] || ! [[ -f "${SECRETS_DIR}/grafana_admin_password.txt" ]]; then
|
||||
create_secret_file "grafana_admin_password.txt" "$(generate_password 32)"
|
||||
fi
|
||||
|
||||
# JWT secrets
|
||||
log "Generating JWT secrets..."
|
||||
if [[ "$force_overwrite" == "true" ]] || ! [[ -f "${SECRETS_DIR}/jwt_secret.txt" ]]; then
|
||||
create_secret_file "jwt_secret.txt" "$(generate_jwt_secret)"
|
||||
fi
|
||||
|
||||
# VNC secrets (for desktop app)
|
||||
log "Generating VNC secrets..."
|
||||
if [[ "$force_overwrite" == "true" ]] || ! [[ -f "${SECRETS_DIR}/vnc_password.txt" ]]; then
|
||||
create_secret_file "vnc_password.txt" "$(generate_password 16)"
|
||||
fi
|
||||
|
||||
# Monitoring secrets
|
||||
log "Generating monitoring secrets..."
|
||||
if [[ "$force_overwrite" == "true" ]] || ! [[ -f "${SECRETS_DIR}/metrics_auth_username.txt" ]]; then
|
||||
create_secret_file "metrics_auth_username.txt" "metrics"
|
||||
fi
|
||||
if [[ "$force_overwrite" == "true" ]] || ! [[ -f "${SECRETS_DIR}/metrics_auth_password.txt" ]]; then
|
||||
create_secret_file "metrics_auth_password.txt" "$(generate_password 32)"
|
||||
fi
|
||||
|
||||
log "Secret generation completed successfully!"
|
||||
}
|
||||
|
||||
# Function to validate all secrets
|
||||
validate_all_secrets() {
|
||||
log "Validating all secret files..."
|
||||
|
||||
# Define expected secrets with minimum lengths
|
||||
declare -A secrets=(
|
||||
["postgres_user.txt"]=8
|
||||
["postgres_password.txt"]=16
|
||||
["redis_password.txt"]=16
|
||||
["keycloak_admin_password.txt"]=16
|
||||
["keycloak_client_secret.txt"]=32
|
||||
["keycloak_auth_client_secret.txt"]=32
|
||||
["grafana_admin_user.txt"]=4
|
||||
["grafana_admin_password.txt"]=16
|
||||
["jwt_secret.txt"]=64
|
||||
["vnc_password.txt"]=8
|
||||
["metrics_auth_username.txt"]=4
|
||||
["metrics_auth_password.txt"]=16
|
||||
)
|
||||
|
||||
local all_valid=true
|
||||
for secret_file in "${!secrets[@]}"; do
|
||||
local filepath="${SECRETS_DIR}/${secret_file}"
|
||||
local min_length=${secrets[$secret_file]}
|
||||
|
||||
if validate_secret_file "$filepath" "$min_length" 2>/dev/null; then
|
||||
log "✓ $secret_file is valid"
|
||||
else
|
||||
error "✗ $secret_file is invalid or missing"
|
||||
all_valid=false
|
||||
fi
|
||||
done
|
||||
|
||||
if [[ "$all_valid" == "true" ]]; then
|
||||
log "All secret files are valid and properly secured!"
|
||||
else
|
||||
error "Some secret files are invalid. Please regenerate secrets."
|
||||
fi
|
||||
}
|
||||
|
||||
# Function to create Docker secrets
|
||||
create_docker_secrets() {
|
||||
log "Creating Docker secrets..."
|
||||
|
||||
# Get the project name (directory name)
|
||||
local project_name=$(basename "$(dirname "$(dirname "$SCRIPT_DIR")")")
|
||||
|
||||
# Define secrets to create
|
||||
declare -A docker_secrets=(
|
||||
["postgres_user"]="postgres_user.txt"
|
||||
["postgres_password"]="postgres_password.txt"
|
||||
["redis_password"]="redis_password.txt"
|
||||
["keycloak_admin_password"]="keycloak_admin_password.txt"
|
||||
["keycloak_client_secret"]="keycloak_client_secret.txt"
|
||||
["grafana_admin_user"]="grafana_admin_user.txt"
|
||||
["grafana_admin_password"]="grafana_admin_password.txt"
|
||||
["jwt_secret"]="jwt_secret.txt"
|
||||
)
|
||||
|
||||
for secret_name in "${!docker_secrets[@]}"; do
|
||||
local secret_file="${docker_secrets[$secret_name]}"
|
||||
local filepath="${SECRETS_DIR}/${secret_file}"
|
||||
local docker_secret_name="${project_name}_${secret_name}"
|
||||
|
||||
# Check if Docker secret already exists
|
||||
if docker secret ls --format "{{.Name}}" | grep -q "^${docker_secret_name}$"; then
|
||||
warn "Docker secret $docker_secret_name already exists"
|
||||
else
|
||||
# Create Docker secret
|
||||
if docker secret create "$docker_secret_name" "$filepath"; then
|
||||
log "Created Docker secret: $docker_secret_name"
|
||||
else
|
||||
error "Failed to create Docker secret: $docker_secret_name"
|
||||
fi
|
||||
fi
|
||||
done
|
||||
}
|
||||
|
||||
# Function to show usage
|
||||
show_usage() {
|
||||
echo "Usage: $0 [OPTIONS]"
|
||||
echo ""
|
||||
echo "Options:"
|
||||
echo " --help Show this help message"
|
||||
echo " --generate Generate all secret files (default)"
|
||||
echo " --force Force overwrite existing secret files"
|
||||
echo " --validate Validate existing secret files"
|
||||
echo " --docker-secrets Create Docker secrets from files"
|
||||
echo " --all Generate files, validate, and create Docker secrets"
|
||||
echo ""
|
||||
echo "Examples:"
|
||||
echo " $0 # Generate secrets (skip existing files)"
|
||||
echo " $0 --force # Generate secrets (overwrite existing files)"
|
||||
echo " $0 --validate # Validate existing secret files"
|
||||
echo " $0 --all # Complete setup (generate, validate, docker secrets)"
|
||||
}
|
||||
|
||||
# Main execution
|
||||
main() {
|
||||
local action="generate"
|
||||
local force_overwrite=false
|
||||
|
||||
# Check dependencies
|
||||
if ! command -v openssl &> /dev/null; then
|
||||
error "openssl is required but not installed"
|
||||
fi
|
||||
|
||||
# Parse command line arguments
|
||||
while [[ $# -gt 0 ]]; do
|
||||
case $1 in
|
||||
--help)
|
||||
show_usage
|
||||
exit 0
|
||||
;;
|
||||
--generate)
|
||||
action="generate"
|
||||
shift
|
||||
;;
|
||||
--force)
|
||||
force_overwrite=true
|
||||
shift
|
||||
;;
|
||||
--validate)
|
||||
action="validate"
|
||||
shift
|
||||
;;
|
||||
--docker-secrets)
|
||||
action="docker-secrets"
|
||||
shift
|
||||
;;
|
||||
--all)
|
||||
action="all"
|
||||
shift
|
||||
;;
|
||||
*)
|
||||
error "Unknown option: $1"
|
||||
;;
|
||||
esac
|
||||
done
|
||||
|
||||
# Ensure secrets directory exists
|
||||
mkdir -p "$SECRETS_DIR"
|
||||
|
||||
# Execute requested action
|
||||
case $action in
|
||||
"generate")
|
||||
generate_all_secrets "$force_overwrite"
|
||||
;;
|
||||
"validate")
|
||||
validate_all_secrets
|
||||
;;
|
||||
"docker-secrets")
|
||||
create_docker_secrets
|
||||
;;
|
||||
"all")
|
||||
generate_all_secrets "$force_overwrite"
|
||||
validate_all_secrets
|
||||
create_docker_secrets
|
||||
;;
|
||||
*)
|
||||
error "Invalid action: $action"
|
||||
;;
|
||||
esac
|
||||
|
||||
log "Operation completed successfully!"
|
||||
}
|
||||
|
||||
# Run main function with all arguments
|
||||
main "$@"
|
||||
@@ -1 +0,0 @@
|
||||
nrscAXfIoOKTAEt
|
||||
@@ -1,192 +0,0 @@
|
||||
# ===================================================================
|
||||
# Docker Versions Catalog - Single Source of Truth
|
||||
# Analogous to gradle/libs.versions.toml for centralized version management
|
||||
# ===================================================================
|
||||
# Last updated: 2025-09-13
|
||||
# Eliminates version redundancy across 12+ Dockerfiles
|
||||
|
||||
[versions]
|
||||
# --- Build Tools ---
|
||||
gradle = "9.1.0"
|
||||
java = "21"
|
||||
node = "22.21.0"
|
||||
|
||||
# --- Base Images ---
|
||||
nginx = "1.25-alpine"
|
||||
alpine = "3.19"
|
||||
eclipse-temurin-jdk = "21-jdk-alpine"
|
||||
eclipse-temurin-jre = "21-jre-alpine"
|
||||
|
||||
# --- Monitoring & Infrastructure Services ---
|
||||
prometheus = "v2.54.1"
|
||||
grafana = "11.3.0"
|
||||
keycloak = "26.0.7"
|
||||
|
||||
# --- Spring Configuration ---
|
||||
spring-profiles-default = "default"
|
||||
spring-profiles-docker = "docker"
|
||||
spring-profiles-prod = "prod"
|
||||
|
||||
# --- Application Versions ---
|
||||
app-version = "1.0.0"
|
||||
|
||||
# --- Zentrale Port-Verwaltung ---
|
||||
# Single Source of Truth für alle Service-Ports
|
||||
|
||||
[service-ports]
|
||||
# --- Infrastructure Services ---
|
||||
api-gateway = 8081
|
||||
auth-server = 8087
|
||||
monitoring-server = 8088
|
||||
|
||||
# --- Application Services ---
|
||||
ping-service = 8082
|
||||
members-service = 8083
|
||||
horses-service = 8084
|
||||
events-service = 8085
|
||||
masterdata-service = 8086
|
||||
|
||||
# --- External Services ---
|
||||
postgres = 5432
|
||||
redis = 6379
|
||||
keycloak = 8180
|
||||
consul = 8500
|
||||
zookeeper = 2181
|
||||
kafka = 9092
|
||||
|
||||
# --- Monitoring Stack ---
|
||||
prometheus = 9090
|
||||
grafana = 3000
|
||||
|
||||
# --- Client Applications ---
|
||||
web-app = 4000
|
||||
desktop-app-vnc = 5901
|
||||
desktop-app-novnc = 6080
|
||||
|
||||
[port-ranges]
|
||||
# --- Port-Range-Definitionen für automatische Port-Zuweisung ---
|
||||
infrastructure = "8081-8088"
|
||||
services = "8082-8099"
|
||||
monitoring = "9090-9099"
|
||||
clients = "4000-4099"
|
||||
vnc = "5901-5999"
|
||||
debug = "5005-5009"
|
||||
|
||||
# --- Reserved Port Ranges ---
|
||||
system-reserved = "0-1023"
|
||||
ephemeral = "32768-65535"
|
||||
|
||||
[build-args]
|
||||
# --- Global Build Arguments (used across all categories) ---
|
||||
global = [
|
||||
"GRADLE_VERSION",
|
||||
"JAVA_VERSION",
|
||||
"BUILD_DATE",
|
||||
"VERSION"
|
||||
]
|
||||
|
||||
# --- Spring Boot Services (dockerfiles/services/* and infrastructure/*) ---
|
||||
spring-services = [
|
||||
"SPRING_PROFILES_ACTIVE",
|
||||
"SERVICE_PATH",
|
||||
"SERVICE_NAME",
|
||||
"SERVICE_PORT"
|
||||
]
|
||||
|
||||
# --- Kotlin/JS Web Clients (dockerfiles/clients/*) ---
|
||||
web-clients = [
|
||||
"NODE_VERSION",
|
||||
"NGINX_VERSION",
|
||||
"CLIENT_PATH",
|
||||
"CLIENT_MODULE",
|
||||
"CLIENT_NAME"
|
||||
]
|
||||
|
||||
[categories]
|
||||
# --- Services Configuration ---
|
||||
[categories.services]
|
||||
default-spring-profile = "docker"
|
||||
default-port-start = 8082
|
||||
services = [
|
||||
"ping-service",
|
||||
"members-service",
|
||||
"horses-service",
|
||||
"events-service",
|
||||
"masterdata-service"
|
||||
]
|
||||
|
||||
# --- Infrastructure Configuration ---
|
||||
[categories.infrastructure]
|
||||
default-spring-profile = "default"
|
||||
services = [
|
||||
"gateway",
|
||||
"auth-server",
|
||||
"monitoring-server"
|
||||
]
|
||||
|
||||
# --- Client Applications Configuration ---
|
||||
[categories.clients]
|
||||
default-node-version = "20.11.0"
|
||||
default-nginx-version = "1.25-alpine"
|
||||
clients = [
|
||||
"web-app",
|
||||
"desktop-app"
|
||||
]
|
||||
|
||||
[environment-mapping]
|
||||
# --- Environment Variable Names for Docker Compose ---
|
||||
# Maps internal version names to environment variable names
|
||||
gradle-version = "DOCKER_GRADLE_VERSION"
|
||||
java-version = "DOCKER_JAVA_VERSION"
|
||||
node-version = "DOCKER_NODE_VERSION"
|
||||
nginx-version = "DOCKER_NGINX_VERSION"
|
||||
prometheus-version = "DOCKER_PROMETHEUS_VERSION"
|
||||
grafana-version = "DOCKER_GRAFANA_VERSION"
|
||||
keycloak-version = "DOCKER_KEYCLOAK_VERSION"
|
||||
spring-profiles-default = "DOCKER_SPRING_PROFILES_DEFAULT"
|
||||
spring-profiles-docker = "DOCKER_SPRING_PROFILES_DOCKER"
|
||||
app-version = "DOCKER_APP_VERSION"
|
||||
|
||||
[environments]
|
||||
# --- Environment-spezifische Konfigurationen ---
|
||||
# Zentrale Verwaltung für dev/test/prod Umgebungen
|
||||
|
||||
[environments.development]
|
||||
spring-profiles = "dev"
|
||||
debug-enabled = true
|
||||
log-level = "DEBUG"
|
||||
health-check-interval = "30s"
|
||||
health-check-timeout = "5s"
|
||||
health-check-retries = 3
|
||||
health-check-start-period = "40s"
|
||||
resource-limits = false
|
||||
jvm-debug-port = 5005
|
||||
hot-reload = true
|
||||
|
||||
[environments.production]
|
||||
spring-profiles = "prod"
|
||||
debug-enabled = false
|
||||
log-level = "INFO"
|
||||
health-check-interval = "15s"
|
||||
health-check-timeout = "3s"
|
||||
health-check-retries = 3
|
||||
health-check-start-period = "30s"
|
||||
resource-limits = true
|
||||
jvm-debug-port = false
|
||||
hot-reload = false
|
||||
security-headers = true
|
||||
tls-enabled = true
|
||||
|
||||
[environments.testing]
|
||||
spring-profiles = "test"
|
||||
debug-enabled = true
|
||||
log-level = "DEBUG"
|
||||
health-check-interval = "10s"
|
||||
health-check-timeout = "5s"
|
||||
health-check-retries = 2
|
||||
health-check-start-period = "20s"
|
||||
resource-limits = false
|
||||
jvm-debug-port = 5005
|
||||
hot-reload = false
|
||||
ephemeral-storage = true
|
||||
test-containers = true
|
||||
@@ -1,7 +0,0 @@
|
||||
# Backend
|
||||
|
||||
Domänenspezifische Services und Gateway.
|
||||
|
||||
- gateway: API Gateway/Auth/Routing
|
||||
- discovery: Service Registry/Discovery (optional)
|
||||
- services: Microservices, pro Domäne ein Service
|
||||
@@ -1,733 +0,0 @@
|
||||
# Gateway Configuration Documentation
|
||||
|
||||
## Überblick
|
||||
|
||||
Dieses Dokument beschreibt alle zentralen Konfigurationseigenschaften für das API Gateway. Die Konfiguration erfolgt über die `application.yml` Datei und kann durch Umgebungsvariablen überschrieben werden.
|
||||
|
||||
## Table of Contents
|
||||
|
||||
- [Server Configuration](#server-configuration)
|
||||
- [Spring Application](#spring-application)
|
||||
- [Consul Service Discovery](#consul-service-discovery)
|
||||
- [Spring Cloud Gateway](#spring-cloud-gateway)
|
||||
- [Circuit Breaker (Resilience4j)](#circuit-breaker-resilience4j)
|
||||
- [Management & Monitoring](#management--monitoring)
|
||||
- [Security](#security)
|
||||
- [Logging](#logging)
|
||||
|
||||
---
|
||||
|
||||
## Server Configuration
|
||||
|
||||
### server.port
|
||||
|
||||
- **Typ**: Integer
|
||||
- **Default**: 8081
|
||||
- **Environment Variable**: `GATEWAY_PORT`
|
||||
- **Beschreibung**: Port, auf dem das Gateway läuft
|
||||
|
||||
### server.netty.connection-timeout
|
||||
|
||||
- **Typ**: Duration
|
||||
- **Default**: 5s
|
||||
- **Beschreibung**: Timeout für initiale TCP-Verbindungen
|
||||
|
||||
### server.netty.idle-timeout
|
||||
|
||||
- **Typ**: Duration
|
||||
- **Default**: 15s
|
||||
- **Beschreibung**: Timeout für inaktive Verbindungen
|
||||
|
||||
**Beispiel:**
|
||||
|
||||
```yaml
|
||||
server:
|
||||
port: 8081
|
||||
netty:
|
||||
connection-timeout: 5s
|
||||
idle-timeout: 15s
|
||||
```
|
||||
|
||||
---
|
||||
|
||||
## Spring Application
|
||||
|
||||
### spring.application.name
|
||||
|
||||
- **Typ**: String
|
||||
- **Default**: api-gateway
|
||||
- **Beschreibung**: Name der Anwendung, wird in Consul und Logs verwendet
|
||||
|
||||
### spring.profiles.active
|
||||
|
||||
- **Typ**: String
|
||||
- **Default**: dev
|
||||
- **Environment Variable**: `SPRING_PROFILES_ACTIVE`
|
||||
- **Beschreibung**: Aktives Spring-Profil (dev, test, prod)
|
||||
- **Mögliche Werte**: dev, test, staging, prod
|
||||
|
||||
### spring.security.user.name / password
|
||||
|
||||
- **Typ**: String
|
||||
- **Default**: admin / admin
|
||||
- **Environment Variables**: `GATEWAY_ADMIN_USER`, `GATEWAY_ADMIN_PASSWORD`
|
||||
- **Beschreibung**: Basic Auth für administrative Endpunkte
|
||||
- **⚠️ Wichtig**: In Produktion durch sichere Werte ersetzen!
|
||||
|
||||
**Beispiel:**
|
||||
|
||||
```yaml
|
||||
spring:
|
||||
application:
|
||||
name: api-gateway
|
||||
profiles:
|
||||
active: ${SPRING_PROFILES_ACTIVE:dev}
|
||||
security:
|
||||
user:
|
||||
name: ${GATEWAY_ADMIN_USER:admin}
|
||||
password: ${GATEWAY_ADMIN_PASSWORD:admin}
|
||||
```
|
||||
|
||||
---
|
||||
|
||||
## Consul Service Discovery
|
||||
|
||||
### spring.cloud.consul.host
|
||||
|
||||
- **Typ**: String
|
||||
- **Default**: localhost
|
||||
- **Environment Variable**: `CONSUL_HOST`
|
||||
- **Beschreibung**: Hostname des Consul-Servers
|
||||
|
||||
### spring.cloud.consul.port
|
||||
|
||||
- **Typ**: Integer
|
||||
- **Default**: 8500
|
||||
- **Environment Variable**: `CONSUL_PORT`
|
||||
- **Beschreibung**: Port des Consul-Servers
|
||||
|
||||
### spring.cloud.consul.enabled
|
||||
|
||||
- **Typ**: Boolean
|
||||
- **Default**: true
|
||||
- **Environment Variable**: `CONSUL_ENABLED`
|
||||
- **Beschreibung**: Aktiviert/Deaktiviert Consul Integration
|
||||
|
||||
### spring.cloud.consul.discovery.enabled
|
||||
|
||||
- **Typ**: Boolean
|
||||
- **Default**: true
|
||||
- **Environment Variable**: `CONSUL_ENABLED`
|
||||
- **Beschreibung**: Aktiviert Service Discovery
|
||||
|
||||
### spring.cloud.consul.discovery.register
|
||||
|
||||
- **Typ**: Boolean
|
||||
- **Default**: true
|
||||
- **Environment Variable**: `CONSUL_ENABLED`
|
||||
- **Beschreibung**: Registriert das Gateway in Consul
|
||||
|
||||
### spring.cloud.consul.discovery.health-check-path
|
||||
|
||||
- **Typ**: String
|
||||
- **Default**: /actuator/health
|
||||
- **Beschreibung**: Pfad für Consul Health Checks
|
||||
|
||||
### spring.cloud.consul.discovery.health-check-interval
|
||||
|
||||
- **Typ**: Duration
|
||||
- **Default**: 10s
|
||||
- **Beschreibung**: Intervall für Health Checks
|
||||
|
||||
### spring.cloud.consul.discovery.instance-id
|
||||
|
||||
- **Typ**: String
|
||||
- **Default**: ${spring.application.name}-${server.port}-${random.uuid}
|
||||
- **Beschreibung**: Eindeutige Instanz-ID für Service Discovery
|
||||
|
||||
**Beispiel:**
|
||||
|
||||
```yaml
|
||||
spring:
|
||||
cloud:
|
||||
consul:
|
||||
host: ${CONSUL_HOST:localhost}
|
||||
port: ${CONSUL_PORT:8500}
|
||||
enabled: ${CONSUL_ENABLED:true}
|
||||
discovery:
|
||||
enabled: ${CONSUL_ENABLED:true}
|
||||
register: ${CONSUL_ENABLED:true}
|
||||
health-check-path: /actuator/health
|
||||
health-check-interval: 10s
|
||||
instance-id: ${spring.application.name}-${server.port}-${random.uuid}
|
||||
```
|
||||
|
||||
---
|
||||
|
||||
## Spring Cloud Gateway
|
||||
|
||||
### Verbindungskonfiguration
|
||||
|
||||
#### spring.cloud.gateway.server.webflux.httpclient.connect-timeout
|
||||
|
||||
- **Typ**: Integer (Millisekunden)
|
||||
- **Default**: 5000
|
||||
- **Beschreibung**: Timeout für Backend-Verbindungen
|
||||
|
||||
#### spring.cloud.gateway.server.webflux.httpclient.response-timeout
|
||||
|
||||
- **Typ**: Duration
|
||||
- **Default**: 30s
|
||||
- **Beschreibung**: Timeout für Backend-Responses
|
||||
|
||||
#### spring.cloud.gateway.server.webflux.httpclient.pool.max-idle-time
|
||||
|
||||
- **Typ**: Duration
|
||||
- **Default**: 15s
|
||||
- **Beschreibung**: Max. Idle-Zeit für Verbindungen im Pool
|
||||
|
||||
#### spring.cloud.gateway.server.webflux.httpclient.pool.max-life-time
|
||||
|
||||
- **Typ**: Duration
|
||||
- **Default**: 60s
|
||||
- **Beschreibung**: Max. Lebensdauer einer Verbindung
|
||||
|
||||
**Beispiel:**
|
||||
|
||||
```yaml
|
||||
spring:
|
||||
cloud:
|
||||
gateway:
|
||||
server:
|
||||
webflux:
|
||||
httpclient:
|
||||
connect-timeout: 5000
|
||||
response-timeout: 30s
|
||||
pool:
|
||||
max-idle-time: 15s
|
||||
max-life-time: 60s
|
||||
```
|
||||
|
||||
### Default Filters
|
||||
|
||||
Diese Filter werden auf **alle** Routen angewendet:
|
||||
|
||||
1. **DedupeResponseHeader**: Entfernt doppelte CORS-Header
|
||||
2. **CircuitBreaker**: Default Circuit Breaker mit Fallback
|
||||
3. **Retry**: Automatische Wiederholung bei Fehlern
|
||||
4. **Security Headers**: X-Content-Type-Options, X-Frame-Options, X-XSS-Protection, etc.
|
||||
5. **Cache-Control**: No-cache Header für alle Responses
|
||||
|
||||
**Beispiel:**
|
||||
|
||||
```yaml
|
||||
spring:
|
||||
cloud:
|
||||
gateway:
|
||||
default-filters:
|
||||
- DedupeResponseHeader=Access-Control-Allow-Credentials Access-Control-Allow-Origin
|
||||
- name: CircuitBreaker
|
||||
args:
|
||||
name: defaultCircuitBreaker
|
||||
fallbackUri: forward:/fallback
|
||||
- name: Retry
|
||||
args:
|
||||
retries: 3
|
||||
statuses: BAD_GATEWAY,GATEWAY_TIMEOUT
|
||||
methods: GET,POST,PUT,DELETE
|
||||
backoff:
|
||||
firstBackoff: 50ms
|
||||
maxBackoff: 500ms
|
||||
factor: 2
|
||||
```
|
||||
|
||||
### Routes
|
||||
|
||||
Das Gateway definiert folgende Service-Routen:
|
||||
|
||||
#### 1. Members Service Route
|
||||
|
||||
- **Path**: `/api/members/**`
|
||||
- **Service**: members-service (via Consul)
|
||||
- **Circuit Breaker**: membersCircuitBreaker
|
||||
- **Fallback**: /fallback/members
|
||||
|
||||
#### 2. Horses Service Route
|
||||
|
||||
- **Path**: `/api/horses/**`
|
||||
- **Service**: horses-service (via Consul)
|
||||
- **Circuit Breaker**: horsesCircuitBreaker
|
||||
- **Fallback**: /fallback/horses
|
||||
|
||||
#### 3. Events Service Route
|
||||
|
||||
- **Path**: `/api/events/**`
|
||||
- **Service**: events-service (via Consul)
|
||||
- **Circuit Breaker**: eventsCircuitBreaker
|
||||
- **Fallback**: /fallback/events
|
||||
|
||||
#### 4. Masterdata Service Route
|
||||
|
||||
- **Path**: `/api/masterdata/**`
|
||||
- **Service**: masterdata-service (via Consul)
|
||||
- **Circuit Breaker**: masterdataCircuitBreaker
|
||||
- **Fallback**: /fallback/masterdata
|
||||
|
||||
#### 5. Auth Service Route
|
||||
|
||||
- **Path**: `/api/auth/**`
|
||||
- **Service**: auth-service (via Consul)
|
||||
- **Circuit Breaker**: authCircuitBreaker
|
||||
- **Fallback**: /fallback/auth
|
||||
|
||||
#### 6. Ping Service Route
|
||||
|
||||
- **Path**: `/api/ping/**`
|
||||
- **Service**: ping-service (via Consul)
|
||||
- **No Circuit Breaker**: Optional service
|
||||
|
||||
**Beispiel einer Route:**
|
||||
|
||||
```yaml
|
||||
spring:
|
||||
cloud:
|
||||
gateway:
|
||||
routes:
|
||||
- id: members-service-route
|
||||
uri: lb://members-service # lb = Load Balanced via Consul
|
||||
predicates:
|
||||
- Path=/api/members/**
|
||||
filters:
|
||||
- StripPrefix=1 # Entfernt /api vom Pfad
|
||||
- name: CircuitBreaker
|
||||
args:
|
||||
name: membersCircuitBreaker
|
||||
fallbackUri: forward:/fallback/members
|
||||
```
|
||||
|
||||
---
|
||||
|
||||
## Circuit Breaker (Resilience4j)
|
||||
|
||||
### Default Konfiguration
|
||||
|
||||
#### resilience4j.circuitbreaker.configs.default.registerHealthIndicator
|
||||
|
||||
- **Typ**: Boolean
|
||||
- **Default**: true
|
||||
- **Beschreibung**: Registriert Circuit Breaker im Health Endpoint
|
||||
|
||||
#### resilience4j.circuitbreaker.configs.default.slidingWindowSize
|
||||
|
||||
- **Typ**: Integer
|
||||
- **Default**: 100
|
||||
- **Beschreibung**: Größe des Sliding Window für Fehlerrate-Berechnung
|
||||
|
||||
#### resilience4j.circuitbreaker.configs.default.minimumNumberOfCalls
|
||||
|
||||
- **Typ**: Integer
|
||||
- **Default**: 20
|
||||
- **Beschreibung**: Mindestanzahl an Calls bevor Circuit Breaker aktiviert wird
|
||||
|
||||
#### resilience4j.circuitbreaker.configs.default.permittedNumberOfCallsInHalfOpenState
|
||||
|
||||
- **Typ**: Integer
|
||||
- **Default**: 3
|
||||
- **Beschreibung**: Anzahl Test-Calls im Half-Open State
|
||||
|
||||
#### resilience4j.circuitbreaker.configs.default.waitDurationInOpenState
|
||||
|
||||
- **Typ**: Duration
|
||||
- **Default**: 5s
|
||||
- **Beschreibung**: Wartezeit bevor von Open zu Half-Open gewechselt wird
|
||||
|
||||
#### resilience4j.circuitbreaker.configs.default.failureRateThreshold
|
||||
|
||||
- **Typ**: Integer (Prozent)
|
||||
- **Default**: 50
|
||||
- **Beschreibung**: Fehlerrate-Schwelle für Circuit Breaker Aktivierung
|
||||
|
||||
### Service-spezifische Circuit Breaker
|
||||
|
||||
Jeder Service hat einen eigenen Circuit Breaker mit angepasster Konfiguration:
|
||||
|
||||
| Service | Sliding Window | Failure Threshold | Besonderheit |
|
||||
|---------|---------------|-------------------|--------------|
|
||||
| members-service | 50 | 50% | Standard |
|
||||
| horses-service | 50 | 50% | Standard |
|
||||
| events-service | 75 | 50% | Größeres Window |
|
||||
| masterdata-service | 30 | 50% | Kleineres Window |
|
||||
| auth-service | 20 | 30% | Sensitiverer Threshold |
|
||||
|
||||
**Beispiel:**
|
||||
|
||||
```yaml
|
||||
resilience4j:
|
||||
circuitbreaker:
|
||||
instances:
|
||||
authCircuitBreaker:
|
||||
baseConfig: default
|
||||
slidingWindowSize: 20
|
||||
failureRateThreshold: 30 # Auth ist kritisch -> niedrigerer Threshold
|
||||
```
|
||||
|
||||
---
|
||||
|
||||
## Management & Monitoring
|
||||
|
||||
### Exposed Endpoints
|
||||
|
||||
#### management.endpoints.web.exposure.include
|
||||
|
||||
- **Typ**: Comma-separated String
|
||||
- **Default**: health,info,metrics,prometheus,gateway,circuitbreakers
|
||||
- **Beschreibung**: Öffentlich verfügbare Actuator Endpoints
|
||||
|
||||
**Verfügbare Endpoints:**
|
||||
|
||||
- `/actuator/health` - Service Health Status
|
||||
- `/actuator/info` - Service Informationen
|
||||
- `/actuator/metrics` - Micrometer Metriken
|
||||
- `/actuator/prometheus` - Prometheus Scrape Endpoint
|
||||
- `/actuator/gateway` - Gateway Routes & Filters
|
||||
- `/actuator/circuitbreakers` - Circuit Breaker Status
|
||||
|
||||
### Health Endpoint
|
||||
|
||||
#### management.endpoint.health.show-details
|
||||
|
||||
- **Typ**: String
|
||||
- **Default**: always
|
||||
- **Mögliche Werte**: never, when-authorized, always
|
||||
- **Beschreibung**: Zeigt detaillierte Health-Informationen
|
||||
|
||||
#### management.endpoint.health.show-components
|
||||
|
||||
- **Typ**: Boolean
|
||||
- **Default**: always
|
||||
- **Beschreibung**: Zeigt Health-Komponenten
|
||||
|
||||
#### management.endpoint.health.probes.enabled
|
||||
|
||||
- **Typ**: Boolean
|
||||
- **Default**: true
|
||||
- **Beschreibung**: Aktiviert Kubernetes Liveness/Readiness Probes
|
||||
|
||||
### Metrics
|
||||
|
||||
#### management.metrics.tags
|
||||
|
||||
- **Beschreibung**: Globale Tags für alle Metriken
|
||||
- **Standard Tags**:
|
||||
- application: ${spring.application.name}
|
||||
- environment: ${spring.profiles.active}
|
||||
- instance: ${spring.cloud.consul.discovery.instance-id}
|
||||
- service: gateway
|
||||
- component: infrastructure
|
||||
- gateway: api-gateway
|
||||
|
||||
#### management.metrics.distribution.percentiles-histogram.http.server.requests
|
||||
|
||||
- **Typ**: Boolean
|
||||
- **Default**: true
|
||||
- **Beschreibung**: Aktiviert Histogram für Request-Zeiten
|
||||
|
||||
#### management.metrics.distribution.percentiles.http.server.requests
|
||||
|
||||
- **Typ**: Array[Double]
|
||||
- **Default**: [0.5, 0.90, 0.95, 0.99]
|
||||
- **Beschreibung**: Percentile-Werte für Request-Zeiten
|
||||
|
||||
### Tracing
|
||||
|
||||
#### management.tracing.enabled
|
||||
|
||||
- **Typ**: Boolean
|
||||
- **Default**: false
|
||||
- **Environment Variable**: `TRACING_ENABLED`
|
||||
- **Beschreibung**: Aktiviert Distributed Tracing
|
||||
|
||||
#### management.tracing.sampling.probability
|
||||
|
||||
- **Typ**: Double (0.0 - 1.0)
|
||||
- **Default**: 1.0
|
||||
- **Environment Variable**: `TRACING_SAMPLING_PROBABILITY`
|
||||
- **Beschreibung**: Sampling-Rate für Traces (1.0 = 100%)
|
||||
|
||||
#### management.zipkin.tracing.endpoint
|
||||
|
||||
- **Typ**: URL
|
||||
- **Default**: <http://localhost:9411/api/v2/spans>
|
||||
- **Environment Variable**: `ZIPKIN_TRACING_ENDPOINT`
|
||||
- **Beschreibung**: Zipkin Server URL
|
||||
|
||||
**Beispiel:**
|
||||
|
||||
```yaml
|
||||
management:
|
||||
endpoints:
|
||||
web:
|
||||
exposure:
|
||||
include: health,info,metrics,prometheus,gateway,circuitbreakers
|
||||
endpoint:
|
||||
health:
|
||||
show-details: always
|
||||
probes:
|
||||
enabled: true
|
||||
tracing:
|
||||
enabled: ${TRACING_ENABLED:false}
|
||||
sampling:
|
||||
probability: ${TRACING_SAMPLING_PROBABILITY:1.0}
|
||||
zipkin:
|
||||
tracing:
|
||||
endpoint: ${ZIPKIN_TRACING_ENDPOINT:http://localhost:9411/api/v2/spans}
|
||||
```
|
||||
|
||||
---
|
||||
|
||||
## Security
|
||||
|
||||
Die Security-Konfiguration erfolgt über Custom Properties unter `gateway.security`:
|
||||
|
||||
### gateway.security.publicPaths
|
||||
|
||||
- **Typ**: Array[String]
|
||||
- **Default**: ["/", "/fallback/**", "/actuator/**", "/webjars/**", "/v3/api-docs/**", "/api/auth/**"]
|
||||
- **Beschreibung**: Pfade, die ohne Authentifizierung zugänglich sind
|
||||
|
||||
### gateway.security.cors.allowedOriginPatterns
|
||||
|
||||
- **Typ**: Array[String]
|
||||
- **Default**: ["http://localhost:[*]", "https://*.meldestelle.at"]
|
||||
- **Beschreibung**: Erlaubte Origin-Patterns für CORS
|
||||
|
||||
### gateway.security.cors.allowedMethods
|
||||
|
||||
- **Typ**: Array[String]
|
||||
- **Default**: ["GET", "POST", "PUT", "DELETE", "OPTIONS", "PATCH"]
|
||||
- **Beschreibung**: Erlaubte HTTP-Methoden
|
||||
|
||||
### gateway.security.cors.allowedHeaders
|
||||
|
||||
- **Typ**: Array[String]
|
||||
- **Default**: ["*"]
|
||||
- **Beschreibung**: Erlaubte Request-Headers
|
||||
|
||||
### gateway.security.cors.exposedHeaders
|
||||
|
||||
- **Typ**: Array[String]
|
||||
- **Default**: ["X-Correlation-ID", "X-RateLimit-Limit", "X-RateLimit-Remaining"]
|
||||
- **Beschreibung**: Headers die an Client exponiert werden
|
||||
|
||||
### gateway.security.cors.allowCredentials
|
||||
|
||||
- **Typ**: Boolean
|
||||
- **Default**: true
|
||||
- **Beschreibung**: Erlaubt Credentials (Cookies, Auth-Header)
|
||||
|
||||
### gateway.security.cors.maxAge
|
||||
|
||||
- **Typ**: Duration
|
||||
- **Default**: 1h
|
||||
- **Beschreibung**: Cache-Zeit für CORS Preflight-Requests
|
||||
|
||||
**Beispiel:**
|
||||
|
||||
```yaml
|
||||
gateway:
|
||||
security:
|
||||
publicPaths:
|
||||
- "/"
|
||||
- "/actuator/**"
|
||||
- "/api/auth/**"
|
||||
cors:
|
||||
allowedOriginPatterns:
|
||||
- "http://localhost:[*]"
|
||||
- "https://*.meldestelle.at"
|
||||
allowedMethods:
|
||||
- GET
|
||||
- POST
|
||||
- PUT
|
||||
- DELETE
|
||||
allowCredentials: true
|
||||
maxAge: 1h
|
||||
```
|
||||
|
||||
### JWT Configuration
|
||||
|
||||
#### spring.security.oauth2.resourceserver.jwt.jwk-set-uri
|
||||
|
||||
- **Typ**: URL
|
||||
- **Environment Variable**: `KEYCLOAK_JWK_SET_URI`
|
||||
- **Beschreibung**: Keycloak JWK Set URI für JWT-Validierung
|
||||
- **Beispiel**: <http://localhost:8180/realms/meldestelle/protocol/openid-connect/certs>
|
||||
|
||||
---
|
||||
|
||||
## Logging
|
||||
|
||||
### logging.level
|
||||
|
||||
- **Beschreibung**: Log-Level für verschiedene Pakete
|
||||
|
||||
**Standard Log-Levels:**
|
||||
|
||||
- `org.springframework.cloud.gateway`: INFO
|
||||
- `org.springframework.cloud.loadbalancer`: DEBUG
|
||||
- `org.springframework.cloud.consul`: INFO
|
||||
- `at.mocode.infrastructure.gateway`: DEBUG
|
||||
- `io.github.resilience4j`: INFO
|
||||
- `reactor.netty.http.client`: INFO
|
||||
- `org.springframework.security`: WARN
|
||||
- `org.springframework.web`: INFO
|
||||
|
||||
### logging.pattern.console
|
||||
|
||||
- **Beschreibung**: Console-Log-Pattern mit Farben und Correlation-ID
|
||||
|
||||
### logging.pattern.file
|
||||
|
||||
- **Beschreibung**: File-Log-Pattern ohne Farben
|
||||
|
||||
### logging.file.name
|
||||
|
||||
- **Typ**: String
|
||||
- **Default**: infrastructure/gateway/logs/gateway.log
|
||||
- **Beschreibung**: Log-Datei Pfad
|
||||
|
||||
### logging.logback.rollingpolicy
|
||||
|
||||
- **clean-history-on-start**: true
|
||||
- **max-file-size**: 100MB
|
||||
- **total-size-cap**: 1GB
|
||||
- **max-history**: 30 (Tage)
|
||||
|
||||
**Beispiel:**
|
||||
|
||||
```yaml
|
||||
logging:
|
||||
level:
|
||||
at.mocode.infrastructure.gateway: DEBUG
|
||||
org.springframework.cloud.gateway: INFO
|
||||
file:
|
||||
name: infrastructure/gateway/logs/gateway.log
|
||||
logback:
|
||||
rollingpolicy:
|
||||
max-file-size: 100MB
|
||||
max-history: 30
|
||||
```
|
||||
|
||||
---
|
||||
|
||||
## Umgebungsvariablen Übersicht
|
||||
|
||||
### Kritische Variablen für Produktion
|
||||
|
||||
| Variable | Beschreibung | Default |
|
||||
|----------|--------------|---------|
|
||||
| `GATEWAY_PORT` | Gateway Port | 8081 |
|
||||
| `CONSUL_HOST` | Consul Server | localhost |
|
||||
| `CONSUL_PORT` | Consul Port | 8500 |
|
||||
| `CONSUL_ENABLED` | Consul Aktivieren | true |
|
||||
| `GATEWAY_ADMIN_USER` | Admin Username | admin |
|
||||
| `GATEWAY_ADMIN_PASSWORD` | Admin Password | admin |
|
||||
| `KEYCLOAK_JWK_SET_URI` | Keycloak JWK URI | <http://localhost:8180/>... |
|
||||
| `TRACING_ENABLED` | Tracing aktivieren | false |
|
||||
| `ZIPKIN_TRACING_ENDPOINT` | Zipkin Server | <http://localhost:9411/>... |
|
||||
| `SPRING_PROFILES_ACTIVE` | Spring Profil | dev |
|
||||
|
||||
---
|
||||
|
||||
## Profile-spezifische Konfiguration
|
||||
|
||||
Das Gateway unterstützt verschiedene Spring Profile:
|
||||
|
||||
### dev (Development)
|
||||
|
||||
- Detailliertes Logging
|
||||
- Alle Monitoring-Endpunkte verfügbar
|
||||
- Tracing optional
|
||||
|
||||
### test
|
||||
|
||||
- Reduziertes Logging
|
||||
- Test-spezifische Timeouts
|
||||
- In-Memory Services optional
|
||||
|
||||
### prod (Production)
|
||||
|
||||
- Production-ready Logging
|
||||
- Sichere Credentials erforderlich
|
||||
- Tracing empfohlen
|
||||
- Rate Limiting aktiviert
|
||||
|
||||
**Beispiel für profile-spezifische Datei:**
|
||||
|
||||
```yaml
|
||||
# application-prod.yml
|
||||
spring:
|
||||
security:
|
||||
user:
|
||||
name: ${GATEWAY_ADMIN_USER} # Muss gesetzt sein!
|
||||
password: ${GATEWAY_ADMIN_PASSWORD} # Muss gesetzt sein!
|
||||
|
||||
management:
|
||||
tracing:
|
||||
enabled: true
|
||||
sampling:
|
||||
probability: 0.1 # 10% Sampling in Production
|
||||
|
||||
logging:
|
||||
level:
|
||||
at.mocode.infrastructure.gateway: INFO # Weniger Logs
|
||||
```
|
||||
|
||||
---
|
||||
|
||||
## Best Practices
|
||||
|
||||
1. **Umgebungsvariablen verwenden**: Nie Credentials in application.yml hardcoden
|
||||
2. **Profile nutzen**: Separate Konfigurationen für dev/test/prod
|
||||
3. **Health Checks aktivieren**: Für Consul und Kubernetes
|
||||
4. **Tracing in Production**: Mindestens 10% Sampling
|
||||
5. **Monitoring exportieren**: Prometheus-Endpunkt für Grafana
|
||||
6. **Circuit Breaker tunen**: An Service-Charakteristiken anpassen
|
||||
7. **CORS restriktiv**: Nur benötigte Origins erlauben
|
||||
8. **Log Rotation**: Verhindert volle Festplatten
|
||||
|
||||
---
|
||||
|
||||
## Troubleshooting
|
||||
|
||||
### Gateway startet nicht
|
||||
|
||||
- ✅ Prüfen: Consul erreichbar?
|
||||
- ✅ Prüfen: Port 8081 frei?
|
||||
- ✅ Prüfen: Keycloak erreichbar? (Optional)
|
||||
|
||||
### Service nicht erreichbar
|
||||
|
||||
- ✅ Prüfen: Service in Consul registriert?
|
||||
- ✅ Prüfen: Circuit Breaker offen?
|
||||
- ✅ Prüfen: Health Check erfolgreich?
|
||||
|
||||
### CORS-Fehler
|
||||
|
||||
- ✅ Prüfen: Origin in allowedOriginPatterns?
|
||||
- ✅ Prüfen: Methode in allowedMethods?
|
||||
- ✅ Prüfen: allowCredentials korrekt?
|
||||
|
||||
### Hohe Latenz
|
||||
|
||||
- ✅ Prüfen: response-timeout zu hoch?
|
||||
- ✅ Prüfen: Backend-Services langsam?
|
||||
- ✅ Prüfen: Connection Pool ausgeschöpft?
|
||||
|
||||
---
|
||||
|
||||
## Weitere Ressourcen
|
||||
|
||||
- [Gateway README](README-INFRA-GATEWAY.md)
|
||||
- [Spring Cloud Gateway Dokumentation](https://docs.spring.io/spring-cloud-gateway/docs/current/reference/html/)
|
||||
- [Resilience4j Dokumentation](https://resilience4j.readme.io/)
|
||||
- [Consul Dokumentation](https://www.consul.io/docs)
|
||||
@@ -1,442 +0,0 @@
|
||||
# Infrastructure/Gateway Module - Comprehensive Documentation
|
||||
|
||||
## Überblick
|
||||
|
||||
Das API-Gateway ist der zentrale und einzige öffentliche Einstiegspunkt für alle Anfragen von externen Clients (z.B. Web-Anwendung, Desktop-Anwendung, mobile Apps) an das Meldestelle-System. Es fungiert als "Pförtner" für die gesamte Microservice-Landschaft und wurde zu einem vollwertigen, produktionstauglichen API Gateway mit modernen Best Practices erweitert.
|
||||
|
||||
**Wichtiger Grundsatz**: Kein externer Client sollte jemals direkt mit einem internen Microservice kommunizieren. Alle Anfragen laufen über das Gateway.
|
||||
|
||||
## Architektur und Technologie
|
||||
|
||||
Das Gateway ist als eigenständiger Spring Boot Service implementiert und nutzt Spring Cloud Gateway als technologische Grundlage. Spring Cloud Gateway ist ein reaktives, nicht-blockierendes Framework, das sich nahtlos in das Spring-Ökosystem integriert.
|
||||
|
||||
### Technologie-Stack
|
||||
|
||||
- **Spring Boot 3.x** - Moderne Spring Boot Anwendung
|
||||
- **Spring Cloud Gateway** - Reaktives Gateway Framework
|
||||
- **Spring WebFlux** - Reaktive Web-Programmierung mit Netty
|
||||
- **Resilience4j** - Circuit Breaker Pattern Implementation
|
||||
- **Consul** - Service Discovery und Health Checks
|
||||
- **Micrometer + Prometheus** - Umfassende Metriken und Monitoring
|
||||
- **JWT** - Token-basierte Authentifizierung
|
||||
- **Reactive Streams** - Non-blocking I/O für optimale Performance
|
||||
|
||||
## Hauptverantwortlichkeiten
|
||||
|
||||
Das Gateway handhabt alle Cross-Cutting Concerns (übergreifende Belange), die für mehrere oder alle Microservices gelten und entlastet damit die Fach-Services von technischen Aufgaben.
|
||||
|
||||
### 1. Dynamisches Routing
|
||||
|
||||
- **Service Discovery Integration**: Vollständige Consul Integration für automatische Service-Erkennung
|
||||
- **Load Balancing**: Intelligente Lastverteilung zwischen Service-Instanzen
|
||||
- **Health-basiertes Routing**: Weiterleitung nur an gesunde Service-Instanzen
|
||||
|
||||
**Verfügbare Routen**:
|
||||
|
||||
- `/api/members/**` → members-service
|
||||
- `/api/horses/**` → horses-service
|
||||
- `/api/events/**` → events-service
|
||||
- `/api/masterdata/**` → masterdata-service
|
||||
- `/api/auth/**` → auth-service
|
||||
- `/api/ping/**` → ping-service
|
||||
|
||||
### 2. Sicherheit und Authentifizierung
|
||||
|
||||
- **JWT Security Enforcement**: Validierung von Bearer Tokens für alle geschützten Endpunkte
|
||||
- **Public Path Exemptions**: Konfigurierbare öffentliche Pfade (`/`, `/health`, `/actuator/**`, `/api/auth/login`)
|
||||
- **User Context Injection**: Automatische Weiterleitung von User-ID und Rolle an Backend Services
|
||||
- **Standardisierte Fehlerbehandlung**: Strukturierte 401 Unauthorized Responses
|
||||
|
||||
### 3. Rate Limiting
|
||||
|
||||
- **Intelligentes Rate Limiting** basierend auf User-Typ:
|
||||
- **Anonymous Users**: 50 Anfragen pro Minute
|
||||
- **Authenticated Users**: 200 Anfragen pro Minute
|
||||
- **Admin Users**: 500 Anfragen pro Minute
|
||||
- **IP-basierte Limits**: Schutz vor DDoS-Attacken
|
||||
- **Custom Headers**: X-RateLimit-* Header für Client-Information
|
||||
|
||||
### 4. Circuit Breaker und Resilienz
|
||||
|
||||
- **Service-spezifische Circuit Breaker**: Resilience4j Integration für jeden Backend Service
|
||||
- **Fallback Mechanismen**: Benutzerfreundliche Fehlermeldungen bei Service-Ausfällen
|
||||
- **Retry Logic**: Automatische Wiederholungen bei transienten Fehlern
|
||||
- **Graceful Degradation**: Systembetrieb auch bei partiellen Service-Ausfällen
|
||||
|
||||
### 5. Monitoring und Observability
|
||||
|
||||
Das Gateway implementiert umfassende Observability durch eine vollständig integrierte Micrometer-basierte Metriken-Architektur.
|
||||
|
||||
#### Automatische Metriken-Erfassung (GatewayMetricsConfig)
|
||||
|
||||
- **Request Duration Tracking**: Automatische Messung aller Request-Response Zyklen
|
||||
- Metric: `gateway_request_duration` (Timer)
|
||||
- Tags: method, path, status, status_series
|
||||
- Percentile-basierte Auswertung (P50, P90, P95, P99)
|
||||
- **Error Rate Monitoring**: Detailliertes Error-Tracking für 4xx/5xx Responses
|
||||
- Metric: `gateway_errors_total` (Counter)
|
||||
- Tags: method, path, status, status_series, error_type
|
||||
- Unterscheidung zwischen client_error und server_error
|
||||
- **Request Volume Tracking**: Vollständige Request-Volumen Überwachung
|
||||
- Metric: `gateway_requests_total` (Counter)
|
||||
- Tags: method, path für detaillierte Analyse
|
||||
- **Circuit Breaker Events**: Monitoring von Resilience-Pattern Events
|
||||
- Metric: `gateway_circuit_breaker_events_total` (Counter)
|
||||
- Integration mit Resilience4j Circuit Breaker Status
|
||||
|
||||
#### Intelligente Pfad-Normalisierung
|
||||
|
||||
- **Kardinalitäts-Kontrolle**: Automatische Normalisierung von dynamischen Pfaden
|
||||
- `/api/horses/123` → `/api/horses/{id}`
|
||||
- UUID-Pattern → `/{uuid}`
|
||||
- Sehr lange Pfade werden gekürzt (100+ Zeichen)
|
||||
|
||||
#### Health Monitoring Integration
|
||||
|
||||
- **Downstream Service Health**: Umfassende Überwachung aller Backend Services
|
||||
- Kritische Services: Members, Horses, Events, Masterdata, Auth
|
||||
- Optionale Services: Ping Service
|
||||
- Circuit Breaker Status Integration
|
||||
- **Distributed Tracing**: Korrelations-ID basiertes Request-Tracking
|
||||
- **Strukturierte Logs**: JSON-Format für maschinelle Auswertung
|
||||
|
||||
#### Prometheus Export
|
||||
|
||||
- **Automatischer Export**: Alle Metriken werden automatisch an Prometheus exportiert
|
||||
- **Common Tags**: Alle Metriken erhalten automatisch Service- und Component-Tags
|
||||
- **Filter-Optimierung**: Rauschen-reduzierende Metrik-Filter für interne Spring/Netty Metriken
|
||||
|
||||
### 6. CORS-Management
|
||||
|
||||
- **Produktionstaugliche CORS-Konfiguration**:
|
||||
- Erlaubte Origins: `https://*.meldestelle.at`, `http://localhost:*`
|
||||
- Alle HTTP-Methoden (GET, POST, PUT, DELETE, PATCH, OPTIONS)
|
||||
- Credential-Support für authentifizierte Anfragen
|
||||
|
||||
## Implementierte Optimierungen
|
||||
|
||||
### Gateway-Konfiguration (application.yml)
|
||||
|
||||
✅ **Vollständige Service-Routen**: Routing für alle Business Services
|
||||
✅ **Circuit Breaker Integration**: Service-spezifische Resilience4j Konfigurationen
|
||||
✅ **Connection Pooling**: Optimierte HTTP-Client-Konfiguration
|
||||
✅ **Security Headers**: Umfassende Sicherheits-Header (X-Content-Type-Options, X-Frame-Options, X-XSS-Protection)
|
||||
✅ **Enhanced Logging**: Strukturierte Logs mit Korrelations-IDs und Performance-Daten
|
||||
|
||||
### Health Monitoring (GatewayHealthIndicator.kt)
|
||||
|
||||
✅ **Downstream Service Monitoring**: Überwachung aller kritischen Services
|
||||
✅ **Service Discovery Integration**: Consul-basierte Service-Erkennung
|
||||
✅ **Test-Environment Handling**: Graceful Degradation in Test-Umgebungen
|
||||
✅ **Detailliertes Error Reporting**: Umfassende Statusinformationen
|
||||
|
||||
### Build-Optimierungen (build.gradle.kts)
|
||||
|
||||
✅ **SINGLE SOURCE OF TRUTH**: Alle Dependencies über libs.versions.toml
|
||||
✅ **Build Info Generation**: Automatische Build-Metadaten
|
||||
✅ **Modern Kotlin Compiler**: Optimierte Compiler-Einstellungen
|
||||
✅ **Dependency Optimization**: Bereinigung redundanter Dependencies
|
||||
|
||||
### Docker-Optimierungen (Dockerfile)
|
||||
|
||||
✅ **Multi-Stage Build**: Spring Boot Layer-Extraktion für 90%+ besseres Caching
|
||||
✅ **Security Hardening**: Non-root User, Security Updates
|
||||
✅ **OCI Compliance**: Vollständige Container-Metadaten
|
||||
✅ **Production-Ready**: Optimierte JVM-Settings für Container-Umgebung
|
||||
|
||||
### Metriken-Integration (GatewayMetricsConfig.kt)
|
||||
|
||||
✅ **Comprehensive Micrometer Integration**: Vollständige Metriken-Erfassung mit automatischem Prometheus Export
|
||||
✅ **Request/Response Time Tracking**: Detaillierte Performance-Metriken mit Percentile-Auswertung
|
||||
✅ **Error Rate Monitoring**: Intelligente Fehler-Klassifikation und -Tracking
|
||||
✅ **Path Normalization**: Kardinalitäts-kontrolle für dynamische API-Pfade
|
||||
✅ **Circuit Breaker Metrics**: Integration mit Resilience4j Event-Tracking
|
||||
✅ **Custom Business Metrics**: Erweiterbare Metrik-Architektur für fachliche KPIs
|
||||
|
||||
### Dokumentation
|
||||
|
||||
✅ **OpenAPI 3.0.3 Spezifikation**: Vollständige API-Dokumentation mit Members Service
|
||||
✅ **Interactive Swagger UI**: Modern dokumentierte API-Endpunkte
|
||||
✅ **Static HTML Documentation**: Responsive, moderne Dokumentations-Website
|
||||
✅ **Health Monitoring Integration**: Real-time Status-Informationen
|
||||
|
||||
## Performance und Reliability
|
||||
|
||||
### Netty Server Optimierungen
|
||||
|
||||
- **Connection Timeouts**: 5 Sekunden für optimale Responsiveness
|
||||
- **Idle Timeout**: 15 Sekunden für effiziente Resource-Nutzung
|
||||
- **Elastic Connection Pool**: Automatische Skalierung basierend auf Load
|
||||
|
||||
### Circuit Breaker Konfiguration
|
||||
|
||||
- **Sliding Window**: 100 Anfragen für Default, service-spezifische Anpassungen
|
||||
- **Failure Rate Threshold**: 50% für Standard-Services, 30% für Auth-Service
|
||||
- **Half-Open State**: 3 Test-Anfragen für Service-Recovery
|
||||
|
||||
### JVM Optimierungen (Container)
|
||||
|
||||
```bash
|
||||
JAVA_OPTS="-server -Xmx512m -Xms256m -XX:+UseG1GC
|
||||
-XX:+UseContainerSupport -XX:MaxRAMPercentage=75.0"
|
||||
```
|
||||
|
||||
## API Gateway Request Flow
|
||||
|
||||
Ein typischer Anfrage-Flow:
|
||||
|
||||
1. **Client Request**: `https://api.meldestelle.at/api/members/123`
|
||||
2. **Gateway Empfang**: Anfrage wird vom Spring Cloud Gateway empfangen
|
||||
3. **Filter-Pipeline**:
|
||||
- **Security Filter**: JWT-Validierung
|
||||
- **Rate Limiting Filter**: Anfrage-Limits prüfen
|
||||
- **Correlation Filter**: Trace-ID generieren
|
||||
- **Logging Filter**: Request-Details erfassen
|
||||
4. **Service Discovery**: Consul-Abfrage für verfügbare `members-service` Instanzen
|
||||
5. **Load Balancing**: Intelligente Auswahl einer gesunden Instanz
|
||||
6. **Circuit Breaker**: Überwachung der Service-Verfügbarkeit
|
||||
7. **Request Forwarding**: Weiterleitung an Backend Service
|
||||
8. **Response Processing**: Antwort-Verarbeitung und Header-Enrichment
|
||||
9. **Client Response**: Strukturierte Antwort an Client
|
||||
|
||||
## Monitoring und Health Checks
|
||||
|
||||
### Actuator Endpunkte
|
||||
|
||||
- `/actuator/health` - Umfassender Health Status aller Services
|
||||
- `/actuator/metrics` - Prometheus-kompatible Metriken
|
||||
- `/actuator/info` - Anwendungs- und Build-Informationen
|
||||
- `/actuator/gateway` - Gateway-spezifische Routing-Informationen
|
||||
- `/actuator/circuitbreakers` - Circuit Breaker Status
|
||||
|
||||
### Key Performance Indicators (KPIs)
|
||||
|
||||
#### Automatisch erfasste Metriken
|
||||
|
||||
- **Request Throughput**: `gateway_requests_total` - Anfragen pro Sekunde nach Method/Path
|
||||
- **Response Times**: `gateway_request_duration` - P50, P90, P95, P99 Percentile nach Status
|
||||
- **Error Rates**: `gateway_errors_total` - 4xx/5xx Response Codes mit Error-Type Klassifikation
|
||||
- **Circuit Breaker Events**: `gateway_circuit_breaker_events_total` - Resilience Pattern Aktivierungen
|
||||
- **Service Availability**: Upstream Service Health via Health Indicators
|
||||
|
||||
#### Verfügbare Metric Tags für detaillierte Analyse
|
||||
|
||||
- **method**: HTTP-Method (GET, POST, PUT, DELETE, etc.)
|
||||
- **path**: Normalisierter API-Pfad (z.B. `/api/horses/{id}`)
|
||||
- **status**: HTTP-Status-Code (200, 404, 500, etc.)
|
||||
- **status_series**: Status-Gruppe (2xx, 3xx, 4xx, 5xx)
|
||||
- **error_type**: Fehler-Klassifikation (client_error, server_error)
|
||||
- **service**: Automatisches "gateway" Tag
|
||||
- **component**: Automatisches "infrastructure" Tag
|
||||
|
||||
#### Prometheus Query Beispiele
|
||||
|
||||
```promql
|
||||
# Request Rate pro Endpunkt
|
||||
rate(gateway_requests_total[5m])
|
||||
|
||||
# 95. Percentile Response Time
|
||||
histogram_quantile(0.95, rate(gateway_request_duration_bucket[5m]))
|
||||
|
||||
# Error Rate nach Service
|
||||
rate(gateway_errors_total[5m]) / rate(gateway_requests_total[5m])
|
||||
|
||||
# Circuit Breaker Aktivierungen
|
||||
increase(gateway_circuit_breaker_events_total[1h])
|
||||
```
|
||||
|
||||
## Security Features
|
||||
|
||||
### JWT Authentication
|
||||
|
||||
- **Bearer Token Validation**: Automatische JWT-Verifikation
|
||||
- **Role Extraction**: User-Rolle für Backend Services verfügbar
|
||||
- **Token Refresh**: Unterstützung für Token-Erneuerung
|
||||
- **Public Endpoints**: Konfigurierbare Ausnahmen für öffentliche APIs
|
||||
|
||||
### Security Headers
|
||||
|
||||
```yaml
|
||||
X-Content-Type-Options: nosniff
|
||||
X-Frame-Options: DENY
|
||||
X-XSS-Protection: 1; mode=block
|
||||
Referrer-Policy: strict-origin-when-cross-origin
|
||||
Cache-Control: no-cache, no-store, must-revalidate
|
||||
```
|
||||
|
||||
## Development und Testing
|
||||
|
||||
### Local Development
|
||||
|
||||
**WICHTIG:** Alle Befehle müssen aus dem Projekt-Root-Verzeichnis (`/home/stefan/WsMeldestelle/Meldestelle`) ausgeführt werden.
|
||||
|
||||
```bash
|
||||
# Sicherstellen, dass Sie im richtigen Verzeichnis sind
|
||||
cd /home/stefan/WsMeldestelle/Meldestelle
|
||||
|
||||
# Gateway starten
|
||||
./gradlew :infrastructure:gateway:bootRun
|
||||
|
||||
# Mit Docker
|
||||
docker build -t meldestelle/gateway:latest -f infrastructure/gateway/Dockerfile .
|
||||
docker run -p 8081:8081 meldestelle/gateway:latest
|
||||
```
|
||||
|
||||
📖 **Detaillierte Startup-Anleitung:** Siehe `GATEWAY-STARTUP-GUIDE.md` im Projekt-Root für vollständige Befehle und Fehlerbehebung.
|
||||
|
||||
### Testing
|
||||
|
||||
```bash
|
||||
# Unit Tests
|
||||
./gradlew :infrastructure:gateway:test
|
||||
|
||||
# Integration Tests (mit Testcontainers)
|
||||
./gradlew :infrastructure:gateway:integrationTest
|
||||
```
|
||||
|
||||
## Konfiguration
|
||||
|
||||
### Environment Variables
|
||||
|
||||
```bash
|
||||
SPRING_PROFILES_ACTIVE=prod
|
||||
CONSUL_HOST=consul.meldestelle.at
|
||||
CONSUL_PORT=8500
|
||||
GATEWAY_ADMIN_USER=admin
|
||||
GATEWAY_ADMIN_PASSWORD=secure-password
|
||||
```
|
||||
|
||||
### Profile-spezifische Konfiguration
|
||||
|
||||
- **dev**: Entwicklungsumgebung mit Debug-Logging
|
||||
- **test**: Test-Umgebung mit Mock Services
|
||||
- **prod**: Produktionsumgebung mit allen Security Features
|
||||
|
||||
## Deployment
|
||||
|
||||
### Docker Deployment
|
||||
|
||||
```bash
|
||||
# Multi-stage Build mit Layer Caching
|
||||
docker build -t meldestelle/gateway:1.0.0 \
|
||||
-f infrastructure/gateway/Dockerfile .
|
||||
|
||||
# Container starten
|
||||
docker run -d \
|
||||
--name gateway \
|
||||
-p 8081:8081 \
|
||||
-e SPRING_PROFILES_ACTIVE=prod \
|
||||
-e CONSUL_HOST=consul \
|
||||
meldestelle/gateway:1.0.0
|
||||
```
|
||||
|
||||
### Kubernetes Deployment
|
||||
|
||||
```yaml
|
||||
apiVersion: apps/v1
|
||||
kind: Deployment
|
||||
metadata:
|
||||
name: api-gateway
|
||||
spec:
|
||||
replicas: 3
|
||||
selector:
|
||||
matchLabels:
|
||||
app: api-gateway
|
||||
template:
|
||||
spec:
|
||||
containers:
|
||||
- name: gateway
|
||||
image: meldestelle/gateway:1.0.0
|
||||
ports:
|
||||
- containerPort: 8081
|
||||
livenessProbe:
|
||||
httpGet:
|
||||
path: /actuator/health
|
||||
port: 8081
|
||||
initialDelaySeconds: 90
|
||||
periodSeconds: 30
|
||||
```
|
||||
|
||||
## Troubleshooting
|
||||
|
||||
### Häufige Probleme
|
||||
|
||||
**Service Discovery Issues**
|
||||
|
||||
- Consul Connectivity prüfen
|
||||
- Service Registration Status überprüfen
|
||||
- DNS Resolution testen
|
||||
|
||||
**Circuit Breaker Activation**
|
||||
|
||||
- Service Health Status prüfen
|
||||
- Failure Rate Threshold analysieren
|
||||
- Manual Circuit Breaker Reset über Actuator
|
||||
|
||||
**Performance Issues**
|
||||
|
||||
- Connection Pool Metrics analysieren
|
||||
- JVM Heap Usage monitoring
|
||||
- Request Rate Limiting überprüfen
|
||||
|
||||
**Metriken und Monitoring Issues**
|
||||
|
||||
- Prometheus Scraping Endpunkt prüfen: `/actuator/prometheus`
|
||||
- Metrics Registry Status überprüfen: `/actuator/metrics`
|
||||
- GatewayMetricsWebFilter Aktivierung validieren
|
||||
- Metric Tags auf Kardinalitäts-Explosion prüfen
|
||||
- Path Normalization bei unerwarteten Metric-Namen
|
||||
|
||||
### Logging und Debugging
|
||||
|
||||
```bash
|
||||
# Logs mit Korrelations-IDs
|
||||
docker logs gateway | grep "correlationId"
|
||||
|
||||
# Circuit Breaker Status
|
||||
curl http://localhost:8081/actuator/circuitbreakers
|
||||
|
||||
# Health Details
|
||||
curl http://localhost:8081/actuator/health
|
||||
```
|
||||
|
||||
## Zukünftige Erweiterungen
|
||||
|
||||
### Geplante Features
|
||||
|
||||
- **OAuth2/OIDC Integration**: Erweiterte Authentifizierung
|
||||
- **GraphQL Gateway**: Unified GraphQL Interface
|
||||
- **Caching Layer**: Redis-basiertes Response Caching
|
||||
- **Request/Response Transformation**: Dynamic Content Modification
|
||||
|
||||
### Performance Optimierungen
|
||||
|
||||
- **HTTP/2 Support**: Moderne Protocol-Unterstützung
|
||||
- **Connection Pooling Tuning**: Erweiterte Pool-Konfiguration
|
||||
- **Reactive Streams Optimization**: Backpressure Handling
|
||||
|
||||
## Dokumentation und Ressourcen
|
||||
|
||||
### API Dokumentation
|
||||
|
||||
- **Swagger UI**: `/swagger` - Interactive API Documentation
|
||||
- **OpenAPI Spec**: `/openapi` - Machine-readable API Specification
|
||||
- **Static Documentation**: `/docs` - Comprehensive Documentation Hub
|
||||
|
||||
### Monitoring Dashboards
|
||||
|
||||
- **Health Status**: `/actuator/health` - Real-time Service Health
|
||||
- **Metrics**: `/actuator/metrics` - Prometheus Metrics
|
||||
- **Gateway Routes**: `/actuator/gateway/routes` - Active Route Information
|
||||
|
||||
---
|
||||
|
||||
**Letzte Aktualisierung**: 14. August 2025
|
||||
|
||||
**Version**: 1.1.0
|
||||
|
||||
**Maintainer**: Meldestelle Development Team
|
||||
|
||||
---
|
||||
|
||||
Diese Dokumentation wurde umfassend aktualisiert und um die neue Micrometer Metrics Integration (GatewayMetricsConfig.kt) erweitert. Sie dokumentiert alle implementierten Optimierungen einschließlich der vollständigen Observability-Architektur mit automatischer Request/Response Zeit Messung, Error Rate Tracking und Custom Business Metrics.
|
||||
+1
-1
@@ -27,7 +27,7 @@ dependencies {
|
||||
// Stellt sicher, dass alle Versionen aus der zentralen BOM kommen.
|
||||
api(platform(projects.platform.platformBom))
|
||||
// Implementiert die provider-agnostische Caching-API.
|
||||
implementation(projects.infrastructure.cache.cacheApi)
|
||||
implementation(projects.backend.infrastructure.cache.cacheApi)
|
||||
// OPTIMIERUNG: Verwendung des `redis-cache`-Bundles aus libs.versions.toml.
|
||||
// Dieses Bundle enthält Spring Data Redis, Lettuce und Jackson-Module.
|
||||
implementation(libs.bundles.redis.cache)
|
||||
+3
-3
@@ -22,7 +22,7 @@ dependencies {
|
||||
// Stellt sicher, dass alle Versionen aus der zentralen BOM kommen
|
||||
implementation(platform(projects.platform.platformBom))
|
||||
// Implementiert die provider-agnostische Event-Store-API
|
||||
api(projects.infrastructure.eventStore.eventStoreApi)
|
||||
api(projects.backend.infrastructure.eventStore.eventStoreApi)
|
||||
// Benötigt Zugriff auf Core-Module für Domänen-Events und Utilities
|
||||
implementation(projects.core.coreDomain)
|
||||
implementation(projects.core.coreUtils)
|
||||
@@ -43,8 +43,8 @@ dependencies {
|
||||
testImplementation(libs.kotlinx.serialization.json)
|
||||
testImplementation(libs.reactor.test)
|
||||
// Für Integration Tests mit beiden Redis-Modulen
|
||||
testImplementation(projects.infrastructure.cache.cacheApi)
|
||||
testImplementation(projects.infrastructure.cache.redisCache)
|
||||
testImplementation(projects.backend.infrastructure.cache.cacheApi)
|
||||
testImplementation(projects.backend.infrastructure.cache.redisCache)
|
||||
}
|
||||
|
||||
// === Task Configuration ===
|
||||
+6
-4
@@ -23,8 +23,8 @@ ARG VERSION
|
||||
FROM gradle:${GRADLE_VERSION}-jdk${JAVA_VERSION}-alpine AS builder
|
||||
|
||||
# Re-declare build arguments for this stage
|
||||
ARG BUILD_DATE
|
||||
ARG VERSION
|
||||
ARG BUILD_DATE
|
||||
|
||||
LABEL stage=builder
|
||||
LABEL service="api-gateway"
|
||||
@@ -57,6 +57,7 @@ RUN chmod +x gradlew
|
||||
COPY platform/ platform/
|
||||
COPY core/ core/
|
||||
|
||||
# Copy infrastructure directories (required by settings.gradle.kts)
|
||||
# Copy infrastructure directories (required by settings.gradle.kts)
|
||||
COPY infrastructure/ infrastructure/
|
||||
|
||||
@@ -65,6 +66,7 @@ COPY domains/ domains/
|
||||
|
||||
# Copy services directories (required by settings.gradle.kts)
|
||||
COPY services/ services/
|
||||
COPY backend/ backend/
|
||||
|
||||
# Copy client directories (required by settings.gradle.kts)
|
||||
COPY clients/ clients/
|
||||
@@ -78,16 +80,16 @@ COPY build.gradle.kts ./
|
||||
# Download and cache dependencies with BuildKit cache mount (removed deprecated flag)
|
||||
RUN --mount=type=cache,target=/home/gradle/.gradle/caches \
|
||||
--mount=type=cache,target=/home/gradle/.gradle/wrapper \
|
||||
./gradlew :infrastructure:gateway:dependencies --info
|
||||
./gradlew :backend:gateway:dependencies --info
|
||||
|
||||
# Build the application with optimizations and build cache (removed deprecated flag)
|
||||
RUN --mount=type=cache,target=/home/gradle/.gradle/caches \
|
||||
--mount=type=cache,target=/home/gradle/.gradle/wrapper \
|
||||
./gradlew :infrastructure:gateway:bootJar --info
|
||||
./gradlew :backend:gateway:bootJar --info
|
||||
|
||||
# Extract JAR layers for better caching in runtime stage
|
||||
RUN mkdir -p build/dependency && \
|
||||
(cd build/dependency; java -Djarmode=layertools -jar /workspace/infrastructure/gateway/build/libs/*.jar extract)
|
||||
(cd build/dependency; java -Djarmode=layertools -jar /workspace/backend/gateway/build/libs/*.jar extract)
|
||||
|
||||
# ===================================================================
|
||||
# Runtime Stage
|
||||
@@ -19,7 +19,7 @@ dependencies {
|
||||
// === Core Dependencies ===
|
||||
implementation(projects.core.coreUtils)
|
||||
implementation(projects.platform.platformDependencies)
|
||||
implementation(projects.infrastructure.monitoring.monitoringClient)
|
||||
implementation(projects.backend.infrastructure.monitoring.monitoringClient)
|
||||
|
||||
// === GATEWAY-SPEZIFISCHE ABHÄNGIGKEITEN ===
|
||||
implementation(libs.bundles.spring.cloud.gateway)
|
||||
Some files were not shown because too many files have changed in this diff Show More
Reference in New Issue
Block a user