Compare commits
3 Commits
| Author | SHA1 | Date | |
|---|---|---|---|
| c086190097 | |||
| 4c0ff6008d | |||
| 5ab0c9524e |
@@ -3,68 +3,68 @@ type: Reference
|
|||||||
status: ACTIVE
|
status: ACTIVE
|
||||||
owner: Lead Architect
|
owner: Lead Architect
|
||||||
---
|
---
|
||||||
# Frontend Architecture & Modularization Strategy
|
# Frontend-Architektur & Modularisierungsstrategie
|
||||||
|
|
||||||
**Status:** DRAFT
|
**Status:** ENTWURF
|
||||||
**Last Updated:** 2026-01-19
|
**Zuletzt aktualisiert:** 2026-01-19
|
||||||
**Context:** Migration to Clean Architecture & Feature Modules
|
**Kontext:** Migration zu Clean Architecture & Feature-Modulen
|
||||||
|
|
||||||
---
|
---
|
||||||
|
|
||||||
## 1. Overview
|
## 1. Übersicht
|
||||||
The frontend architecture of **Meldestelle** is based on **Kotlin Multiplatform (KMP)** with **Compose Multiplatform** for UI. We follow a strict **Clean Architecture** approach to ensure testability, scalability, and separation of concerns.
|
Die Frontend-Architektur von **Meldestelle** basiert auf **Kotlin Multiplatform (KMP)** mit **Compose Multiplatform** für die Benutzeroberfläche. Wir folgen einem strikten **Clean Architecture**-Ansatz, um Testbarkeit, Skalierbarkeit und Trennung der Zuständigkeiten sicherzustellen.
|
||||||
|
|
||||||
## 2. Module Structure
|
## 2. Modulstruktur
|
||||||
The project is organized into the following layers:
|
Das Projekt ist in folgende Schichten unterteilt:
|
||||||
|
|
||||||
### 2.1 Core Modules (`frontend/core`)
|
### 2.1 Core-Module (`frontend/core`)
|
||||||
Reusable components that are agnostic of specific business features.
|
Wiederverwendbare Komponenten, die unabhängig von spezifischen Geschäftsfunktionen sind.
|
||||||
* `core-network`: Central HTTP Client configuration (Auth, Logging, ContentNegotiation).
|
* `core-network`: Zentrale HTTP-Client-Konfiguration (Auth, Logging, ContentNegotiation).
|
||||||
* `core-sync`: Generic synchronization logic (`SyncManager`, `SyncableRepository`).
|
* `core-sync`: Generische Synchronisierungslogik (`SyncManager`, `SyncableRepository`).
|
||||||
* `core-ui`: Shared UI components and design system.
|
* `core-ui`: Gemeinsame UI-Komponenten und Design-System.
|
||||||
|
|
||||||
### 2.2 Feature Modules (`frontend/features`)
|
### 2.2 Feature-Module (`frontend/features`)
|
||||||
Each business domain (e.g., `ping`, `auth`, `events`) resides in its own module.
|
Jede Geschäftsdomäne (z.B. `ping`, `auth`, `events`) liegt in ihrem eigenen Modul.
|
||||||
A feature module MUST follow the **Clean Architecture** package structure:
|
Ein Feature-Modul MUSS die **Clean Architecture** Paketstruktur einhalten:
|
||||||
|
|
||||||
* `at.mocode.{feature}.feature.domain`
|
* `at.mocode.{feature}.feature.domain`
|
||||||
* **Entities:** Pure data classes.
|
* **Entitäten:** Reine Datenklassen.
|
||||||
* **Interfaces:** Repository interfaces, Service interfaces.
|
* **Interfaces:** Repository-Interfaces, Service-Interfaces.
|
||||||
* **Use Cases:** Business logic (optional, for complex logic).
|
* **Use Cases:** Geschäftslogik (optional, für komplexe Logik).
|
||||||
* `at.mocode.{feature}.feature.data`
|
* `at.mocode.{feature}.feature.data`
|
||||||
* **Implementations:** Repository implementations, API Clients.
|
* **Implementierungen:** Repository-Implementierungen, API-Clients.
|
||||||
* **DTOs:** Data Transfer Objects (if different from domain entities).
|
* **DTOs:** Data Transfer Objects (wenn von Domain-Entitäten abweichend).
|
||||||
* `at.mocode.{feature}.feature.presentation`
|
* `at.mocode.{feature}.feature.presentation`
|
||||||
* **ViewModels:** State management.
|
* **ViewModels:** Zustandsverwaltung.
|
||||||
* **Screens:** Composable functions.
|
* **Screens:** Composable-Funktionen.
|
||||||
* `at.mocode.{feature}.feature.di`
|
* `at.mocode.{feature}.feature.di`
|
||||||
* **Koin Module:** Dependency injection configuration.
|
* **Koin-Modul:** Konfiguration der Dependency Injection.
|
||||||
|
|
||||||
### 2.3 Shells (`frontend/shells`)
|
### 2.3 Shells (`frontend/shells`)
|
||||||
Application entry points that wire everything together.
|
Anwendungs-Einstiegspunkte, die alles zusammenführen.
|
||||||
* `meldestelle-portal`: The main web/desktop application.
|
* `meldestelle-portal`: Die Haupt-Web-/Desktop-Anwendung.
|
||||||
|
|
||||||
## 3. Migration Strategy (Transition Phase)
|
## 3. Migrationsstrategie (Übergangsphase)
|
||||||
We are currently migrating from a monolithic `clients` package structure to modular feature modules.
|
Wir migrieren aktuell von einer monolithischen `clients`-Paketstruktur zu modularen Feature-Modulen.
|
||||||
|
|
||||||
**Rules for Migration:**
|
**Regeln für die Migration:**
|
||||||
1. **New Features:** Must be implemented directly in `frontend/features/{name}` using the Clean Architecture structure.
|
1. **Neue Features:** Müssen direkt in `frontend/features/{name}` unter Verwendung der Clean Architecture-Struktur implementiert werden.
|
||||||
2. **Existing Features:** Will be migrated incrementally.
|
2. **Bestehende Features:** Werden schrittweise migriert.
|
||||||
3. **Coexistence:** During the transition, legacy code in `clients/` is permitted but deprecated.
|
3. **Koexistenz:** Während des Übergangs ist Legacy-Code in `clients/` erlaubt, aber als veraltet markiert.
|
||||||
4. **Dependency Injection:** Legacy code must use the new Koin modules if available.
|
4. **Dependency Injection:** Legacy-Code muss die neuen Koin-Module verwenden, sofern verfügbar.
|
||||||
5. **No Ghost Classes:** Do not duplicate classes. If a class is moved to a feature module, delete the old one in `clients/`.
|
5. **Keine Ghost-Klassen:** Klassen nicht duplizieren. Wenn eine Klasse in ein Feature-Modul verschoben wird, muss die alte in `clients/` gelöscht werden.
|
||||||
|
|
||||||
## 4. Key Decisions (ADRs)
|
## 4. Wichtige Entscheidungen (ADRs)
|
||||||
|
|
||||||
### ADR-001: Sync Logic Decoupling
|
### ADR-001: Entkopplung der Sync-Logik
|
||||||
* **Decision:** ViewModels must not depend directly on `SyncManager`.
|
* **Entscheidung:** ViewModels dürfen nicht direkt vom `SyncManager` abhängen.
|
||||||
* **Reason:** To allow easier testing and to hide the complexity of the generic sync mechanism.
|
* **Begründung:** Um einfacheres Testen zu ermöglichen und die Komplexität des generischen Sync-Mechanismus zu verbergen.
|
||||||
* **Implementation:** Introduce a domain service interface (e.g., `PingSyncService`) that wraps the `SyncManager` call.
|
* **Umsetzung:** Ein Domain-Service-Interface (z.B. `PingSyncService`) einführen, das den `SyncManager`-Aufruf kapselt.
|
||||||
|
|
||||||
### ADR-002: Feature Module Isolation
|
### ADR-002: Feature-Modul-Isolation
|
||||||
* **Decision:** Feature modules should not depend on each other directly if possible.
|
* **Entscheidung:** Feature-Module sollten nach Möglichkeit nicht direkt voneinander abhängen.
|
||||||
* **Communication:** Use shared Core modules or loose coupling via interfaces/events if cross-feature communication is needed.
|
* **Kommunikation:** Gemeinsame Core-Module oder lose Kopplung über Interfaces/Events verwenden, wenn modulübergreifende Kommunikation nötig ist.
|
||||||
|
|
||||||
---
|
---
|
||||||
|
|
||||||
**Approved by:** Lead Architect
|
**Freigegeben von:** Lead Architect
|
||||||
|
|||||||
@@ -2,200 +2,173 @@
|
|||||||
type: Guide
|
type: Guide
|
||||||
status: ACTIVE
|
status: ACTIVE
|
||||||
owner: DevOps Engineer
|
owner: DevOps Engineer
|
||||||
|
source: https://about.gitea.com/resources/tutorials/enable-gitea-actions-cache-to-accelerate-cicd/
|
||||||
|
author: Nanguan Lin
|
||||||
|
date: 2023-10-26
|
||||||
---
|
---
|
||||||
# Enable Gitea Actions Cache to Accelerate CI/CD
|
|
||||||
|
|
||||||
[Gitea](/)
|
# Gitea Actions Cache aktivieren und CI/CD beschleunigen
|
||||||
|
|
||||||
Open main menu
|
> **Quelle:** [Gitea Tutorial](https://about.gitea.com/resources/tutorials/enable-gitea-actions-cache-to-accelerate-cicd/) — übersetzt und für dieses Projekt adaptiert.
|
||||||
|
|
||||||
Products
|
## Einleitung
|
||||||
|
|
||||||
[Gitea Cloud](/products/cloud/)
|
Caching ist ein wesentlicher Bestandteil moderner Softwareentwicklung. In diesem Dokument wird erläutert, wie der Gitea Actions Cache (Giteas integriertes CI/CD-System) aktiviert wird, um Build-Zeiten zu reduzieren.
|
||||||
|
|
||||||
Get a DevOps instance in minutes
|
Gitea Actions nutzt zwei Arten von Caches:
|
||||||
|
|
||||||
[Gitea Enterprise](/products/gitea-enterprise/)
|
1. **Runner Tool Cache** — wird beim Start eines Runners angelegt. Der Runner erstellt ein Volume namens `act-toolcache`, das ins lokale Dateisystem eingehängt wird (standardmäßig `/opt/hostedtoolcache`). Wenn eine Action wie `setup-go` verwendet wird, lädt sie eine Go-Version herunter und speichert sie in diesem Volume — dadurch werden redundante Downloads verhindert.
|
||||||
|
|
||||||
Run an enhanced DevOps instance yourself
|
2. **Action Cache (`actions/cache`)** — feingranularer Cache, der aus GitHub Actions stammt, aber vollständig mit Gitea Actions kompatibel ist. Er verwendet einen Hash-Schlüssel zum Abrufen eines spezifischen Caches. Details zur Konfiguration: [GitHub Offizielle Dokumentation](https://docs.github.com/en/actions/using-workflows/caching-dependencies-to-speed-up-workflows).
|
||||||
|
|
||||||
[Gitea](/products/gitea/)
|
---
|
||||||
|
|
||||||
Run a free DevOps instance yourself
|
## Runner Tool Cache verwenden
|
||||||
|
|
||||||
[Gitea Actions](/products/runner/)
|
Die Einrichtung ist unkompliziert: Die Umgebungsvariable `RUNNER_TOOL_CACHE` im Workflow setzen — der Act Runner erkennt diese automatisch und speichert den Download-Cache dort.
|
||||||
|
|
||||||
Automate your Gitea workflows
|
> **Hinweis:** `/toolcache` ist im Upstream-Projekt `nektos/act` [hardcodiert](https://github.com/nektos/act/blob/4fae81efe4cdd9e09e7ef8e874a2d63b1ed98524/pkg/runner/run_context.go#L137-L139) und kann nicht geändert werden.
|
||||||
|
|
||||||
[Tea](/products/tea/)
|
**Beispiel-Konfiguration:**
|
||||||
|
|
||||||
Command line tool to interact with Gitea Servers
|
```yaml
|
||||||
|
jobs:
|
||||||
|
build:
|
||||||
|
env:
|
||||||
|
RUNNER_TOOL_CACHE: /toolcache
|
||||||
|
# ...
|
||||||
|
```
|
||||||
|
|
||||||
Resources
|
Alternativ kann ein **Docker Volume** explizit gemountet werden:
|
||||||
|
|
||||||
[News](/news)
|
```yaml
|
||||||
|
jobs:
|
||||||
|
build:
|
||||||
|
runs-on: ubuntu-latest
|
||||||
|
container:
|
||||||
|
image: dein_docker_image
|
||||||
|
volumes:
|
||||||
|
- dein_docker_volume:/opt/hostedtoolcache # Standard-Cache-Pfad des Runners
|
||||||
|
```
|
||||||
|
|
||||||
|
Vergleich der Download-Zeiten:
|
||||||
|
|
||||||
|
- Vor dem Cache: 
|
||||||
|
- Nach dem Cache: 
|
||||||
|
|
||||||
What happened around CommitGo and Gitea
|
---
|
||||||
|
|
||||||
|
## Cache Action verwenden
|
||||||
|
|
||||||
[Documentations](https://docs.gitea.com)
|
Der Runner verwendet einen Cache-Server zum Speichern von Schlüssel/Wert-Paaren. Dieser ist standardmäßig aktiviert — `actions/cache` kann direkt genutzt werden.
|
||||||
|
|
||||||
Documentation for Gitea and related tools
|
**Beispiel-Konfiguration:**
|
||||||
|
|
||||||
[Tutorials](/resources/tutorials/)
|
```yaml
|
||||||
|
name: Caching mit Go
|
||||||
|
on: push
|
||||||
|
jobs:
|
||||||
|
Cache-Go:
|
||||||
|
name: Cache Go
|
||||||
|
runs-on: ubuntu-latest
|
||||||
|
steps:
|
||||||
|
- uses: actions/checkout@v3
|
||||||
|
- uses: actions/setup-go@v3
|
||||||
|
with:
|
||||||
|
go-version: '>=1.20.1'
|
||||||
|
- uses: https://gitea.com/actions/go-hashfiles@v0.0.1
|
||||||
|
id: hash-go
|
||||||
|
with:
|
||||||
|
patterns: |
|
||||||
|
go.mod
|
||||||
|
go.sum
|
||||||
|
- name: Go Cache
|
||||||
|
id: cache-go
|
||||||
|
uses: actions/cache@v3
|
||||||
|
with:
|
||||||
|
path: |
|
||||||
|
/dein_cache_pfad
|
||||||
|
key: go_path-${{ steps.hash-go.outputs.hash }}
|
||||||
|
restore-keys: |-
|
||||||
|
go_cache-${{ steps.hash-go.outputs.hash }}
|
||||||
|
```
|
||||||
|
|
||||||
Tutorals and advice on using Gitea
|
Hier wird `go-hashfiles` verwendet, um einen Hash aus `go.mod` und `go.sum` zu erzeugen. Der Cache-Pfad und Schlüssel sind je nach Programmiersprache anzupassen.
|
||||||
|
|
||||||
[Blog](/blog)
|
> **Wichtige Hinweise:**
|
||||||
|
>
|
||||||
|
> 1. Bei Verwendung des Runners mit Docker kann es zu Netzwerkproblemen mit dem Cache-Server kommen. In diesem Fall muss `host` und `port` des Cache-Servers in der `config.yaml` des Act Runners angepasst werden. Details: [Gitea Dokumentation](https://docs.gitea.com/usage/actions/act-runner#configuring-cache-when-starting-a-runner-using-docker-image)
|
||||||
|
> 2. Die eingebaute Funktion `hashFiles` im Workflow-YAML wird in Gitea Actions aktuell **nicht** unterstützt. Als Alternative: [`go-hashfiles`](https://gitea.com/actions/go-hashfiles) (gepflegt von den Gitea-Maintainern).
|
||||||
|
|
||||||
Release notes and updates about Gitea Products
|
---
|
||||||
|
|
||||||
Community
|
## Vollständiges Beispiel
|
||||||
|
|
||||||
[Forum](https://forum.gitea.com)
|
Annahme: Es wird eine App namens `Hello-Gitea` mit Go gebaut, mit aktiviertem Gitea Actions Workflow für jeden Push.
|
||||||
|
|
||||||
Find or help out with community support
|
Workflow-Datei (auch verfügbar [auf Gitea](https://gitea.com/lng2020/cache_example/src/branch/main/.gitea/workflows/cache.yaml)):
|
||||||
|
|
||||||
[Chatroom](https://discord.gg/gitea)
|
```yaml
|
||||||
|
name: Test Cache
|
||||||
Chat with the community
|
on:
|
||||||
|
push
|
||||||
[Open Source](https://github.com/go-gitea/gitea)
|
jobs:
|
||||||
|
TestCache:
|
||||||
View Gitea code and contribute development
|
env:
|
||||||
|
RUNNER_TOOL_CACHE: /toolcache # Runner Tool Cache
|
||||||
[Community Blog](https://blog.gitea.com)
|
name: Cache Go
|
||||||
|
runs-on: ubuntu-latest
|
||||||
Release notes and updates about Gitea
|
steps:
|
||||||
|
- uses: actions/checkout@v3
|
||||||
[Translation](https://translate.gitea.com)
|
|
||||||
|
- uses: actions/setup-go@v3
|
||||||
Help translate Gitea
|
with:
|
||||||
|
go-version: '>=1.20.1'
|
||||||
[Supporters](/community/supporters/)
|
|
||||||
|
- name: go-hashfiles laden
|
||||||
View supporters of Gitea
|
uses: https://gitea.com/actions/go-hashfiles@v0.0.1
|
||||||
|
id: hash-go
|
||||||
[Pricing](/pricing)[Cloud](https://cloud.gitea.com)
|
with:
|
||||||
|
patterns: |-
|
||||||
[Sign In](https://gitea.com/user/login) [Contact Us](/contact/contact)
|
go.mod
|
||||||
|
go.sum
|
||||||

|
|
||||||
|
- name: Hash ausgeben
|
||||||
# Enable Gitea Actions Cache to Accelerate CI/CD
|
run: echo ${{ steps.hash-go.outputs.hash }}
|
||||||
|
|
||||||

|
- name: Go Cache
|
||||||
|
id: cache-go
|
||||||
[Nanguan Lin](https://github.com/lng2020)
|
uses: https://github.com/actions/cache@v3 # Action Cache
|
||||||
|
with:
|
||||||
2023-10-26
|
path: |-
|
||||||
|
/root/go/pkg/mod
|
||||||
4 min read
|
/root/.cache/go-build
|
||||||
|
key: go_cache-${{ steps.hash-go.outputs.hash }}
|
||||||
[CI/CD](/resources/tutorials?category=cicd)
|
restore-keys: |-
|
||||||
|
go_cache-${{ steps.hash-go.outputs.hash }}
|
||||||
## Introduction
|
|
||||||
|
- name: Build
|
||||||
Caching is a vital aspect of modern computer science. Today, we will discuss enabling Gitea Actions(Gitea's built-in CI/CD) cache to speed up CI/CD.
|
run: go build -v .
|
||||||
|
|
||||||
Gitea Actions utilizes two types of caches. The first is the Runner Tool Cache, created when launching a runner. This runner creates a volume named `act-toolcache`, which is mounted to the local file system(usually `/opt/hostedtoolcache`). When an action like `setup-go` is used, it downloads and installs a version of Go, storing it in this special volume, thus preventing redundant downloads of dependencies.
|
- name: Test
|
||||||
|
run: go test -v ./...
|
||||||
The second type is more fine-grained. Originating from Github Actions but compatible with Gitea Actions, it's called `action/cache`. This action uses a hash key to retrieve the specific cache. For more specific information and detailed configuration about this action, refer to this [Github Offical Doc](https://docs.github.com/en/actions/using-workflows/caching-dependencies-to-speed-up-workflows). In this tutorial, we will enable both types of caches to accelerate CI/CD.
|
```
|
||||||
|
|
||||||
## Use Runner Tool Cache
|
Nach der Einrichtung sind beide Cache-Typen aktiv:
|
||||||
|
|
||||||
The process is straightforward. Just add an `env` variable called `RUNNER_TOOL_CACHE` in your Gitea action workflow, and the Gitea act runner will automatically detect this environment and store the download cache there.
|
- Tool Cache: 
|
||||||
|
- Action Cache: 
|
||||||
**Notice**: For now, `/toolcache` is [hardcoded](https://github.com/nektos/act/blob/4fae81efe4cdd9e09e7ef8e874a2d63b1ed98524/pkg/runner/run_context.go#L137-L139) in the upstream project `nektos/act`. So it cannot be changed.
|
|
||||||
|
---
|
||||||
An example configuration:
|
|
||||||
|
## Häufige Fragen (FAQ)
|
||||||
`jobs: build: env: RUNNER_TOOL_CACHE: /toolcache ...`
|
|
||||||
|
**F: Warum muss `RUNNER_TOOL_CACHE: /toolcache` explizit gesetzt werden? Sollte das nicht standardmäßig funktionieren?**
|
||||||
Alternatively, you can use `Docker Volume` to specifically mount the cache volume:
|
|
||||||
|
A: Das ist ein Upstream-Problem von `nektos/act`. Details: [Issue #70](https://gitea.com/gitea/act_runner/issues/70).
|
||||||
`jobs: build: runs-on: ubuntu-latest container: image: your_docker_image volumes: - your_docker_volumn:/opt/hostedtoolcache # this is where Runner store their cache default`
|
|
||||||
|
---
|
||||||
download time before: 
|
|
||||||
|
**F: Können mehrere Act Runner auf demselben Host den Runner Tool Cache teilen?**
|
||||||
download time after: 
|
|
||||||
|
A: Ja. Dazu ein Docker Volume verwenden und das Cache-Verzeichnis einmappen.
|
||||||
## Use Cache Action
|
|
||||||
|
|
||||||
The Runner uses a cache server to store the key/value pair cache. The cache server is enabled by default. So You can directly use the `action/cache`.
|
|
||||||
|
|
||||||
An example configuration:
|
|
||||||
|
|
||||||
`name: Caching with Go on: push jobs: Cache-Go: name: Cache Go runs-on: ubuntu-latest steps: - uses: actions/checkout@v3 - uses: actions/setup-go@v3 with: go-version: '>=1.20.1' - uses: https://gitea.com/actions/go-hashfiles@v0.0.1 id: hash-go with: patterns: | go.mod go.sum - name: cache go id: cache-go uses: actions/cache@v3 with: # Specify with your cache path path: | /your_cache_path key: go_path-${{ steps.hash-go.outputs.hash }} restore-keys: |- go_cache-${{ steps.hash-go.outputs.hash }}`
|
|
||||||
|
|
||||||
This example utilizes a go cache and `go-hashfiles` to generate a hash. You should specify your cache path according to your programming language and define the key in any form you like.
|
|
||||||
|
|
||||||
**Notice**
|
|
||||||
|
|
||||||
1. If you are running the Runner with docker. You may encounter network issue with the cache server. You should change the cache server host and port in `config.yaml` for your Act Runner. The configuration is explained [here](https://docs.gitea.com/usage/actions/act-runner#configuring-cache-when-starting-a-runner-using-docker-image) in detail.
|
|
||||||
2. The built-in function `hashFiles` in the workflow yaml is not supported in Gitea Actions right now. You can use [`go-hashfiles`](https://gitea.com/actions/go-hashfiles)(maintained by Gitea maintainers) or other alternatives instead.
|
|
||||||
|
|
||||||
## A Complete Example
|
|
||||||
|
|
||||||
Let's use an example to demonstrate how to utilize these two types of caches in a real development environment.
|
|
||||||
|
|
||||||
Assume we're going to build an app called `Hello-Gitea` using Go, and we enable the Gitea Actions workflow for every Push.
|
|
||||||
|
|
||||||
Here is the workflow yaml(this file is also available [on Gitea website](https://gitea.com/lng2020/cache_example/src/branch/main/.gitea/workflows/cache.yaml))
|
|
||||||
|
|
||||||
`name: Test Cache on: push jobs: TestCache: env: RUNNER_TOOL_CACHE: /toolcache # Runner Tool Cache name: Cache Go runs-on: ubuntu-latest steps: - uses: actions/checkout@v3 - uses: actions/setup-go@v3 with: go-version: '>=1.20.1' - name: Get go-hashfiles uses: https://gitea.com/actions/go-hashfiles@v0.0.1 id: hash-go with: patterns: |- go.mod go.sum - name: Echo hash run: echo ${{ steps.hash-go.outputs.hash }} - name: Cache go id: cache-go uses: https://github.com/actions/cache@v3 # Action cache with: # specify with your GOMODCACHE and GOCACHE path: |- /root/go/pkg/mod /root/.cache/go-build key: go_cache-${{ steps.hash-go.outputs.hash }} restore-keys: |- go_cache-${{ steps.hash-go.outputs.hash }} - name: Build run: go build -v . - name: Test run: go test -v ./...`
|
|
||||||
|
|
||||||
After setting everything up, we can see how these caches are utilized.
|
|
||||||
|
|
||||||

|
|
||||||
|
|
||||||

|
|
||||||
|
|
||||||
## FAQ
|
|
||||||
|
|
||||||
Q: Why should I specify `RUNNER_TOOL_CACHE: /toolcache` to make the Runner Tool Cache work? It seems like it should cache the file by default
|
|
||||||
|
|
||||||
A: It's an upstream issue of `nektos/act`. See the [issue](https://gitea.com/gitea/act_runner/issues/70) for more details.
|
|
||||||
|
|
||||||
Q: Can different act runners on the same host share the Runner Tool Cache?
|
|
||||||
|
|
||||||
A: Yes, they can. To do so, use a Docker volume to map the cache directory.
|
|
||||||
|
|
||||||
## Footer
|
|
||||||
|
|
||||||

|
|
||||||
|
|
||||||
Private, Fast, Reliable DevOps Platform
|
|
||||||
|
|
||||||
[LinkedIn](https://linkedin.com/company/commitgo)[X](https://twitter.com/giteaio)[GitHub](https://github.com/go-gitea/gitea)[Gitea](https://gitea.com/gitea)
|
|
||||||
|
|
||||||
© 2026 CommitGo, Inc. All rights reserved.
|
|
||||||
|
|
||||||
### Products
|
|
||||||
|
|
||||||
* [Gitea Cloud](/products/cloud)
|
|
||||||
* [Gitea Enterprise](/products/gitea-enterprise)
|
|
||||||
* [Gitea](/products/gitea)
|
|
||||||
* [Gitea Runner](/products/runner)
|
|
||||||
* [Tea Command-line Tool](/products/tea)
|
|
||||||
|
|
||||||
### Support
|
|
||||||
|
|
||||||
* [Pricing](/pricing/)
|
|
||||||
* [Documentation](https://docs.gitea.com)
|
|
||||||
* [Tutorials](/resources/tutorials/)
|
|
||||||
* [API](https://docs.gitea.com/api/1.21/)
|
|
||||||
* [Blog](https://blog.gitea.com)
|
|
||||||
* [Forum](https://forum.gitea.com)
|
|
||||||
* [Chatroom](https://discord.gg/gitea)
|
|
||||||
|
|
||||||
### About Us
|
|
||||||
|
|
||||||
* [What is DevOps](/about/devops)
|
|
||||||
* [Why Gitea](/about/whygitea)
|
|
||||||
* [Contact Us](/contact/contact)
|
|
||||||
* [Compliance](/about/compliance)
|
|
||||||
|
|
||||||
### Legal
|
|
||||||
|
|
||||||
* [Privacy](/privacy-policy/)
|
|
||||||
* [Terms](/terms-of-service/)
|
|
||||||
|
|||||||
@@ -73,7 +73,7 @@ Wir validieren die gesamte Architektur-Kette (Frontend -> Gateway -> Service ->
|
|||||||
4. **Infrastructure Setup (Home-Server):**
|
4. **Infrastructure Setup (Home-Server):**
|
||||||
* Hardware: Minisforum MS-R1 (ARM64, 12 Cores, 10G LAN) ✅ **GELIEFERT (07.02.2026)**.
|
* Hardware: Minisforum MS-R1 (ARM64, 12 Cores, 10G LAN) ✅ **GELIEFERT (07.02.2026)**.
|
||||||
* OS: Debian 12 (Vendor Variant) als Host.
|
* OS: Debian 12 (Vendor Variant) als Host.
|
||||||
* Hypervisor: **Incus** (LXC/LXD Fork).
|
* Hypervisor: **Proxmox VE 8.4.10** (`pve.mo-code.at`).
|
||||||
* Virtualization Strategy:
|
* Virtualization Strategy:
|
||||||
* `infra-gitea` (LXC Container): Gitea + Actions Runner (Native ARM Builds).
|
* `infra-gitea` (LXC Container): Gitea + Actions Runner (Native ARM Builds).
|
||||||
* `docker-host-prod` (VM): Debian VM als Docker Host für den Meldestelle-Stack (Isolation, keine Nesting-Probleme).
|
* `docker-host-prod` (VM): Debian VM als Docker Host für den Meldestelle-Stack (Isolation, keine Nesting-Probleme).
|
||||||
|
|||||||
@@ -0,0 +1,431 @@
|
|||||||
|
---
|
||||||
|
type: Guide
|
||||||
|
status: ACTIVE
|
||||||
|
owner: DevOps Engineer
|
||||||
|
---
|
||||||
|
# Installations-Anleitung: Lokaler AI-Stack auf Zora (MS-R1)
|
||||||
|
|
||||||
|
> **Ziel:** Ollama + Open WebUI als isolierter Proxmox LXC-Container auf Zora.
|
||||||
|
> Vollständig lokal, datenschutzkonform, erreichbar via Pangolin-Tunnel.
|
||||||
|
> **Datum:** 2026-03-06 | **Aktualisiert:** 2026-03-06 (Incus → Proxmox)
|
||||||
|
|
||||||
|
---
|
||||||
|
|
||||||
|
## Hardware-Profil: CIX P1 (CP8180) — Was steckt drin?
|
||||||
|
|
||||||
|
| Komponente | Detail | Bedeutung für KI |
|
||||||
|
|---|---|---|
|
||||||
|
| **CPU** | 12 Cores: 4x Cortex-X4 (fast, ~2.6GHz) + 4x A720 (medium) + 4x A520 (slow) | Tri-Cluster → großzügige Kern-Zuweisung sinnvoll |
|
||||||
|
| **GPU** | Arm Immortalis-G720 MC10 | Vulkan 1.3 — experimentelle GPU-Beschleunigung möglich |
|
||||||
|
| **RAM** | 64 GB LPDDR5 5500MHz | Auch 70B-Modelle laufen vollständig im RAM! |
|
||||||
|
| **NPU** | CIX P1 integrierte NPU | ⚠️ Aktuell kein Ollama/llama.cpp-Support — Zukunft |
|
||||||
|
| **OS** | Proxmox VE 8.4.10 | Hypervisor auf Debian-Basis, ARM64-native |
|
||||||
|
|
||||||
|
### CPU-Kerne im Detail
|
||||||
|
|
||||||
|
```
|
||||||
|
Cores 0– 3 → Cortex-A520 (Efficiency / langsam)
|
||||||
|
Cores 4– 7 → Cortex-A720 (Balanced / mittel)
|
||||||
|
Cores 8–11 → Cortex-X4 (Performance / schnell)
|
||||||
|
```
|
||||||
|
|
||||||
|
Der AI-Container bekommt 10 Kerne (2–11), Proxmox behält Kern 0–1 für Host-Betrieb.
|
||||||
|
CPU-Governor auf `performance` für die X4-Kerne maximiert den Inferenz-Durchsatz.
|
||||||
|
|
||||||
|
---
|
||||||
|
|
||||||
|
## Architektur-Entscheidung: Warum separater Proxmox LXC-Container?
|
||||||
|
|
||||||
|
```
|
||||||
|
Zora — Proxmox 8.4.10 (10.0.0.20)
|
||||||
|
├── VM 102 gitea-runner (10.0.0.23) ← Gitea CI/CD Runner
|
||||||
|
├── VM 110 meldestelle-host (10.0.0.50) ← Docker App-Stack
|
||||||
|
├── LXC 100 pangolin-client ← Pangolin Tunnel
|
||||||
|
├── LXC 101 gitea (10.0.0.22) ← Gitea Server
|
||||||
|
├── LXC 103 immich ← Immich
|
||||||
|
└── LXC 111 ai-stack (10.0.0.60) ← Ollama + Open WebUI ← NEU
|
||||||
|
```
|
||||||
|
|
||||||
|
**Begründung:** Modelle (5–40 GB pro Modell) wachsen unkontrolliert.
|
||||||
|
Isolierter LXC-Container schützt den App-Stack vor RAM/CPU-Hunger der KI.
|
||||||
|
Unabhängige Updates — Ollama-Modelle liegen im Container-Volume, nicht im Git-Repo.
|
||||||
|
|
||||||
|
---
|
||||||
|
|
||||||
|
## Phase 1 — Proxmox Host vorbereiten
|
||||||
|
|
||||||
|
### 1.1 — CPU Governor auf Performance setzen (auf Proxmox-Node)
|
||||||
|
|
||||||
|
```bash
|
||||||
|
# SSH auf den Proxmox-Node
|
||||||
|
ssh root@10.0.0.20
|
||||||
|
# oder: ssh root@pve.mo-code.at
|
||||||
|
|
||||||
|
# cpufrequtils installieren
|
||||||
|
apt-get install -y cpufrequtils
|
||||||
|
|
||||||
|
# Alle 12 Kerne auf Performance
|
||||||
|
for i in $(seq 0 11); do
|
||||||
|
cpufreq-set -c $i -g performance
|
||||||
|
done
|
||||||
|
|
||||||
|
# Prüfen
|
||||||
|
cat /sys/devices/system/cpu/cpu*/cpufreq/scaling_governor
|
||||||
|
# Erwartete Ausgabe: 12x "performance"
|
||||||
|
|
||||||
|
# Persistent machen
|
||||||
|
tee /etc/systemd/system/cpu-performance.service > /dev/null <<'EOF'
|
||||||
|
[Unit]
|
||||||
|
Description=Set CPU Governor to Performance
|
||||||
|
After=multi-user.target
|
||||||
|
|
||||||
|
[Service]
|
||||||
|
Type=oneshot
|
||||||
|
ExecStart=/bin/bash -c 'for i in $(seq 0 11); do cpufreq-set -c $i -g performance; done'
|
||||||
|
RemainAfterExit=yes
|
||||||
|
|
||||||
|
[Install]
|
||||||
|
WantedBy=multi-user.target
|
||||||
|
EOF
|
||||||
|
|
||||||
|
systemctl daemon-reload
|
||||||
|
systemctl enable --now cpu-performance.service
|
||||||
|
```
|
||||||
|
|
||||||
|
### 1.2 — Huge Pages aktivieren (bessere RAM-Nutzung für große Modelle)
|
||||||
|
|
||||||
|
```bash
|
||||||
|
# Auf dem Proxmox-Node:
|
||||||
|
echo "vm.nr_hugepages = 512" >> /etc/sysctl.conf
|
||||||
|
sysctl -p
|
||||||
|
```
|
||||||
|
|
||||||
|
---
|
||||||
|
|
||||||
|
## Phase 2 — Proxmox LXC-Container erstellen
|
||||||
|
|
||||||
|
> ℹ️ **Alle Befehle laufen auf dem Proxmox-Node** (`ssh root@10.0.0.20`)
|
||||||
|
> Alternativ: Proxmox Web-UI unter `https://pve.mo-code.at:8006`
|
||||||
|
|
||||||
|
### 2.1 — Debian 12 Template herunterladen
|
||||||
|
|
||||||
|
```bash
|
||||||
|
# Template-Liste aktualisieren
|
||||||
|
pveam update
|
||||||
|
|
||||||
|
# Debian 12 ARM64 Template suchen und herunterladen
|
||||||
|
pveam available --section system | grep debian-12.*arm64
|
||||||
|
pveam download local debian-12-standard_12.7-1_arm64.tar.zst
|
||||||
|
```
|
||||||
|
|
||||||
|
### 2.2 — Container erstellen (CT 111)
|
||||||
|
|
||||||
|
```bash
|
||||||
|
pct create 111 local:vztmpl/debian-12-standard_12.7-1_arm64.tar.zst \
|
||||||
|
--hostname ai-stack \
|
||||||
|
--arch aarch64 \
|
||||||
|
--cores 10 \
|
||||||
|
--memory 49152 \
|
||||||
|
--swap 4096 \
|
||||||
|
--rootfs local-lvm:200 \
|
||||||
|
--net0 name=eth0,bridge=vmbr0,ip=10.0.0.60/24,gw=10.0.0.138,firewall=1 \
|
||||||
|
--nameserver 10.0.0.138 \
|
||||||
|
--searchdomain mo-code.at \
|
||||||
|
--unprivileged 1 \
|
||||||
|
--features nesting=1 \
|
||||||
|
--password
|
||||||
|
|
||||||
|
# Container starten
|
||||||
|
pct start 111
|
||||||
|
|
||||||
|
# Status prüfen
|
||||||
|
pct status 111
|
||||||
|
pct list
|
||||||
|
```
|
||||||
|
|
||||||
|
### 2.3 — CPU-Pinning konfigurieren (Performance-Kerne für KI)
|
||||||
|
|
||||||
|
```bash
|
||||||
|
# Kerne 2–11 dem Container zuweisen (Kerne 8–11 = X4 Performance-Kerne!)
|
||||||
|
# In der Container-Config:
|
||||||
|
echo "cpulimit: 10" >> /etc/pve/lxc/111.conf
|
||||||
|
echo "cpuunits: 1024" >> /etc/pve/lxc/111.conf
|
||||||
|
|
||||||
|
# Alternativ via Web-UI:
|
||||||
|
# CT 111 → Options → CPU Limit: 10 Cores
|
||||||
|
```
|
||||||
|
|
||||||
|
### 2.4 — In Container einloggen und Basis-Setup
|
||||||
|
|
||||||
|
```bash
|
||||||
|
# Direkt per pct:
|
||||||
|
pct enter 111
|
||||||
|
|
||||||
|
# Im Container:
|
||||||
|
apt-get update && apt-get upgrade -y
|
||||||
|
apt-get install -y curl wget git htop nano ca-certificates gnupg lsb-release
|
||||||
|
|
||||||
|
# Docker installieren (für Open WebUI)
|
||||||
|
curl -fsSL https://get.docker.com | sh
|
||||||
|
systemctl enable --now docker
|
||||||
|
|
||||||
|
# Benutzer anlegen
|
||||||
|
useradd -m -s /bin/bash aiuser
|
||||||
|
usermod -aG docker aiuser
|
||||||
|
```
|
||||||
|
|
||||||
|
---
|
||||||
|
|
||||||
|
## Phase 3 — Ollama installieren & optimieren
|
||||||
|
|
||||||
|
### 3.1 — Ollama installieren
|
||||||
|
|
||||||
|
```bash
|
||||||
|
# Im Container (pct enter 111):
|
||||||
|
curl -fsSL https://ollama.com/install.sh | sh
|
||||||
|
|
||||||
|
# ARM64 wird automatisch erkannt
|
||||||
|
ollama --version
|
||||||
|
```
|
||||||
|
|
||||||
|
### 3.2 — Ollama-Service konfigurieren (Performance-Tuning)
|
||||||
|
|
||||||
|
```bash
|
||||||
|
mkdir -p /etc/systemd/system/ollama.service.d/
|
||||||
|
cat > /etc/systemd/system/ollama.service.d/override.conf << 'EOF'
|
||||||
|
[Service]
|
||||||
|
# Auf allen Interfaces lauschen (nicht nur localhost)
|
||||||
|
Environment="OLLAMA_HOST=0.0.0.0:11434"
|
||||||
|
|
||||||
|
# Alle zugewiesenen CPU-Kerne nutzen
|
||||||
|
Environment="OLLAMA_NUM_THREADS=10"
|
||||||
|
|
||||||
|
# Modelle 24h im RAM halten (kein ständiges Laden)
|
||||||
|
Environment="OLLAMA_KEEP_ALIVE=24h"
|
||||||
|
|
||||||
|
# Bis zu 2 Modelle gleichzeitig geladen halten
|
||||||
|
Environment="OLLAMA_MAX_LOADED_MODELS=2"
|
||||||
|
|
||||||
|
# Flash Attention aktivieren (schnellere Verarbeitung langer Kontexte)
|
||||||
|
Environment="OLLAMA_FLASH_ATTENTION=1"
|
||||||
|
|
||||||
|
# Kontext-Größe erhöhen für längere Gespräche
|
||||||
|
Environment="OLLAMA_MAX_CONTEXT_LENGTH=8192"
|
||||||
|
EOF
|
||||||
|
|
||||||
|
systemctl daemon-reload
|
||||||
|
systemctl restart ollama
|
||||||
|
systemctl status ollama
|
||||||
|
```
|
||||||
|
|
||||||
|
### 3.3 — Vulkan GPU-Beschleunigung (Immortalis-G720)
|
||||||
|
|
||||||
|
> ⚠️ **Experimentell** — CIX P1 + Immortalis-G720 Vulkan-Treiber sind noch nicht
|
||||||
|
> vollständig im Mainline-Kernel. Zuerst ohne Vulkan starten, später nachrüsten.
|
||||||
|
|
||||||
|
```bash
|
||||||
|
# Prüfen ob Vulkan-Device sichtbar ist
|
||||||
|
apt-get install -y vulkan-tools
|
||||||
|
vulkaninfo --summary 2>/dev/null | grep -i "GPU\|device\|driver"
|
||||||
|
|
||||||
|
# Falls Vulkan verfügbar — in override.conf ergänzen:
|
||||||
|
# Environment="OLLAMA_GPU_LAYERS=999"
|
||||||
|
# → Dann ollama neu starten und testen
|
||||||
|
```
|
||||||
|
|
||||||
|
---
|
||||||
|
|
||||||
|
## Phase 4 — Modelle herunterladen
|
||||||
|
|
||||||
|
### Empfohlene Modelle für 64 GB ARM64
|
||||||
|
|
||||||
|
```bash
|
||||||
|
# Im Container:
|
||||||
|
ollama pull llama3.1:8b # 5 GB — schnell, Allrounder, Deutsch OK
|
||||||
|
ollama pull qwen2.5-coder:14b # 9 GB — Beste Code-Qualität für IDEA!
|
||||||
|
ollama pull nomic-embed-text # 300MB — Pflicht für RAG/Embeddings
|
||||||
|
|
||||||
|
# Optional (wenn du mehr Power willst):
|
||||||
|
ollama pull llama3.1:70b # 40 GB — Maximale Qualität, läuft in 64GB RAM!
|
||||||
|
ollama pull qwen2.5:32b # 20 GB — Gute Balance Qualität/Speed
|
||||||
|
|
||||||
|
# Testen:
|
||||||
|
ollama run llama3.1:8b "Erkläre mir Spring Boot in einem Satz auf Deutsch"
|
||||||
|
```
|
||||||
|
|
||||||
|
### Modell-Entscheidungshilfe
|
||||||
|
|
||||||
|
| Modell | RAM | Speed | Qualität | Empfehlung |
|
||||||
|
|---|---|---|---|---|
|
||||||
|
| `llama3.1:8b` | 5 GB | ⚡⚡⚡ | ★★★ | Täglicher Chat, schnelle Antworten |
|
||||||
|
| `qwen2.5-coder:14b` | 9 GB | ⚡⚡ | ★★★★ | **IDEA-Integration, Kotlin/Java Code** |
|
||||||
|
| `qwen2.5:32b` | 20 GB | ⚡ | ★★★★★ | Tiefe Analysen, Architektur-Fragen |
|
||||||
|
| `llama3.1:70b` | 40 GB | 🐢 | ★★★★★ | Maximale Qualität, geduldige Anfragen |
|
||||||
|
| `nomic-embed-text` | 300 MB | ⚡⚡⚡ | RAG | **Pflicht für Docs-RAG** |
|
||||||
|
|
||||||
|
---
|
||||||
|
|
||||||
|
## Phase 5 — Open WebUI installieren
|
||||||
|
|
||||||
|
```bash
|
||||||
|
# Im Container (pct enter 111):
|
||||||
|
docker run -d \
|
||||||
|
--name open-webui \
|
||||||
|
--restart always \
|
||||||
|
-p 3001:8080 \
|
||||||
|
-v open-webui:/app/backend/data \
|
||||||
|
-e OLLAMA_BASE_URL=http://host.docker.internal:11434 \
|
||||||
|
--add-host=host.docker.internal:10.0.0.60 \
|
||||||
|
ghcr.io/open-webui/open-webui:main
|
||||||
|
|
||||||
|
# Prüfen:
|
||||||
|
docker ps
|
||||||
|
curl http://localhost:3001
|
||||||
|
```
|
||||||
|
|
||||||
|
### 5.1 — Open WebUI RAG-Konfiguration
|
||||||
|
|
||||||
|
```
|
||||||
|
Browser: http://10.0.0.60:3001
|
||||||
|
|
||||||
|
1. Admin-Account anlegen (erster Login)
|
||||||
|
2. Settings → Admin Panel → Connections
|
||||||
|
→ Ollama URL: http://10.0.0.60:11434 ✓
|
||||||
|
|
||||||
|
3. Settings → Admin Panel → Documents
|
||||||
|
→ Embedding Model: nomic-embed-text
|
||||||
|
→ Chunk Size: 1500
|
||||||
|
→ Chunk Overlap: 150
|
||||||
|
|
||||||
|
4. Workspace → Documents → Upload
|
||||||
|
→ Deine /docs/**/*.md Dateien hochladen
|
||||||
|
→ Besonders: 04_Agents/Playbooks/, 01_Architecture/adr/
|
||||||
|
```
|
||||||
|
|
||||||
|
---
|
||||||
|
|
||||||
|
## Phase 6 — Pangolin-Route konfigurieren
|
||||||
|
|
||||||
|
| Route | Ziel | Port | Sichtbarkeit |
|
||||||
|
|---|---|---|---|
|
||||||
|
| `ai.mo-code.at` | `10.0.0.60` | `3001` | Nur intern / VPN! |
|
||||||
|
|
||||||
|
> 🔒 **Sicherheit:** Open WebUI NIEMALS ohne Auth öffentlich exponieren.
|
||||||
|
> Pangolin-Zugang nur via VPN oder mit Basic-Auth absichern.
|
||||||
|
|
||||||
|
---
|
||||||
|
|
||||||
|
## Phase 7 — IntelliJ IDEA Integration
|
||||||
|
|
||||||
|
### Option A: Continue.dev Plugin (empfohlen für Code-Completion)
|
||||||
|
|
||||||
|
```
|
||||||
|
1. IDEA → Settings → Plugins → "Continue" installieren
|
||||||
|
2. Continue-Konfiguration öffnen (~/.continue/config.json):
|
||||||
|
```
|
||||||
|
|
||||||
|
```json
|
||||||
|
{
|
||||||
|
"models": [
|
||||||
|
{
|
||||||
|
"title": "Zora-Coder (qwen2.5)",
|
||||||
|
"provider": "ollama",
|
||||||
|
"model": "qwen2.5-coder:14b",
|
||||||
|
"apiBase": "http://10.0.0.60:11434"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"title": "Zora-Chat (llama3.1)",
|
||||||
|
"provider": "ollama",
|
||||||
|
"model": "llama3.1:8b",
|
||||||
|
"apiBase": "http://10.0.0.60:11434"
|
||||||
|
}
|
||||||
|
],
|
||||||
|
"tabAutocompleteModel": {
|
||||||
|
"title": "Zora-Autocomplete",
|
||||||
|
"provider": "ollama",
|
||||||
|
"model": "qwen2.5-coder:14b",
|
||||||
|
"apiBase": "http://10.0.0.60:11434"
|
||||||
|
},
|
||||||
|
"embeddingsProvider": {
|
||||||
|
"provider": "ollama",
|
||||||
|
"model": "nomic-embed-text",
|
||||||
|
"apiBase": "http://10.0.0.60:11434"
|
||||||
|
}
|
||||||
|
}
|
||||||
|
```
|
||||||
|
|
||||||
|
```
|
||||||
|
3. In IDEA:
|
||||||
|
- Ctrl+I → Chat öffnen (Inline-Fragen im Code)
|
||||||
|
- Ctrl+Shift+I → Tab Autocomplete aktivieren
|
||||||
|
- Alle Daten bleiben auf Zora — kein Cloud-Kontakt!
|
||||||
|
```
|
||||||
|
|
||||||
|
### Option B: JetBrains AI Assistant mit lokalem Modell
|
||||||
|
|
||||||
|
```
|
||||||
|
Settings → Tools → AI Assistant
|
||||||
|
→ "Use custom AI provider"
|
||||||
|
→ Endpoint: http://10.0.0.60:11434/v1
|
||||||
|
→ Model: qwen2.5-coder:14b
|
||||||
|
→ API Key: ollama (beliebiger String)
|
||||||
|
```
|
||||||
|
|
||||||
|
---
|
||||||
|
|
||||||
|
## Zukunft: NPU-Beschleunigung
|
||||||
|
|
||||||
|
Der CIX P1 hat eine integrierte NPU, die aktuell **nicht von Ollama/llama.cpp unterstützt** wird.
|
||||||
|
|
||||||
|
**Roadmap:**
|
||||||
|
- `llama.cpp` arbeitet an OpenCL/Vulkan-Backend → Immortalis-G720 wird profitieren
|
||||||
|
- CIX P1 NPU-Treiber müssen von CIX Technology als Open-Source freigegeben werden
|
||||||
|
- **Empfehlung:** System ohne NPU in Betrieb nehmen, NPU-Support nachrüsten sobald verfügbar
|
||||||
|
|
||||||
|
**Monitoring:**
|
||||||
|
- https://github.com/ollama/ollama/issues (Filter: "vulkan", "arm64")
|
||||||
|
- https://github.com/ggml-org/llama.cpp/issues (Filter: "vulkan")
|
||||||
|
|
||||||
|
---
|
||||||
|
|
||||||
|
## Quick-Reference: Wichtige Befehle
|
||||||
|
|
||||||
|
```bash
|
||||||
|
# Container verwalten (auf Proxmox-Node: ssh root@10.0.0.20)
|
||||||
|
pct start 111
|
||||||
|
pct stop 111
|
||||||
|
pct enter 111
|
||||||
|
pct status 111
|
||||||
|
|
||||||
|
# Modelle verwalten (im Container)
|
||||||
|
ollama list # Installierte Modelle
|
||||||
|
ollama pull <modell> # Neues Modell herunterladen
|
||||||
|
ollama rm <modell> # Modell löschen
|
||||||
|
ollama ps # Laufende Modelle
|
||||||
|
|
||||||
|
# Logs
|
||||||
|
journalctl -u ollama -f # Ollama-Logs live
|
||||||
|
docker logs -f open-webui # Open WebUI Logs
|
||||||
|
|
||||||
|
# Performance prüfen
|
||||||
|
htop # CPU/RAM-Auslastung
|
||||||
|
ollama ps # Welches Modell läuft, RAM-Nutzung
|
||||||
|
```
|
||||||
|
|
||||||
|
---
|
||||||
|
|
||||||
|
## Netz-Übersicht nach diesem Setup
|
||||||
|
|
||||||
|
```
|
||||||
|
Zora — Proxmox 8.4.10 (10.0.0.20)
|
||||||
|
├── VM 102 gitea-runner 10.0.0.23 Gitea CI/CD Runner
|
||||||
|
├── VM 110 meldestelle-host 10.0.0.50 Docker App-Stack
|
||||||
|
├── LXC 101 gitea 10.0.0.22 Gitea Server
|
||||||
|
├── LXC 103 immich Immich
|
||||||
|
└── LXC 111 ai-stack 10.0.0.60 Ollama :11434 | Open WebUI :3001
|
||||||
|
|
||||||
|
Pangolin-Tunnel:
|
||||||
|
├── ai.mo-code.at → 10.0.0.60:3001 (Open WebUI — nur intern/VPN)
|
||||||
|
├── api.mo-code.at → 10.0.0.50:8081 (API Gateway)
|
||||||
|
└── auth.mo-code.at → 10.0.0.50:8180 (Keycloak)
|
||||||
|
```
|
||||||
@@ -57,9 +57,11 @@ sudo iptables -t nat -A POSTROUTING -s 10.0.6.0/24 ! -d 10.0.6.0/24 -j MASQUERAD
|
|||||||
|
|
||||||
Aufgrund der ARM64-Architektur und Kernel-Einschränkungen wurden folgende Anpassungen vorgenommen:
|
Aufgrund der ARM64-Architektur und Kernel-Einschränkungen wurden folgende Anpassungen vorgenommen:
|
||||||
|
|
||||||
* **Firewall-Modus:** Das System nutzt `iptables-legacy`, da moderne NFT-Module teilweise fehlen.
|
* **Hypervisor:** Proxmox VE 8.4.10 läuft auf Zora (`pve.mo-code.at`, IP `10.0.0.20`).
|
||||||
* **NAT-Regel:** Da Incus die Firewall nicht automatisch verwalten kann, muss der Internetzugriff für Container manuell maskiert werden:
|
* **Netz-Bridge:** `vmbr0`, Subnetz `10.0.0.0/24`, Gateway `10.0.0.138`.
|
||||||
`sudo iptables -t nat -A POSTROUTING -s 10.0.6.0/24 ! -d 10.0.6.0/24 -j MASQUERADE`
|
* **Firewall-Modus:** Proxmox verwaltet Firewall und NAT automatisch via `vmbr0` — keine manuelle iptables-Regel nötig.
|
||||||
|
|
||||||
|
> ℹ️ Frühere Einträge zu Incus/iptables-MASQUERADE sind historisch (Testbetrieb Feb 2026) und wurden durch Proxmox abgelöst.
|
||||||
|
|
||||||
## Wichtige Befehle
|
## Wichtige Befehle
|
||||||
|
|
||||||
@@ -70,7 +72,11 @@ Aufgrund der ARM64-Architektur und Kernel-Einschränkungen wurden folgende Anpas
|
|||||||
|
|
||||||
## 2. Incus_Konfiguration&Bedienungsanleitung.md
|
## 2. Incus_Konfiguration&Bedienungsanleitung.md
|
||||||
|
|
||||||
# Infrastruktur-Dokumentation: Incus Virtualisierung
|
> ⚠️ **HISTORISCH (Testbetrieb Feb 2026) — ABGELÖST durch Proxmox VE 8.4.10**
|
||||||
|
> Diese Sektion dokumentiert den ursprünglichen Incus-Testbetrieb. Zora läuft heute auf Proxmox.
|
||||||
|
> Aktueller Stand: `SSoT_Konfigurations-Masterplan_Zora.md`
|
||||||
|
|
||||||
|
# Infrastruktur-Dokumentation: Incus Virtualisierung (HISTORISCH)
|
||||||
|
|
||||||
## 1. Virtualisierungs-Strategie
|
## 1. Virtualisierungs-Strategie
|
||||||
|
|
||||||
|
|||||||
@@ -6,44 +6,112 @@ owner: DevOps Engineer
|
|||||||
# SSoT Konfigurations-Masterplan für Zora (ARM64)
|
# SSoT Konfigurations-Masterplan für Zora (ARM64)
|
||||||
|
|
||||||
## 1. System-Umgebung (Infrastruktur)
|
## 1. System-Umgebung (Infrastruktur)
|
||||||
| Parameter | Wert | Erklärung |
|
|
||||||
|:-------------------|:--------------|:-------------------------------------------------|
|
| 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`). |
|
| **Architektur** | `linux/arm64` | Native Architektur von Zora (CIX P1 / CP8180). |
|
||||||
| **Projekt-IP** | `10.0.6.50` | Feste IP für den Docker-Host `prod-meldestelle`. |
|
| **Hypervisor** | Proxmox VE 8.4.10 | `pve.mo-code.at` — Web-UI: `https://pve.mo-code.at:8006` |
|
||||||
| **DNS-Server** | `10.0.6.1` | Zora übernimmt die Namensauflösung. |
|
| **Proxmox-Node-IP** | `10.0.0.20` | SSH: `ssh root@10.0.0.20` |
|
||||||
|
| **Netz-Bridge** | `vmbr0` | Alle VMs und Container im Subnetz `10.0.0.0/24` |
|
||||||
|
| **Gateway (Router)** | `10.0.0.138` | Standard-Gateway für alle VMs/Container |
|
||||||
|
|
||||||
|
### VM & Container Übersicht
|
||||||
|
|
||||||
|
| ID | Name | Typ | IP | Start-Reihenfolge | Zweck |
|
||||||
|
|:----|:------------------|:-----|:--------------|:------------------|:-----------------------------|
|
||||||
|
| 100 | pangolin-client | LXC | `10.0.0.21` | order=1, up=30 | Pangolin Tunnel Client |
|
||||||
|
| 101 | gitea | LXC | `10.0.0.22` | order=2, up=30 | Gitea Server |
|
||||||
|
| 102 | gitea-runner | VM | `10.0.0.23` | — | Gitea CI/CD Runner (aarch64) |
|
||||||
|
| 103 | immich | LXC | `10.0.0.24` | order=3, up=30 | Immich Foto-Server |
|
||||||
|
| 110 | meldestelle-host | VM | `10.0.0.50` | — | Docker App-Stack |
|
||||||
|
| 111 | ai-stack | LXC | `10.0.0.60` | — | Ollama + Open WebUI (geplant)|
|
||||||
|
|
||||||
|
|
||||||
|
### Detaillierte Ressourcen-Konfiguration
|
||||||
|
|
||||||
|
#### CT 100 — pangolin-client (LXC)
|
||||||
|
| Parameter | Wert |
|
||||||
|
|:-----------------|:---------------------------------------|
|
||||||
|
| **OS** | Ubuntu, arm64 |
|
||||||
|
| **CPU** | 4 Cores (cpulimit=4) |
|
||||||
|
| **RAM** | 512 MiB + 512 MiB Swap |
|
||||||
|
| **Disk** | 8 GB (`local:100/vm-100-disk-0.raw`) |
|
||||||
|
| **Netzwerk** | eth0 → vmbr0, IP `10.0.0.21/24`, GW `10.0.0.138`, Firewall: Yes |
|
||||||
|
| **Typ** | Unprivileged, nesting=1 |
|
||||||
|
| **Autostart** | Ja — order=1, up=30 |
|
||||||
|
|
||||||
|
#### CT 101 — gitea (LXC)
|
||||||
|
| Parameter | Wert |
|
||||||
|
|:-----------------|:---------------------------------------|
|
||||||
|
| **OS** | Ubuntu, arm64 |
|
||||||
|
| **CPU** | 4 Cores |
|
||||||
|
| **RAM** | 1.00 GiB + 512 MiB Swap |
|
||||||
|
| **Disk** | 20 GB (`local:101/vm-101-disk-0.raw`) |
|
||||||
|
| **Netzwerk** | eth0 → vmbr0, IP `10.0.0.22/24`, GW `10.0.0.138`, Firewall: Yes |
|
||||||
|
| **Typ** | Unprivileged, nesting=1 |
|
||||||
|
| **Autostart** | Ja — order=2, up=30 |
|
||||||
|
|
||||||
|
#### CT 103 — immich (LXC)
|
||||||
|
| Parameter | Wert |
|
||||||
|
|:-----------------|:---------------------------------------|
|
||||||
|
| **OS** | Ubuntu, arm64 |
|
||||||
|
| **CPU** | 8 Cores |
|
||||||
|
| **RAM** | 10.00 GiB + 512 MiB Swap |
|
||||||
|
| **Root Disk** | 200 GB (`local:103/vm-103-disk-0.raw`) |
|
||||||
|
| **Mount Point** | mp0: `/mnt/immich_gross` → `/mnt/fotos` (Foto-Bibliothek) |
|
||||||
|
| **Netzwerk** | eth0 → vmbr0, IP `10.0.0.24/24`, GW `10.0.0.138`, Firewall: Yes |
|
||||||
|
| **Typ** | Unprivileged, nesting=1, keyctl=1, fuse=1 |
|
||||||
|
| **Autostart** | Ja — order=3, up=30 |
|
||||||
|
|
||||||
|
#### VM 102 — gitea-runner (QEMU/KVM)
|
||||||
|
| Parameter | Wert |
|
||||||
|
|:-----------------|:-----------------------------------------------------------------|
|
||||||
|
| **BIOS** | OVMF (UEFI) |
|
||||||
|
| **Machine** | virt (ARM64) |
|
||||||
|
| **CPU** | 8 Cores (1 Socket, host-type, numa=1) |
|
||||||
|
| **RAM** | 16.00 GiB (balloon=0, kein Dynamic Memory) |
|
||||||
|
| **Disk** | 50 GB SSD (`local:102/vm-102-disk-1.qcow2`, aio=io_uring, iothread=1) |
|
||||||
|
| **EFI Disk** | `local:102/vm-102-disk-0.qcow2`, efitype=4m, 64 MB |
|
||||||
|
| **Netzwerk** | virtio, bridge=vmbr0, Firewall: Yes |
|
||||||
|
| **SCSI** | VirtIO SCSI single |
|
||||||
|
|
||||||
## 2. Mail-Relay (SSoT Identity)
|
## 2. Mail-Relay (SSoT Identity)
|
||||||
|
|
||||||
Diese Daten müssen in der Spring Boot `application.yml` oder `.env` abgeglichen werden.
|
Diese Daten müssen in der Spring Boot `application.yml` oder `.env` abgeglichen werden.
|
||||||
* **SMTP-Host:** `10.0.6.1` (Zora Host Relay)
|
|
||||||
|
* **SMTP-Host:** `10.0.0.20` (Zora Proxmox-Node als Mail-Relay)
|
||||||
* **SMTP-Port:** `25` (Passwortloser interner Zugriff via `mynetworks`)
|
* **SMTP-Port:** `25` (Passwortloser interner Zugriff via `mynetworks`)
|
||||||
* **Absender:** `zora@mo-code.at` (Verifizierte World4You Identität)
|
* **Absender:** `zora@mo-code.at` (Verifizierte World4You Identität)
|
||||||
|
|
||||||
## 3. Docker-Image Checkliste (ARM64 Kompatibilitä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 |
|
| Dienst | Empfohlenes Image | Status |
|
||||||
|:---------------|:---------------------------------|:-----------------------------------------------|
|
|:---------------|:-------------------------------------------|:-----------------------------------------------|
|
||||||
| **Datenbank** | `postgres:15-alpine` | ARM64 Support: Ja |
|
| **Datenbank** | `postgres:16-alpine` | ARM64 Support: Ja |
|
||||||
| **Cache** | `valkey/valkey:8-alpine` | ARM64 Support: Ja (Besserer Support als Redis) |
|
| **Cache** | `valkey/valkey:9-alpine` | ARM64 Support: Ja (Besserer Support als Redis) |
|
||||||
| **Identity** | `quay.io/keycloak/keycloak:24.0` | ARM64 Support: Ja (Offiziell) |
|
| **Identity** | `quay.io/keycloak/keycloak:26.4` | ARM64 Support: Ja (Offiziell) |
|
||||||
| **Monitoring** | `prom/prometheus:latest` | ARM64 Support: Ja |
|
| **Monitoring** | `prom/prometheus:v3.7.3` | ARM64 Support: Ja |
|
||||||
| **Dashboards** | `grafana/grafana:latest` | ARM64 Support: Ja |
|
| **Dashboards** | `grafana/grafana:12.3` | ARM64 Support: Ja |
|
||||||
|
|
||||||
## 4. Backend & Gateway (Spring Boot)
|
## 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.
|
* **Base Image:** `eclipse-temurin:25-jre-alpine` (ARM64-native, via Gitea-Pipeline gebaut)
|
||||||
* **Build-Prozess:** Dein Gitea-Runner auf Zora baut automatisch für ARM64, da er auf der gleichen Hardware läuft.
|
* **Build-Prozess:** Gitea-Runner (VM 102, `10.0.0.23`) baut nativ für `linux/arm64`
|
||||||
|
|
||||||
## 5. Keycloak SSoT Integration
|
## 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
|
* **External Issuer:** `http://10.0.0.50:8180/realms/meldestelle`
|
||||||
Stelle sicher, dass deine Ingress-Rules auf die IP der Meldestelle zeigen:
|
* **Internal Issuer:** `http://keycloak:8080/realms/meldestelle` (Docker-intern)
|
||||||
* `api.mo-code.at` -> `http://10.0.6.50:8080` (Gateway)
|
* **Client-IDs:** `api-gateway`, `web-app`
|
||||||
* `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)
|
## 6. Pangolin Tunnel Routing
|
||||||
|
|
||||||
|
> Pangolin läuft auf CT 100 (pangolin-client, `10.0.0.21`) als Tunnel-Client zu `pangolin.mo-code.at`.
|
||||||
|
|
||||||
|
| Route | Ziel (intern) | Port | Sichtbarkeit |
|
||||||
|
|:-----------------------|:---------------|:-------|:---------------------|
|
||||||
|
| `api.mo-code.at` | `10.0.0.50` | `8081` | Öffentlich |
|
||||||
|
| `auth.mo-code.at` | `10.0.0.50` | `8180` | Öffentlich |
|
||||||
|
| `git.mo-code.at` | `10.0.0.22` | `3000` | Öffentlich |
|
||||||
|
| `photos.mo-code.at` | `10.0.0.24` | `2283` | Nur intern / VPN |
|
||||||
|
| `ai.mo-code.at` | `10.0.0.60` | `3001` | Nur intern / VPN |
|
||||||
|
|||||||
@@ -11,7 +11,7 @@ Das System nutzt das **Single Source of Truth (SSoT)** Prinzip für den gesamten
|
|||||||
| Parameter | Wert | Funktion |
|
| Parameter | Wert | Funktion |
|
||||||
|:-------------------|:-------------------------|:-------------------------------------------------|
|
|:-------------------|:-------------------------|:-------------------------------------------------|
|
||||||
| **Zentraler Host** | `zora.mo-code.at` | Primärer Mail-Transfer-Agent (MTA). |
|
| **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. |
|
| **Gateway IP** | `10.0.0.20` | Proxmox-Node-IP, interne Erreichbarkeit für alle VMs/Container. |
|
||||||
| **Relay Host** | `smtp.world4you.com:587` | Externer Provider für den tatsächlichen Versand. |
|
| **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. |
|
| **SSoT Account** | `zora@mo-code.at` | Die verifizierte Absender-Identität. |
|
||||||
|
|
||||||
@@ -20,7 +20,7 @@ Das System nutzt das **Single Source of Truth (SSoT)** Prinzip für den gesamten
|
|||||||
## 2. Technische Umsetzung (Der "Postbote")
|
## 2. Technische Umsetzung (Der "Postbote")
|
||||||
Wir haben Postfix als **Satellitensystem** konfiguriert. Er nimmt Briefe im internen Netzwerk entgegen und bringt sie sicher zum Provider.
|
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).
|
* **Sicherheit:** Postfix lauscht auf Port 25, erlaubt den Versand aber **nur** für Anfragen aus dem internen Netz `10.0.0.0/8` (Proxmox vmbr0 / Docker).
|
||||||
* **Authentifizierung:** Nur Zora kennt das Passwort für den World4You-Account (gespeichert in `sasl_passwd`).
|
* **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.
|
* **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.
|
* **Verschlüsselung:** Die Verbindung zu World4You ist via TLS (STARTTLS) abgesichert.
|
||||||
@@ -38,7 +38,7 @@ Ein Dienst stellt einen Zustand fest, der gemeldet werden muss.
|
|||||||
|
|
||||||
### Phase B: Der interne Transport
|
### Phase B: Der interne Transport
|
||||||
Der Dienst verbindet sich ohne Passwort (da er sich im vertrauenswürdigen Netz befindet) mit:
|
Der Dienst verbindet sich ohne Passwort (da er sich im vertrauenswürdigen Netz befindet) mit:
|
||||||
`SMTP_HOST: 10.0.6.1` | `SMTP_PORT: 25`
|
`SMTP_HOST: 10.0.0.20` | `SMTP_PORT: 25`
|
||||||
Dies minimiert das Risiko: Keine Passwörter in `.env`-Dateien von Applikationen.
|
Dies minimiert das Risiko: Keine Passwörter in `.env`-Dateien von Applikationen.
|
||||||
|
|
||||||
### Phase C: Die externe Zustellung
|
### Phase C: Die externe Zustellung
|
||||||
|
|||||||
@@ -5,47 +5,47 @@ owner: DevOps Engineer
|
|||||||
tags: [gradle, kotlin, dsl, build]
|
tags: [gradle, kotlin, dsl, build]
|
||||||
---
|
---
|
||||||
|
|
||||||
# Gradle Kotlin DSL Primer
|
# Gradle Kotlin DSL – Einführung
|
||||||
|
|
||||||
**Quelle:** [Original Gradle Documentation](https://docs.gradle.org/current/userguide/kotlin_dsl.html)
|
**Quelle:** [Offizielle Gradle-Dokumentation](https://docs.gradle.org/current/userguide/kotlin_dsl.html)
|
||||||
**Kontext:** Dieses Dokument dient als Referenz für die im Projekt verwendete Gradle Kotlin DSL. Es fasst die wichtigsten Konzepte und Syntax-Elemente zusammen.
|
**Kontext:** Dieses Dokument dient als Referenz für die im Projekt verwendete Gradle Kotlin DSL. Es fasst die wichtigsten Konzepte und Syntax-Elemente zusammen.
|
||||||
|
|
||||||
---
|
---
|
||||||
|
|
||||||
Gradle’s Kotlin DSL offers an alternative to the traditional Groovy DSL, delivering an enhanced editing experience in supported IDEs.
|
Gradles Kotlin DSL bietet eine Alternative zur traditionellen Groovy DSL und liefert eine verbesserte Editor-Erfahrung in unterstützten IDEs.
|
||||||
|
|
||||||
## Key Concepts
|
## Wichtige Konzepte
|
||||||
|
|
||||||
### Script File Names
|
### Skript-Dateinamen
|
||||||
* Groovy DSL: `.gradle`
|
* Groovy DSL: `.gradle`
|
||||||
* Kotlin DSL: `.gradle.kts`
|
* Kotlin DSL: `.gradle.kts`
|
||||||
|
|
||||||
To activate the Kotlin DSL, use the `.gradle.kts` extension for your build scripts, settings file (`settings.gradle.kts`), and initialization scripts (`init.gradle.kts`).
|
Um die Kotlin DSL zu aktivieren, wird die Erweiterung `.gradle.kts` für Build-Skripte, die Settings-Datei (`settings.gradle.kts`) und Initialisierungsskripte (`init.gradle.kts`) verwendet.
|
||||||
|
|
||||||
### Type-safe Model Accessors
|
### Typsichere Model-Accessors
|
||||||
The Kotlin DSL replaces Groovy's dynamic resolution with type-safe model accessors for elements contributed by plugins (configurations, tasks, extensions). This provides better IDE support (code completion, refactoring).
|
Die Kotlin DSL ersetzt Groovys dynamische Auflösung durch typsichere Model-Accessors für Elemente, die von Plugins bereitgestellt werden (Konfigurationen, Tasks, Erweiterungen). Dies sorgt für bessere IDE-Unterstützung (Code-Vervollständigung, Refactoring).
|
||||||
|
|
||||||
**Example:**
|
**Beispiel:**
|
||||||
```kotlin
|
```kotlin
|
||||||
plugins {
|
plugins {
|
||||||
`java-library`
|
`java-library`
|
||||||
}
|
}
|
||||||
|
|
||||||
dependencies {
|
dependencies {
|
||||||
// 'api', 'implementation' are type-safe accessors
|
// 'api', 'implementation' sind typsichere Accessors
|
||||||
api("junit:junit:4.13")
|
api("junit:junit:4.13")
|
||||||
implementation("org.apache.commons:commons-lang3:3.12.0")
|
implementation("org.apache.commons:commons-lang3:3.12.0")
|
||||||
}
|
}
|
||||||
|
|
||||||
tasks {
|
tasks {
|
||||||
// 'test' is a type-safe accessor for the Test task
|
// 'test' ist ein typsicherer Accessor für den Test-Task
|
||||||
test {
|
test {
|
||||||
useJUnitPlatform()
|
useJUnitPlatform()
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
```
|
```
|
||||||
|
|
||||||
Accessors are available for elements contributed by plugins applied in the `plugins {}` block. For elements created dynamically later in the script, you must fall back to string-based lookups:
|
Accessors stehen für Elemente zur Verfügung, die von Plugins im `plugins {}`-Block bereitgestellt werden. Für dynamisch im Skript erstellte Elemente muss auf zeichenkettenbasierte Lookups zurückgegriffen werden:
|
||||||
```kotlin
|
```kotlin
|
||||||
configurations.create("custom")
|
configurations.create("custom")
|
||||||
|
|
||||||
@@ -55,20 +55,20 @@ dependencies {
|
|||||||
```
|
```
|
||||||
|
|
||||||
### Lazy Property Assignment
|
### Lazy Property Assignment
|
||||||
The Kotlin DSL supports lazy property assignment using the `=` operator for types like `Property` and `ConfigurableFileCollection`. This is the preferred way over the `set()` method.
|
Die Kotlin DSL unterstützt die verzögerte Zuweisung von Properties mit dem `=`-Operator für Typen wie `Property` und `ConfigurableFileCollection`. Dies ist der bevorzugte Weg gegenüber der `set()`-Methode.
|
||||||
|
|
||||||
```kotlin
|
```kotlin
|
||||||
// Instead of:
|
// Anstatt:
|
||||||
// javaVersion.set(JavaLanguageVersion.of(17))
|
// javaVersion.set(JavaLanguageVersion.of(17))
|
||||||
|
|
||||||
// Use:
|
// Verwende:
|
||||||
javaVersion = JavaLanguageVersion.of(17)
|
javaVersion = JavaLanguageVersion.of(17)
|
||||||
```
|
```
|
||||||
|
|
||||||
### Working with Containers
|
### Arbeiten mit Containern
|
||||||
You can interact with containers like `tasks` or `configurations` in several ways:
|
Mit Containern wie `tasks` oder `configurations` kann auf verschiedene Weisen interagiert werden:
|
||||||
|
|
||||||
1. **Container API (using `named` and `register`):**
|
1. **Container API (mit `named` und `register`):**
|
||||||
```kotlin
|
```kotlin
|
||||||
tasks.named<Test>("test") {
|
tasks.named<Test>("test") {
|
||||||
testLogging.showExceptions = true
|
testLogging.showExceptions = true
|
||||||
@@ -79,7 +79,7 @@ You can interact with containers like `tasks` or `configurations` in several way
|
|||||||
}
|
}
|
||||||
```
|
```
|
||||||
|
|
||||||
2. **Delegated Properties (using `by existing` and `by registering`):**
|
2. **Delegierte Properties (mit `by existing` und `by registering`):**
|
||||||
```kotlin
|
```kotlin
|
||||||
val test by tasks.existing(Test::class) {
|
val test by tasks.existing(Test::class) {
|
||||||
testLogging.showStackTraces = true
|
testLogging.showStackTraces = true
|
||||||
@@ -91,17 +91,17 @@ You can interact with containers like `tasks` or `configurations` in several way
|
|||||||
```
|
```
|
||||||
|
|
||||||
### Extra Properties
|
### Extra Properties
|
||||||
Access project or task-level extra properties via delegated properties:
|
Auf extra Properties auf Projekt- oder Task-Ebene wird über delegierte Properties zugegriffen:
|
||||||
```kotlin
|
```kotlin
|
||||||
// Define an extra property
|
// Eine extra Property definieren
|
||||||
val myNewProperty by extra("initial value")
|
val myNewProperty by extra("Initialwert")
|
||||||
|
|
||||||
// Read an existing extra property
|
// Eine bestehende extra Property lesen
|
||||||
val myExtraProperty: String by extra
|
val myExtraProperty: String by extra
|
||||||
```
|
```
|
||||||
|
|
||||||
### Kotlin DSL Plugin (`kotlin-dsl`)
|
### Kotlin DSL Plugin (`kotlin-dsl`)
|
||||||
This plugin is essential for developing build logic in Kotlin (e.g., in `buildSrc` or for convention plugins). It automatically applies the Kotlin plugin and adds necessary dependencies like `kotlin-stdlib` and `gradleKotlinDsl()`.
|
Dieses Plugin ist essenziell für die Entwicklung von Build-Logik in Kotlin (z.B. in `buildSrc` oder für Convention Plugins). Es wendet automatisch das Kotlin-Plugin an und fügt notwendige Abhängigkeiten wie `kotlin-stdlib` und `gradleKotlinDsl()` hinzu.
|
||||||
|
|
||||||
```kotlin
|
```kotlin
|
||||||
// buildSrc/build.gradle.kts
|
// buildSrc/build.gradle.kts
|
||||||
|
|||||||
@@ -5,69 +5,69 @@ owner: Lead Architect
|
|||||||
tags: [kotlin, release-notes, tech-stack]
|
tags: [kotlin, release-notes, tech-stack]
|
||||||
---
|
---
|
||||||
|
|
||||||
# What's new in Kotlin 2.3.0
|
# Was ist neu in Kotlin 2.3.0
|
||||||
|
|
||||||
**Quelle:** [Original Kotlin Documentation](https://kotlinlang.org/docs/whatsnew23.html)
|
**Quelle:** [Offizielle Kotlin-Dokumentation](https://kotlinlang.org/docs/whatsnew23.html)
|
||||||
**Datum des Dokuments:** 16. Dezember 2025
|
**Datum des Dokuments:** 16. Dezember 2025
|
||||||
**Kontext:** Dieses Dokument dient als Referenz für die im Projekt verwendete Kotlin-Version.
|
**Kontext:** Dieses Dokument dient als Referenz für die im Projekt verwendete Kotlin-Version.
|
||||||
|
|
||||||
---
|
---
|
||||||
|
|
||||||
The Kotlin 2.3.0 release is out! Here are the main highlights:
|
Kotlin 2.3.0 ist erschienen! Hier sind die wichtigsten Highlights:
|
||||||
|
|
||||||
* **Language:** More stable and default features, unused return value checker, explicit backing fields, and changes to context-sensitive resolution.
|
* **Sprache:** Mehr stabile und standardmäßig aktivierte Features, Checker für ungenutzte Rückgabewerte, explizite Backing Fields und Änderungen bei der kontextsensitiven Auflösung.
|
||||||
* **Kotlin/JVM:** Support for Java 25.
|
* **Kotlin/JVM:** Unterstützung für Java 25.
|
||||||
* **Kotlin/Native:** Improved interop through Swift export, faster build time for release tasks, C and Objective-C library import in Beta.
|
* **Kotlin/Native:** Verbesserte Interoperabilität durch Swift-Export, schnellere Build-Zeiten für Release-Tasks, C- und Objective-C-Bibliotheksimport in Beta.
|
||||||
* **Kotlin/Wasm:** Fully qualified names and new exception handling proposal enabled by default, as well as new compact storage for Latin-1 characters.
|
* **Kotlin/Wasm:** Vollständig qualifizierte Namen und neuer Ausnahmebehandlungsvorschlag standardmäßig aktiviert, sowie kompakter Speicher für Latin-1-Zeichen.
|
||||||
* **Kotlin/JS:** New experimental suspend function export, `LongArray` representation, unified companion object access, and more.
|
* **Kotlin/JS:** Neuer experimenteller Export von Suspend-Funktionen, `LongArray`-Darstellung, einheitlicher Companion-Object-Zugriff und mehr.
|
||||||
* **Gradle:** Compatibility with Gradle 9.0 and a new API for registering generated sources.
|
* **Gradle:** Kompatibilität mit Gradle 9.0 und neue API zur Registrierung generierter Quellen.
|
||||||
* **Compose compiler:** Stack traces for minified Android applications.
|
* **Compose Compiler:** Stack Traces für minimierte Android-Anwendungen.
|
||||||
* **Standard library:** Stable time tracking functionality and improved UUID generation and parsing.
|
* **Standardbibliothek:** Stabile Zeiterfassungsfunktionalität sowie verbesserte UUID-Generierung und -Analyse.
|
||||||
|
|
||||||
## Language
|
## Sprache
|
||||||
|
|
||||||
Kotlin 2.3.0 focuses on feature stabilization, introduces a new mechanism for detecting unused return values, and improves context-sensitive resolution.
|
Kotlin 2.3.0 konzentriert sich auf die Stabilisierung von Features, führt einen neuen Mechanismus zur Erkennung ungenutzter Rückgabewerte ein und verbessert die kontextsensitive Auflösung.
|
||||||
|
|
||||||
### Stable features
|
### Stabile Features
|
||||||
|
|
||||||
The following features have now graduated to Stable:
|
Folgende Features sind nun stabil:
|
||||||
* Support for nested type aliases
|
* Unterstützung für verschachtelte Typ-Aliase
|
||||||
* Data-flow-based exhaustiveness checks for `when` expressions
|
* Datenflussbasierte Vollständigkeitsprüfungen für `when`-Ausdrücke
|
||||||
|
|
||||||
### Features enabled by default
|
### Standardmäßig aktivierte Features
|
||||||
* Support for `return` statements in expression bodies with explicit return types is now enabled by default.
|
* Unterstützung für `return`-Anweisungen in Ausdrucks-Bodies mit explizitem Rückgabetyp ist nun standardmäßig aktiviert.
|
||||||
|
|
||||||
### Experimental: Unused return value checker
|
### Experimentell: Checker für ungenutzte Rückgabewerte
|
||||||
Kotlin 2.3.0 introduces the unused return value checker to help prevent ignored results.
|
Kotlin 2.3.0 führt den Checker für ungenutzte Rückgabewerte ein, um das versehentliche Ignorieren von Ergebnissen zu verhindern.
|
||||||
|
|
||||||
### Experimental: Explicit backing fields
|
### Experimentell: Explizite Backing Fields
|
||||||
A new syntax for explicitly declaring the underlying field that holds a property's value, simplifying the common backing properties pattern.
|
Eine neue Syntax zur expliziten Deklaration des zugrundeliegenden Felds, das den Wert einer Property hält – vereinfacht das verbreitete Backing-Properties-Muster.
|
||||||
|
|
||||||
## Kotlin/JVM: Support for Java 25
|
## Kotlin/JVM: Unterstützung für Java 25
|
||||||
Starting with Kotlin 2.3.0, the compiler can generate classes containing Java 25 bytecode.
|
Ab Kotlin 2.3.0 kann der Compiler Klassen mit Java-25-Bytecode generieren.
|
||||||
|
|
||||||
## Kotlin/Native
|
## Kotlin/Native
|
||||||
* **Improved Swift Export:** Direct mapping for native enum classes and variadic function parameters.
|
* **Verbesserter Swift-Export:** Direkte Zuordnung für native Enum-Klassen und variadische Funktionsparameter.
|
||||||
* **C and Objective-C Library Import is in Beta:** Better diagnostics for binary compatibility issues.
|
* **C- und Objective-C-Bibliotheksimport in Beta:** Bessere Diagnosen bei binären Kompatibilitätsproblemen.
|
||||||
* **Faster Build Time:** Up to 40% faster release builds, especially for iOS targets.
|
* **Schnellere Build-Zeit:** Bis zu 40 % schnellere Release-Builds, besonders für iOS-Targets.
|
||||||
|
|
||||||
## Kotlin/Wasm
|
## Kotlin/Wasm
|
||||||
* **Fully Qualified Names Enabled by Default:** `KClass.qualifiedName` is now available at runtime without extra configuration.
|
* **Vollständig qualifizierte Namen standardmäßig aktiviert:** `KClass.qualifiedName` ist nun ohne zusätzliche Konfiguration zur Laufzeit verfügbar.
|
||||||
* **Compact Storage for Latin-1 Characters:** Reduces metadata and binary size.
|
* **Kompakter Speicher für Latin-1-Zeichen:** Reduziert Metadaten- und Binärgröße.
|
||||||
* **New Exception Handling for `wasmWasi`:** Enabled by default for better compatibility with modern WebAssembly runtimes.
|
* **Neue Ausnahmebehandlung für `wasmWasi`:** Standardmäßig aktiviert für bessere Kompatibilität mit modernen WebAssembly-Laufzeitumgebungen.
|
||||||
|
|
||||||
## Kotlin/JS
|
## Kotlin/JS
|
||||||
* **Experimental Suspend Function Export:** Export suspend functions directly to JavaScript using `@JsExport`.
|
* **Experimenteller Export von Suspend-Funktionen:** Suspend-Funktionen direkt nach JavaScript exportieren mittels `@JsExport`.
|
||||||
* **`BigInt64Array` for `LongArray`:** Simplifies interop with JavaScript APIs that use typed arrays.
|
* **`BigInt64Array` für `LongArray`:** Vereinfacht die Interoperabilität mit JavaScript-APIs, die typisierte Arrays verwenden.
|
||||||
* **Unified Companion Object Access:** Consistent access to companion objects in interfaces across all JS module systems.
|
* **Einheitlicher Companion-Object-Zugriff:** Konsistenter Zugriff auf Companion Objects in Interfaces über alle JS-Modulsysteme hinweg.
|
||||||
|
|
||||||
## Gradle
|
## Gradle
|
||||||
* Fully compatible with Gradle 7.6.3 through 9.0.0.
|
* Vollständig kompatibel mit Gradle 7.6.3 bis 9.0.0.
|
||||||
* New experimental API for registering generated sources.
|
* Neue experimentelle API zur Registrierung generierter Quellen.
|
||||||
|
|
||||||
## Standard library
|
## Standardbibliothek
|
||||||
* **Stable Time Tracking:** `kotlin.time.Clock` and `kotlin.time.Instant` are now stable.
|
* **Stabile Zeiterfassung:** `kotlin.time.Clock` und `kotlin.time.Instant` sind nun stabil.
|
||||||
* **Improved UUID Generation:** New functions like `Uuid.parseOrNull()`, `Uuid.generateV4()`, and `Uuid.generateV7()`.
|
* **Verbesserte UUID-Generierung:** Neue Funktionen wie `Uuid.parseOrNull()`, `Uuid.generateV4()` und `Uuid.generateV7()`.
|
||||||
|
|
||||||
## Compose compiler
|
## Compose Compiler
|
||||||
* **Stack Traces for Minified Android Apps:** The compiler now outputs ProGuard mappings for Compose stack traces when applications are minified by R8.
|
* **Stack Traces für minimierte Android-Apps:** Der Compiler gibt nun ProGuard-Mappings für Compose-Stack-Traces aus, wenn Anwendungen durch R8 minimiert werden.
|
||||||
|
|||||||
@@ -3,12 +3,12 @@ type: ADR
|
|||||||
status: DRAFT
|
status: DRAFT
|
||||||
owner: Lead Architect
|
owner: Lead Architect
|
||||||
---
|
---
|
||||||
# PENDING DECISIONS: Backend Infrastructure & Architecture
|
# OFFENE ENTSCHEIDUNGEN: Backend-Infrastruktur & Architektur
|
||||||
|
|
||||||
**Status:** RESOLVED
|
**Status:** GELÖST
|
||||||
**Date:** 2026-01-15
|
**Datum:** 2026-01-15
|
||||||
**See:** [ADR 001: Backend Infrastructure & Architecture Decisions](001-backend-infrastructure-decisions.md)
|
**Siehe:** [ADR 001: Backend-Infrastruktur & Architekturentscheidungen](001-backend-infrastructure-decisions.md)
|
||||||
|
|
||||||
---
|
---
|
||||||
|
|
||||||
*This document is kept for historical context. All decisions have been moved to ADR 001.*
|
*Dieses Dokument wird aus historischen Gründen aufbewahrt. Alle Entscheidungen wurden in ADR 001 überführt.*
|
||||||
|
|||||||
@@ -3,70 +3,70 @@ type: ADR
|
|||||||
status: ACTIVE
|
status: ACTIVE
|
||||||
owner: Lead Architect
|
owner: Lead Architect
|
||||||
---
|
---
|
||||||
# ADR 001: Backend Infrastructure & Architecture Decisions
|
# ADR 001: Backend-Infrastruktur & Architekturentscheidungen
|
||||||
|
|
||||||
**Status:** ACCEPTED
|
**Status:** AKZEPTIERT
|
||||||
**Date:** 2026-01-15
|
**Datum:** 2026-01-15
|
||||||
**Author:** Lead Architect
|
**Autor:** Lead Architect
|
||||||
**Context:** "Operation Tracer Bullet" (Phase 1) - Hardening of the `ping-service`.
|
**Kontext:** „Operation Tracer Bullet" (Phase 1) – Härtung des `ping-service`.
|
||||||
|
|
||||||
---
|
---
|
||||||
|
|
||||||
## 1. Persistence Strategy: JPA vs. Exposed
|
## 1. Persistenzstrategie: JPA vs. Exposed
|
||||||
|
|
||||||
**Decision:** **Hybrid Approach (Command/Query Separation)**
|
**Entscheidung:** **Hybrider Ansatz (Command/Query-Trennung)**
|
||||||
* **Primary (Command/Write):** We use **JPA (Hibernate)** for the standard "Write Model" in our microservices.
|
* **Primär (Command/Write):** Wir verwenden **JPA (Hibernate)** für das Standard-„Write Model" in unseren Microservices.
|
||||||
* *Reason:* Best integration with Spring Data, transaction management, and validation. Standard for Enterprise Spring Boot.
|
* *Begründung:* Beste Integration mit Spring Data, Transaktionsverwaltung und Validierung. Standard für Enterprise Spring Boot.
|
||||||
* **Secondary (Query/Read/Batch):** We allow **Exposed** for complex read queries or bulk operations where JPA overhead is too high.
|
* **Sekundär (Query/Read/Batch):** Wir erlauben **Exposed** für komplexe Leseabfragen oder Bulk-Operationen, bei denen der JPA-Overhead zu hoch ist.
|
||||||
* *Reason:* Kotlin-native, type-safe SQL generation, better performance for read-heavy operations.
|
* *Begründung:* Kotlin-nativ, typsichere SQL-Generierung, bessere Performance bei leselastigen Operationen.
|
||||||
|
|
||||||
**Action:**
|
**Maßnahmen:**
|
||||||
* The `backend/infrastructure/persistence` module will support **both**.
|
* Das Modul `backend/infrastructure/persistence` unterstützt **beide** Ansätze.
|
||||||
* `ping-service` will primarily use **JPA** for its entities (`PingEntity`).
|
* `ping-service` verwendet primär **JPA** für seine Entitäten (`PingEntity`).
|
||||||
* We will NOT remove JPA from `ping-service`.
|
* JPA wird NICHT aus dem `ping-service` entfernt.
|
||||||
* We will NOT remove Exposed from `infrastructure/persistence`.
|
* Exposed wird NICHT aus `infrastructure/persistence` entfernt.
|
||||||
|
|
||||||
## 2. Security Shared Module
|
## 2. Gemeinsames Security-Modul
|
||||||
|
|
||||||
**Decision:** **Extract `backend/infrastructure/security`**
|
**Entscheidung:** **Extraktion von `backend/infrastructure/security`**
|
||||||
* **Reason:** We strictly follow DRY (Don't Repeat Yourself). Security configuration (OAuth2 Resource Server, JWT Converter, CORS, Global Method Security) is identical for all microservices.
|
* **Begründung:** Wir folgen konsequent dem DRY-Prinzip (Don't Repeat Yourself). Die Sicherheitskonfiguration (OAuth2 Resource Server, JWT Converter, CORS, Global Method Security) ist für alle Microservices identisch.
|
||||||
* **Scope:**
|
* **Umfang:**
|
||||||
* `SecurityConfig`: Standard `SecurityFilterChain`.
|
* `SecurityConfig`: Standard `SecurityFilterChain`.
|
||||||
* `KeycloakRoleConverter`: Extracting roles from JWT.
|
* `KeycloakRoleConverter`: Rollen aus JWT extrahieren.
|
||||||
* `CorsConfig`: Centralized CORS policy.
|
* `CorsConfig`: Zentrale CORS-Richtlinie.
|
||||||
|
|
||||||
**Action:**
|
**Maßnahmen:**
|
||||||
* Create `backend/infrastructure/security`.
|
* `backend/infrastructure/security` erstellen.
|
||||||
* Move security logic from `ping-service` (if any) to this module.
|
* Sicherheitslogik aus `ping-service` (falls vorhanden) in dieses Modul verschieben.
|
||||||
|
|
||||||
## 3. Messaging vs. Sync Protocol
|
## 3. Messaging vs. Sync-Protokoll
|
||||||
|
|
||||||
**Decision:** **REST-based Pull (Phase 1) -> Kafka (Phase 3)**
|
**Entscheidung:** **REST-basiertes Pull (Phase 1) → Kafka (Phase 3)**
|
||||||
* **Phase 1 (Tracer Bullet):** We do **NOT** use Kafka for the simple `ping-service` yet.
|
* **Phase 1 (Tracer Bullet):** Für den einfachen `ping-service` wird Kafka noch NICHT verwendet.
|
||||||
* *Reason:* Keep the "Tracer Bullet" simple. We want to validate the HTTP/Auth chain first.
|
* *Begründung:* Die „Tracer Bullet" soll einfach bleiben. Zuerst die HTTP/Auth-Kette validieren.
|
||||||
* **Phase 3 (Offline Sync):** We will introduce Kafka for the "Outbox Pattern" later.
|
* **Phase 3 (Offline-Sync):** Kafka wird später für das „Outbox Pattern" eingeführt.
|
||||||
* *Reason:* Reliable event delivery for offline clients requires a durable log.
|
* *Begründung:* Zuverlässige Event-Zustellung für Offline-Clients erfordert ein dauerhaftes Log.
|
||||||
|
|
||||||
**Action:**
|
**Maßnahmen:**
|
||||||
* Remove `reactor-kafka` dependency from `ping-service` for now to reduce noise.
|
* `reactor-kafka`-Abhängigkeit vorerst aus `ping-service` entfernen, um die Komplexität zu reduzieren.
|
||||||
* Focus on `PingEntity` (JPA) and REST endpoints.
|
* Fokus auf `PingEntity` (JPA) und REST-Endpunkte.
|
||||||
|
|
||||||
## 4. Database Migration (Flyway)
|
## 4. Datenbank-Migration (Flyway)
|
||||||
|
|
||||||
**Decision:** **Database per Service (Option A)**
|
**Entscheidung:** **Datenbank pro Service (Option A)**
|
||||||
* **Reason:** Microservices autonomy. Each service owns its schema.
|
* **Begründung:** Autonomie der Microservices. Jeder Service besitzt sein eigenes Schema.
|
||||||
* **Location:** `src/main/resources/db/migration` inside each service module.
|
* **Ablageort:** `src/main/resources/db/migration` innerhalb jedes Service-Moduls.
|
||||||
* **Naming:** `V{Version}__{Description}.sql` (e.g., `V1__init_ping_schema.sql`).
|
* **Benennung:** `V{Version}__{Beschreibung}.sql` (z.B. `V1__init_ping_schema.sql`).
|
||||||
|
|
||||||
**Action:**
|
**Maßnahmen:**
|
||||||
* `ping-service` must contain `V1__init.sql`.
|
* `ping-service` muss `V1__init.sql` enthalten.
|
||||||
* `spring.flyway.enabled=true` in `application.yml`.
|
* `spring.flyway.enabled=true` in `application.yml`.
|
||||||
|
|
||||||
---
|
---
|
||||||
|
|
||||||
## Summary of Tasks for Senior Backend Developer
|
## Zusammenfassung der Aufgaben für den Senior Backend Developer
|
||||||
|
|
||||||
1. **Persistence:** Use JPA for `PingEntity`.
|
1. **Persistenz:** JPA für `PingEntity` verwenden.
|
||||||
2. **Security:** Wait for `infrastructure/security` module (Architect will create skeleton) OR start implementing in `ping-service` and refactor later (preferred: Architect creates module now).
|
2. **Security:** Auf das Modul `infrastructure/security` warten (Architect erstellt Skeleton) ODER direkt im `ping-service` implementieren und später refaktorieren (bevorzugt: Architect erstellt Modul sofort).
|
||||||
3. **Messaging:** Ignore Kafka for now.
|
3. **Messaging:** Kafka vorerst ignorieren.
|
||||||
4. **Flyway:** Create `V1__init.sql` in `ping-service`.
|
4. **Flyway:** `V1__init.sql` im `ping-service` erstellen.
|
||||||
|
|||||||
@@ -3,13 +3,13 @@ type: Guide
|
|||||||
status: ACTIVE
|
status: ACTIVE
|
||||||
owner: Frontend Expert
|
owner: Frontend Expert
|
||||||
---
|
---
|
||||||
# SQLDelight Integration in Compose Multiplatform
|
# SQLDelight-Integration in Compose Multiplatform
|
||||||
|
|
||||||
This guide shows how to integrate SQLDelight in a Compose Multiplatform project with Koin dependency injection.
|
Diese Anleitung zeigt, wie SQLDelight in einem Compose Multiplatform-Projekt mit Koin Dependency Injection integriert wird.
|
||||||
|
|
||||||
## Step 1: Add Dependencies
|
## Schritt 1: Abhängigkeiten hinzufügen
|
||||||
|
|
||||||
Add below dependencies In `gradle/libs.versions.toml`:
|
Folgende Abhängigkeiten in `gradle/libs.versions.toml` eintragen:
|
||||||
|
|
||||||
```toml
|
```toml
|
||||||
[versions]
|
[versions]
|
||||||
@@ -28,7 +28,7 @@ koin-compose = { module = "io.insert-koin:koin-compose", version.ref = "koin" }
|
|||||||
sqldelight = { id = "app.cash.sqldelight", version.ref = "sqldelight" }
|
sqldelight = { id = "app.cash.sqldelight", version.ref = "sqldelight" }
|
||||||
```
|
```
|
||||||
|
|
||||||
In `build.gradle.kts` (project level):
|
In `build.gradle.kts` (Projektebene):
|
||||||
|
|
||||||
```kotlin
|
```kotlin
|
||||||
plugins {
|
plugins {
|
||||||
@@ -75,13 +75,13 @@ sqldelight {
|
|||||||
|
|
||||||
```
|
```
|
||||||
|
|
||||||
##Step 2: Create SQL Schema
|
## Schritt 2: SQL-Schema erstellen
|
||||||
|
|
||||||
**Create directory structure:**
|
**Verzeichnisstruktur anlegen:**
|
||||||
|
|
||||||
`shared/src/commonMain/sqldelight/com/example/database/`
|
`shared/src/commonMain/sqldelight/com/example/database/`
|
||||||
|
|
||||||
Create `User.sq` file:
|
Datei `User.sq` erstellen:
|
||||||
|
|
||||||
```sql
|
```sql
|
||||||
CREATE TABLE User
|
CREATE TABLE User
|
||||||
@@ -91,48 +91,48 @@ CREATE TABLE User
|
|||||||
imageUrl TEXT
|
imageUrl TEXT
|
||||||
);
|
);
|
||||||
|
|
||||||
-- Insert a new user
|
-- Neuen Benutzer einfügen
|
||||||
insertUser
|
insertUser
|
||||||
:
|
::
|
||||||
INSERT INTO User(name, imageUrl)
|
INSERT INTO User(name, imageUrl)
|
||||||
VALUES (?, ?);
|
VALUES (?, ?);
|
||||||
|
|
||||||
-- Get all users
|
-- Alle Benutzer abrufen
|
||||||
getAllUsers
|
getAllUsers
|
||||||
:
|
::
|
||||||
SELECT *
|
SELECT *
|
||||||
FROM User;
|
FROM User;
|
||||||
|
|
||||||
-- Get user by ID
|
-- Benutzer nach ID abrufen
|
||||||
getUserById
|
getUserById
|
||||||
:
|
::
|
||||||
SELECT *
|
SELECT *
|
||||||
FROM User
|
FROM User
|
||||||
WHERE id = ?;
|
WHERE id = ?;
|
||||||
|
|
||||||
-- Update user
|
-- Benutzer aktualisieren
|
||||||
updateUser
|
updateUser
|
||||||
:
|
::
|
||||||
UPDATE User
|
UPDATE User
|
||||||
SET name = ?,
|
SET name = ?,
|
||||||
imageUrl = ?
|
imageUrl = ?
|
||||||
WHERE id = ?;
|
WHERE id = ?;
|
||||||
|
|
||||||
-- Delete user
|
-- Benutzer löschen
|
||||||
deleteUser
|
deleteUser
|
||||||
:
|
::
|
||||||
DELETE
|
DELETE
|
||||||
FROM User
|
FROM User
|
||||||
WHERE id = ?;
|
WHERE id = ?;
|
||||||
|
|
||||||
-- Delete all users
|
-- Alle Benutzer löschen
|
||||||
deleteAllUsers
|
deleteAllUsers
|
||||||
:
|
::
|
||||||
DELETE
|
DELETE
|
||||||
FROM User;
|
FROM User;
|
||||||
```
|
```
|
||||||
|
|
||||||
## Step 3: Create Database Driver Interface
|
## Schritt 3: Datenbank-Treiber-Interface erstellen
|
||||||
|
|
||||||
In `shared/src/commonMain/kotlin/database/DatabaseDriverFactory.kt`:
|
In `shared/src/commonMain/kotlin/database/DatabaseDriverFactory.kt`:
|
||||||
|
|
||||||
@@ -146,7 +146,7 @@ expect class DatabaseDriverFactory {
|
|||||||
}
|
}
|
||||||
```
|
```
|
||||||
|
|
||||||
## Step 4: Platform-Specific Implementations
|
## Schritt 4: Plattformspezifische Implementierungen
|
||||||
|
|
||||||
### Android —
|
### Android —
|
||||||
|
|
||||||
@@ -211,7 +211,7 @@ actual class DatabaseDriverFactory {
|
|||||||
|
|
||||||
```
|
```
|
||||||
|
|
||||||
## Step 5: Create Repository
|
## Schritt 5: Repository erstellen
|
||||||
|
|
||||||
In `shared/src/commonMain/kotlin/repository/UserRepository.kt`:
|
In `shared/src/commonMain/kotlin/repository/UserRepository.kt`:
|
||||||
|
|
||||||
@@ -255,7 +255,7 @@ class UserRepository(private val database: AppDatabase) {
|
|||||||
|
|
||||||
```
|
```
|
||||||
|
|
||||||
## Step 6: Setup Koin Modules
|
## Schritt 6: Koin-Module konfigurieren
|
||||||
|
|
||||||
In `shared/src/commonMain/kotlin/di/DatabaseModule.kt`:
|
In `shared/src/commonMain/kotlin/di/DatabaseModule.kt`:
|
||||||
|
|
||||||
@@ -275,7 +275,7 @@ val databaseModule = module {
|
|||||||
|
|
||||||
```
|
```
|
||||||
|
|
||||||
### Platform-specific modules
|
### Plattformspezifische Module
|
||||||
|
|
||||||
### Android —
|
### Android —
|
||||||
|
|
||||||
@@ -326,7 +326,7 @@ actual val platformModule = module {
|
|||||||
|
|
||||||
```
|
```
|
||||||
|
|
||||||
### Common module declaration —
|
### Gemeinsame Modul-Deklaration —
|
||||||
|
|
||||||
`shared/src/commonMain/kotlin/di/PlatformModule.kt`:
|
`shared/src/commonMain/kotlin/di/PlatformModule.kt`:
|
||||||
|
|
||||||
@@ -339,7 +339,7 @@ expect val platformModule: Module
|
|||||||
|
|
||||||
```
|
```
|
||||||
|
|
||||||
## Step 7: Initialize Koin
|
## Schritt 7: Koin initialisieren
|
||||||
|
|
||||||
In `shared/src/commonMain/kotlin/di/KoinInit.kt`:
|
In `shared/src/commonMain/kotlin/di/KoinInit.kt`:
|
||||||
|
|
||||||
@@ -359,7 +359,7 @@ fun initKoin(appDeclaration: KoinAppDeclaration = {}) = startKoin {
|
|||||||
|
|
||||||
```
|
```
|
||||||
|
|
||||||
## Step 8: Platform Initialization
|
## Schritt 8: Plattform-Initialisierung
|
||||||
|
|
||||||
### Android —
|
### Android —
|
||||||
|
|
||||||
@@ -423,9 +423,9 @@ fun main() {
|
|||||||
|
|
||||||
```
|
```
|
||||||
|
|
||||||
## Step 9: Use in Compose
|
## Schritt 9: In Compose verwenden
|
||||||
|
|
||||||
### Create VieModel —
|
### ViewModel erstellen —
|
||||||
|
|
||||||
In `shared/src/commonMain/kotlin/viewmodel/UserViewModel.kt`:
|
In `shared/src/commonMain/kotlin/viewmodel/UserViewModel.kt`:
|
||||||
|
|
||||||
@@ -478,7 +478,7 @@ class UserViewModel(private val userRepository: UserRepository) : ViewModel() {
|
|||||||
|
|
||||||
```
|
```
|
||||||
|
|
||||||
Use in Compose Screen:
|
Im Compose-Screen verwenden:
|
||||||
|
|
||||||
```kotlin
|
```kotlin
|
||||||
@Composable
|
@Composable
|
||||||
@@ -509,21 +509,20 @@ fun UserItem(user: User, onDelete: () -> Unit) {
|
|||||||
)
|
)
|
||||||
|
|
||||||
Button(onClick = onDelete) {
|
Button(onClick = onDelete) {
|
||||||
Text("Delete")
|
Text("Löschen")
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
```
|
```
|
||||||
|
|
||||||
### That’s It!
|
### Fertig!
|
||||||
|
|
||||||
You now have SQLDelight fully integrated in your Compose Multiplatform project with:
|
SQLDelight ist nun vollständig in das Compose Multiplatform-Projekt integriert mit:
|
||||||
|
|
||||||
- Database working on Android, iOS, and Desktop
|
- Datenbankbetrieb auf Android, iOS und Desktop
|
||||||
- Koin dependency injection setup
|
- Koin Dependency Injection konfiguriert
|
||||||
- Repository pattern for clean architecture
|
- Repository-Pattern für Clean Architecture
|
||||||
- Ready-to-use User table with CRUD operations
|
- Einsatzbereite User-Tabelle mit CRUD-Operationen
|
||||||
|
|
||||||
The database will automatically handle platform-specific implementations while sharing the same business logic across
|
Die Datenbank verwaltet automatisch die plattformspezifischen Implementierungen, während dieselbe Geschäftslogik auf allen Plattformen geteilt wird.
|
||||||
all platforms.
|
|
||||||
|
|||||||
@@ -31,7 +31,7 @@ owner: DevOps Engineer
|
|||||||
Keycloak-Secrets.
|
Keycloak-Secrets.
|
||||||
*[ ] **Stack-Launch (dc-infra.yaml):** * Start von **Postgres**, **Keycloak** und **Valkey** (Redis-Alternative).
|
*[ ] **Stack-Launch (dc-infra.yaml):** * Start von **Postgres**, **Keycloak** und **Valkey** (Redis-Alternative).
|
||||||
*[ ] **Wichtig:** Kontrolle der Logs auf ARM64-Kompatibilität (`exec format error` vermeiden).
|
*[ ] **Wichtig:** Kontrolle der Logs auf ARM64-Kompatibilität (`exec format error` vermeiden).
|
||||||
*[ ] **Netzwerk-Check:** * Testen der Erreichbarkeit von Zoras Mail-Relay (`10.0.6.1:25`) aus dem neuen Stack heraus.
|
*[ ] **Netzwerk-Check:** * Testen der Erreichbarkeit von Zoras Mail-Relay (`10.0.0.20:25`) aus dem neuen Stack heraus.
|
||||||
|
|
||||||
---
|
---
|
||||||
|
|
||||||
@@ -40,8 +40,8 @@ owner: DevOps Engineer
|
|||||||
**Ziel:** Den Ping-Service über das Spring Cloud Gateway erreichbar machen.
|
**Ziel:** Den Ping-Service über das Spring Cloud Gateway erreichbar machen.
|
||||||
|
|
||||||
*[ ] **Backend-Start (dc-backend.yaml):** * Deployment des **api-gateways** und des **ping-services**.
|
*[ ] **Backend-Start (dc-backend.yaml):** * Deployment des **api-gateways** und des **ping-services**.
|
||||||
*[ ] **Cloudflare-Tunnel Update:** * Hinzufügen der Route `api.mo-code.at`, die auf die IP der Meldestelle (`10.0.6.50`)
|
*[ ] **Pangolin-Tunnel Update:** * Hinzufügen der Route `api.mo-code.at`, die auf die IP der Meldestelle (`10.0.0.50`)
|
||||||
und den Port des Gateways (`8080`) zeigt.
|
und den Port des Gateways (`8081`) zeigt.
|
||||||
*[ ] **Keycloak-Veredelung:** * Konfiguration des Realms und Erstellen des Clients für die Meldestelle im
|
*[ ] **Keycloak-Veredelung:** * Konfiguration des Realms und Erstellen des Clients für die Meldestelle im
|
||||||
Keycloak-Admin-Panel (via `auth.mo-code.at`).
|
Keycloak-Admin-Panel (via `auth.mo-code.at`).
|
||||||
|
|
||||||
|
|||||||
@@ -9,7 +9,7 @@ tags: [e2e, smoke, docker, migration, ktor-3.4.0, exposed-1.0.0]
|
|||||||
|
|
||||||
# E2E Smoke – Migration Exposed 1.0.0 & Ktor 3.4.0
|
# E2E Smoke – Migration Exposed 1.0.0 & Ktor 3.4.0
|
||||||
|
|
||||||
## Setup
|
## Einrichtung
|
||||||
- Compose: docker compose --profile all up --build -d
|
- Compose: docker compose --profile all up --build -d
|
||||||
- Services (Auszug):
|
- Services (Auszug):
|
||||||
- api-gateway (8080/actuator, 8080/api via Proxy)
|
- api-gateway (8080/actuator, 8080/api via Proxy)
|
||||||
@@ -25,11 +25,11 @@ tags: [e2e, smoke, docker, migration, ktor-3.4.0, exposed-1.0.0]
|
|||||||
- Web-App Health: 200 OK (Fallback-Assets aktiv, Favicon bereitgestellt)
|
- Web-App Health: 200 OK (Fallback-Assets aktiv, Favicon bereitgestellt)
|
||||||
- Desktop-App: Xvfb/XFCE/x11vnc/noVNC aktiv, Zugriff via http://localhost:6080/
|
- Desktop-App: Xvfb/XFCE/x11vnc/noVNC aktiv, Zugriff via http://localhost:6080/
|
||||||
|
|
||||||
## Observability
|
## Beobachtbarkeit
|
||||||
- Prometheus-Metriken erreichbar (Gateway/Ping)
|
- Prometheus-Metriken erreichbar (Gateway/Ping)
|
||||||
- Logs ohne kritische Fehler im Happy Path
|
- Logs ohne kritische Fehler im Happy Path
|
||||||
|
|
||||||
## Issues & Notes
|
## Probleme & Hinweise
|
||||||
- Frontend KMP/JS-Build schlägt in Builder aktuell fehl (fehlende JS-Implementierungen in Auth/Ping-Data). Nginx liefert Fallback-Assets aus; Favicon hinzugefügt, um 404 zu vermeiden.
|
- Frontend KMP/JS-Build schlägt in Builder aktuell fehl (fehlende JS-Implementierungen in Auth/Ping-Data). Nginx liefert Fallback-Assets aus; Favicon hinzugefügt, um 404 zu vermeiden.
|
||||||
|
|
||||||
## Entscheidung
|
## Entscheidung
|
||||||
|
|||||||
@@ -0,0 +1,73 @@
|
|||||||
|
# Journal - 2026-03-06 (Session 2)
|
||||||
|
|
||||||
|
## 📝 Zusammenfassung
|
||||||
|
|
||||||
|
Strategische Planungssession mit dem Lead Architect. Drei konkrete Bugs aus der Tiefenanalyse behoben (Valkey-Inkonsistenz, Dependency Verification, backup.sh Hardcodes). Vollständige Schritt-für-Schritt-Anleitung für das heutige Meldestellen-Host-Setup erstellt. Architektur-Entscheidung für einen lokalen AI-Stack (Ollama + Open WebUI) als separaten Proxmox LXC-Container (CT 111) auf Zora getroffen und Installations-Anleitung dokumentiert. Korrektur: Zora läuft auf Proxmox 8.4.10 (nicht Incus); IPs im Netz 10.0.0.0/24.
|
||||||
|
|
||||||
|
---
|
||||||
|
|
||||||
|
## 🛠️ Änderungen
|
||||||
|
|
||||||
|
### 1. Bug-Fixes aus Tiefenanalyse
|
||||||
|
|
||||||
|
* **`dc-backend.yaml`:** ping-service von veralteten `SPRING_DATA_REDIS_*` auf `SPRING_DATA_VALKEY_*` umgestellt — konsistent mit api-gateway.
|
||||||
|
* **`gradle.properties`:** `org.gradle.dependency.verification=lenient` → `strict` — Sicherheits-Level angehoben, da eigene Gitea-Registry vorhanden.
|
||||||
|
* **`config/scripts/backup.sh`:** `.env` via `source` geladen, `grandmo`-Hardcode entfernt, `DB_USER` liest `${POSTGRES_USER}` aus `.env`, `BACKUP_DIR` und `BACKUP_RETENTION_DAYS` konfigurierbar.
|
||||||
|
* **`.env` + `.env.example`:** `BACKUP_DIR` und `BACKUP_RETENTION_DAYS` als neue SSoT-Variablen ergänzt.
|
||||||
|
|
||||||
|
### 2. Neue Dokumentation
|
||||||
|
|
||||||
|
* **`docs/01_Architecture/Minisforum-MS-R1/AI_Stack_Ollama_Setup.md`:** Vollständige Installations-Anleitung für Ollama + Open WebUI auf Zora als Proxmox LXC-Container (CT 111, IP 10.0.0.60). Enthält Hardware-Profil (CIX P1 / CP8180), CPU-Governor-Tuning auf Proxmox-Node, `pct create`-Befehle, Modell-Matrix, Open-WebUI-RAG-Setup, Pangolin-Routing und IntelliJ IDEA Continue.dev-Integration.
|
||||||
|
|
||||||
|
---
|
||||||
|
|
||||||
|
## 🏗️ Architektur-Entscheidungen
|
||||||
|
|
||||||
|
### AI-Stack: Separater Proxmox LXC-Container (nicht im App-Repo)
|
||||||
|
|
||||||
|
**Entscheidung:** Ollama + Open WebUI laufen in einem eigenen Proxmox LXC-Container `ai-stack` (CT 111, IP 10.0.0.60), **nicht** als Docker-Service im Meldestelle-Repo.
|
||||||
|
|
||||||
|
**Begründung:**
|
||||||
|
* Modelle (5–40 GB pro Modell) wachsen unkontrolliert — Isolation schützt den App-Stack.
|
||||||
|
* Unabhängige Updates ohne Risiko für den Meldestelle-Produktivbetrieb.
|
||||||
|
* RAM/CPU-Hunger der KI-Inference beeinflusst nicht die Keycloak/Gateway/DB-Verfügbarkeit.
|
||||||
|
|
||||||
|
### Datenschutz: Vollständig lokal via Ollama
|
||||||
|
|
||||||
|
* Kein Byte verlässt das Heimnetz — alle Inferenz läuft auf Zora CPU (CIX P1, 12 Cores).
|
||||||
|
* IDEA-Integration via **Continue.dev Plugin** mit `http://10.0.0.60:11434` als Endpoint.
|
||||||
|
* Pangolin-Route `ai.mo-code.at` → nur intern / VPN exponieren.
|
||||||
|
|
||||||
|
### NPU: Noch nicht nutzbar
|
||||||
|
|
||||||
|
* CIX P1 NPU aktuell **kein** Ollama/llama.cpp-Support.
|
||||||
|
* Immortalis-G720 (Vulkan 1.3) — experimentell, nachrüsten sobald stabil.
|
||||||
|
* Primärer Pfad: CPU-Inferenz mit NEON/SVE2-Optimierungen (ARM64-native Ollama).
|
||||||
|
|
||||||
|
---
|
||||||
|
|
||||||
|
## 📚 Gelerntes
|
||||||
|
|
||||||
|
* **CIX P1 (CP8180) = Tri-Cluster ARM:** 4x Cortex-X4 (fast) + 4x A720 (medium) + 4x A520 (slow) — alle 12 Kerne Ollama zuweisen, CPU-Governor auf `performance` setzen.
|
||||||
|
* **64 GB RAM = 70B-Modelle möglich:** `llama3.1:70b` (~40 GB) läuft vollständig im RAM — einzigartige Stärke dieser Hardware.
|
||||||
|
* **Proxmox vmbr0:** Routing und NAT werden von Proxmox via `vmbr0` automatisch verwaltet — keine manuelle iptables-Regel nötig.
|
||||||
|
* **Kafka-Entscheidung bestätigt:** Bleibt im Build für Phase 3 (Outbox-Pattern / Event-Driven).
|
||||||
|
* **Ghost Services bleiben ON HOLD:** Bewusste Entscheidung — erst Fachexperten-Session (FEI/ÖTO Regelwerk) bevor fachliche Implementierung beginnt.
|
||||||
|
|
||||||
|
---
|
||||||
|
|
||||||
|
## 🔜 Nächste Schritte
|
||||||
|
|
||||||
|
### Heute Abend (Priorität)
|
||||||
|
1. Meldestellen-Host aufsetzen nach Anleitung (siehe Haupt-Session-Log)
|
||||||
|
2. `.env` auf Zora mit Server-IP konfigurieren (`KC_HOSTNAME`, `JWT_ISSUER_URI`)
|
||||||
|
3. Docker-Stack starten (Infra → Backend → Ops)
|
||||||
|
4. Ping-Service + Login verifizieren
|
||||||
|
5. `ai-stack` Proxmox LXC-Container (CT 111) aufsetzen, Ollama + Open WebUI installieren
|
||||||
|
6. Continue.dev in IDEA konfigurieren
|
||||||
|
|
||||||
|
### Nächste Sessions
|
||||||
|
* **Session 2:** Grafana Dashboards einrichten + Pangolin-URLs finalisieren
|
||||||
|
* **Session 3:** Willkommensseite + Design-System (Tokens, Farben, Typografie)
|
||||||
|
* **Session 4:** Fachexperten-Session — FEI/ÖTO Regelwerk, Anforderungen, Rollen definieren
|
||||||
|
* **Session 5:** Admin-Dashboard (Backend) + Rollen-Management in Keycloak
|
||||||
@@ -0,0 +1,74 @@
|
|||||||
|
---
|
||||||
|
type: Journal
|
||||||
|
status: ACTIVE
|
||||||
|
owner: Curator
|
||||||
|
date: 2026-03-06
|
||||||
|
session: Immich & Pangolin — Konfiguration dokumentiert
|
||||||
|
---
|
||||||
|
|
||||||
|
# Session Log — 2026-03-06: Immich & Pangolin Konfiguration
|
||||||
|
|
||||||
|
## 📋 Kontext
|
||||||
|
|
||||||
|
Ergänzungssession zur Proxmox-Korrektursession vom selben Tag.
|
||||||
|
10 neue Screenshots wurden geliefert, die die vollständige Konfiguration von
|
||||||
|
CT 100 (pangolin-client) und CT 103 (immich) sowie die detaillierten Hardware-Specs
|
||||||
|
von VM 102 (gitea-runner) dokumentieren.
|
||||||
|
|
||||||
|
---
|
||||||
|
|
||||||
|
## 🛠️ Änderungen
|
||||||
|
|
||||||
|
### `SSoT_Konfigurations-Masterplan_Zora.md`
|
||||||
|
|
||||||
|
**Neue Daten aus Screenshots (06.03.2026, 13:25–13:27):**
|
||||||
|
|
||||||
|
#### CT 100 — pangolin-client (LXC)
|
||||||
|
- IP ergänzt: `10.0.0.21/24`
|
||||||
|
- Ressourcen dokumentiert: 4 Cores, 512 MiB RAM, 512 MiB Swap, 8 GB Disk
|
||||||
|
- OS: Ubuntu arm64, Unprivileged, nesting=1
|
||||||
|
- Autostart: order=1, up=30
|
||||||
|
|
||||||
|
#### CT 101 — gitea (LXC)
|
||||||
|
- Ressourcen ergänzt: 4 Cores, 1 GiB RAM, 512 MiB Swap, 20 GB Disk
|
||||||
|
- OS: Ubuntu arm64, Unprivileged, nesting=1
|
||||||
|
- Autostart: order=2, up=30
|
||||||
|
|
||||||
|
#### CT 103 — immich (LXC) ← NEU vollständig dokumentiert
|
||||||
|
- IP: `10.0.0.24/24`
|
||||||
|
- Ressourcen: 8 Cores, 10 GiB RAM, 512 MiB Swap
|
||||||
|
- Root Disk: 200 GB (`local:103/vm-103-disk-0.raw`)
|
||||||
|
- Mount Point mp0: `/mnt/immich_gross` → `/mnt/fotos` (externe Foto-Bibliothek)
|
||||||
|
- OS: Ubuntu arm64, Unprivileged
|
||||||
|
- Features: `nesting=1, keyctl=1, fuse=1` (Docker-in-LXC kompatibel)
|
||||||
|
- Autostart: order=3, up=30
|
||||||
|
|
||||||
|
#### VM 102 — gitea-runner (QEMU/KVM) ← Hardware-Details ergänzt
|
||||||
|
- IP: `10.0.0.23/24` (bestätigt)
|
||||||
|
- BIOS: OVMF (UEFI), Machine: virt (ARM64)
|
||||||
|
- CPU: 8 Cores, 1 Socket, host-type, numa=1
|
||||||
|
- RAM: 16 GiB (balloon=0 — kein Dynamic Memory)
|
||||||
|
- Disk: 50 GB SSD (aio=io_uring, iothread=1 — maximale I/O-Performance)
|
||||||
|
- EFI Disk: 64 MB, efitype=4m
|
||||||
|
- Netzwerk: virtio, vmbr0, Firewall aktiv
|
||||||
|
- SCSI: VirtIO SCSI single
|
||||||
|
|
||||||
|
#### Pangolin Tunnel Routing erweitert
|
||||||
|
- Route `photos.mo-code.at` → CT 103 Immich (`10.0.0.24:2283`) ergänzt (intern/VPN)
|
||||||
|
- Pangolin-Kontext-Hinweis: CT 100 (10.0.0.21) ist der Tunnel-Client
|
||||||
|
|
||||||
|
---
|
||||||
|
|
||||||
|
## 📚 Gelernt
|
||||||
|
|
||||||
|
- **Immich Features:** `keyctl=1` und `fuse=1` sind für Docker-in-LXC und Immich-Thumbnail-Verarbeitung notwendig.
|
||||||
|
- **io_uring:** Der Gitea-Runner nutzt modernes async I/O für maximale Build-Performance auf NVMe.
|
||||||
|
- **Start-Reihenfolge:** Pangolin (order=1) → Gitea (order=2) → Immich (order=3) — sinnvolle Abhängigkeitskette.
|
||||||
|
- **balloon=0 beim Runner:** Festes RAM verhindert Memory-Ballooning-Latenzen bei intensiven CI-Builds.
|
||||||
|
|
||||||
|
---
|
||||||
|
|
||||||
|
## 🔜 Nächste Schritte
|
||||||
|
|
||||||
|
1. Pangolin-Route `photos.mo-code.at` im Pangolin-Dashboard anlegen (sobald Immich-Setup abgeschlossen).
|
||||||
|
2. Immich-Setup-Anleitung erstellen (optional, eigene Session).
|
||||||
@@ -0,0 +1,57 @@
|
|||||||
|
---
|
||||||
|
type: Journal
|
||||||
|
status: ACTIVE
|
||||||
|
owner: Lead Architect
|
||||||
|
---
|
||||||
|
# Journal - 2026-03-06 (Session 3 — Proxmox-Korrektur)
|
||||||
|
|
||||||
|
## 📝 Zusammenfassung
|
||||||
|
|
||||||
|
Korrektur-Session: Die vorherige Installations-Anleitung für den AI-Stack verwendete fälschlicherweise **Incus** als Container-Technologie und das IP-Subnetz **10.0.6.x**. Die Analyse der Proxmox-Screenshots ergab den korrekten Ist-Stand: Zora läuft auf **Proxmox VE 8.4.10** (`pve.mo-code.at`), alle VMs und Container befinden sich im Subnetz **10.0.0.0/24**. Alle betroffenen Dokumentationsdateien wurden korrigiert.
|
||||||
|
|
||||||
|
---
|
||||||
|
|
||||||
|
## 🔍 Ist-Stand Zora (aus Proxmox-Screenshots)
|
||||||
|
|
||||||
|
| ID | Name | Typ | IP | Specs |
|
||||||
|
|:----|:------------------|:-----|:-------------|:-------------------------------|
|
||||||
|
| 100 | pangolin-client | LXC | — | Pangolin Tunnel |
|
||||||
|
| 101 | gitea | LXC | `10.0.0.22` | Bridge vmbr0, GW 10.0.0.138 |
|
||||||
|
| 102 | gitea-runner | VM | `10.0.0.24` | aarch64, 16 GB RAM, 8 Cores, 50 GB |
|
||||||
|
| 103 | immich | LXC | — | Immich Foto-Server |
|
||||||
|
| 110 | meldestelle-host | VM | `10.0.0.50` | aarch64, 16 GB RAM, 8 Cores, 150 GB |
|
||||||
|
|
||||||
|
* **Proxmox-Node:** `10.0.0.20` / `pve.mo-code.at`
|
||||||
|
* **Netz-Bridge:** `vmbr0`, Subnetz `10.0.0.0/24`, Gateway `10.0.0.138`
|
||||||
|
* **Beide VMs (102, 110):** QEMU KVM, aarch64, UEFI (OVMF), cpu=host, numa=1
|
||||||
|
|
||||||
|
---
|
||||||
|
|
||||||
|
## 🛠️ Geänderte Dateien
|
||||||
|
|
||||||
|
| Datei | Änderung |
|
||||||
|
|:------|:---------|
|
||||||
|
| `docs/01_Architecture/Minisforum-MS-R1/AI_Stack_Ollama_Setup.md` | Vollständiger Rewrite: Incus→Proxmox LXC (CT 111), `incus launch`→`pct create`, alle IPs 10.0.6.x→10.0.0.x, Phase 1 auf Proxmox-Node, Incus-NAT-Sektion entfernt |
|
||||||
|
| `docs/99_Journal/2026-03-06_Session_Log_DevOps_und_AI_Stack.md` | AI-Stack-Entscheidung korrigiert: Incus→Proxmox, IPs aktualisiert, iptables→vmbr0 |
|
||||||
|
| `docs/01_Architecture/MASTER_ROADMAP_2026_Q1.md` | Hypervisor: Incus→Proxmox VE 8.4.10 |
|
||||||
|
| `docs/01_Architecture/Minisforum-MS-R1/SSoT_Konfigurations-Masterplan_Zora.md` | Vollständiger Rewrite: Proxmox-Tabelle mit allen VMs/LXCs, IPs korrigiert, Images auf aktuelle Versionen |
|
||||||
|
| `docs/01_Architecture/Minisforum-MS-R1/Zentrales_Mail-Relay-SSoT_Zora.md` | SMTP-Host: 10.0.6.1→10.0.0.20, Incus/Docker→Proxmox vmbr0/Docker |
|
||||||
|
| `docs/07_Infrastructure/Zora_Infrastructure_Deployment_02-2026.md` | Mail-Relay-IP korrigiert, Cloudflare→Pangolin, Port 8080→8081, IP 10.0.6.50→10.0.0.50 |
|
||||||
|
| `docs/01_Architecture/Minisforum-MS-R1/MS-R1_Konfiguration&Bedienung.md` | Firewall-Sektion auf Proxmox aktualisiert, Incus-Sektion als ⚠️ HISTORISCH markiert |
|
||||||
|
|
||||||
|
---
|
||||||
|
|
||||||
|
## 📚 Gelerntes
|
||||||
|
|
||||||
|
* **Incus war Testbetrieb (Feb 2026):** Nach dem Incus-Test wurde auf Proxmox VE umgestellt — alle Docs spiegelten noch den alten Zustand wider.
|
||||||
|
* **Proxmox vmbr0 vereinfacht NAT:** Keine manuellen iptables-MASQUERADE-Regeln nötig — Proxmox erledigt das automatisch.
|
||||||
|
* **Core-Pinning in Proxmox:** Gitea-Runner und Meldestelle-Host sind auf 8 Kerne (4 große + 4 mittlere) gebunden → `cpu=host`, `numa=1` in VM-Config.
|
||||||
|
* **Docs-as-Code Pflicht:** Screenshots als Primärquelle genutzt um den wahren Ist-Stand zu ermitteln — wichtig wenn mündliche Korrekturen noch nicht in Docs eingeflossen sind.
|
||||||
|
|
||||||
|
---
|
||||||
|
|
||||||
|
## 🔜 Nächste Schritte
|
||||||
|
|
||||||
|
1. AI-Stack LXC (CT 111, `10.0.0.60`) in Proxmox erstellen nach `AI_Stack_Ollama_Setup.md`
|
||||||
|
2. Continue.dev Plugin in IDEA konfigurieren
|
||||||
|
3. Grafana Dashboards + Pangolin-URLs finalisieren
|
||||||
@@ -0,0 +1,54 @@
|
|||||||
|
---
|
||||||
|
type: Journal
|
||||||
|
status: FINAL
|
||||||
|
owner: Lead Architect
|
||||||
|
date: 2026-03-06
|
||||||
|
---
|
||||||
|
# Session Log – Übersetzung aller Dokumente auf Deutsch
|
||||||
|
|
||||||
|
**Datum:** 06.03.2026
|
||||||
|
**Agent:** 🏗️ Lead Architect (Curator)
|
||||||
|
**Ziel:** Alle englischsprachigen Markdown-Dateien in `docs/` auf Deutsch übersetzen.
|
||||||
|
|
||||||
|
---
|
||||||
|
|
||||||
|
## Ausgangslage
|
||||||
|
|
||||||
|
Ein automatischer Sprachscan hat 7 Dateien identifiziert, die noch überwiegend auf Englisch verfasst waren. Alle anderen Dokumente waren bereits auf Deutsch.
|
||||||
|
|
||||||
|
---
|
||||||
|
|
||||||
|
## Übersetzte Dateien
|
||||||
|
|
||||||
|
| Datei | Bereich | Anmerkung |
|
||||||
|
|---|---|---|
|
||||||
|
| `01_Architecture/02_Frontend_Architecture.md` | Architektur | Vollständige Übersetzung inkl. ADR-Abschnitte |
|
||||||
|
| `01_Architecture/adr/001-backend-infrastructure-decisions.md` | ADR | Vollständige Übersetzung, Code-Blöcke unverändert |
|
||||||
|
| `01_Architecture/adr/000-PENDING-backend-infrastructure-decisions.md` | ADR | Kurzdokument, vollständig übersetzt |
|
||||||
|
| `01_Architecture/Reference/Tech_Stack/Gradle_Kotlin_DSL_Primer.md` | Referenz | Fließtext übersetzt, Code-Kommentare eingedeutscht |
|
||||||
|
| `01_Architecture/Reference/Tech_Stack/Kotlin_2-3-0_ReleaseNotes.md` | Referenz | Vollständige Übersetzung der Release Notes |
|
||||||
|
| `02_Guides/SQLDelight_Integration_Compose_Multiplatform.md` | Anleitung | Schritt-für-Schritt-Anleitung eingedeutscht, Code unverändert |
|
||||||
|
| `90_Reports/2026-01-31_E2E_Smoke_Migration_Exposed_Ktor.md` | Report | War bereits größtenteils Deutsch – fehlende Abschnittsüberschriften übersetzt |
|
||||||
|
|
||||||
|
---
|
||||||
|
|
||||||
|
## Prinzipien bei der Übersetzung
|
||||||
|
|
||||||
|
- **Code-Blöcke:** Unverändert — nur Kommentare innerhalb von Code-Blöcken wurden übersetzt
|
||||||
|
- **Fachbegriffe:** Etablierte englische Fachbegriffe (Clean Architecture, Repository, ViewModel, Use Case, etc.) wurden beibehalten
|
||||||
|
- **Frontmatter:** Werte wie `ACTIVE`, `DRAFT`, `Report` etc. blieben unverändert (technische Metadaten)
|
||||||
|
- **Externe Quellenangaben:** URLs und Quellenverweise blieben auf Englisch
|
||||||
|
|
||||||
|
---
|
||||||
|
|
||||||
|
## Gelerntes
|
||||||
|
|
||||||
|
- Der automatische Sprachscan via Python-Regex ist ein effizientes Werkzeug zur Identifizierung englischer Dokumente
|
||||||
|
- Manche Dokumente waren bereits hybrid (z.B. der E2E-Report) — dort genügten gezielte Korrekturen der Abschnittsüberschriften
|
||||||
|
|
||||||
|
---
|
||||||
|
|
||||||
|
## Nächste Schritte
|
||||||
|
|
||||||
|
- Bei neuen Dokumenten: direkt auf Deutsch verfassen
|
||||||
|
- Neue externe Referenzen (z.B. Release Notes) beim Einpflegen sofort übersetzen
|
||||||
|
After Width: | Height: | Size: 54 KiB |
|
After Width: | Height: | Size: 55 KiB |
|
After Width: | Height: | Size: 58 KiB |
|
After Width: | Height: | Size: 54 KiB |
|
After Width: | Height: | Size: 61 KiB |
|
After Width: | Height: | Size: 58 KiB |
|
After Width: | Height: | Size: 57 KiB |
|
After Width: | Height: | Size: 54 KiB |
|
After Width: | Height: | Size: 59 KiB |
|
After Width: | Height: | Size: 72 KiB |
|
After Width: | Height: | Size: 55 KiB |
|
After Width: | Height: | Size: 54 KiB |
|
After Width: | Height: | Size: 71 KiB |
|
After Width: | Height: | Size: 65 KiB |
|
After Width: | Height: | Size: 64 KiB |
|
After Width: | Height: | Size: 70 KiB |