Erster - Push für Zora

This commit is contained in:
Stefan Mogeritsch 2026-02-11 00:01:05 +01:00
parent e97c3344ed
commit 6e2780cc0f
6 changed files with 211 additions and 0 deletions

View File

@ -0,0 +1,118 @@
name: Build and Publish Docker Images
run-name: Build & Publish by @${{ github.actor }}
on:
push:
branches: [ "main" ]
paths:
- 'backend/**'
- 'platform/**'
- 'core/**'
- 'frontend/**'
- 'config/docker/**'
- 'build.gradle.kts'
- 'settings.gradle.kts'
- 'gradle.properties'
- 'docker-compose.yaml'
- '.gitea/workflows/docker-publish.yaml'
env:
REGISTRY: git.mo-code.at
IMAGE_PREFIX: mo-code/meldestelle
# Build Arguments
GRADLE_VERSION: "8.5"
JAVA_VERSION: "21"
jobs:
build-and-push:
runs-on: ubuntu-latest
strategy:
fail-fast: false
matrix:
include:
- service: api-gateway
context: .
dockerfile: backend/infrastructure/gateway/Dockerfile
image: gateway
- service: ping-service
context: .
dockerfile: backend/services/ping/Dockerfile
image: ping-service
- service: web-app
context: .
dockerfile: config/docker/caddy/web-app/Dockerfile
image: web-app
steps:
- name: Checkout repository
uses: actions/checkout@v3
# Java Setup für den Frontend Build (Gradle braucht Java)
- name: Set up JDK 21
uses: actions/setup-java@v4
with:
java-version: '21'
distribution: 'temurin'
# Cache für Gradle
- name: Setup Gradle Cache
uses: actions/cache@v3
with:
path: |
~/.gradle/caches
~/.gradle/wrapper
key: ${{ runner.os }}-gradle-${{ hashFiles('**/*.gradle*', '**/gradle-wrapper.properties') }}
restore-keys: |
${{ runner.os }}-gradle-
# Frontend Build (nur für web-app)
# Baut die statischen Dateien, die das Dockerfile dann per COPY reinzieht
- name: Build Frontend (Kotlin JS)
if: matrix.service == 'web-app'
run: |
chmod +x gradlew
./gradlew :frontend:shells:meldestelle-portal:jsBrowserDistribution -Pproduction=true --no-daemon
# QEMU für Multi-Arch Support (ARM64 + AMD64)
- name: Set up QEMU
uses: docker/setup-qemu-action@v3
# Docker Buildx für erweiterten Build-Support
- name: Set up Docker Buildx
uses: docker/setup-buildx-action@v3
# Login bei der Gitea Registry
- name: Log in to the Container registry
uses: docker/login-action@v3
with:
registry: ${{ env.REGISTRY }}
username: ${{ secrets.REGISTRY_USER }}
password: ${{ secrets.REGISTRY_TOKEN }}
# Metadaten extrahieren (Tags, Labels)
- name: Extract metadata (tags, labels) for Docker
id: meta
uses: docker/metadata-action@v5
with:
images: ${{ env.REGISTRY }}/${{ env.IMAGE_PREFIX }}-${{ matrix.image }}
tags: |
type=raw,value=latest,enable=${{ github.ref == 'refs/heads/main' }}
type=sha,format=long
# Build und Push
- name: Build and push Docker image
uses: docker/build-push-action@v5
with:
context: ${{ matrix.context }}
file: ${{ matrix.dockerfile }}
push: true
platforms: linux/amd64,linux/arm64
tags: ${{ steps.meta.outputs.tags }}
labels: ${{ steps.meta.outputs.labels }}
build-args: |
DOCKER_BUILD_DATE=$(date -u +'%Y-%m-%dT%H:%M:%SZ')
VERSION=${{ github.sha }}
GRADLE_VERSION=${{ env.GRADLE_VERSION }}
JAVA_VERSION=${{ env.JAVA_VERSION }}
cache-from: type=gha
cache-to: type=gha,mode=max

