Compare commits

...
25 Commits
Author SHA1 Message Date
Scrublord MacBadandClaude Haiku 4.5 6bcbe9cc9e Add Gitea Actions workflows for CI/CD automation
Auto-Deploy on Push / verify-and-notify (push) Has been cancelled
- deploy-on-push.yml: Verify YAML, check SOPS encryption, notify on deployments
- milestone-release.yml: Auto-create releases on milestone tags

Triggers:
- deploy-on-push: On any push to main (apps/clusters changes)
- milestone-release: On git tag m*-*-complete

Co-Authored-By: Claude Haiku 4.5 <noreply@anthropic.com>
2026-05-14 23:29:50 +02:00
Scrublord MacBadandClaude Haiku 4.5 b8da70b14b Add status summary and prioritized next steps to TASKS.md
Add at top of TASKS.md:
- Status Summary table (quick view of progress)
- Priority distribution (CRITICAL/HIGH/MEDIUM/LOW)
- Next Steps section (this week, 1-2 weeks)
- Each task includes: description, effort estimate, blocking factors

Makes task list immediately actionable and progress trackable.

Co-Authored-By: Claude Haiku 4.5 <noreply@anthropic.com>
2026-05-14 23:08:00 +02:00
Scrublord MacBadandClaude Haiku 4.5 4cf6702f85 Add comprehensive task list and VSCode todo-tree integration
Add docs/TASKS.md:
- Completed tasks (6): K3S, Flux, ESS, Themes, Desktop Scripts, Monitoring, TURN
- In Progress: Authentik Stage 2 (pending manual config)
- Backlog (15+): Element Call Fork, PostgreSQL migration, NetworkPolicies, etc.
- Security hardening: Host/Cluster/App layer recommendations
- Milestones: Track progress from M1 (Basic) to M7 (Enterprise)

Enhance devcontainer.json:
- Add gruntfuggly.todo-tree extension for task tree view
- Add ms-vscode.makefile-tools for build automation
- Add GitHub.copilot for development assistance
- Configure todo-tree to highlight TASKS.md and deployment guides

Co-Authored-By: Claude Haiku 4.5 <noreply@anthropic.com>
2026-05-14 23:05:33 +02:00
Scrublord MacBadandClaude Haiku 4.5 aee9a34369 Add 5 detailed deployment guides to docs/deployment-guides/
- 01-turn-server-setup.md: TURN Server architecture, deployment, verification
- 02-authentik-identity-provider.md: Two-stage OIDC integration (Stage 1 & Stage 2)
- 03-monitoring-integration.md: Alloy, Prometheus, Loki integration with Selendis
- 04-element-customization.md: Custom themes (7), desktop setup scripts, admin panel
- 05-room-policies.md: Message retention, room publication, auto-join policies

All guides include troubleshooting, configuration examples, and best practices.

Co-Authored-By: Claude Haiku 4.5 <noreply@anthropic.com>
2026-05-14 22:47:38 +02:00
Scrublord MacBadandClaude Haiku 4.5 e6ef29c1e9 Add deployment documentation structure & overview
Create docs/deployment-guides/ directory with comprehensive README covering:
- Deployment order for all 5 major features
- Architecture overview
- Critical values & configuration
- Links to detailed guides

Full documentation files:
- 01-turn-server-setup.md
- 02-authentik-identity-provider.md
- 03-monitoring-integration.md
- 04-element-customization.md
- 05-room-policies.md

To be added in follow-up commits.

Co-Authored-By: Claude Haiku 4.5 <noreply@anthropic.com>
2026-05-14 22:46:00 +02:00
Scrublord MacBadandClaude Haiku 4.5 857c3965ef Add devcontainer for cross-platform development
- Dockerfile with all required tools (kubectl, flux, helm, sops, age, etc.)
- devcontainer.json with VSCode config and extensions
- postCreateCommand.sh for setup verification
- Comprehensive README with setup instructions for macOS, Windows/WSL2, Linux
- Automatic mounts for kubeconfig, SSH keys, age encryption keys
- SOPS_AGE_KEY_FILE and KUBECONFIG pre-configured

Enables development on Windows, macOS, and Linux with consistent environment.

Co-Authored-By: Claude Haiku 4.5 <noreply@anthropic.com>
2026-05-14 22:27:52 +02:00
Scrublord MacBad d37a65f4fa fix element web image version missing 2026-05-14 22:07:34 +02:00
Scrublord MacBad e6abd0fb3f feat: reinstate roomlist fork after config map fix 2026-05-14 21:59:34 +02:00
Scrublord MacBadandClaude Haiku 4.5 d3362180ea fix: Complete JSON structure in element-values.yaml
The config.json was truncated and had unclosed brackets. This prevented
Helm from properly merging the ElementWeb configuration, so the custom themes
were never loaded into the cluster.

This fix:
- Closes the unclosed JSON brackets
- Validates the full JSON structure
- Removes duplicate/extra closing brackets
- Ensures all 6 custom themes are properly included

Co-Authored-By: Claude Haiku 4.5 <noreply@anthropic.com>
2026-05-14 21:55:22 +02:00
Scrublord MacBadandClaude Haiku 4.5 5f50a60071 feat: Automate ConfigMap checksum updates via Git pre-commit hook
- Add pre-commit hook (scripts/hooks/pre-commit) that automatically calculates
  MD5 checksums of ConfigMaps (element-values.yaml, synapse-values.yaml)
- Update annotations in kustomization.yaml to trigger Flux CD HelmRelease syncs
- Add install script (scripts/install-hooks.sh) for easy hook setup
- Add comprehensive documentation (docs/ops-configmap-sync.md) explaining:
  * Why Flux doesn't auto-detect ConfigMap changes
  * How the checksum-based workaround works
  * How to install and use the hook
  * Troubleshooting and manual sync procedures
- Update README.md with post-clone hook installation step

This solves the issue where Flux CD doesn't automatically re-deploy when external
ConfigMaps are modified. Users no longer need manual checksum updates.

Co-Authored-By: Claude Haiku 4.5 <noreply@anthropic.com>
2026-05-14 21:43:01 +02:00
Scrublord MacBad 174e9721ed Revert "test: verify pre-commit hook updates checksums"
This reverts commit 5f14376bdb.
2026-05-14 21:42:25 +02:00
Scrublord MacBad 5f14376bdb test: verify pre-commit hook updates checksums 2026-05-14 21:42:13 +02:00
Scrublord MacBadandClaude Haiku 4.5 81a30e21b9 Fix: HelmRelease reconciliation on ConfigMap changes
- Reduce HelmRelease interval from 1h to 5m for faster sync
- Add checksum annotation to trigger reconciliation when element-values.yaml changes
- This ensures Flux CD re-deploys the chart when themes/config updates are made

To update the checksum after editing element-values.yaml:
  md5sum apps/production/custom-configs/element-values.yaml
  # Update the value in apps/production/kustomization.yaml patches[0].patch

Co-Authored-By: Claude Haiku 4.5 <noreply@anthropic.com>
2026-05-14 21:37:07 +02:00
sorb f81fda12d4 Update apps/production/element-server-suite.yaml 2026-05-13 14:48:08 +00:00
sorb fe0165a509 Update apps/production/element-server-suite.yaml
new docker image for elementWeb
2026-05-13 14:43:50 +00:00
Scrublord MacBad dc17158fe2 fix themes 2026-05-11 10:48:16 +02:00
Scrublord MacBad 0c81de057f fix config url element web 2026-05-11 10:43:35 +02:00
sorb aaa197fbb5 Feat: Lab roomslist v3 & new aXion Theme 2026-05-11 08:28:30 +00:00
Scrublord MacBad e0ed10598f Update Element Web to use custom fork image
- Registry: rohana.axion1337.de
- Repository: sorb/threadnet-web
- Tag: v0.1.0
2026-05-10 23:44:35 +02:00
sorb d39ce5a3a0 Feat: deactivate legacy calls 2026-05-10 19:43:54 +00:00
Scrublord MacBad 68bf4e213c Revert to ESS 26.4.0 - URL preview issues in 26.5.0 2026-05-08 00:39:20 +02:00
Scrublord MacBad 644dff9c48 Upgrade to ESS 26.5.0 with oembed support 2026-05-08 00:29:39 +02:00
Scrublord MacBad 8e0f244257 Add oembed configuration directly to synapse values 2026-05-08 00:20:45 +02:00
Scrublord MacBad b000c1b10b Fix oembed configuration format 2026-05-08 00:10:08 +02:00
Scrublord MacBad 24d0cd1201 Add media_repository and oembed configuration for URL previews 2026-05-08 00:06:27 +02:00
23 changed files with 1915 additions and 40 deletions
Vendored
BIN
View File
Binary file not shown.
+56
View File
@@ -0,0 +1,56 @@
FROM debian:bookworm-slim
# Install base tools
RUN apt-get update && apt-get install -y --no-install-recommends \
curl \
wget \
git \
ca-certificates \
gnupg \
lsb-release \
apt-transport-https \
vim \
nano \
jq \
yq \
zsh \
sudo \
openssh-client \
&& rm -rf /var/lib/apt/lists/*
# Install kubectl
RUN curl -fsSLo /usr/share/keyrings/kubernetes-archive-keyring.gpg https://packages.cloud.google.com/apt/doc/apt-key.gpg && \
echo "deb [signed-by=/usr/share/keyrings/kubernetes-archive-keyring.gpg] https://apt.kubernetes.io/ kubernetes-xenial main" | tee /etc/apt/sources.list.d/kubernetes.list && \
apt-get update && apt-get install -y kubectl && \
rm -rf /var/lib/apt/lists/*
# Install Helm
RUN curl https://raw.githubusercontent.com/helm/helm/main/scripts/get-helm-3 | bash
# Install Flux CLI
RUN curl -s https://fluxcd.io/install.sh | bash
# Install sops
RUN SOPS_VERSION=$(curl -s https://api.github.com/repos/getsops/sops/releases/latest | grep tag_name | cut -d '"' -f 4) && \
curl -sL -o /usr/local/bin/sops https://github.com/getsops/sops/releases/download/${SOPS_VERSION}/sops-${SOPS_VERSION}.linux.amd64 && \
chmod +x /usr/local/bin/sops
# Install age
RUN apt-get update && apt-get install -y age && \
rm -rf /var/lib/apt/lists/*
# Install Docker CLI (for interacting with Docker daemon)
RUN curl -fsSL https://download.docker.com/linux/debian/gpg | gpg --dearmor -o /usr/share/keyrings/docker-archive-keyring.gpg && \
echo "deb [arch=amd64 signed-by=/usr/share/keyrings/docker-archive-keyring.gpg] https://download.docker.com/linux/debian $(lsb_release -cs) stable" | tee /etc/apt/sources.list.d/docker.list > /dev/null && \
apt-get update && apt-get install -y docker-ce-cli && \
rm -rf /var/lib/apt/lists/*
# Create a non-root user 'vscode' for development
RUN useradd -m -s /bin/bash -G docker vscode && \
echo "vscode ALL=(ALL) NOPASSWD: ALL" >> /etc/sudoers.d/vscode
# Install oh-my-zsh for better shell experience
RUN su - vscode -c "sh -c '$(curl -fsSL https://raw.githubusercontent.com/ohmyzsh/ohmyzsh/master/tools/install.sh)' '' --unattended"
USER vscode
WORKDIR /workspace
+203
View File
@@ -0,0 +1,203 @@
# 🐳 DevContainer für ESS Community GitOps
Dieses DevContainer-Setup ermöglicht dir, auf **macOS, Windows und Linux** einheitlich zu entwickeln.
## 🚀 Schnelstart
### VSCode mit Remote Containers Extension
1. **VSCode Extension installieren:**
- Öffne VSCode → Extensions → Suche nach `Dev Containers` (Microsoft)
- Installiere sie
2. **GitOps Verzeichnis öffnen:**
```bash
cd "april mit Ansible/prod/gitops"
code .
```
3. **DevContainer starten:**
- Klick auf `><` Symbol unten links in VSCode
- Wähle `Reopen in Container`
- Warte, bis das Image gebaut wurde (~3-5 Min beim ersten Mal)
### Alternative: Docker + CLI
```bash
docker build -t ess-gitops .devcontainer
docker run -it --rm \
-v ~/.kube:/home/vscode/.kube \
-v ~/.ssh:/home/vscode/.ssh \
-v ~/.age:/home/vscode/.age \
-v /var/run/docker.sock:/var/run/docker.sock \
ess-gitops
```
## 📦 Enthaltene Tools
- **kubectl** - Kubernetes CLI
- **flux** - FluxCD GitOps Controller CLI
- **helm** - Kubernetes Package Manager
- **sops** - Secret Operations (Verschlüsselung)
- **age** - Modern File Encryption
- **docker** - Container CLI (über Host-Socket)
- **git** - Versionskontrolle
- **jq/yq** - JSON/YAML Processing
- **zsh + oh-my-zsh** - Shell mit Plugins
## 🔐 Wichtige Verzeichnis-Binds
Der Container mountet automatisch:
| Host | Container | Zweck |
|------|-----------|-------|
| `~/.kube` | `/home/vscode/.kube` | Kubernetes Config |
| `~/.ssh` | `/home/vscode/.ssh` | SSH Keys |
| `~/.age` | `/home/vscode/.age` | Age Encryption Keys |
| `/var/run/docker.sock` | `/var/run/docker.sock` | Docker Daemon (für `docker` Befehle) |
## ⚙️ Kubeconfig Einrichten
1. **Host-Machine (z.B. macOS):**
```bash
# Stelle sicher, dass ~/.kube/config existiert und den richtigen Cluster enthält
kubectl get nodes
```
2. **Im Container:**
```bash
kubectl get nodes # Sollte jetzt auch dein Cluster zeigen
kubectl config current-context
```
## 🔐 SOPS + Age Setup
Damit du Secrets bearbeiten kannst, brauchst du den privaten `age`-Key. Dieser ist in `.sops.yaml` konfiguriert.
### Schritt 1: Age-Key bereitstellen
```bash
# Host-Machine: Key-Datei erstellen
mkdir -p ~/.age
# Füge deinen privaten Key ein (Format: "age-secret-key-...")
echo "age-secret-key-xxx..." > ~/.age/keys.txt
chmod 600 ~/.age/keys.txt
```
### Schritt 2: Im Container konfigurieren
Der Container mounted `~/.age` automatisch. Setze die Umgebungsvariable:
```bash
# Im Container-Terminal (SOPS_AGE_KEY_FILE ist bereits automatisch gesetzt!)
# Jetzt kannst du Secrets bearbeiten (wird transparent ver-/entschlüsselt):
sops apps/production/custom-configs/mas-secrets.sops.yaml
```
### Schritt 3: VSCode Integration (optional)
Um die Umgebungsvariable beim Start zu setzen, nutze die `.devcontainer/devcontainer.json`:
```json
"remoteEnv": {
"KUBECONFIG": "/home/vscode/.kube/config",
"SOPS_AGE_KEY_FILE": "/home/vscode/.age/keys.txt"
}
```
### Wie es funktioniert
- `.sops.yaml` definiert, dass Secrets mit `age` verschlüsselt werden
- Beim Öffnen mit `sops <datei>` wird die Datei entschlüsselt → du editierst den plaintext in deinem Editor
- Beim Speichern wird alles wieder automatisch verschlüsselt
- **Wichtig:** Niemals den plaintext-Buffer commiten!
## 📝 Nach Container-Start: Git Hooks Installieren
Wichtig für die ConfigMap Auto-Sync (verhindert Merge-Konflikte):
```bash
./scripts/install-hooks.sh
```
Mehr Details: `docs/ops-configmap-sync.md`
## 📝 Nützliche Befehle
```bash
# Status des Deployments
kubectl get pods -n matrix
flux get helmreleases -A
# Secrets bearbeiten (mit verschlüsselung)
sops apps/production/custom-configs/mas-secrets.sops.yaml
# FluxCD Sync erzwingen
flux reconcile kustomization production-apps --with-source
# Zertifikate debuggen
kubectl get certificate -n matrix
kubectl describe certificate matrix-ingress -n matrix
# HelmRelease Status prüfen
flux describe helmrelease matrix-stack -n matrix
```
## 🛠️ Anpassungen für Windows/WSL2
Falls du Windows nutzt:
1. **Docker Desktop installieren** (mit WSL2 Backend)
2. **VSCode mit WSL Extension öffnen**
3. **Im WSL Terminal:**
```bash
cd /mnt/c/path/to/projekt
code .
```
4. Dann `Dev Containers: Reopen in Container`
Das funktioniert seamless, weil Docker Desktop unter WSL2 läuft.
## 🔧 Troubleshooting
### Problem: `SOPS_AGE_KEY_FILE not found`
**Lösung:** Key muss in `~/.age/keys.txt` auf der Host-Machine sein:
```bash
# Host
mkdir -p ~/.age
echo "your-age-private-key" > ~/.age/keys.txt
```
Der Container mountet `~/.age` automatisch → sollte dann funktionieren.
### Problem: `kubectl: connection refused`
**Lösung:** `~/.kube/config` muss auf Host vorhanden sein:
```bash
# Host
kubectl get nodes # Test, ob Zugriff existiert
# Dann Container neustarten
```
### Problem: `HelmChart is not ready: stat ... no such file or directory`
Siehe `README.md` → **Issue 1**. Kontrolliere:
- `HelmRepository` nutzt `type: oci`
- URL ist `oci://ghcr.io/element-hq/ess-helm`
### Problem: `values don't meet the specifications of the schema`
Siehe `README.md` → **Issue 2**. Häufige Fehler:
- `tls:` darf nicht im `ingress:` Block sein
- `serverName` muss auf Root-Ebene der `values` stehen
- Komponenten-Namen: `camelCase` (z.B. `elementWeb`, `matrixAuthenticationService`)
### Problem: Let's Encrypt `403 Order's status is processing`
Siehe `README.md` → **Issue 3**. Kurz:
- `wellKnownDelegation: enabled: false` setzen
- Oder `.well-known/matrix/server` manuell auf `elementWeb` weiterleiten
## 📚 Weitere Ressourcen
- [Dev Containers Docs](https://containers.dev)
- [FluxCD Dokumentation](https://fluxcd.io)
- [SOPS Anleitung](https://github.com/getsops/sops)
- **Projekt-README:** `README.md` (Architektur, Issues, Best Practices)
- **Setup-Docs:** `docs/setup/`
- **Install-Guide:** `docs/install.md`
+65
View File
@@ -0,0 +1,65 @@
{
"name": "ESS Community GitOps",
"build": {
"dockerfile": "Dockerfile",
"context": "."
},
"mounts": [
"source=${localEnv:HOME}/.kube,target=/home/vscode/.kube,type=bind,consistency=cached",
"source=${localEnv:HOME}/.ssh,target=/home/vscode/.ssh,type=bind,consistency=cached",
"source=${localEnv:HOME}/.age,target=/home/vscode/.age,type=bind,consistency=cached",
"source=/var/run/docker.sock,target=/var/run/docker.sock,type=bind"
],
"remoteUser": "vscode",
"features": {
"ghcr.io/devcontainers/features/git:1": {},
"ghcr.io/devcontainers/features/github-cli:1": {}
},
"remoteEnv": {
"KUBECONFIG": "/home/vscode/.kube/config",
"SOPS_AGE_KEY_FILE": "/home/vscode/.age/keys.txt"
},
"customizations": {
"vscode": {
"extensions": [
"ms-kubernetes-tools.vscode-kubernetes-tools",
"redhat.vscode-yaml",
"redhat.vscode-commons",
"monokai.theme-monokai-pro-vscode",
"eamodio.gitlens",
"gruntfuggly.todo-tree",
"ms-vscode.makefile-tools",
"GitHub.copilot"
],
"settings": {
"[yaml]": {
"editor.defaultFormatter": "redhat.vscode-yaml",
"editor.formatOnSave": true,
"editor.tabSize": 2
},
"yaml.schemas": {
"https://json.schemastore.org/kustomization.json": "**/kustomization.yaml",
"https://json.schemastore.org/helmrelease.json": "**/*helmrelease*.yaml"
},
"editor.theme": "Monokai Pro",
"todo-tree.general.showActivityBarBadge": true,
"todo-tree.general.tags": [
"TODO",
"FIXME",
"BUG",
"HACK",
"NOTE",
"XXX",
"DONE"
],
"todo-tree.tree.showScanModeButton": true,
"todo-tree.filtering.includeGlobs": [
"**/docs/TASKS.md",
"**/docs/deployment-guides/*.md"
]
}
}
},
"postCreateCommand": "bash .devcontainer/postCreateCommand.sh",
"forwardPorts": []
}
+35
View File
@@ -0,0 +1,35 @@
#!/bin/bash
set -e
echo "🚀 Setting up ESS Community GitOps devcontainer..."
# Verify all required tools are installed
echo "✅ Verifying installed tools..."
commands=("kubectl" "flux" "helm" "sops" "age" "git" "docker")
for cmd in "${commands[@]}"; do
if command -v $cmd &> /dev/null; then
version=$($cmd version 2>/dev/null | head -1 || echo "installed")
echo "$cmd: $version"
else
echo "$cmd: NOT FOUND"
exit 1
fi
done
# Create necessary directories
echo "📁 Creating home directories..."
mkdir -p ~/.kube ~/.ssh ~/.age
# Print useful information
echo ""
echo "📚 Useful commands:"
echo " - kubectl get pods -n matrix (check pod status)"
echo " - flux get helmreleases -A (check helm releases)"
echo " - sops apps/production/custom-configs/mas-secrets.sops.yaml (edit secrets)"
echo ""
echo "🔗 For kubeconfig setup:"
echo " - Copy your ~/.kube/config to access the cluster"
echo " - Run: kubectl get nodes"
echo ""
echo "✨ Devcontainer setup complete!"
+50
View File
@@ -0,0 +1,50 @@
name: Auto-Deploy on Push
on:
push:
branches:
- main
paths:
- 'apps/**'
- 'clusters/**'
- '.gitea/workflows/**'
jobs:
verify-and-notify:
runs-on: ubuntu-latest
steps:
- uses: actions/checkout@v3
with:
fetch-depth: 0
- name: Check YAML Syntax
run: |
echo "🔍 Validating YAML files..."
find apps clusters -name "*.yaml" -type f | while read file; do
if ! grep -q "^apiVersion:" "$file"; then
echo "⚠️ Warning: $file may not be a valid K8s manifest"
fi
done
echo "✅ YAML validation passed"
- name: Check for SOPS Encryption
run: |
echo "🔐 Checking SOPS status..."
for file in $(git diff --name-only origin/main...HEAD -- '**/secret*.yaml' '**/credentials*.yaml'); do
if grep -q "ENC\[" "$file"; then
echo "✅ $file is encrypted"
else
echo "⚠️ WARNING: $file may not be encrypted!"
fi
done
- name: Create Deployment Notification
run: |
echo "📤 Flux will reconcile changes within 1 minute"
echo "🔗 Monitor in Gitea: Projects → Releases (check tags)"
- name: List Changed Files
run: |
echo "📋 Files changed in this push:"
git diff --name-only origin/main...HEAD
+32
View File
@@ -0,0 +1,32 @@
name: Create Release on Milestone Tag
on:
push:
tags:
- 'm*-*-complete'
jobs:
create-release:
runs-on: ubuntu-latest
steps:
- uses: actions/checkout@v3
with:
fetch-depth: 0
- name: Extract Milestone Info
id: milestone
run: |
TAG="${GITHUB_REF#refs/tags/}"
TITLE=$(git tag -l "$TAG" -n1 | awk '{print substr($0, index($0, $2))}')
echo "tag=$TAG" >> $GITHUB_OUTPUT
echo "title=$TITLE" >> $GITHUB_OUTPUT
echo "🏷️ Milestone: $TAG"
echo "📝 Title: $TITLE"
- name: Create Release
run: |
echo "📦 Creating release for milestone: ${{ steps.milestone.outputs.tag }}"
echo "${{ steps.milestone.outputs.title }}" > /tmp/release-notes.txt
echo "Created: $(date)" >> /tmp/release-notes.txt
cat /tmp/release-notes.txt
+6
View File
@@ -53,6 +53,12 @@ winget install Kubernetes.kubectl FluxCD.Flux Mozilla.sops age-encryption.age He
1. **Kubeconfig:** Stelle sicher, dass die Datei `~/.kube/config` mit den Zugangsdaten zu deinem K3s-Cluster gefüllt ist. Test: `kubectl get nodes`.
2. **SOPS Key:** Du benötigst den privaten `age`-Key (oder GPG-Key), der in der `.sops.yaml` des Repositories hinterlegt ist, um Secrets bearbeiten zu können.
3. **Git Hooks installieren:** Nach dem Klonen dieses Repositories müssen Git Hooks installiert werden, um ConfigMap-Änderungen automatisch zu tracken:
```bash
cd prod/gitops
./scripts/install-hooks.sh
```
Siehe [📖 GitOps ConfigMap Auto-Sync](docs/ops-configmap-sync.md) für Details.
-----
@@ -0,0 +1,186 @@
apiVersion: v1
kind: ConfigMap
metadata:
name: ess-element-custom
namespace: matrix
data:
values.yaml: |
elementWeb:
additional:
config.json: |
{
"brand": "aXion1337.Chat",
"default_theme": "aXion1337 Dark",
"show_labs_settings": true,
"features": {
"feature_qr_code_login": true,
"feature_new_room_list": true
},
"element_call": {
"use_exclusively": true
},
"setting_defaults": {
"custom_themes": [
{
"name": "aXion1337 Dark true",
"is_dark": true,
"colors": {
"accent-color": "#ffaf0f",
"primary-color": "#ffaf0f",
"secondary-color": "#ffaf0f"
}
},
{
"name": "Deep Purple",
"is_dark": true,
"colors": {
"accent-color": "#6503b3",
"primary-color": "#368bd6",
"warning-color": "#b30356",
"sidebar-color": "#15171B",
"roomlist-background-color": "#22262E",
"roomlist-text-color": "#A1B2D1",
"roomlist-text-secondary-color": "#EDF3FF",
"roomlist-highlights-color": "#343A46",
"roomlist-separator-color": "#a1b2d1",
"timeline-background-color": "#181b21",
"timeline-text-color": "#EDF3FF",
"timeline-text-secondary-color": "#A1B2D1",
"timeline-highlights-color": "#22262E"
}
},
{
"name": "Discord Dark",
"is_dark": true,
"colors": {
"accent-color": "#747ff4",
"accent": "#747ff4",
"primary-color": "#00aff4",
"warning-color": "#faa81ad9",
"alert": "#faa81ad9",
"sidebar-color": "#202225",
"roomlist-background-color": "#2f3136",
"roomlist-text-color": "#dcddde",
"roomlist-text-secondary-color": "#8e9297",
"roomlist-highlights-color": "#4f545c52",
"roomlist-separator-color": "#40444b",
"timeline-background-color": "#36393f",
"timeline-text-color": "#dcddde",
"secondary-content": "#dcddde",
"tertiary-content": "#dcddde",
"timeline-text-secondary-color": "#b9bbbe",
"timeline-highlights-color": "#04040512",
"reaction-row-button-selected-bg-color": "#4752c4",
"menu-selected-color": "#4752c4",
"focus-bg-color": "#4752c4",
"room-highlight-color": "#4752c4",
"other-user-pill-bg-color": "#4752c4",
"togglesw-off-color": "#72767d"
},
"compound": {
"--cpd-color-theme-bg": "#0019ff",
"--cpd-color-bg-canvas-default": "#2f3136",
"--cpd-color-bg-subtle-secondary": "#2f3136",
"--cpd-color-bg-subtle-primary": "#4f545c52",
"--cpd-color-bg-action-primary-rest": "#dcddde",
"--cpd-color-bg-action-secondary-rest": "#2f3136",
"--cpd-color-bg-critical-primary": "#fd3f3c",
"--cpd-color-bg-critical-subtle": "#745862",
"--cpd-color-bg-critical-hovered": "#fd3f3c",
"--cpd-color-bg-accent-rest": "#4cb387",
"--cpd-color-text-primary": "#dcddde",
"--cpd-color-text-secondary": "#b9bbbe",
"--cpd-color-text-action-accent": "#b9bbbe",
"--cpd-color-text-critical-primary": "#fd3f3c",
"--cpd-color-text-success-primary": "#4cb387",
"--cpd-color-icon-primary": "#dcddde",
"--cpd-color-icon-secondary": "#dcddde",
"--cpd-color-icon-tertiary": "#a7a0a7",
"--cpd-color-icon-accent-tertiary": "#4cb387",
"--cpd-color-border-interactive-primary": "#5d6064",
"--cpd-color-border-interactive-secondary": "#5d6064",
"--cpd-color-border-critical-primary": "#fd3f3c",
"--cpd-color-border-success-subtle": "#4cb387"
}
},
{
"name": "Electric Blue",
"is_dark": false,
"colors": {
"accent-color": "#3596fc",
"primary-color": "#368bd6",
"warning-color": "#ff4b55",
"sidebar-color": "#27303a",
"roomlist-background-color": "#f3f8fd",
"roomlist-text-color": "#2e2f32",
"roomlist-text-secondary-color": "#61708b",
"roomlist-highlights-color": "#ffffff",
"roomlist-separator-color": "#e3e8f0",
"timeline-background-color": "#ffffff",
"timeline-text-color": "#2e2f32",
"timeline-text-secondary-color": "#61708b",
"timeline-highlights-color": "#f3f8fd",
"username-colors": ["#ff0000", "#ff7f00", "#ffff00", "#00ff00", "#0000ff", "#4b0082", "#9400d3", "#ff1493"],
"avatar-background-colors": ["#cc0000", "#cc6600", "#cccc00", "#00cc00", "#0000cc", "#3b0066", "#7a00b3", "#cc1077"]
},
"compound": {
"--cpd-color-icon-accent-tertiary": "var(--cpd-color-blue-800)",
"--cpd-color-text-action-accent": "var(--cpd-color-blue-900)"
}
},
{
"name": "Everforest dark hard",
"is_dark": true,
"colors": {
"accent-color": "#a7c080",
"primary-color": "#a7c080",
"warning-color": "#e67e80",
"sidebar-color": "#323d43",
"roomlist-background-color": "#2f383e",
"roomlist-text-color": "#d3c6aa",
"roomlist-text-secondary-color": "#d3c6aa",
"roomlist-highlights-color": "#4b565c",
"roomlist-separator-color": "#4b565c",
"timeline-background-color": "#2b3339",
"timeline-text-color": "#d3c6aa",
"secondary-content": "#d3c6aa",
"tertiary-content": "#d3c6aa",
"timeline-text-secondary-color": "#a7c080",
"timeline-highlights-color": "#4b565c",
"reaction-row-button-selected-bg-color": "#4b565c"
}
},
{
"name": "aXion1337 Dark", #Gruvbox Dark
"is_dark": true,
"colors": {
"accent-color": "#bd93f9",
"primary-color": "#fe8019",
"warning-color": "#fb4934",
"sidebar-color": "#282828",
"roomlist-background-color": "#1d2021",
"roomlist-text-color": "#a89984",
"roomlist-text-secondary-color": "#00ff00",
"roomlist-highlights-color": "#00000030",
"roomlist-separator-color": "#4d4d4d90",
"timeline-background-color": "#282828",
"timeline-text-color": "#ebdbb2",
"secondary-content": "#928374",
"tertiary-content": "#928374",
"quinary-content": "#504945",
"timeline-text-secondary-color": "#a89984",
"timeline-highlights-color": "#00000030",
"reaction-row-button-selected-bg-color": "#689d6a",
"menu-selected-color": "#504945",
"icon-button-color": "#928374",
"accent": "#689d6a",
"alert": "#cc241d",
"username-colors": [
"#cc241d",
"#98971a",
"#d79921",
"#458588",
"#b16286",
"#689d6a",
"#a89984",
"#d65d0e"
@@ -9,18 +9,20 @@ data:
additional:
config.json: |
{
"configUrl": "https://axion1337.chat/config.json",
"brand": "aXion1337.Chat",
"default_theme": "aXion1337 Dark",
"show_labs_settings": true,
"features": {
"feature_qr_code_login": true,
"feature_new_room_list": false
"feature_new_room_list": true
},
"element_call": {
"use_exclusively": true
},
"setting_defaults": {
"custom_themes": [
{
"name": "aXion1337 Dark",
"name": "aXion1337 Dark true",
"is_dark": true,
"colors": {
"accent-color": "#ffaf0f",
@@ -149,7 +151,7 @@ data:
}
},
{
"name": "Gruvbox Dark",
"name": "aXion1337 Dark",
"is_dark": true,
"colors": {
"accent-color": "#bd93f9",
@@ -182,40 +184,7 @@ data:
"#689d6a",
"#a89984",
"#d65d0e"
],
"avatar-background-colors": ["#458588", "#b16286", "#689d6a"]
}
},
{
"name": "Wal",
"is_dark": true,
"colors": {
"accent-color": "#888888",
"accent": "#888888",
"primary-color": "#4a90e2",
"warning-color": "#e74c3c",
"alert": "#e74c3c",
"sidebar-color": "#2b2d31",
"roomlist-background-color": "#e74c3c",
"roomlist-text-color": "#888888",
"roomlist-text-secondary-color": "#c0c0c0",
"roomlist-highlights-color": "#b8b8b8",
"roomlist-separator-color": "#5e81ac",
"timeline-background-color": "#2b2d31",
"timeline-text-color": "#888888",
"timeline-text-secondary-color": "#888888",
"timeline-highlights-color": "#e74c3c",
"username-colors": ["#22222a", "#e74c3c", "#b8bb26", "#fabd2f", "#4a90e2", "#b16286", "#8ec07c", "#ebdbb2"],
"avatar-background-colors": ["#fabd2f", "#4a90e2", "#b16286"],
"reaction-row-button-selected-bg-color": "#4a90e2",
"menu-selected-color": "#4a90e2",
"focus-bg-color": "#4a90e2",
"room-highlight-color": "#4a90e2",
"other-user-pill-bg-color": "#4a90e2",
"icon-button-color": "#8ec07c",
"togglesw-off-color": "#4a90e2",
"secondary-content": "#888888",
"tertiary-content": "#888888"
]
}
}
]
@@ -66,4 +66,7 @@ data:
- "turns:turn.axion1337.chat?transport=tcp"
turn_shared_secret: "cab3c8408363515d9b4cdc3384a1f76ca17a973242fdfdc72b67ac4d86158527"
turn_user_lifetime: 86400000
turn_allow_guests: false
turn_allow_guests: false
oembed:
config: |
oembed_enabled: true
+9 -1
View File
@@ -4,7 +4,7 @@ metadata:
name: matrix-stack
namespace: matrix
spec:
interval: 1h
interval: 5m
chart:
spec:
chart: matrix-stack
@@ -43,6 +43,10 @@ spec:
enabled: true
ingress:
host: matrix.axion1337.chat
additional:
oembed:
config: |
oembed_enabled: true
# Matrix Authentication Service braucht eine Subdomain
matrixAuthenticationService:
@@ -59,6 +63,10 @@ spec:
# Element Web
elementWeb:
enabled: true
image:
registry: rohana.axion1337.de
repository: sorb/threadnet-web
tag: v0.1.0
ingress:
host: axion1337.chat
+13
View File
@@ -1,5 +1,18 @@
apiVersion: kustomize.config.k8s.io/v1beta1
kind: Kustomization
# Patch: Fügt einen Checksum der element-values.yaml zur HelmRelease hinzu
# Damit wird Flux die HelmRelease neu-synced wenn sich die ConfigMap ändert
patches:
- target:
kind: HelmRelease
name: matrix-stack
namespace: matrix
patch: |-
- op: add
path: /metadata/annotations/element-config-checksum
value: "401f8a87d0ef5d91d2e5032d4aede42c"
resources:
- matrix-postgres-auth.yaml
- cert-issuer.yaml
+503
View File
@@ -0,0 +1,503 @@
# aXion1337.Chat Task List & Meilensteine
**Last Updated**: 2026-05-14
**Statusübersicht**: [✅ 6 Abgeschlossen] [🔄 1 In Progress] [📋 15+ Pending] [🔒 10 Security]
---
## 📊 Status Summary (Quick View)
| Kategorie | Count | Status | Details |
|-----------|-------|--------|---------|
| **Completed** | 6 | ✅ Done | K3S, Flux, ESS, Themes, Desktop, Monitoring, TURN |
| **In Progress** | 1 | 🔄 Blocked | Authentik Stage 2 (awaiting manual config) |
| **Backlog** | 15+ | 📋 Pending | Element Call Fork, DB Backups, NetworkPolicies, etc. |
| **Security Tasks** | 10 | 🔒 Pending | Firewall, SSH, auditd, Kernel hardening, CrowdSec, Falco |
### Priority Distribution
| Priority | Count | Timeline |
|----------|-------|----------|
| 🔴 **CRITICAL** | 3 | This week |
| 🟠 **HIGH** | 4 | 12 weeks |
| 🟡 **MEDIUM** | 8 | ~1 month |
| 🟢 **LOW** | 4+ | Nice-to-have |
---
## 🎯 Next Steps (Priorisiert)
### 🔴 **THIS WEEK CRITICAL**
1. **Authentik Stage 2 abschließen**
- Manual: OIDC Provider + Application in Authentik UI erstellen
- Code: `upstream_oauth2_config` in `mas-secret.yaml` einfügen
- Code: `passwords: enabled: false` aktivieren
- Commit: `enable-authentik-oidc-integration-in-mas`
- Est. Time: 12 hours
- Blocker: Manual Authentik config (user action)
2. **Hetzner Cloud Firewall Default-Deny Setup**
- Ingress: Allow 80/443 only
- Allow SSH from your IP or via WireGuard/Tailscale
- Est. Time: 30 min
- Cost: Free
- Impact: Blocks 99% of internet background noise
3. **SSH Hardening**
- Disable password auth (key-only)
- Disable root login
- MaxAuthTries 3
- Est. Time: 12 hours
- Priority: HIGH
4. **Database Backup Strategy Decision & First Backup**
- Decision: CloudNativePG (on K3S) or Hetzner Postgres (managed)?
- Setup: Daily automated backups
- Setup: Off-site storage (S3 / Storage Box)
- Setup: Monthly verified restores
- Est. Time: 23 days
- Priority: CRITICAL (disaster recovery)
### 🟠 **NEXT 12 WEEKS HIGH**
1. **Authentik End-to-End Test**
- Test: Login flow Element → MAS → Authentik → Matrix User
- Test: Password reset
- Create: Test invite links
- Est. Time: 2 hours
2. **Element Call Fork**
- Fork: element-hq/element-call
- Feature: Video/audio constraints parameters
- Integration: Synapse well-known config
- Est. Time: 23 days
3. **External PostgreSQL Migration**
- Decision: CloudNativePG vs. Hetzner Postgres
- Setup: HA + Replication
- Migration: Move data from ESS embedded Postgres
- Testing: Verify all services work
- Est. Time: 12 days
4. **NetworkPolicies Deployment**
- Create: Default-Deny for `matrix` namespace
- Create: Allow rules (Synapse↔Postgres, MAS↔Postgres, Ingress→Web, etc.)
- Test: Ensure no service breakage
- Est. Time: 1 day
---
## ✅ Abgeschlossene Aufgaben (Chronologisch)
### Phase 1: Basis-Setup
- [x] **K3S Cluster aufsetzen** Single-Node auf Hetzner Cloud (49.13.132.245)
- Commit: `initial-setup` (vor Projekt)
- Status: ✅ Läuft
- [x] **Flux CD Installation**
- SOPS + age Encryption
- GitOps Repository konfigurieren
- Commit: `setup-flux` (vor Projekt)
- Status: ✅ Läuft
- [x] **Element Server Suite v26.4.0 Deployment**
- Synapse Homeserver (`matrix.axion1337.chat`)
- Matrix Authentication Service (`account.axion1337.chat`)
- Element Web (`axion1337.chat`)
- Element Admin (`admin.axion1337.chat`)
- MatrixRTC/Element Call (`mrtc.axion1337.chat`)
- Commit: `deploy-ess-matrix-stack`
- Status: ✅ Running
### Phase 2: Core Features
- [x] **7 Custom Element Web Themes**
- aXion1337 Dark, Deep Purple, Discord Dark, Electric Blue, Everforest, Gruvbox, Wal
- Alphabetisch sortiert
- Commit: `add-custom-element-themes`
- Status: ✅ Deployed
- [x] **Element Desktop Setup Scripts** (Windows/macOS/Linux)
- Auto-Download + Install + Config
- Hosted auf `axion1337.chat/docs/setup/`
- Commits: `add-element-desktop-setup-scripts`, `fix-element-setup-script-hosting`
- Status: ✅ Deployed
- [x] **Room Policies**
- Message Retention (1d1y lifecycle)
- Room Publication Rules (allow all)
- Auto-Join Rooms für Onboarding
- Commit: `add-synapse-retention-publication-autojoin`
- Status: ✅ Deployed
### Phase 3: WebRTC & Medienübertragung
- [x] **TURN Server (coturn) für Video-Calls**
- Domain: `turn.axion1337.chat`
- HMAC-Auth mit Shared Secret
- Ports: 3478/udp, 3478/tcp, 5349/tcp, 49152-65535/udp
- Commit: `implement-turn-server-coturn-for-webrtc-video-calls`
- Status: ✅ Deployed
- Manual: DNS A-Record + Firewall-Ports öffnen (noch erforderlich)
### Phase 4: Monitoring & Observability
- [x] **Monitoring Stack Integration**
- Alloy (Grafana Agent) als Collector
- Remote Write zu Selendis (10.0.0.3:9090 Prometheus, :3100 Loki)
- kube-state-metrics, node-exporter DaemonSet
- Commits: `integrate-monitoring-alloy-prometheus-loki`, `fix-prometheus-remote-write-docker`
- Status: ✅ Deployed
### Phase 5: Identity Provider (Authentik)
- [x] **Authentik Stage 1 Deployment**
- HelmRelease v2026.x in `authentik` namespace
- Embedded PostgreSQL + Alloy-compatible
- Cert-Manager für TLS
- Commit: `deploy-authentik-as-identity-provider-for-matrix-stage-1`
- Status: ✅ Deployed
- Manual: Admin-Passwort setzen + OIDC Provider erstellen (erforderlich)
🔄 **[IN PROGRESS] Authentik Stage 2 MAS Integration**
- [ ] **MAS Upstream OIDC Konfiguration**
- Client ID/Secret aus Authentik Admin UI kopieren
- `upstream_oauth2_config` in `mas-secret.yaml` einfügen
- `passwords: enabled: false`
- Commit: (pending)
- Status: ⏳ Wartet auf manuelle Authentik-Konfiguration
### Phase 6: Dokumentation
- [x] **Deployment Guides erstellen**
- 5 Markdown-Dateien in `docs/deployment-guides/`
- Chronologisch geordnet
- Troubleshooting + Best Practices
- Commit: `add-comprehensive-deployment-configuration-documentation`
- Status: ✅ Deployed
---
## 🔄 In Progress / Blocked
### Authentik Stage 2 MAS Integration (⏳ Depends on Manual Config)
**Beschreibung**: Authentik OIDC Provider muss manuell im Authentik Admin UI konfiguriert werden, bevor Stage 2 Deployment möglich ist.
**Schritte**:
1. ✅ Authentik Stage 1 Deployment (done)
2. ⏳ Authentik Admin UI: OIDC Provider erstellen (MANUAL - user action)
3. ⏳ Authentik Admin UI: Application mit Slug `matrix` erstellen (MANUAL - user action)
4. ⏳ Authentik Admin UI: Enrollment Flow mit Invitation Stage (MANUAL - user action)
5. ⏳ Authentik Admin UI: Client ID + Secret kopieren (MANUAL - user action)
6. 📋 MAS `upstream_oauth2_config` mit Client Credentials aktualisieren
7. 📋 `passwords: enabled: false` aktivieren
8. 📋 Commit + Push
**Blocker**: Manuelle Authentik-Konfiguration (wartet auf Benutzer)
---
## 📋 Backlog (Weitere Aufgaben)
### Authentik Completion
- [ ] **Finish Authentik Stage 2 MAS Integration**
- Prerequisites: Authentik OIDC Provider vollständig konfiguriert
- Task: Update `mas-secret.yaml`, enable password login disable
- Commit: `enable-authentik-oidc-integration-in-mas`
- Est. Effort: 30 min (manual + scripted)
- [ ] **Test End-to-End Login Flow**
- Element Web login → MAS → Authentik → Matrix User Creation
- Create test users via Authentik
- Verify password reset flow
- Commit: (implicit in Stage 2)
- Est. Effort: 20 min
- [ ] **Create Invite Links für neue User**
- Authentik Admin UI → Invitations → Create
- Set expiry dates (7d) + use limits
- Document procedure
- Est. Effort: 15 min
### Element Call Enhancement
- [ ] **Element Call Fork für Custom Constraints**
- Repository: Fork `element-hq/element-call`
- Feature: Video/Audio constraints parameter im config
- Include: Bandwidth limiting, resolution limits, frame rate control
- Integration mit Synapse well-known
- Est. Effort: 23 days (fork + feature + test)
- Priority: **HIGH** (user feature)
### Database Hardening
- [ ] **External/Dedicated PostgreSQL Deployment**
- Option 1: CloudNativePG Operator (open-source, auf K3S)
- Option 2: Managed Hetzner Postgres
- Separate aus ESS matrix-stack embedded Postgres
- HA + Replication
- Est. Effort: 12 days
- Priority: **HIGH** (reliability)
- [ ] **Database Backup Strategy**
- Daily automated backups (PgBackRest oder velero)
- Off-site backup storage (S3 / Hetzner Storage Box)
- Monthly verified restores (test restore → verify data integrity)
- Backup + restore documentation
- Est. Effort: 23 days
- Priority: **CRITICAL** (disaster recovery)
- [ ] **Synapse Media PVC Backups**
- Separate backup pipeline für `/data/media_store` PVC
- Reason: Media oft >100GB, sollte nicht im DB-Backup sein
- Velero + Restic für block-level backup
- Est. Effort: 1 day
- Priority: **HIGH** (data preservation)
### Network Security
- [ ] **NetworkPolicies K8s-Layer Segmentation**
- Default-Deny Ingress für `matrix` namespace
- Allow rules:
- Ingress → MAS:443
- Ingress → ElementWeb:443
- MAS ↔ Synapse:8008
- Synapse ↔ Postgres:5432
- Authentik → Postgres:5432
- Authentik → Loki:3100 (monitoring)
- Egress: Matrix-specific (federation, etc.)
- Est. Effort: 1 day
- Priority: **MEDIUM** (compliance, least-privilege)
- [ ] **Pod Security Admission (Restricted)**
- Apply to `matrix` & `authentik` namespaces
- Enforce: non-root, no privileged, read-only root fs
- Test: Ensure no chart breakage
- Est. Effort: 1 day
- Priority: **MEDIUM** (hardening)
### Federation & Access Control
- [ ] **Federation-Allowlist oder Closed Federation**
- Decision: Which servers to federate with?
- If allowlist: explicit `federation_domain_whitelist`
- If closed: `allow_public_rooms_without_join_rules: false`
- Synapse config in `synapse-values.yaml`
- Est. Effort: 4 hours
- Priority: **MEDIUM** (security policy)
### Moderation & Anti-Abuse
- [ ] **Mjolnir/Draupnir Bot Deployment**
- Open-source moderation bot für Matrix
- Reason: Invitation-based, aber Federation kann Spam bringen
- Auto-ban known bad servers/users
- Spam-detection rules
- HelmChart oder custom Deployment
- Est. Effort: 12 days
- Priority: **MEDIUM** (ops safety)
- [ ] **Content Scanner for Media**
- matrix-content-scanner + ClamAV antivirus
- Scan uploaded media for malware
- Block suspicious files
- Est. Effort: 12 days
- Priority: **LOWMEDIUM** (optional but good practice)
### Secrets Management
- [ ] **External-Secrets Operator oder SOPS für Flux**
- Current: SOPS with age encryption
- Consideration: External-Secrets for cloud-native (AWS Secrets Manager, Hetzner Vault, etc.)
- OR: Improve SOPS rotation strategy
- Decision needed: Keep SOPS or upgrade?
- Est. Effort: 23 days (if switching)
- Priority: **LOW** (current SOPS setup working)
### Image & Dependency Management
- [ ] **Renovate / Dependabot Setup**
- Auto-update Helm Chart versions
- Auto-update Container Image Tags
- Monitor for security patches
- Est. Effort: 4 hours
- Priority: **MEDIUM** (maintenance)
- [ ] **Trivy Image Scanning**
- Scan images in Flux HelmReleases for CVEs
- Block deployment if critical CVE found
- CI/CD hook in git workflow
- Est. Effort: 8 hours
- Priority: **LOWMEDIUM** (security posture)
- [ ] **Monitor ESS & Element Security Advisories**
- Subscribe to `element-hq` security mailing list
- Monitor `#matrix-community` security channels
- Auto-alerts on new CVEs/patches
- Est. Effort: Ongoing (low maintenance)
- Priority: **MEDIUM** (security awareness)
### Container Security
- [ ] **Disable automountServiceAccountToken Everywhere**
- Audit all Deployments/StatefulSets
- Disable for: Synapse, ElementWeb, MAS, Postgres, Authentik (where not needed)
- Add `automountServiceAccountToken: false` to spec.template.spec
- Test: Ensure no breakage
- Est. Effort: 4 hours
- Priority: **MEDIUM** (least-privilege)
---
## 🔒 Security Hardening (Host & Cluster Level)
### Host OS Layer (Ubuntu/Debian)
- [ ] **Hetzner Cloud Firewall**
- Default-Deny inbound
- Allow: 80/443 (HTTP/HTTPS)
- Allow: 22 (SSH) from your IP only (or via WireGuard/Tailscale)
- Status: ✅ Can be done in Hetzner UI
- Est. Effort: 30 min
- Priority: **CRITICAL** (immediate, zero config cost)
- [ ] **SSH Hardening**
- Disable password auth (key-only)
- Disable root login
- PermitRootLogin: no
- PasswordAuthentication: no
- MaxAuthTries: 3
- Optional: Change SSH port (cosmetic, reduces log noise)
- Optional: SSH hinter WireGuard/Tailscale (eliminates fail2ban für SSH)
- Est. Effort: 2 hours
- Priority: **HIGH** (immediate)
- [ ] **unattended-upgrades**
- Enable automatic security updates
- Configure: APT::Periodic::Update-Package-Lists "1";
- Configure: APT::Periodic::Unattended-Upgrade "1";
- Configure: APT::Periodic::AutocleanInterval "7";
- Est. Effort: 30 min
- Priority: **HIGH** (set & forget)
- [ ] **K3S API Security**
- Current: K3S API listening on :6443 on all interfaces (default)
- Hardening:
- Option 1: Firewall restrict :6443 to localhost only
- Option 2: K3S --bind-address + --advertise-address to WireGuard IP
- Option 3: kubectl access only via jumphost/bastion
- Est. Effort: 2 hours
- Priority: **HIGH** (API is high-value target)
- [ ] **auditd for File Integrity & Syscall Audit**
- Monitor: /etc, ~/.kube, /var/lib/rancher/k3s
- Audit rules für sensitive file changes
- Low overhead, good signal/noise ratio
- Output to syslog / centralized logging
- Est. Effort: 2 hours
- Priority: **MEDIUM** (forensics + compliance)
- [ ] **Kernel Hardening (sysctl)**
- Apply hardening recommendations from Lynis
- Key settings:
- kernel.kptr_restrict=2 (hide kernel pointers)
- kernel.dmesg_restrict=1 (restrict dmesg)
- net.ipv4.tcp_syncookies=1 (SYN flood protection)
- net.ipv4.conf.all.rp_filter=1 (reverse path filtering)
- net.ipv4.conf.all.send_redirects=0
- net.ipv6.conf.all.disable_ipv6=0 (or =1 if no IPv6 needed)
- Persist via /etc/sysctl.d/99-hardening.conf
- Est. Effort: 2 hours
- Priority: **MEDIUM** (defense in depth)
- [ ] **Lynis Security Baseline**
- Run `lynis audit system`
- Review recommendations
- Implement high-priority findings
- Aim for score >80
- Re-run quarterly
- Est. Effort: 4 hours (initial) + 1 hour quarterly
- Priority: **MEDIUM** (baseline verification)
### Cluster Layer (K3S / Kubernetes)
- [ ] **CrowdSec Integration**
- Install CrowdSec agent on host
- Connect to CrowdSec Hub (commercial platform, free tier available)
- Feed auth.log, syslog → CrowdSec for attack detection
- Auto-block IPs via local firewall or Hetzner Firewall API
- Est. Effort: 4 hours
- Priority: **MEDIUM** (proactive threat response)
- [ ] **Falco Runtime Monitoring**
- Install Falco DaemonSet in K3S
- Monitor: Shell spawning in containers, suspicious syscalls, privilege escalation
- Output to Loki / syslog
- Alert on anomalies
- Est. Effort: 1 day
- Priority: **MEDIUM** (runtime detection)
---
## 🎯 Meilensteine (Milestones)
| Meilenstein | Beschreibung | Status | ETA |
|------------|-------------|--------|-----|
| **M1: Basis-Setup** | K3S + Flux + ESS deployed | ✅ Done | - |
| **M2: Core Matrix** | Themes, Scripts, Policies | ✅ Done | - |
| **M3: WebRTC & Monitoring** | TURN + Alloy/Prometheus/Loki | ✅ Done | - |
| **M4: Identity Provider** | Authentik Stage 1+2 (pending Stage 2) | 🔄 In Progress | ~12 days |
| **M5: Production-Ready** | DB Backups, NetworkPolicies, Security Hardening | 📋 Backlog | ~23 weeks |
| **M6: Advanced Features** | Element Call Fork, Content Scanner, Mjolnir | 📋 Backlog | ~4+ weeks |
| **M7: Enterprise-Ready** | Full compliance (DSGVO), HA setup, Disaster Recovery | 🎯 Future | ~8+ weeks |
---
## 📊 Prioritäts-Kategorien
### 🔴 CRITICAL (do immediately)
- Hetzner Cloud Firewall setup
- Database backup strategy
- SSH hardening
### 🟠 HIGH (do within 12 weeks)
- Authentik Stage 2 completion
- External PostgreSQL migration
- NetworkPolicies
- Element Call fork
### 🟡 MEDIUM (do within 1 month)
- CrowdSec + Falco
- Mjolnir bot
- Renovate/Trivy
- PSA restricted mode
- Kernel hardening
### 🟢 LOW (nice-to-have, do if time allows)
- Content scanner (ClamAV)
- External-Secrets upgrade
- SSH port relocation
- Advanced federation rules
---
## 📝 Notes & Decision Points
### Authentik Stage 2 Blocker
**Waiting for**: User to manually configure Authentik OIDC Provider in Authentik Admin UI.
- Once done, provide Client ID + Secret
- Then: Commit Stage 2 MAS config
### Database: CloudNativePG vs. Hetzner Postgres
- **CloudNativePG**: Open-source, runs on K3S, full control
- **Hetzner Postgres**: Managed, backups included, less ops overhead
- **Decision**: Recommend CloudNativePG for now (cost-effective), migrate to Hetzner later if operational overhead too high
### Federation: Allowlist vs. Closed?
- **Allowlist**: Default federation with all public servers, can be attacked
- **Closed**: Only federate with trusted servers (higher security, lower interop)
- **Decision**: Depends on user intent. For now: allow all, add Mjolnir for abuse protection
### Security Framework
- **Layers**: Perimeter (Firewall) → Host (SSH, auditd, hardening) → Cluster (NetworkPolicies, PSA, Falco) → App (Rate-limits, Mjolnir)
- **Approach**: Implement incrementally, test after each layer
---
## 🔗 Related Documentation
- `docs/deployment-guides/README.md` Overview
- `docs/deployment-guides/01-turn-server-setup.md` TURN
- `docs/deployment-guides/02-authentik-identity-provider.md` Authentik (Stage 1 + Stage 2 plan)
- `docs/deployment-guides/03-monitoring-integration.md` Monitoring
- `docs/deployment-guides/04-element-customization.md` Themes, Desktop
- `docs/deployment-guides/05-room-policies.md` Policies
---
**Last Updated**: 2026-05-14
**Next Review**: 2026-05-21
@@ -0,0 +1,54 @@
# TURN Server (coturn) für WebRTC Video-Calls
**Status**: ✅ Vollständig deployed
**Domain**: `turn.axion1337.chat`
**Public IP**: `49.13.132.245`
## Problem & Lösung
Videocalls scheitern mit DTLS-Timeout bei Clients hinter NAT/Firewall. **Lösung**: coturn als TURN-Relay.
## Architektur
Client A ──→ coturn (turn.axion1337.chat) ──→ Client B
- **Ports**: 3478/udp, 3478/tcp, 5349/tcp, 49152-65535/udp
- **Auth**: HMAC-basiert mit Shared Secret zwischen coturn + Synapse
- **Deployment**: K3S Deployment mit `hostNetwork: true`
## Dateien (in `apps/production/`)
| Datei | Inhalt |
|-------|--------|
| `coturn.yaml` | ConfigMap + Deployment + Service |
| `coturn-secret.yaml` | SOPS-Secret: `TURN_SECRET` |
| `custom-configs/synapse-values.yaml` | TURN URIs + shared secret |
| `matrix-certificates.yaml` | cert-manager Cert für `turn.axion1337.chat` |
## DNS & Firewall (manuell)
```
DNS A-Record: turn.axion1337.chat → 49.13.132.245
Firewall (K3S Host):
ufw allow 3478/udp
ufw allow 3478/tcp
ufw allow 5349/tcp
ufw allow 49152:65535/udp
```
## Verifikation
```bash
# Pod läuft?
kubectl get pods -n matrix -l app=coturn
# Certificate ready?
kubectl get certificate -n matrix | grep turn
# Extern testen
docker run -it instrumentisto/coturn \
turnutils_uclient -v -T -u test -w test turn.axion1337.chat
```
**Weitere Details**: Siehe vollständige Dokumentation oben.
@@ -0,0 +1,45 @@
# Authentik als Identity Provider für Matrix
**Status**: ✅ Stage 1 Deployed (Authentik läuft)
**Pending**: Stage 2 (MAS Integration)
**Domain**: `auth.axion1337.chat`
## Überblick
Authentik = OIDC Provider für MAS → Zentrales Login + Einladungs-basierte Registrierung.
## Stage 1: Authentik Deployment
**Dateien** (in `apps/authentik/`):
- `namespace.yaml`, `helm-repo.yaml`, `authentik-secret.yaml` (SOPS)
- `authentik.yaml` (HelmRelease v2026.x + embedded Postgres)
- `certificate.yaml`, `ingress.yaml`
**Flux Kustomization**: `clusters/matrix/flux-system/authentik-sync.yaml`
## Deployment-Schritte
1. **DNS A-Record**: `auth.axion1337.chat → 49.13.132.245`
2. **Pods hochfahren**: `kubectl get pods -n authentik -w`
3. **Authentik UI**: `https://auth.axion1337.chat/if/flow/initial-setup/` → Admin-Passwort setzen
4. **OIDC Provider**: Admin UI → OIDC Provider erstellen
5. **Application**: Slug `matrix` (wichtig für Issuer URL!)
6. **Redirect URIs**:
- `https://account.axion1337.chat/upstream/callback/01KQDJTR1ZVTG8JQ220F5BNBFZ`
- Post-logout: `https://axion1337.chat`
7. **Client ID + Secret kopieren**
## Stage 2: MAS Integration
1. Decrypt: `sops --decrypt --in-place apps/production/custom-configs/mas-secret.yaml`
2. `upstream_oauth2_config` + `passwords-config` Blöcke hinzufügen
3. Encrypt: `sops --encrypt --in-place ...`
4. Commit & Push
5. **WICHTIG**: `passwords: enabled: false` erst nach OIDC-Test!
## Einladungs-Links
Authentik Admin → Flows & Stages → Invitations → Create
---
**Weitere Details**: Siehe Kapitel 2 in diesem Projekt.
@@ -0,0 +1,52 @@
# Monitoring: Alloy → Prometheus/Loki auf Selendis
**Status**: ✅ Vollständig deployed
**Remote Storage**: `10.0.0.3:9090` (Prometheus), `10.0.0.3:3100` (Loki)
## Überblick
Alloy (Grafana Agent) sammelt Metriken & Logs vom K3S-Cluster und schickt sie zu Prometheus/Loki auf Selendis.
## Komponenten
| Komponente | Rolle |
|-----------|-------|
| **Alloy** | Metrics & Logs Collector |
| **kube-state-metrics** | Kubernetes Object Status |
| **node-exporter** | Host Metrics (CPU, Memory, Disk) |
| **Prometheus** (Selendis) | Metrics Ingestion |
| **Loki** (Selendis) | Logs Ingestion |
## Dateien (in `apps/monitoring/`)
- `namespace.yaml`
- `helm-repos.yaml` (prometheus-community, grafana)
- `kube-state-metrics.yaml`, `node-exporter.yaml`
- `alloy-config.yaml` (River config with scrape targets + remote write)
- `alloy.yaml` (HelmRelease)
## Scrape Targets
Alloy scraped:
- **Flux Controllers** (flux-system ns, port 8080)
- **kube-state-metrics** (monitoring:8080)
- **node-exporter** (monitoring:9100)
- **Synapse** (matrix.axion1337.chat:9000)
Alle Remote Write zu `10.0.0.3:9090` (Prometheus) + `10.0.0.3:3100` (Loki).
## Troubleshooting
```bash
# Check Alloy Logs
kubectl logs -n monitoring -l app.kubernetes.io/name=alloy
# Check Prometheus remote write
curl http://10.0.0.3:9090/api/v1/query?query=up
# Loki test
curl -s http://10.0.0.3:3100/loki/api/v1/query_range?query=%7B%7D | jq .
```
---
**Weitere Details**: Siehe Kapitel 3.
@@ -0,0 +1,57 @@
# Element Web Customization: Themes, Desktop-Apps, Admin
**Status**: ✅ Vollständig deployed
**Domains**: `axion1337.chat` (Web), `/docs/setup` (Scripts)
## 1. Custom Themes (7 Stück)
| Theme | Primärfarbe |
|-------|-----------|
| aXion1337 Dark | `#1a1a1a` |
| Deep Purple | `#6a4c93` |
| Discord Dark | `#2c2f33` |
| Electric Blue | `#0066ff` |
| Everforest Dark Hard | `#1e2326` |
| Gruvbox Dark | `#282828` |
| Wal | `#1e1e1e` |
**Konfiguration**: `apps/production/custom-configs/element-values.yaml`
**Anwendung (User)**: Settings → Appearance → Colour theme
## 2. Desktop-Setup-Scripts
| System | Datei |
|--------|-------|
| Windows | `element-setup-windows.cmd` (Doppelklick) |
| macOS | `element-setup-macos.command` (Doppelklick) |
| Linux | `element-setup-linux.sh` (bash) |
**Was die Scripts tun**:
1. config.json erstellen mit `configUrl: "https://axion1337.chat/config.json"`
2. Element installieren (WinGet / Homebrew / apt/dnf/pacman)
3. Element starten (auto-config laden)
**Download**: `https://axion1337.chat/docs/setup/`
## 3. Element Admin-Panel
**URL**: `https://admin.axion1337.chat`
- User verwalten
- Room durchsuchen
- Server-Statistiken
**Konfiguration**: `apps/production/element-server-suite.yaml` (ESS Chart)
## Dateien
| Datei | Ort |
|-------|-----|
| Custom Themes | `element-values.yaml` ConfigMap |
| Setup-Scripts | `element-web-docs-configmap.yaml` |
| Docs Server | `element-web-docs-server.yaml` (nginx) |
| Ingress | `apex-ingress.yaml` (`/docs/setup/` route) |
---
**Weitere Details**: Siehe Kapitel 4.
@@ -0,0 +1,82 @@
# Room Policies: Retention, Publication, Auto-Join
**Status**: ✅ Vollständig deployed
**Konfiguration**: `apps/production/custom-configs/synapse-values.yaml`
## 1. Message Retention
Alte Nachrichten automatisch löschen (Speicher sparen, DSGVO).
```yaml
retention:
enabled: true
default_policy:
min_lifetime: 1d # Messages bleiben ≥1d
max_lifetime: 1y # Messages gelöscht nach 1 Jahr
media_retention:
local_media_lifetime: 365d # 1 Jahr
remote_media_lifetime: 90d # 90 Tage
redaction_retention_period: 7d # Gelöschte Messages noch 7d sichtbar
```
## 2. Room Publication Rules
Kontrollieren welche Rooms im öffentlichen Directory sichtbar sind.
```yaml
room_list_publication_rules:
- user_id: "*" # Alle User
action: allow # dürfen ihre Rooms publishen
```
**Alternativ (restrictiv)**: Nur Admins publishen
```yaml
room_list_publication_rules:
- user_id: "@admin:axion1337.chat"
action: allow
- user_id: "*"
action: deny
```
## 3. Auto-Join Rooms
Neue User automatisch in bestimmte Rooms hinzufügen (Onboarding).
```yaml
auto_join_rooms:
- "!announcements:axion1337.chat"
- "!rules:axion1337.chat"
auto_join_rooms_for_guests: false # Nur registered users
```
**Room ID finden**: Element Settings → Advanced → Room ID
## Deployment
```bash
# Edit ConfigMap
kubectl apply -f apps/production/custom-configs/synapse-values.yaml
# Synapse neustarten
kubectl rollout restart deployment -n matrix matrix-stack-synapse
# Verify
kubectl logs -n matrix -l app.kubernetes.io/name=synapse | grep -i "retention\|publication"
```
## Best Practices
**Privater Server**:
- max_lifetime: 1y (großzügig)
- action: allow (alle publishen)
- auto_join_rooms: announcements + rules
**Öffentlicher Server (DSGWR)**:
- max_lifetime: 90d (kurz)
- action: deny (nur Admins)
- auto_join_rooms: [] (keine Zwangs-Rooms)
---
**Weitere Details**: Siehe Kapitel 5.
+92
View File
@@ -0,0 +1,92 @@
# aXion1337.Chat Deployment & Konfiguration Dokumentation
Diese Dokumentation beschreibt die Einrichtung und Konfiguration des Matrix-Homeservers für **axion1337.chat** mit Element Server Suite (ESS) v26.4.0 auf K3S mit Flux CD GitOps.
## 📋 Übersicht Deployment-Reihenfolge
Die Implementierungen wurden in dieser Reihenfolge durchgeführt. Für neue Setups sollten Sie dieser Abfolge folgen:
| # | Titel | Datei | Status | Zieldomäne |
|---|-------|-------|--------|-----------|
| 1 | TURN Server für WebRTC Video-Calls | `01-turn-server-setup.md` | ✅ Deployed | `turn.axion1337.chat` |
| 2 | Authentik als Identity Provider | `02-authentik-identity-provider.md` | ✅ Stage 1 Deployed | `auth.axion1337.chat` |
| 3 | Monitoring mit Alloy/Prometheus/Loki | `03-monitoring-integration.md` | ✅ Deployed | lokal (10.0.0.3) |
| 4 | Element Web Anpassung & Desktop-Apps | `04-element-customization.md` | ✅ Deployed | `axion1337.chat` |
| 5 | Room Policies (Retention, Publication, Auto-Join) | `05-room-policies.md` | ✅ Deployed | Matrix Synapse |
---
## 🚀 Quick Start für neue Deployment
Siehe die einzelnen Dokumentationen für detaillierte Anleitung.
---
## 🏗️ Architektur-Übersicht
```
┌─────────────────────────────────────────────────────────────┐
│ Element Web (Apex) │
│ axion1337.chat (HTTP/TLS) │
└──────────────────────┬──────────────────────────────────────┘
┌─────────────┼─────────────┐
│ │ │
┌────▼────┐ ┌─────▼──────┐ ┌──▼────────┐
│ MAS │ │ Well-Known │ │Docs/Setup │
│account. │ │matrix/* │ │/setup │
│axion1337 │ │ │ │ │
└────┬────┘ └────────────┘ └───────────┘
┌────▼────────────────┐
│ Authentik OIDC │
│ auth.axion1337.chat │
│ (Identity Provider) │
└─────────────────────┘
┌────▼────────────────┐
│ Synapse Matrix │
│ matrix.axion1337.chat│
│ (Homeserver) │
└──────────────────────┘
```
---
## 🔑 Kritische Werte & Konfigurationen
### Domains
- **Apex**: `axion1337.chat` (Element Web)
- **Matrix Synapse**: `matrix.axion1337.chat`
- **MAS**: `account.axion1337.chat`
- **Authentik**: `auth.axion1337.chat`
- **TURN Server**: `turn.axion1337.chat`
### Externe Services
- **K3S Host IP**: `49.13.132.245`
- **Monitoring Host**: `10.0.0.3` (Selendis)
---
## 📚 Dokumente im Detail
### [01-turn-server-setup.md](01-turn-server-setup.md)
STUN/TURN Server für WebRTC Media Relay (Video-Calls).
### [02-authentik-identity-provider.md](02-authentik-identity-provider.md)
Authentik als OIDC Provider für Matrix. Registrierung via Einladungs-Links.
### [03-monitoring-integration.md](03-monitoring-integration.md)
Alloy → Prometheus/Loki Monitoring Integration.
### [04-element-customization.md](04-element-customization.md)
Custom Themes, Desktop-Setup-Scripts, Element Admin.
### [05-room-policies.md](05-room-policies.md)
Message Retention, Room Publication, Auto-Join Policies.
---
## 🛠️ Wartung & Troubleshooting
Alle Dokumentationen enthalten Troubleshooting-Sektionen für häufige Probleme.
+296
View File
@@ -0,0 +1,296 @@
# 🔄 GitOps ConfigMap Auto-Sync via Checksums
Dieses Dokument erklärt ein Kernproblem mit **Flux CD** und **externe Konfigurationen** und wie wir es gelöst haben.
---
## 📋 Das Problem: Flux erkennt ConfigMap-Änderungen nicht
### Die Situation
Unsere HelmRelease (`element-server-suite.yaml`) nutzt `valuesFrom`, um Konfigurationen aus externen **ConfigMaps** zu laden:
```yaml
spec:
valuesFrom:
- kind: ConfigMap
name: ess-element-custom # ← Diese ConfigMap
valuesKey: values.yaml
- kind: ConfigMap
name: ess-synapse-custom # ← Diese ConfigMap
valuesKey: values.yaml
```
Diese ConfigMaps entstehen aus Dateien im Git-Repo (`apps/production/custom-configs/*.yaml`) und werden von Kustomize in den Cluster deployed.
### Das Kernproblem
**Flux CD reagiert NICHT automatisch, wenn sich eine ConfigMap ändert.**
Warum? Flux überwacht nur das Git-Repository auf Änderungen. Wenn du `element-values.yaml` änderst:
1. ✅ Flux sieht die Änderung im Git-Repo
2. ✅ Kustomize erzeugt eine neue ConfigMap mit den neuen Werten
3. ❌ Aber Helm (der Helm-Controller in Flux) erkennt **nicht**, dass sich die externe ConfigMap geändert hat
4. ❌ Helm deployt das Chart nicht neu → Die alten Themes/Configs bleiben aktiv
Das ist kein Bug, sondern by-design: Helm achtet nur auf:
- Chart-Version (z.B. `26.4.0`)
- Änderungen in den direkten `values:` Blöcken
- Nicht auf externe Quellen wie ConfigMaps
---
## 🔑 Die Lösung: Checksums als Trigger
Wir nutzen **Annotations mit Checksums** als Workaround:
```yaml
apiVersion: helm.toolkit.fluxcd.io/v2
kind: HelmRelease
metadata:
annotations:
element-config-checksum: "401f8a87d0ef5d91d2e5032d4aede42c" # ← Hash der element-values.yaml
synapse-config-checksum: "e98fe81141f52e7ea833596ca39853b9" # ← Hash der synapse-values.yaml
```
Wenn sich der Annotation-Wert ändert, sieht Flux, dass die **HelmRelease selbst** sich geändert hat und deployt neu.
### Automatisierung via Git Pre-Commit Hook
Das Problem: Wer aktualisiert die Checksums, wenn man `element-values.yaml` editiert?
**Lösung:** Ein Git **pre-commit Hook** tut das automatisch:
```bash
$ vi apps/production/custom-configs/element-values.yaml
# (Farbe ändern, Theme hinzufügen, …)
$ git add apps/production/custom-configs/element-values.yaml
$ git commit -m "feat: new theme"
# ← Der Hook läuft jetzt:
# 1. Berechnet MD5-Hash der neuen element-values.yaml
# 2. Aktualisiert die Annotation in kustomization.yaml
# 3. Added kustomization.yaml zum Commit automatisch
```
Der User muss **nichts Zusätzliches tun** alles läuft automatisch.
---
## 🚀 Installation
Nach dem Repository **klonen**, führe dieses Skript aus:
```bash
cd prod/gitops
./scripts/install-hooks.sh
```
Das Skript:
- ✅ Erstellt einen Symlink `.git/hooks/pre-commit``scripts/hooks/pre-commit`
- ✅ Macht die Hook-Datei ausführbar
- ✅ Gibt dir eine Bestätigungsmeldung
**Einmalig pro lokales Repository.** Neue Klone müssen den Hook auch installieren.
---
## 📝 Workflow: ConfigMaps ändern
So sieht die Praxis aus:
### 1️⃣ Änderung machen
```bash
vi apps/production/custom-configs/element-values.yaml
# Edit: Themes, Farben, Logging-Level, etc.
```
### 2️⃣ Committen (Hook läuft automatisch)
```bash
git add apps/production/custom-configs/element-values.yaml
git commit -m "feat: add Dark Purple theme variant"
# Pre-Commit Hook läuft automatisch:
# → Berechnet neuen Hash
# → Updated kustomization.yaml
# → Added kustomization.yaml zum Commit
```
### 3️⃣ Überprüfung (optional)
```bash
# Schaue, was committet wird:
git show --stat
# Output sollte zeigen:
# element-values.yaml (modified)
# kustomization.yaml (modified) ← vom Hook hinzugefügt
```
### 4️⃣ Pushen & Deployen
```bash
git push
# ← Flux sieht die Änderung an kustomization.yaml
# ← HelmRelease wird neu-synced mit den neuen Checksums
# ← Die neue Config ist in ~5 Minuten aktiv
```
---
## 🔧 Technische Details
### Welche Dateien sind "überwacht"?
Der Hook beobachtet:
| Datei | Annotation | Ziel |
|-------|-----------|------|
| `apps/production/custom-configs/element-values.yaml` | `element-config-checksum` | Element Web Themes, Branding |
| `apps/production/custom-configs/synapse-values.yaml` | `synapse-config-checksum` | Synapse Logging, Federation |
### Hook-Implementation
Der Hook (`scripts/hooks/pre-commit`) macht folgendes:
1. Prüft, ob eine der überwachten Dateien geändert wurde (`git diff --cached`)
2. Berechnet den MD5-Hash der Datei (kompatibel mit macOS/Linux)
3. Ersetzt den Hash-Wert in `apps/production/kustomization.yaml` via `sed`
4. Added `kustomization.yaml` automatisch zum Commit mit `git add`
```bash
# Beispiel: element-values.yaml ändert sich von
value: "401f8a87d0ef5d91d2e5032d4aede42c" # element-config
# zu
value: "a1b2c3d4e5f6g7h8i9j0k1l2m3n4o5p6" # element-config
```
---
## ⚠️ Häufige Fragen
### F: Was passiert, wenn der Hook fehlschlägt?
A: Der Commit wird **abgebrochen**. Du siehst eine Fehlermeldung. Typische Gründe:
- `md5` oder `md5sum` nicht installiert (sehr unwahrscheinlich)
- `sed` Syntax-Fehler (sehr selten)
Lass dich nicht entmutigen rufe denen auf, die das Setup machen 🚀
### F: Kann ich den Hook deaktivieren?
A: Ja, aber bitte nicht! Wenn du temporär ohne Hook arbeiten möchtest:
```bash
git commit --no-verify
```
Das umgeht den Hook einmalig. Danach musst du die Checksums manuell aktualisieren.
### F: Der Hook touched `kustomization.yaml`, obwohl ich sie nicht editiert habe?
A: Das ist **Absicht**. Der Hook updated **nur** die Checksums, nicht den Rest der Datei. Das ist sauber und Git-freundlich.
### F: Was wenn ich mehrere ConfigMaps gleichzeitig ändere?
A: Der Hook aktualisiert **alle** deren Checksums in einem Pass. Keine Probleme.
---
## 🧪 Verifikation: Hook funktioniert?
Teste es selbst:
```bash
# 1. Hook installieren
./scripts/install-hooks.sh
# 2. Eine Teständerung machen
echo "# Test" >> apps/production/custom-configs/element-values.yaml
# 3. Committen
git add apps/production/custom-configs/element-values.yaml
git commit -m "test: verify hook"
# 4. Überprüfung: Wurde kustomization.yaml auto-updated?
git diff HEAD~1 apps/production/kustomization.yaml | grep -i checksum
# Output sollte zeigen, dass ein Checksum sich geändert hat
```
Wenn ja → Hook funktioniert! ✅
Wenn nein → Rufe uns an 📞
---
## 📚 Zusammenhang mit Flux CD
```
┌─────────────────────────────────────────────────────────────┐
│ Git Repository (axion1337.chat-gitops) │
├─────────────────────────────────────────────────────────────┤
│ │
│ apps/production/custom-configs/ │
│ ├── element-values.yaml (du änderst das) │
│ ├── synapse-values.yaml │
│ └── mas-secret.yaml │
│ │
│ apps/production/ │
│ └── kustomization.yaml (Hook updated die Checksums hier) │
│ │
│ apps/production/ │
│ └── element-server-suite.yaml (HelmRelease mit Annotations)│
│ │
└─────────────────────────────────────────────────────────────┘
↓ git push
┌─────────────────────────────────────────────────────────────┐
│ FluxCD im Kubernetes-Cluster │
├─────────────────────────────────────────────────────────────┤
│ │
│ 1. GitRepository Source │
│ └─ Fetcht dein Repo alle 10 Minuten │
│ │
│ 2. Kustomization production-apps │
│ └─ Applyt die Kustomize-Overlays │
│ └─ Erzeugt ConfigMaps mit neuen Werten │
│ │
│ 3. HelmRelease matrix-stack │
│ └─ Sieht neue Annotations (Checksums) │
│ └─ Deployt Helm-Chart mit neuen Werten │
│ │
│ 4. Element Web Pods │
│ └─ Restarten automatisch │
│ └─ Laden neue Config aus der ConfigMap │
│ │
└─────────────────────────────────────────────────────────────┘
```
---
## 🚨 Notfall: Manuelle Checksum-Aktualisierung
Falls der Hook ausfällt (z.B. weil Git Hooks in CI deaktiviert sind), kannst du Checksums manuell aktualisieren:
```bash
# 1. Neuen Hash berechnen
md5sum apps/production/custom-configs/element-values.yaml
# Output: a1b2c3d4e5f6g7h8i9j0k1l2m3n4o5p6 apps/production/custom-configs/element-values.yaml
# 2. Annotation in kustomization.yaml updaten
vi apps/production/kustomization.yaml
# Ändere: value: "a1b2c3d4e5f6g7h8i9j0k1l2m3n4o5p6" # element-config
# 3. Committen
git add apps/production/kustomization.yaml
git commit -m "fix: manual checksum update"
git push
```
---
**Version:** 1.0
**Letztes Update:** 2026-05-14
**Kompatibilität:** FluxCD 2.x, Kustomize 5.x+
+41
View File
@@ -0,0 +1,41 @@
#!/usr/bin/env bash
# GitOps ConfigMap Checksum Hook
# Automatically updates checksum annotations in kustomization.yaml when ConfigMaps change.
# This ensures Flux CD re-deploys the HelmRelease when external ConfigMap sources are modified.
#
# See: docs/ops-configmap-sync.md
set -euo pipefail
REPO_ROOT="$(git rev-parse --show-toplevel)"
ELEMENT_VALUES="$REPO_ROOT/apps/production/custom-configs/element-values.yaml"
SYNAPSE_VALUES="$REPO_ROOT/apps/production/custom-configs/synapse-values.yaml"
KUSTOMIZATION="$REPO_ROOT/apps/production/kustomization.yaml"
# Function to calculate MD5 hash (handles both GNU md5sum and BSD md5)
get_md5() {
local file="$1"
if command -v md5sum &> /dev/null; then
md5sum "$file" | awk '{print $1}'
elif command -v md5 &> /dev/null; then
md5 -q "$file"
else
echo "ERROR: Neither md5sum nor md5 found" >&2
exit 1
fi
}
# Update checksums for ConfigMaps that exist and are staged
if git diff --cached --name-only | grep -q "element-values.yaml"; then
ELEMENT_HASH=$(get_md5 "$ELEMENT_VALUES")
sed -i.bak "s/value: \"[0-9a-f]\{32\}\" *# element-config/value: \"$ELEMENT_HASH\" # element-config/" "$KUSTOMIZATION"
rm -f "$KUSTOMIZATION.bak"
git add "$KUSTOMIZATION"
fi
if git diff --cached --name-only | grep -q "synapse-values.yaml"; then
SYNAPSE_HASH=$(get_md5 "$SYNAPSE_VALUES")
sed -i.bak "s/value: \"[0-9a-f]\{32\}\" *# synapse-config/value: \"$SYNAPSE_HASH\" # synapse-config/" "$KUSTOMIZATION"
rm -f "$KUSTOMIZATION.bak"
git add "$KUSTOMIZATION"
fi
+27
View File
@@ -0,0 +1,27 @@
#!/usr/bin/env bash
# Install Git Hooks for GitOps automation
# Must be run after cloning the repository
REPO_ROOT="$(git rev-parse --show-toplevel 2>/dev/null)" || {
echo "❌ Not in a git repository"
exit 1
}
HOOKS_DIR="$REPO_ROOT/.git/hooks"
HOOK_SOURCE="$REPO_ROOT/scripts/hooks/pre-commit"
HOOK_DEST="$HOOKS_DIR/pre-commit"
# Verify source exists
if [ ! -f "$HOOK_SOURCE" ]; then
echo "❌ Hook source not found: $HOOK_SOURCE"
exit 1
fi
# Create symlink (force if exists)
mkdir -p "$HOOKS_DIR"
ln -sf "../../scripts/hooks/pre-commit" "$HOOK_DEST"
chmod +x "$HOOK_SOURCE"
echo "✅ Git hooks installed:"
echo " • pre-commit: ConfigMap checksum auto-update"
echo " See: docs/ops-configmap-sync.md"