View File

@ -1,4 +1,5 @@
# syntax=docker/dockerfile:1.8
# ===================================================================
# Dockerfile for Meldestelle Web-App (Hybrid Build)
# Version: 3.2.0 - Optimized & Cleaned

View File

@ -7,6 +7,7 @@ services:
# --- API-GATEWAY: Spring Cloud Gateway ---
api-gateway:
image: "${DOCKER_REGISTRY:-git.mo-code.at/mo-code}/meldestelle-gateway:${DOCKER_TAG:-latest}"
build:
context: .
dockerfile: backend/infrastructure/gateway/Dockerfile
@ -78,6 +79,7 @@ services:
# --- MICROSERVICE: Ping Service ---
ping-service:
image: "${DOCKER_REGISTRY:-git.mo-code.at/mo-code}/meldestelle-ping-service:${DOCKER_TAG:-latest}"
build:
context: .
dockerfile: backend/services/ping/Dockerfile

View File

@ -7,6 +7,7 @@ services:
# --- WEB-APP ---
web-app:
image: "${DOCKER_REGISTRY:-git.mo-code.at/mo-code}/meldestelle-web-app:${DOCKER_TAG:-latest}"
build:
context: . # Wichtig: Root Context für Monorepo Zugriff
dockerfile: config/docker/caddy/web-app/Dockerfile

View File

@ -0,0 +1,44 @@
# SSoT Konfigurations-Masterplan für Zora (ARM64)
## 1. System-Umgebung (Infrastruktur)
| Parameter | Wert | Erklärung |
|:-------------------|:--------------|:-------------------------------------------------|
| **Architektur** | `linux/arm64` | Native Architektur von Zora (Host). |
| **Host-IP (Zora)** | `10.0.6.1` | Gateway für alle Container (Bridge `incusbr0`). |
| **Projekt-IP** | `10.0.6.50` | Feste IP für den Docker-Host `prod-meldestelle`. |
| **DNS-Server** | `10.0.6.1` | Zora übernimmt die Namensauflösung. |
## 2. Mail-Relay (SSoT Identity)
Diese Daten müssen in der Spring Boot `application.yml` oder `.env` abgeglichen werden.
* **SMTP-Host:** `10.0.6.1` (Zora Host Relay)
* **SMTP-Port:** `25` (Passwortloser interner Zugriff via `mynetworks`)
* **Absender:** `zora@mo-code.at` (Verifizierte World4You Identität)
## 3. Docker-Image Checkliste (ARM64 Kompatibilität)
Bitte prüfe in deinen `docker-compose.yaml` Dateien, ob diese Images genutzt werden (alle unterstützen offiziell ARM64):
| Dienst | Empfohlenes Image | Status |
|:---------------|:---------------------------------|:-----------------------------------------------|
| **Datenbank** | `postgres:15-alpine` | ARM64 Support: Ja |
| **Cache** | `valkey/valkey:8-alpine` | ARM64 Support: Ja (Besserer Support als Redis) |
| **Identity** | `quay.io/keycloak/keycloak:24.0` | ARM64 Support: Ja (Offiziell) |
| **Monitoring** | `prom/prometheus:latest` | ARM64 Support: Ja |
| **Dashboards** | `grafana/grafana:latest` | ARM64 Support: Ja |
## 4. Backend & Gateway (Spring Boot)
Da du diese selbst baust, ist die Dockerfile-Konfiguration entscheidend:
* **Base Image:** Nutze `eclipse-temurin:17-jre-alpine` oder `21-jre-alpine`. Diese sind für ARM64 optimiert.
* **Build-Prozess:** Dein Gitea-Runner auf Zora baut automatisch für ARM64, da er auf der gleichen Hardware läuft.
## 5. Keycloak SSoT Integration
Wichtige Endpunkte für deine Microservices in der IDEA:
* **External Issuer:** `https://auth.mo-code.at/realms/mocode-realm`
* **Internal Issuer:** `http://infra-keycloak:8080/realms/mocode-realm` (Für die Kommunikation innerhalb des Docker-Netzwerks)
* **Client-ID:** `meldestelle-client`
## 6. Cloudflare Tunnel Routing
Stelle sicher, dass deine Ingress-Rules auf die IP der Meldestelle zeigen:
* `api.mo-code.at` -> `http://10.0.6.50:8080` (Gateway)
* `auth.mo-code.at` -> `http://10.0.6.50:8180` (Keycloak)
* `git.mo-code.at` -> `http://10.0.6.100:3000` (Gitea LXC - bereits aktiv)

View File

@ -0,0 +1,45 @@
# Dokumentation: Zentrales Mail-Relay (SSoT) auf Zora
## 1. Identität & Rollenverteilung
Das System nutzt das **Single Source of Truth (SSoT)** Prinzip für den gesamten E-Mail-Verkehr. Anstatt dass jeder Dienst (Gitea, Keycloak, Spring Boot) eigene Zugangsdaten für World4You speichert, übernimmt **Zora** die zentrale Verwaltung.
| Parameter | Wert | Funktion |
|:-------------------|:-------------------------|:-------------------------------------------------|
| **Zentraler Host** | `zora.mo-code.at` | Primärer Mail-Transfer-Agent (MTA). |
| **Gateway IP** | `10.0.6.1` | Interne Erreichbarkeit für alle Container/VMs. |
| **Relay Host** | `smtp.world4you.com:587` | Externer Provider für den tatsächlichen Versand. |
| **SSoT Account** | `zora@mo-code.at` | Die verifizierte Absender-Identität. |
---
## 2. Technische Umsetzung (Der "Postbote")
Wir haben Postfix als **Satellitensystem** konfiguriert. Er nimmt Briefe im internen Netzwerk entgegen und bringt sie sicher zum Provider.
* **Sicherheit:** Postfix lauscht auf Port 25, erlaubt den Versand aber **nur** für Anfragen aus dem internen Netz `10.0.0.0/8` (Incus/Docker).
* **Authentifizierung:** Nur Zora kennt das Passwort für den World4You-Account (gespeichert in `sasl_passwd`).
* **Umschreibung (Canonical Mapping):** Postfix korrigiert automatisch Absender wie `root@zora` oder `grandmo@zora` zu `zora@mo-code.at`, damit der Provider die Mails nicht ablehnt.
* **Verschlüsselung:** Die Verbindung zu World4You ist via TLS (STARTTLS) abgesichert.
---
## 3. Vorstellung: Der Benachrichtigungs-Weg
Unsere Vision für den "Empire-Workflow" sieht wie folgt aus:
### Phase A: Das Ereignis (Trigger)
Ein Dienst stellt einen Zustand fest, der gemeldet werden muss.
* **Gitea:** Ein neuer Pull Request wurde erstellt.
* **Prometheus/Alertmanager:** Die Festplatte von Zora ist zu 90% voll.
* **Spring Boot:** Ein User hat sein Passwort für die "Meldestelle" vergessen.
### Phase B: Der interne Transport
Der Dienst verbindet sich ohne Passwort (da er sich im vertrauenswürdigen Netz befindet) mit:
`SMTP_HOST: 10.0.6.1` | `SMTP_PORT: 25`
Dies minimiert das Risiko: Keine Passwörter in `.env`-Dateien von Applikationen.
### Phase C: Die externe Zustellung
Zora nimmt die Mail an, prüft sie, fügt ggf. die korrekte Absenderadresse hinzu und reicht sie an World4You weiter. Von dort landet sie in deinem Gmail-Postfach.
---
## 4. Status Quo (Erfolgskontrolle)
Dass dieser Weg bereits perfekt funktioniert, wurde durch die Gitea Test-Email am **10.02.2026 um 00:56 Uhr** bewiesen. Die Mail kam sauber signiert und verschlüsselt an.