Add documentation to wiki branch

- Deployment guides for TURN, Authentik, Monitoring, Element, Policies
- Task tracking (TASKS.md)
- Element desktop setup scripts for all platforms
- Installation guide

Co-Authored-By: Claude Haiku 4.5 <noreply@anthropic.com>
This commit is contained in:
Scrublord MacBad 2026-05-14 23:38:28 +02:00
parent 20e041ca94
commit 0ff598e8e0
17 changed files with 14777 additions and 0 deletions

503
docs/TASKS.md Normal file
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

View File

@ -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.

View File

@ -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.

View File

@ -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.

View File

@ -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.

View File

@ -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.

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.

78
docs/install.md Normal file
View File

@ -0,0 +1,78 @@
## 🚀 Step-by-Step Installationsanleitung (From Scratch)
Diese Anleitung geht davon aus, dass du einen frischen Server (Ubuntu/Debian) mit öffentlicher IP hast und deine lokalen Tools (Flux CLI, kubectl, sops, age) installiert sind.
### Schritt 1: Kubernetes (K3s) auf dem Server installieren
Logge dich per SSH auf deinem Server ein und installiere ein frisches K3s. Wir nutzen K3s mit dem Standard-Traefik-Ingress.
```bash
# Auf dem Server ausführen:
curl -sfL https://get.k3s.io | sh -
# Kubeconfig kopieren und Berechtigungen setzen (für den lokalen Zugriff)
sudo cp /etc/rancher/k3s/k3s.yaml ~/.kube/config
sudo chown $USER ~/.kube/config
```
*Kopiere dir den Inhalt der `~/.kube/config` auf deinen lokalen Rechner, damit dein lokales `kubectl` den Server steuern kann. Vergiss nicht, die IP `127.0.0.1` in der Datei durch die öffentliche IP deines Servers zu ersetzen.*
### Schritt 2: Den SOPS-Verschlüsselungs-Key generieren
Damit Flux deine verschlüsselten Passwörter (SMTP, Datenbank) im Cluster lesen kann, braucht es einen privaten Schlüssel. Wir nutzen `age`.
```bash
# Auf deinem lokalen Rechner ausführen:
# 1. Key generieren
age-keygen -o age.agekey
# 2. Den Public Key (steht in der Datei) in die .sops.yaml des Repos eintragen!
# 3. Den Private Key als Secret in den Cluster laden (in den flux-system Namespace)
cat age.agekey | kubectl create secret generic sops-age \
--namespace=flux-system \
--from-file=age.agekey=/dev/stdin
```
### Schritt 3: Das Git-Repository vorbereiten
Stelle sicher, dass deine GitOps-Struktur gepusht ist und du ein Personal Access Token (PAT) für dein Git-Repository hast (bei GitHub/GitLab).
* Das Token benötigt Lese- und Schreibrechte auf das Repository.
### Schritt 4: Flux Bootstrap (Der Startschuss)
Das ist der magische Befehl. Er installiert den Flux-Controller in deinem Cluster und verbindet ihn mit deinem Repository. Ab diesem Moment übernimmt Flux das Steuer.
**Für GitHub:**
```bash
export GITHUB_TOKEN="dein-personal-access-token"
export GITHUB_USER="dein-github-username"
flux bootstrap github \
--owner=$GITHUB_USER \
--repository=dein-repo-name \
--branch=main \
--path=prod/gitops/clusters/matrix \
--personal
```
**Für Gitea/GitLab/Generisches Git (wie in deinem Setup scheinbar genutzt):**
```bash
flux bootstrap git \
--url=https://rohana.axion1337.de/sorb/axion1337.chat-gitops.git \
--branch=main \
--path=prod/gitops/clusters/matrix \
--username=dein-git-user \
--password=dein-git-token
```
### Schritt 5: Zurücklehnen und beobachten
Flux klont jetzt dein Repo, liest die Kustomizations und wendet sie in der richtigen Reihenfolge an (`infra-apps` -> `production-apps`).
Du kannst den Fortschritt live verfolgen:
```bash
# Zeigt den GitOps-Sync-Status:
flux get kustomizations --watch
# Zeigt das Helm-Deployment der Element Server Suite:
flux get helmreleases -n matrix --watch
# Zeigt, wie die Pods hochfahren:
kubectl get pods -n matrix -w
```
Sobald alle Pods auf `Running` stehen und die Zertifikate über Let's Encrypt validiert wurden (`kubectl get certificate -n matrix`), ist dein Matrix-Stack unter `https://axion1337.chat` erreichbar.

117
docs/oldwiki/authentik.md Normal file
View File

@ -0,0 +1,117 @@
# Authentik als Einladungs- und Self-Registration-Layer vor MAS in ESS Community
## Kurzurteil
Ja — in deinem Setup ist **Authentik** technisch sinnvoll einsetzbar, aber **nicht als Ersatz für den Matrix Authentication Service**, sondern **als Upstream-OIDC-Provider vor MAS**. Das ist der sauberste Weg, weil Synapse heute eine stabile, vereinfachte Integration mit MAS hat, ESS Community zusätzliche MAS-Konfiguration ausdrücklich über `matrixAuthenticationService.additional` vorsieht, und MAS jede OIDC-konforme Upstream-Identitätsquelle unterstützt. Für ein ESS-Deployment mit delegierter Authentifizierung ist das deutlich kohärenter als eine Direktanbindung von Synapse an Authentik vorbei. citeturn31view0turn7view2turn14view1turn23search0
Wichtig ist aber die Abgrenzung: Wenn dein einziges Problem wirklich nur lautet „im Admin-Frontend kann ich keine Registration Tokens mehr klicken“, dann **brauchst du Authentik nicht zwingend**. MAS hat weiterhin eine Admin-API mit Endpunkten für User-Registration-Tokens; der fehlende Komfort liegt also eher in der Oberfläche als in der Funktion selbst. Die API ist mit `urn:mas:admin` abgesichert und kann sowohl interaktiv als auch automatisiert benutzt werden. citeturn19search0turn28search0turn28search1turn28search2
## Warum Authentik hier die bessere Plattform sein kann
Der Mehrwert von Authentik entsteht dann, wenn du **mehr als nur ein Token-Feld** willst: Einladungen, Self-Service-Enrolment, E-Mail-Verifikation, Policies, Gruppen-Zuweisung, später vielleicht weitere Login-Quellen hinter derselben Oberfläche. Authentik kann selbst als OpenID Provider auftreten, aber auch als Relying Party gegenüber anderen OAuth/OIDC-Quellen arbeiten; MAS sieht dann nur noch **eine** saubere OIDC-Oberfläche, während Authentik die eigentliche Onboarding- und Policy-Logik kapselt. Das passt sehr gut zu MAS, weil MAS nach oben bewusst nur OIDC unterstützt und SAML/LDAP nicht selbst als Upstream sprechen will. citeturn21view0turn21view3turn14view1
Für dein Ziel „potenzielle Anwender sollen sich selbst registrieren können“ ist der entscheidende Unterschied: Bei MAS-Registration-Tokens autorisierst du eine **Matrix-Registrierung**; bei Authentik autorisierst du zunächst eine **Identität im IdP**, und MAS übernimmt diese Identität anschließend per OIDC und legt daraus den Matrix-Account an. Das ist architektonisch stärker, weil dieselbe Identität später auch für andere Dienste nutzbar wird. MAS kann beim Upstream-Login den Matrix-Localpart, Display Name und E-Mail aus Claims übernehmen; für neue Nutzer gibt es dabei sogar einen expliziten Bestätigungs- bzw. Attribut-Import-Schritt. citeturn24search0turn14view0
## Wann Authentik nicht nötig ist
Wenn du ausschließlich einen „Einladungs-Code“ für Matrix brauchst und keinerlei separates Identitätsmanagement, dann ist die schlankere Lösung wahrscheinlich: **bei MAS bleiben und die Registration-Tokens per Admin-API verwalten**. Dafür brauchst du keinen zusätzlichen Dienst, keine zweite Postgres-Anwendung und keine zweite Policy-Oberfläche. Das ist betriebsärmer und passt gut zu kleinen Community-Setups. citeturn19search0turn28search0turn28search2
Sobald du aber Dinge wie diese willst, kippt die Bewertung klar zugunsten von Authentik: verschiedene Onboarding-Flows, Einladungs-Links statt nackter Codes, E-Mail-Verifikation, Domain-Allow-Lists, Gruppen-Zuweisung, zentrale MFA-Politik oder später externe Identity-Sources. Authentik bringt dafür sowohl vorgefertigte Einladungs-Blueprints als auch Enrolment-Flows mit und kann bei Bedarf eigene Expression Policies für restriktivere Zulassungslogik einsetzen. citeturn21view1turn21view2turn30search3
## Empfohlene Zielarchitektur
Die von mir empfohlene Zielarchitektur ist:
**Element Web / Clients → MAS → Authentik → Benutzerquelle(n)**
Synapse bleibt dabei an MAS delegiert. Das ist genau der Pfad, den die Synapse- und MAS-Dokumentation heute unterstützen: Synapse integriert stabil mit MAS, und MAS kann wiederum Upstream-OIDC-Provider sprechen. Eine direkte Synapse-OIDC-Integration mit Authentik ist zwar technisch dokumentiert, wäre in deinem ESS/MAS-Setup aber die weniger saubere Variante, weil du damit an der in ESS bereits vorgesehenen Delegationsschicht vorbeikonfigurierst. citeturn31view0turn14view2turn14view1turn7view2
Für Authentik selbst ist das Standardmaterial: auf Kubernetes per Helm deployen, in Produktion ein echtes PostgreSQL verwenden statt der Demo-Datenbank, und E-Mail konfigurieren, wenn du Einladungen oder Verifikations-Mails nutzen willst. Das ist wichtig, weil Authentik-Einladungen und E-Mail-basierte Enrolment-Flows ohne Mailtransport ihren eigentlichen Nutzen verlieren. citeturn34view0turn25search1
Ein entscheidender UX-Punkt: Wenn in MAS genau **ein** Upstream-Provider konfiguriert ist und die lokale Passwortdatenbank deaktiviert wird, startet MAS den Upstream-Authentifizierungsfluss automatisch. Damit verhält sich das System für Endnutzer fast so, als wäre Authentik „direkt“ integriert, obwohl MAS weiterhin die Matrix-native Auth-Schicht bleibt. citeturn26view0
## Konkrete Integration in ESS und FluxCD
Der erste praktische Schritt ist, Authentik als eigene GitOps-Anwendung in Kubernetes einzuführen. Offiziell ist dafür das Helm-Chart vorgesehen; produktiv sollte die Datenbank extern bzw. operator-basiert laufen, und Mail sollte von Anfang an mitgedacht werden. Danach erzeugst du in Authentik eine **Application + OAuth2/OIDC Provider**-Kombination. Das ist der von Authentik empfohlene Weg zur Erstellung eines OIDC-Providers. citeturn34view0turn35view0
Für den OIDC-Provider in Authentik verwendest du als Redirect-URI **nicht** die Synapse-Callback-URL aus der direkten Synapse-Dokumentation, sondern die von MAS erwartete Upstream-Callback-URL. MAS verlangt für Upstream-Provider eine stabile ULID als Provider-ID und verwendet daraus die Callback-URL `https://<auth-service-domain>/upstream/callback/<id>`. Optional kannst du zusätzlich die Backchannel-Logout-URL `https://<auth-service-domain>/upstream/backchannel-logout/<id>` hinterlegen. Authentik unterstützt für OIDC-Anwendungen Front- und Back-Channel-Logout, sofern der Provider entsprechend konfiguriert ist. citeturn14view1turn26view3turn35view1
In ESS selbst musst du dafür **keinen Chart forken**. Die vorgesehene Stelle ist `matrixAuthenticationService.additional`. Dort gibst du MAS die Upstream-OIDC-Konfiguration und schaltest die lokale Passwortdatenbank ab, wenn Authentik der alleinige Eintrittspunkt werden soll. Genau dafür ist die ESS-Advanced-Dokumentation da. citeturn7view2
Ein praktikabler MAS-Werteblock für deine GitOps-Struktur sieht so aus:
```yaml
matrixAuthenticationService:
additional:
10-authentik-upstream.yaml:
config: |
passwords:
enabled: false
account:
password_registration_enabled: false
upstream_oauth2:
providers:
- id: 01JVXXXXXXXXXXXXXXXAUTHN
issuer: "https://auth.example.com/application/o/matrix-mas/"
human_name: "Community Login"
client_id: "mas-community"
client_secret: "AUS_SOPS_SECRET"
token_endpoint_auth_method: client_secret_post
scope: "openid profile email"
fetch_userinfo: true
on_backchannel_logout: logout_browser_only
claims_imports:
localpart:
action: require
template: "{{ user.preferred_username }}"
# Nur für Bestandskonten und nur nach Pilotphase:
# on_conflict: set
displayname:
action: force
template: "{{ user.name }}"
email:
action: force
template: "{{ user.email }}"
```
Die inhaltliche Grundlage dafür kommt direkt aus den MAS-Upstream-OIDC-Dokumenten: Provider-`id` als ULID, `issuer`, `client_id`, `client_secret`, Scope, optionale UserInfo-Nutzung und Claim-Mapping für `localpart`, `displayname` und `email`. ESS injiziert genau solche zusätzlichen MAS-Dateien über `matrixAuthenticationService.additional`. citeturn14view1turn14view0turn13view5turn7view2
Für das eigentliche Onboarding in Authentik hast du zwei gute Varianten. Wenn du das MAS-Token-Modell möglichst ähnlich nachbauen willst, nimmst du **Invitations**. Authentik kann Einladungs-URLs an konkrete Empfänger senden oder generische Einladungslinks bereitstellen, bei denen Benutzer ihre Credentials selbst festlegen. Wenn du eher echte Self-Service-Registrierung willst, nimmst du einen Enrolment-Flow, optional mit E-Mail-Verifikation. Beide Muster sind offiziell dokumentiert; es gibt sogar vorgefertigte Blueprints für invitation-based enrollment und Beispiel-Flows für Enrolment mit oder ohne E-Mail-Verifikation. citeturn21view1turn21view2
Wenn du bei der Benutzerführung in Element noch glatter werden willst, kannst du optional in Element Web `sso_redirect_options` setzen, damit Nutzer auf der Login- oder Welcome-Seite sofort in den OIDC-/SSO-Flow gehen. Das ist kein Muss — MAS kann bei einem einzigen Upstream-Provider ohnehin automatisch weiterleiten — aber es verbessert den Eindruck eines „SSO-only“-Setups. citeturn15view4turn26view0
Ein optionaler Element-Web-Block dafür wäre:
```json
{
"sso_redirect_options": {
"on_login_page": true,
"on_welcome_page": true
}
}
```
## Risiken und Fallstricke
Der heikelste Punkt ist die **Abbildung auf bestehende Matrix-Konten**. MAS kann Upstream-Identitäten an vorhandene lokale Nutzer binden, wenn der gemappte `localpart` passt. Standardmäßig verweigert MAS diese Verknüpfung aber; dafür gibt es `claims_imports.localpart.on_conflict` mit Werten wie `set`, `add` oder `replace`. Die Dokumentation warnt ausdrücklich davor, dass das bei unsauberem Mapping ein Account-Takeover-Risiko werden kann. In der Praxis heißt das: `on_conflict` nur dann einschalten, wenn du sicher garantieren kannst, dass Authentik-`preferred_username` oder ein anderes Attribut **eindeutig und dauerhaft** dem gewünschten Matrix-Localpart entspricht. citeturn26view2turn14view0
Der zweite Betriebsfallstrick ist GitOps-spezifisch: Änderungen und Ergänzungen im `upstream_oauth2.providers`-Block synchronisiert MAS beim Start in seine Datenbank, **Entfernungen** aber nicht automatisch. Wenn du einen Provider wieder herausnimmst oder umbenennst, brauchst du zusätzlich `mas-cli config sync --prune`. Für FluxCD ist das wichtig, weil „Config aus Git gelöscht“ hier nicht automatisch „Provider aus MAS-DB gelöscht“ bedeutet. citeturn27search1turn13view5
Der dritte Punkt betrifft Logout-Semantik. Sowohl MAS als auch Authentik können OIDC-Logout verarbeiten, aber du solltest den Modus bewusst wählen. `logout_all` in MAS ist am konsequentesten, kann aber auch Sessions beenden, die aus derselben Upstream-Sitzung stammen und über andere Flows erzeugt wurden. `logout_browser_only` ist meist die konservativere Wahl für einen ersten Rollout. Auf Authentik-Seite kannst du zusätzlich vollständiges Single Logout aktivieren, wenn Logout aus einer Anwendung auch die Authentik-Sitzung selbst und andere verbundene Anwendungen beenden soll. citeturn26view0turn35view1
Falls du Authentik doch nicht einführst und stattdessen bei MAS-Registration-Tokens bleibst, solltest du den ESS-Hinweis ernst nehmen: `account.password_registration_email_required: false` darf auf einem öffentlich föderierenden System nur zusammen mit Einschränkungen wie `registration_token_required: true` benutzt werden, sonst läufst du direkt in Missbrauch und Spam. MAS selbst dokumentiert dieselben Schalter im `account`-Block: Passwort-Registrierung ist standardmäßig aus, E-Mail-Pflicht standardmäßig an, Registration-Token-Pflicht standardmäßig aus. citeturn7view2turn13view0turn13view1turn13view2
## Praktische Entscheidung
Wenn dein Zielbild lautet **„Einladungen, Self-Service, Verifikation, Gruppen, spätere Erweiterbarkeit“**, dann ist meine klare Empfehlung: **Authentik vor MAS**. Das ist in ESS Community sauber integrierbar, nutzt die offiziell vorgesehenen Konfigurationspfade und hält Synapse in der heute empfohlenen MAS-Architektur. citeturn7view2turn31view0turn14view1
Wenn dein Zielbild dagegen nur lautet **„ich will wieder Registration Tokens vergeben können, aber ohne zweiten IdP zu betreiben“**, dann ist die wirtschaftlichere Lösung sehr wahrscheinlich: **MAS Admin API automatisieren statt Authentik einführen**. Funktional ist das möglich; der fehlende Baustein ist nur die Bedienoberfläche, nicht die darunterliegende Token-Funktion. citeturn19search0turn28search0turn28search2
## Offene Punkte und Grenzen
Die produktseitigen Integrationsfragen sind gut durch die offiziellen Dokumentationen abgedeckt. Was ich in diesem Bericht bewusst generisch gehalten habe, sind deine **konkreten Datei- und Pfadnamen im GitOps-Repo** sowie die **genaue Secret-Aufteilung** zwischen ConfigMap und SOPS-Secret. Die technische Empfehlung steht trotzdem fest: MAS bleibt die Matrix-Schicht, Authentik wird der Upstream-IdP, und die Integration erfolgt über `matrixAuthenticationService.additional` in ESS. citeturn7view2turn14view1

View File

@ -0,0 +1,327 @@
# MISSING_MATRIX_RTC_TRANSPORT in ESS 26.4.0: Ursachenanalyse und vollständiger Fix
**Die Ursache ist Hypothese 1: `wellKnownDelegation.enabled: false` ist der Kill-Switch.** In genau dieser Konfiguration schreibt das ESS-Chart den Schlüssel `org.matrix.msc4143.rtc_foci` normalerweise automatisch in das an `https://axion1337.chat/.well-known/matrix/client` ausgelieferte JSON-Dokument sobald `wellKnownDelegation.enabled: true` **und** `matrixRTC.enabled: true` gesetzt sind. Mit `wellKnownDelegation: false` fällt dieses Dokument komplett weg. Element Web hat damit keinen Discovery-Pfad zur LiveKit-Instanz auf `mrtc.axion1337.chat`, und Matrix-JS-SDK wirft genau deshalb `MISSING_MATRIX_RTC_TRANSPORT`. Hypothese 2 (Synapse-Custom-Keys sind bogus) ist ebenfalls korrekt. Hypothese 4 (Element Web braucht explizites `rtc_foci`) ist **falsch** Element Web liest `rtc_foci` ausschließlich aus Well-Known, niemals aus `config.json`. Hypothese 5 ist ein *sekundäres* Thema: LiveKit UDP-Ports müssen offen sein, aber der Fehler `MISSING_MATRIX_RTC_TRANSPORT` entsteht ausschließlich aus der Discovery, nicht aus Medien-Erreichbarkeit.
## Wie die Fehlerkette konkret abläuft
Element Web ruft beim Start eines Anrufs intern zwei Discovery-Pfade auf: `GET /_matrix/client/v1/rtc/transports` gegen Synapse (MSC4143, ab Synapse 1.140) und als Fallback `GET https://<serverName>/.well-known/matrix/client`, wo der Schlüssel `org.matrix.msc4143.rtc_foci` erwartet wird. Das ESS-Chart befüllt **beide** Pfade automatisch, sobald `matrixRTC.enabled: true` ist: In `wellKnownDelegation` wird das `rtc_foci`-Array injiziert, in Synapse wird der `matrix_rtc.transports`-Block in die `homeserver.yaml` gemerged (chart-intern, siehe ess-helm Changelog Eintrag #855: *"Configure experimental MSC4143 advertisement in Synapse when MatrixRTC is enabled. This is in addition to the MSC4143 advertisement on the client well-known endpoint for now, but it is expected to replace it in time."*). **Beide Mechanismen werden durch `wellKnownDelegation.enabled: false` nicht vollständig deaktiviert** die Synapse-Seite wird zwar weiter gesetzt, aber weil kein Well-Known am Apex existiert, kann Element Web den Homeserver gar nicht über `default_server_name` auflösen und daher auch den Transport-Endpunkt nicht konsistent nutzen. Resultat: leere Transport-Liste, Fehler ausgelöst.
Ein korrektes `/.well-known/matrix/client` sieht so aus (das ist exakt, was das Chart ausliefern würde):
```json
{
"m.homeserver": { "base_url": "https://matrix.axion1337.chat" },
"m.identity_server": { "base_url": "https://vector.im" },
"org.matrix.msc4143.rtc_foci": [
{ "type": "livekit",
"livekit_service_url": "https://mrtc.axion1337.chat" }
]
}
```
Der Schlüsselname ist **`org.matrix.msc4143.rtc_foci`** (MSC-Prefix, kein `m.rtc_foci`). Das Value-Objekt hat zwingend `type: "livekit"` und `livekit_service_url: "https://<matrixRTC.ingress.host>"`.
## Warum die Custom-Synapse-Values aktuell wirkungslos sind
Die Keys `matrix_rtc_enabled` und `matrix_rtc_uri` **existieren in Synapse nicht**. Synapse kennt für MatrixRTC genau zwei Dinge: einen `experimental_features`-Block (`msc3266_enabled`, `msc4140_enabled`, `msc4222_enabled`, und implementierungsabhängig `msc4143_enabled`) und einen Top-Level-Block `matrix_rtc.transports:` für den neuen `/v1/rtc/transports`-Endpunkt. Das ESS-Chart setzt diese **automatisch**, sobald `matrixRTC.enabled: true` ist. Synapse ignoriert unbekannte Top-Level-Keys in der `homeserver.yaml` stillschweigend; der Container crasht nicht, aber es passiert auch exakt gar nichts. Der ganze `rtc-config`-Block muss raus. Der `url-previews`-Block ist dagegen legitim die Keys `url_preview_enabled`, `url_preview_ip_range_blacklist`, `max_spider_size` sind echte Synapse-Optionen.
## Der eigentliche Grund für die "ACME Race Condition"
Das Problem war **nicht** ein Bug, sondern eine vorhersagbare Fehlkonfiguration: Beide Ingresses (Element Web und wellKnownDelegation) forderten über die `cert-manager.io/cluster-issuer`-Annotation **jeweils ein eigenes TLS-Secret** für denselben Host `axion1337.chat` an. Cert-manager erzeugt dann zwei `Certificate`-Objekte mit unterschiedlichen `secretName`s → zwei `Order`-Objekte → HTTP-01-Solver-Ingresses überschreiben sich gegenseitig → Let's-Encrypt-Rate-Limit schlägt zu (5 duplicate certs / 7 Tage). Siehe cert-manager Issue #2342 und Discussion #3511: *"If both ingresses have their own secret to save the certificate tls, cert-manager runs havoc and exhausts the ACME limit very quickly."* Die saubere Lösung ist, dass genau **eine** Zertifikat-Quelle für `axion1337.chat` existiert.
Das ESS-Chart selbst erwartet, dass `elementWeb.ingress.host` **nicht** gleich `serverName` ist. Der Standard-Pattern ist: Element Web auf `chat.<apex>` bzw. `app.<apex>`, Well-Known auf dem Apex, und eine optionale `baseDomainRedirect.url` leitet `/` auf dem Apex zu Element Web weiter.
## Fix 1 (empfohlen): Element Web auf Subdomain umziehen
Das ist die Lösung, für die das Chart designt ist, und erfordert genau eine DNS-Änderung sowie YAML-Anpassungen.
### DNS-Voraussetzungen
| Record | Typ | Ziel | Zweck |
|---|---|---|---|
| `axion1337.chat` | A/AAAA | öffentliche IP des K3s-Nodes | Apex: Well-Known + Cert für Matrix-Server-Delegation |
| `matrix.axion1337.chat` | A/AAAA | K3s-Node-IP | Synapse |
| `account.axion1337.chat` | A/AAAA | K3s-Node-IP | Matrix Authentication Service |
| `mrtc.axion1337.chat` | A/AAAA | K3s-Node-IP | LiveKit-Signaling + lk-jwt-service |
| `chat.axion1337.chat` | A/AAAA | K3s-Node-IP | **NEU**: Element Web |
| `admin.axion1337.chat` | A/AAAA | K3s-Node-IP | Element Admin |
### Angepasster HelmRelease (`apps/production/element-server-suite.yaml`)
```yaml
apiVersion: helm.toolkit.fluxcd.io/v2
kind: HelmRelease
metadata:
name: matrix-stack
namespace: matrix
spec:
interval: 1h
chart:
spec:
chart: matrix-stack
version: "26.4.0"
sourceRef:
kind: HelmRepository
name: element-ess-oci
namespace: flux-system
valuesFrom:
- kind: ConfigMap
name: ess-synapse-custom
valuesKey: values.yaml
- kind: ConfigMap
name: ess-element-custom
valuesKey: values.yaml
- kind: Secret
name: ess-mas-values-secret
valuesKey: values.yaml
values:
serverName: axion1337.chat
certManager:
clusterIssuer: letsencrypt-prod
postgres:
enabled: true
synapse:
enabled: true
ingress:
host: matrix.axion1337.chat
matrixAuthenticationService:
enabled: true
ingress:
host: account.axion1337.chat
matrixRTC:
enabled: true
ingress:
host: mrtc.axion1337.chat
# SFU public-IP override empfohlen, falls der Node hinter NAT steht
# und STUN die falsche Adresse zurückgibt:
# sfu:
# useStunToDiscoverPublicIP: false
# manualIP: "<public-IP-of-node>"
elementWeb:
enabled: true
ingress:
host: chat.axion1337.chat # <- NICHT mehr der Apex
elementAdmin:
enabled: true
ingress:
host: admin.axion1337.chat
wellKnownDelegation:
enabled: true # <- zurück auf true (Default)
# Optional: Redirect vom Apex "/" auf Element Web.
# Das Chart-Feature kam in 26.x hinzu; falls dein konkreter Wert-Key
# fehlt, siehe Fix 2 (eigene IngressRoute) als sichere Alternative.
baseDomainRedirect:
url: https://chat.axion1337.chat
```
Mit diesem Setup beansprucht **genau ein** Chart-erzeugter Ingress den Apex `axion1337.chat`, nämlich der der `wellKnownDelegation`. Es gibt nur ein Zertifikat, keine Race Condition. Element Web läuft auf `chat.axion1337.chat` und bekommt sein eigenes, konfliktfreies Cert.
### Bereinigter Synapse-ConfigMap (`apps/production/custom-configs/synapse-values.yaml`)
```yaml
apiVersion: v1
kind: ConfigMap
metadata:
name: ess-synapse-custom
namespace: matrix
data:
values.yaml: |
synapse:
logging:
rootLevel: INFO
levelOverrides:
synapse.media.url_previewer: DEBUG
additional:
# RTC-Block ENTFERNT: matrix_rtc_enabled / matrix_rtc_uri sind keine
# gültigen Synapse-Keys. Das ESS-Chart setzt matrix_rtc.transports und
# die nötigen experimental_features automatisch, wenn matrixRTC.enabled=true.
1-url-previews:
config: |
url_preview_enabled: true
url_preview_ip_range_blacklist:
- '127.0.0.0/8'
- '10.0.0.0/8'
- '172.16.0.0/12'
- '192.168.0.0/16'
- '100.64.0.0/10'
- '192.0.0.0/24'
- '169.254.0.0/16'
- '192.88.99.0/24'
- '198.18.0.0/15'
- '192.0.2.0/24'
- '198.51.100.0/24'
- '203.0.113.0/24'
- '224.0.0.0/4'
- '::1/128'
- 'fe80::/10'
- 'fc00::/7'
- '2001:db8::/32'
- 'ff00::/8'
- 'fec0::/10'
max_spider_size: 10M
```
Wichtige Details zum `additional`-Mechanismus: die Keys werden **alphabetisch sortiert** gemerged, daher die `1-`/`2-`-Namenskonvention. Arrays werden ersetzt, nicht zusammengeführt.
### Element-Web-ConfigMap (`apps/production/custom-configs/element-values.yaml`)
Hier ist **keine** RTC-spezifische Änderung nötig. Element Web hat gemäß `element-web/docs/config.md` keinen `rtc_foci`-Key und entdeckt den Transport ausschließlich über Well-Known. Der optionale `element_call`-Block steuert nur Branding und Verhalten:
```yaml
apiVersion: v1
kind: ConfigMap
metadata:
name: ess-element-custom
namespace: matrix
data:
values.yaml: |
elementWeb:
additional:
config.json: |
{
"brand": "aXion1337.Chat",
"element_call": {
"brand": "aXion1337 Call",
"use_exclusively": true
},
"features": {
"feature_video_rooms": true,
"feature_element_call_video_rooms": true
},
"show_labs_settings": true
}
```
`use_exclusively: true` entfernt die Legacy-Jitsi-Option aus dem UI, sodass Anrufe garantiert über MatrixRTC/LiveKit laufen.
## Fix 2 (Alternative): Apex manuell splitten per Traefik IngressRoute
Falls `baseDomainRedirect` in deiner 26.4.0-Revision nicht greift oder du Element Web auf dem Apex behalten willst, ersetze beide Chart-Ingresses durch eine **einzige Traefik IngressRoute mit einem einzigen Certificate**. Dadurch sieht cert-manager nur noch eine Quelle für `axion1337.chat`, und Traefik routet Pfad-basiert.
```yaml
# apps/production/apex-ingress.yaml
apiVersion: cert-manager.io/v1
kind: Certificate
metadata:
name: axion-apex-tls
namespace: matrix
spec:
secretName: axion-apex-tls
issuerRef:
name: letsencrypt-prod
kind: ClusterIssuer
dnsNames:
- axion1337.chat
---
apiVersion: traefik.io/v1alpha1
kind: IngressRoute
metadata:
name: axion-apex
namespace: matrix
spec:
entryPoints: [websecure]
tls:
secretName: axion-apex-tls
routes:
# Höchste Priorität: /.well-known/matrix/* -> wellKnownDelegation-Service
- match: Host(`axion1337.chat`) && PathPrefix(`/.well-known/matrix`)
kind: Rule
priority: 100
services:
- name: matrix-stack-well-known-delegation # ggf. Service-Namen mit `kubectl get svc -n matrix` verifizieren
port: 8080
# Niedrigere Priorität: alles andere -> Element Web
- match: Host(`axion1337.chat`)
kind: Rule
priority: 10
services:
- name: matrix-stack-element-web
port: 8080
```
Dazu muss in der HelmRelease die automatische Chart-Ingress-Erzeugung für diese beiden Komponenten unterbunden werden setze `wellKnownDelegation.ingress.className: "none"` bzw. `elementWeb.ingress.className: "none"` oder setze die `host`-Werte auf Dummy-Hostnames, sodass die Chart-Ingresses nicht denselben Apex beanspruchen. Fix 1 ist wegen geringerer Komplexität klar zu bevorzugen.
## Netzwerk- und Firewall-Anforderungen für LiveKit
**Das ist der nächste Stolperstein nach dem Well-Known-Fix.** Die HTTPS-Ingress auf `mrtc.axion1337.chat` terminiert nur **Signaling (WSS auf TCP 443)** und die lk-jwt-service-Endpunkte `/sfu/get`, `/get_token`, `/healthz`. WebRTC-Medien laufen **nicht** über den Ingress, sondern direkt zum Node auf UDP/TCP-NodePorts.
Öffne auf deiner K3s-Node-Firewall (und im Router/Cloud-Security-Group):
| Port | Protokoll | Standard ESS CE | Zweck |
|---|---|---|---|
| 80, 443 | TCP | — | Ingress + ACME HTTP-01 |
| `rtcMuxedUdp` NodePort | **UDP** | 30002 (CE) / 30882 (Pro) | **Kritisch**: WebRTC-Medien (UDP-Mux). Ohne das: keine Audio/Video-Daten |
| `rtcTcp` NodePort | TCP | 30881 | ICE/TCP-Fallback für Clients ohne UDP |
| `turn` NodePort | UDP | 30004 | Nur falls `matrixRTC.sfu.exposedServices.turn.enabled: true` |
| `turnTLS` Port | TCP | 31443 oder 443 | Nur falls TURN/TLS aktiv; braucht SNI-Passthrough und eigenes Hostname |
Ermittle die tatsächlichen NodePorts per `kubectl get svc -n matrix | grep rtc`. Wenn dein Node hinter NAT steht und LiveKits STUN-basierte Public-IP-Erkennung die falsche Adresse zurückliefert, setze zusätzlich:
```yaml
matrixRTC:
sfu:
useStunToDiscoverPublicIP: false
manualIP: "<deine-öffentliche-IP>"
```
## Verifikationsschritte
Nach Reconcile (`flux reconcile helmrelease matrix-stack -n matrix`) diese vier Tests durchführen:
**1. Well-Known für Matrix-Client liefert rtc_foci:**
```bash
curl -sS https://axion1337.chat/.well-known/matrix/client | jq .
# Erwartung: JSON mit "m.homeserver" UND "org.matrix.msc4143.rtc_foci"
# das livekit_service_url == "https://mrtc.axion1337.chat" enthält.
curl -sS https://axion1337.chat/.well-known/matrix/server | jq .
# Erwartung: {"m.server": "matrix.axion1337.chat:443"}
```
**2. lk-jwt-service und LiveKit-Signaling sind erreichbar:**
```bash
curl -i https://mrtc.axion1337.chat/healthz
# Erwartung: HTTP/1.1 200 OK
curl -i https://mrtc.axion1337.chat/sfu/get
# Erwartung: HTTP/1.1 405 Method Not Allowed (akzeptiert nur POST)
curl -i -H "Connection: Upgrade" -H "Upgrade: websocket" \
-H "Sec-WebSocket-Key: dGhlIHNhbXBsZSBub25jZQ==" \
-H "Sec-WebSocket-Version: 13" \
https://mrtc.axion1337.chat/
# Erwartung: HTTP/1.1 101 Switching Protocols (WebSocket-Upgrade)
```
**3. Synapse bietet den MSC4143-Endpunkt an:**
```bash
TOKEN="<gültiges-access-token>"
curl -sS -H "Authorization: Bearer $TOKEN" \
https://matrix.axion1337.chat/_matrix/client/v1/rtc/transports | jq .
# Erwartung: {"transports":[{"type":"livekit","livekit_service_url":"https://mrtc.axion1337.chat"}]}
```
**4. UDP-Medien kommen an:** In Element Web Call starten → im Chrome/Firefox-DevTools unter Netzwerk → WS prüfen, dass `wss://mrtc.axion1337.chat/rtc?access_token=...` einen `101`-Upgrade bekommt; unter `chrome://webrtc-internals` nach ICE-Candidate-Paaren mit Status `succeeded` und Typ `host/srflx` schauen. Falls nur Signaling, aber kein Media: UDP-NodePort auf Firewall prüfen.
## ACME-Race dauerhaft vermeiden
Merksatz: **Ein Hostname ⇒ genau ein `Certificate`-Objekt ⇒ genau ein `secretName`.** Drei betriebliche Strategien:
- **Subdomain-Trennung (Fix 1):** Jede Chart-Komponente bekommt einen eigenen FQDN, jeder FQDN genau ein Cert. Keine Kollision möglich. Das ist die vom Chart vorgesehene Form.
- **Geteiltes Secret:** Wenn zwei Ingresses denselben Host tragen müssen, trägt nur **einer** die `cert-manager.io/cluster-issuer`-Annotation. Beide referenzieren `spec.tls[].secretName` auf dasselbe Secret. Traefik wählt das Zertifikat korrekt aus.
- **DNS-01 statt HTTP-01:** Löst den Solver-Ingress-Konflikt grundsätzlich, weil kein zweiter Ingress erzeugt wird. Setzt DNS-Provider-Credentials im ClusterIssuer voraus.
## Vom Benutzer übersehene Chart-Werte
Außer den oben beschriebenen Korrekturen sind diese Keys erwähnenswert, falls du feintunen willst. `matrixRTC.hostAliases` ist ein dokumentierter Workaround gegen Cluster-interne DNS-Probleme, wenn der lk-jwt-service-Pod den Homeserver-Apex bzw. Synapse über den Ingress-Controller statt direkt erreichen muss. `matrixRTC.sfu.exposedServices.<name>.portType` akzeptiert `NodePort`, `HostPort` oder `LoadBalancer` für bare-metal K3s ohne externen LB ist `NodePort` richtig. `matrixRTC.sfu.additional."user-config.yaml".config` erlaubt rohes LiveKit-YAML für Spezialfälle (STUN-Server, Codecs). `wellKnownDelegation.additional.client` / `.server` / `.element` erlauben, in die erzeugten JSON-Dokumente zusätzliche Felder einzumischen normalerweise nicht nötig, aber nützlich für föderative Sonderfälle.
## Fazit
Der eigentliche Defekt war ein einziger Kippschalter: `wellKnownDelegation.enabled: false` hat den einzig existierenden Discovery-Kanal für den LiveKit-Focus gekappt. Der darum herum gebaute Custom-Synapse-Block ist ein Red Herring die zugehörigen Schlüssel existieren in Synapse schlicht nicht und werden ignoriert. Die ursprünglich empfundene ACME-Race ist kein Bug des Charts, sondern die vorhersagbare Folge davon, dass zwei Chart-erzeugte Ingresses (Element Web **auf dem Apex** plus Well-Known) jeweils ein eigenes Let's-Encrypt-Zertifikat für denselben Host anforderten. Sobald Element Web nach `chat.axion1337.chat` wandert und Well-Known wieder aktiv ist, produziert das Chart automatisch das korrekte `org.matrix.msc4143.rtc_foci`-Feld, injiziert den `matrix_rtc.transports`-Block in Synapse, und Element Call funktioniert vorausgesetzt die UDP-NodePort-Firewall ist offen, was nach dem Discovery-Fix der zweite Punkt auf der Prüfliste ist.

12083
docs/oldwiki/home.md Normal file

File diff suppressed because it is too large Load Diff

498
docs/oldwiki/invitereg.md Normal file
View File

@ -0,0 +1,498 @@
# Invite-basierte Selbstregistrierung mit MAS in ESS Community unter Ansible und FluxCD
## Zusammenfassung
Für ein entity["company","Element","matrix software company"]-basiertes ESS-Community-Deployment mit aktivem Matrix Authentication Service ist eine invite-basierte Selbstregistrierung **ohne Authentik** sauber umsetzbar. Der belastbare Weg ist: **MAS-Registrierung aktivieren, Registrierungstoken erzwingen, Tokens über die MAS Admin API erzeugen, und Standard-Onboarding über Synapse `auto_join_rooms` abbilden**. In MAS-/MSC3861-Setups sind die alten Synapse-Mechanismen für Registration Tokens bzw. Shared-Secret-Registration nicht mehr der richtige Pfad: Die Synapse-Registration-Token-API ist in diesem Modus deaktiviert, ebenso die Shared-Secret-Registration-API; die offizielle Automationsoberfläche für externe Tools ist stattdessen die MAS Admin API. citeturn1view2turn20view1turn26search11turn26search5turn35view0
Für die Zuweisung zu Räumen und Spaces gilt: **MAS-Claims sind für Identitätsattribute gedacht, nicht für Raum-/Space-Mitgliedschaften**. Der robuste Standard ist daher eine Zweiteilung: **allgemeine Onboarding-Räume und Spaces über Synapse `auto_join_rooms`**, und **feingranulare, zielgruppenspezifische Mitgliedschaften über einen kleinen Post-Registration-Provisioner oder ein Synapse-Modul** über `on_user_registration` bzw. `on_user_login`. Gruppen/Communities sind heute kein sinnvolles Ziel mehr, weil Synapse diese Funktion deprecated und anschließend entfernt hat; für aktuelle Deployments solltest du konsequent mit **Spaces + Rooms** arbeiten. citeturn16view0turn16view1turn16view2turn34view0turn35view0turn17search0turn17search2
Für GitOps empfehle ich eine klare Trennung zwischen **statischer Konfiguration** und **operativem Invite-Zustand**. Statisch in Git/SOPS/Flux gehören: MAS-Account-Settings, SMTP-Daten, der MAS-Admin-OAuth-Client und optionale Onboarding-Policies. **Kurzlebige Einmal-Tokens** sollten dagegen in der Regel **nicht** als dauerhafter Desired State in Git geführt werden, sondern bei Bedarf über die MAS Admin API erzeugt, per E-Mail verschickt und nur optional als Audit-Record abgelegt werden. Das passt deutlich besser zu FluxCD als das “GitOpsen” flüchtiger Einladungen. Die optionale LiveKit-/Element-Call-Schicht ist für den Registrierungsfluss architektonisch unabhängig. citeturn20view1turn23view0turn23view3turn25search0turn25search13
## Zielbild und Architektur
Die offizielle ESS-Dokumentation unterstützt zusätzliche Konfiguration für Synapse, MAS, Element Web und MatrixRTC/LiveKit jeweils über `additional`-Blöcke. MAS läuft dabei neben Synapse und spricht mit Synapse über den dedizierten `matrix_authentication_service`-Mechanismus; Synapse 1.136+ führt diese Integration als stabile Konfiguration. Für dein Ziel bedeutet das: ESS/Helm liefert die Plattform, MAS erzwingt die Token-basierte Registrierung, Synapse übernimmt Mitgliedschaften, und Element Web kann optional eine eigene Landing-/Invite-Seite anzeigen. citeturn1view2turn1view5turn31view1turn35view0turn24search0
```mermaid
flowchart TB
subgraph GitOps["GitOps-Steuerung"]
A[Ansible]
F[FluxCD]
G[Git Repository]
S[SOPS Secrets]
A --> G
S --> G
F --> G
end
subgraph K8s["Kubernetes / ESS Helm"]
HR[HelmRelease matrix-stack]
EW[Element Web]
MAS[Matrix Authentication Service]
SYN[Synapse]
PG[(PostgreSQL)]
SMTP[SMTP]
MOD[Optional: Post-Registration Provisioner / Synapse-Modul]
LK[Optional: LiveKit / Element Call]
end
G --> HR
HR --> EW
HR --> MAS
HR --> SYN
HR --> PG
HR --> LK
MAS --> PG
SYN --> PG
MAS --> SMTP
MAS <--> SYN
EW --> MAS
EW --> SYN
A -->|MAS Admin API| MAS
A -->|E-Mail Einladung| User[Neuer Benutzer]
User -->|Invite-Link + Registration Token| EW
User -->|Registrierung| MAS
MAS -->|User-Provisionierung| SYN
SYN -->|auto_join_rooms| User
MOD -->|join/invite per Synapse Admin API| SYN
```
Die praktikabelste Zielarchitektur ist deshalb: **Invite-Mail → MAS Token-Registierung → Synapse-Provisionierung → automatisches Standard-Onboarding via `auto_join_rooms` → optionaler Fein-Provisioner für zusätzliche Spaces/Räume**. Für Spaces ist wichtig: Synapse behandelt Spaces “unter der Haube” als Räume, daher können Space-Aliasse in `auto_join_rooms` verwendet werden. **Automatisch erzeugen** kann Synapse über `autocreate_auto_join_rooms` jedoch **keine Spaces**; Spaces müssen also vorher existieren. citeturn16view0turn16view1turn16view5
Die Optionen lassen sich so einordnen:
| Option | Bewertung | Stärken | Schwächen | Geeignet für |
|---|---|---|---|---|
| MAS Registration Tokens | **Empfohlen** | Nativ im MAS-Stack, sauber mit ESS/MAS, externe Tooling-Anbindung über Admin API | Keine offizielle, dokumentierte “Einladungs-E-Mail-Engine” für Invite-Links; Token-Versand musst du selbst automatisieren | ESS Community mit FluxCD/Ansible citeturn20view1turn12view0turn37view1turn1view2 |
| Authentik Invitations | Möglich, aber hier unnötig | Fertiges Invite-/Enrollment-Modell, URL-basierte Invitations | Zusätzlicher IdP-Layer, mehr bewegliche Teile, für dein Ziel kein Muss | Wenn ohnehin zentraler OIDC-IdP Standard ist citeturn36search0turn36search1 |
| Manuelle Admin-Erstellung | Solide als Fallback | Maximal kontrolliert, kein Self-Service nötig | Kein Selbstregistrierungsfluss, hoher Betriebsaufwand | Break-glass, Admin-/Testkonten citeturn27view1turn26search5 |
Wichtig für die Zielmodellierung: **Groups/Communities** sind im aktuellen Synapse-Kontext kein tragfähiges Onboarding-Ziel mehr. Die offizielle Synapse-Kommunikation beschreibt Groups/Communities als deprecated und ab Synapse 1.61 entfernt; Spaces sind der vorgesehene Ersatz. Wenn du also “Spaces, Groups, Rooms” als Zielbild denkst, sollte die reale Implementierung **Spaces + Rooms** heißen. citeturn17search0turn17search2
## MAS-Konfiguration und GitOps-Manifeste
ESS stellt laut offizieller Doku genau den von dir benötigten Mechanismus bereit: Zusätzliche MAS-Konfiguration wird unter `matrixAuthenticationService.additional` in YAML-Fragmente gelegt und in die finale MAS-Konfiguration gemerged. Dasselbe gilt für Synapse unter `synapse.additional` und für Element Web unter `elementWeb.additional`. citeturn1view2turn31view1
Der kleinste sinnvolle MAS-Block für invite-basierte Self-Registration sieht so aus. Die Felder `password_registration_enabled`, `registration_token_required` und `password_registration_email_required` sind offiziell dokumentiert; ESS dokumentiert zusätzlich explizit, dass `password_registration_email_required: false` **nur** in Kombination mit Restriktionen wie `registration_token_required: true` auf öffentlich föderierenden Deployments verantwortbar ist, weil die Instanz sonst missbraucht werden kann. citeturn2view4turn20view0turn1view2
```yaml
apiVersion: v1
kind: Secret
metadata:
name: ess-mas-values-secret
namespace: matrix
stringData:
values.yaml: |
matrixAuthenticationService:
additional:
10-account.yaml:
config: |
passwords:
enabled: true
minimum_complexity: 3
account:
password_registration_enabled: true
registration_token_required: true
password_registration_email_required: false
password_change_allowed: true
password_recovery_enabled: false
login_with_email_allowed: false
# Optional, falls du Recoveries / Verifizierung brauchst
email:
from: '"Matrix Auth" <no-reply@__DOMAIN__>'
reply_to: '"Support" <support@__DOMAIN__>'
transport: smtp
mode: starttls
hostname: __SMTP_HOST__
port: 587
username: __SMTP_USERNAME__
password: __SMTP_PASSWORD__
# Für halböffentliche Setups empfehlenswert
captcha:
service: cloudflare_turnstile
site_key: __TURNSTILE_SITE_KEY__
secret_key: __TURNSTILE_SECRET_KEY__
policy:
data:
registration:
banned_usernames:
literals: ["admin", "root", "support"]
emails:
allowed_addresses:
suffixes: ["@example.org"]
requester:
banned_ips:
- 10.0.0.0/8
- 192.168.0.0/16
rate_limiting:
registration:
burst: 2
per_second: 0.0003
login:
per_ip:
burst: 5
per_second: 0.02
per_account:
burst: 30
per_second: 0.1
```
Damit externe Tools Tokens anlegen können, muss die **MAS Admin API** aktiviert werden. Die offizielle MAS-Doku sagt ausdrücklich, dass `adminapi` nicht standardmäßig exponiert ist und in einen Listener aufgenommen werden muss; Zugriffe werden mit dem Scope `urn:mas:admin` geschützt. Für automatisierte Tools ist der dokumentierte Weg ein **OAuth-Client mit `client_credentials`**, dessen `client_id` in `policy.data.admin_clients` steht. citeturn20view1turn23view0turn23view3
```yaml
apiVersion: v1
kind: Secret
metadata:
name: ess-mas-admin-client
namespace: matrix
stringData:
admin-client.yaml: |
http:
listeners:
- name: web
resources:
- name: discovery
- name: human
- name: oauth
- name: compat
- name: graphql
playground: false
- name: assets
path: ./share/assets/
- name: adminapi
binds:
- address: "[::]:8080"
clients:
- client_id: 01JV0000000000000000000001
client_auth_method: client_secret_basic
client_secret: "__MAS_ADMIN_CLIENT_SECRET__"
policy:
data:
admin_clients:
- 01JV0000000000000000000001
```
Dieses Secret bindest du wiederum als weiteren `additional`-Eintrag ein. So vermeidest du Dateipfad-Annahmen im Container und hältst den Client-Secret-Wert SOPS-fähig. citeturn31view1turn20view1turn23view0
```yaml
apiVersion: v1
kind: Secret
metadata:
name: ess-mas-values-secret
namespace: matrix
stringData:
values.yaml: |
matrixAuthenticationService:
additional:
20-admin-client.yaml:
configSecret: ess-mas-admin-client
configSecretKey: admin-client.yaml
```
Für FluxCD genügt ein klassisches `valuesFrom`-Muster. Das bildet dein bestehendes Repo-Schema mit ConfigMaps/Secrets gut ab und bleibt mit SOPS kompatibel. citeturn31view1turn1view2
```yaml
apiVersion: helm.toolkit.fluxcd.io/v2
kind: HelmRelease
metadata:
name: matrix-stack
namespace: matrix
spec:
interval: 1h
chart:
spec:
chart: matrix-stack
sourceRef:
kind: HelmRepository
name: element-ess-oci
namespace: flux-system
valuesFrom:
- kind: ConfigMap
name: ess-synapse-custom
valuesKey: values.yaml
- kind: ConfigMap
name: ess-element-custom
valuesKey: values.yaml
- kind: Secret
name: ess-mas-values-secret
valuesKey: values.yaml
values:
serverName: "__SERVER_NAME__"
postgres:
enabled: true
synapse:
enabled: true
ingress:
host: "__SYNAPSE_HOST__"
matrixAuthenticationService:
enabled: true
ingress:
host: "__MAS_HOST__"
elementWeb:
enabled: true
ingress:
host: "__ELEMENT_HOST__"
matrixRTC:
enabled: true
ingress:
host: "__MRTC_HOST__"
```
Für das automatische Standard-Onboarding nimmst du Synapse `auto_join_rooms`. Die offizielle Synapse-Doku bestätigt: neue Benutzer werden automatisch zu den gelisteten Räumen hinzugefügt; **Space-Aliasse sind erlaubt**, weil Spaces Räume sind; **Spaces werden aber nicht automatisch erzeugt**, und für private/invite-only Auto-Join-Setups muss `auto_join_mxid_localpart` gesetzt sein, wobei dieser Benutzer in den betreffenden Räumen Mitglied sein und Einladungsrechte haben muss. citeturn16view0turn16view1turn16view2
```yaml
apiVersion: v1
kind: ConfigMap
metadata:
name: ess-synapse-custom
namespace: matrix
data:
values.yaml: |
synapse:
additional:
20-onboarding.yaml:
config: |
auto_join_rooms:
- "#welcome:__SERVER_NAME__"
- "#announcements:__SERVER_NAME__"
- "#community-space:__SERVER_NAME__"
autocreate_auto_join_rooms: false
auto_join_mxid_localpart: system
auto_join_rooms_for_guests: false
```
Für die User Experience kannst du Element Web mit einer eigenen Welcome-/Invite-Seite versehen. Offiziell unterstützt Element Web dafür `embedded_pages.welcome_url`, `login_for_welcome`, Branding-Parameter und für native OIDC-Setups OIDC-Client-Optionen. Für deinen Fall ist das vor allem nützlich, **weil die offizielle MAS-Dokumentation keinen stabil dokumentierten URL-Parameter zum Prefill eines Registration Tokens beschreibt**; die saubere Lösung ist daher oft eine eigene Landing-Page, die den Token erklärt oder temporär speichert und dann zum Registrierungsfluss führt. Diese Aussage ist eine Architektur-Inferenz aus den offiziellen Element- und MAS-Dokumenten. citeturn24search0turn20view1turn22view0
```yaml
apiVersion: v1
kind: ConfigMap
metadata:
name: ess-element-custom
namespace: matrix
data:
values.yaml: |
elementWeb:
additional:
config.json: |
{
"embedded_pages": {
"welcome_url": "https://__ELEMENT_HOST__/invite/index.html",
"login_for_welcome": false
},
"branding": {
"auth_header_logo_url": "https://__ELEMENT_HOST__/assets/logo.svg"
}
}
```
Ein wichtiger Betriebs-Hinweis: Es gibt aktuell ein **offenes GitHub-Issue** im ESS-Helm-Repository, das meldet, dass `matrixAuthenticationService.additional.*` in bestimmten Konstellationen ignoriert werden könne. Das ist kein offizieller Release-Hinweis, aber als Failure-Mode ernst zu nehmen. Deshalb solltest du nach jeder Änderung das **gerenderte MAS-ConfigFile im Pod** prüfen, bevor du mit echten Einladungen arbeitest. citeturn38view0turn31view1
## Einladungsworkflow und Provisionierung
Der saubere GitOps-Ablauf ist in der Praxis fünfstufig. Zuerst legst du **statische Konfiguration** in Git ab: MAS-Settings, SMTP, Admin-Client, Synapse Auto-Join. Danach reconciled Flux diese Ressourcen in den Cluster. Anschließend erzeugt Ansible oder ein Shell-Skript **on demand** ein kurzlebiges Registration Token über die MAS Admin API. Dieses Token wird per E-Mail verschickt entweder als Link zu deiner eigenen Invite-Landing-Page oder als Nachricht mit Token + Registrierungsanweisung. Beim ersten erfolgreichen Abschluss der Registrierung provisioniert MAS den Account in Synapse; Synapse zieht dann `auto_join_rooms`. Wenn du danach noch gezielt Spaces/Räume abhängig von Abteilung, Rolle oder Domäne vergeben willst, übernimmt das ein Provisioner oder ein Synapse-Modul. citeturn20view1turn12view0turn16view0turn34view0
Für die **MAS Admin API** ist der dokumentierte Automationspfad `client_credentials`. Die MAS-Doku nennt dafür explizit statische Clients + `policy.data.admin_clients`. Das Access-Token kannst du discovery-basiert holen, damit du keine Token-Endpoint-Pfade hart codierst. citeturn20view1turn22view0turn23view0
```bash
#!/usr/bin/env bash
set -euo pipefail
MAS_ISSUER="https://account.__DOMAIN__/"
CLIENT_ID="01JV0000000000000000000001"
CLIENT_SECRET="${MAS_ADMIN_CLIENT_SECRET}"
TOKEN_ENDPOINT="$(
curl -fsSL "${MAS_ISSUER}.well-known/openid-configuration" \
| jq -r '.token_endpoint'
)"
ACCESS_TOKEN="$(
curl -fsSL -u "${CLIENT_ID}:${CLIENT_SECRET}" \
-H 'Content-Type: application/x-www-form-urlencoded' \
-d 'grant_type=client_credentials' \
-d 'scope=urn:mas:admin' \
"${TOKEN_ENDPOINT}" \
| jq -r '.access_token'
)"
curl -fsSL -X POST "https://account.__DOMAIN__/api/admin/v1/user-registration-tokens" \
-H "Authorization: Bearer ${ACCESS_TOKEN}" \
-H 'Content-Type: application/json' \
-d '{
"usage_limit": 1,
"expires_at": "2026-05-01T12:00:00Z"
}' | jq
```
Die MAS-OpenAPI-Spezifikation dokumentiert für Registration Tokens genau die Felder, die du dafür brauchst: `token` optional, `usage_limit`, `expires_at`, dazu die Verwaltungsendpunkte zum **Listen**, **Updaten**, **Revoken** und **Unrevoken** unter `/api/admin/v1/user-registration-tokens`. “Valid” bedeutet laut Spec: nicht abgelaufen, nicht widerrufen und Usage-Limit nicht ausgeschöpft. Für Invite-Flows solltest du in der Regel **`usage_limit: 1` und kurze Expiry-Zeiten** verwenden. citeturn12view0turn13view0turn37view0turn37view1turn37view2
Beispiel für Rotation bzw. Widerruf eines ungenutzten Tokens:
```bash
TOKEN_ID="01JVABCDEF..."
curl -fsSL -X POST "https://account.__DOMAIN__/api/admin/v1/user-registration-tokens/${TOKEN_ID}/revoke" \
-H "Authorization: Bearer ${ACCESS_TOKEN}"
```
Wenn du Token-Limits oder die Ablaufzeit nachträglich anpassen willst, ist laut MAS-Admin-Spec `PUT /api/admin/v1/user-registration-tokens/{id}` der vorgesehene Weg. citeturn13view0turn11view0
In Ansible lässt sich derselbe Flow sehr gut abbilden. Hier ein minimales Beispiel mit Discovery, Token-Erzeugung und Mailversand. Der SMTP-Provider ist bewusst als Platzhalter gelassen, weil du ihn nicht spezifiziert hast. Die Speicherung des erzeugten Registration-Tokens in Git ist **optional**; ich würde standardmäßig nur **Token-ID, Empfänger, Ablaufzeit und Versandzeitpunkt** als Audit speichern, nicht das Secret selbst. citeturn20view1turn12view0turn3view1turn2view5
```yaml
- name: Discover MAS token endpoint
ansible.builtin.uri:
url: "https://account.__DOMAIN__/.well-known/openid-configuration"
return_content: true
register: oidc_discovery
- name: Get MAS admin access token
ansible.builtin.uri:
url: "{{ oidc_discovery.json.token_endpoint }}"
method: POST
user: "{{ mas_admin_client_id }}"
password: "{{ mas_admin_client_secret }}"
force_basic_auth: true
body_format: form-urlencoded
body:
grant_type: client_credentials
scope: urn:mas:admin
return_content: true
register: mas_oauth
- name: Create single-use registration token
ansible.builtin.uri:
url: "https://account.__DOMAIN__/api/admin/v1/user-registration-tokens"
method: POST
headers:
Authorization: "Bearer {{ mas_oauth.json.access_token }}"
body_format: json
body:
usage_limit: 1
expires_at: "{{ invite_expires_at }}"
return_content: true
register: mas_invite
- name: Build invite URL
ansible.builtin.set_fact:
invite_url: "https://__ELEMENT_HOST__/invite/?token={{ mas_invite.json.data.attributes.token | urlencode }}"
- name: Send invitation email
community.general.mail:
host: "__SMTP_HOST__"
port: 587
secure: starttls
username: "__SMTP_USER__"
password: "__SMTP_PASSWORD__"
to: "{{ invitee_email }}"
from: "no-reply@__DOMAIN__"
subject: "Deine Matrix-Einladung"
body: |
Hallo,
hier ist deine Einladung für Matrix.
Einladung: {{ invite_url }}
Das Token ist einmalig nutzbar und gültig bis {{ invite_expires_at }}.
```
Für die **automatische Zuweisung** zu Spaces/Räumen nach erster Anmeldung gibt es drei robuste Muster:
Erstens der Standardpfad über `auto_join_rooms`: ideal für **alle** neuen Benutzer, z. B. `#welcome`, `#announcements` und ein Haupt-Space. Das ist die einfachste und offizielle Lösung. Zweitens ein **Post-Registration-Provisioner**, der den Benutzer zusätzlich in weitere Räume einlädt oder joined. Dafür ist der offizielle Synapse-Admin-Endpunkt `POST /_synapse/admin/v1/join/<room_id_or_alias>` gedacht. Drittens ein **Synapse-Modul**, das `on_user_registration` oder `on_user_login` implementiert. Die Primärdoku beschreibt genau diese Callback-Punkte; seit Synapse 1.135 müssen Module allerdings worker-safe sein, weil `on_user_registration` auch auf Workern laufen kann. citeturn16view0turn27view0turn34view0turn35view0
Ein Provisioner gegen die Synapse Admin API kann so aussehen. Dabei setze ich voraus, dass du bereits einen **user-bound** Synapse-Admin-Token hast; dafür verweist die offizielle MAS-Doku auf den Device-Code-Flow mit Synapse-Admin-Scopes. Dasselbe Dokument zeigt auch, wie man kombinierte MAS-/Synapse-Admin-Tokens interaktiv anfordern kann. citeturn27view0turn32search1turn32search0
```bash
#!/usr/bin/env bash
set -euo pipefail
SYNAPSE_BASE="https://matrix.__DOMAIN__"
SYNAPSE_ADMIN_TOKEN="${SYNAPSE_ADMIN_TOKEN}"
USER_ID="$1"
join_room() {
local alias="$1"
curl -fsSL -X POST \
-H "Authorization: Bearer ${SYNAPSE_ADMIN_TOKEN}" \
-H 'Content-Type: application/json' \
"${SYNAPSE_BASE}/_synapse/admin/v1/join/${alias}" \
-d "{\"user_id\":\"${USER_ID}\"}" >/dev/null
}
join_room "#community-space:__SERVER_NAME__"
join_room "#announcements:__SERVER_NAME__"
join_room "#team-general:__SERVER_NAME__"
```
Wichtig ist hier die Abgrenzung zu “Claim Mappings”: Die offizielle MAS-OIDC-Doku beschreibt `claims_imports` für **`localpart`**, **`displayname`**, **`email`** und **`account_name`**. Daraus folgt: Claim-Mappings sind nützlich, wenn du später doch einen Upstream-OIDC-Provider ergänzen willst, aber sie lösen **nicht** die Mitgliedschaft in Spaces/Räumen. Für deinen Authentik-freien Invite-Flow ist das korrekte Modell also **Token + Synapse-Onboarding**, nicht “Claims → Rooms”. citeturn21search1turn9search4
## Sicherheit und Betriebsmodell
Die sicherste Konfiguration für dein Szenario ist nicht “offene Registrierung mit etwas Deko”, sondern **echte Invite-only-Registrierung**. Das bedeutet konkret: `password_registration_enabled: true`, `registration_token_required: true` und nur dann `password_registration_email_required: false`, wenn du bewusst auf Token-Schutz, kurze Laufzeiten, Single-Use und gute Missbrauchsbarrieren setzt. Genau davor warnt die ESS-Doku ausdrücklich: Ein öffentlich föderierender Server ohne Mailpflicht **und** ohne starke Restriktionen wird missbraucht. citeturn2view4turn20view0turn1view2
Ich würde die Sicherheitsprofile so priorisieren:
| Profil | Empfohlene Settings | Wann sinnvoll | Kommentar |
|---|---|---|---|
| Striktes Invite-only | `password_registration_enabled: true`, `registration_token_required: true`, `password_registration_email_required: false`, `usage_limit: 1`, kurze Expiry | Kleine Community, kuratierte Benutzerbasis | Beste Mischung aus UX und Missbrauchsschutz citeturn2view4turn12view0turn37view2 |
| Invite-only mit Recovery | Wie oben, aber `password_recovery_enabled: true` und SMTP voll konfiguriert | Wenn Nutzer Self-Service-Passwort-Reset brauchen | Erhöht Komfort, verlangt sauberen Mailbetrieb citeturn2view4turn2view5 |
| Halböffentlich | Tokenpflicht + CAPTCHA + E-Mail-Allowlist + restriktivere Rate-Limits | Wenn Einladungen wiederverwendbar oder breiter verteilt werden | Mehr Schutz gegen Bot-/Spam-Missbrauch citeturn3view2turn20view0turn3view1 |
Zu den wichtigsten Härtungsmaßnahmen gehören: **Single-Use (`usage_limit: 1`)**, **kurze Gültigkeit**, **Rate Limits für Registrierungen**, **optional CAPTCHA**, **optional Domain-Allowlist für E-Mails**, **Banned IP/User-Agent-Regeln** und ein **interner oder streng geschützter MAS-Admin-API-Zugang**. MAS dokumentiert all diese Stellhebel explizit: `policy.data.registration.*`, `emails.allowed_addresses`, `requester.banned_ips`, CAPTCHA-Provider und `rate_limiting.registration`. citeturn20view0turn3view1turn3view2turn2view5
Für die Raum-/Space-Seite gilt zusätzlich: Halte sensible Onboarding-Räume **invite-only** und vermische “öffentlich sichtbare Discovery” nicht mit einem privaten Invite-Modell. Die Matrix-/Synapse-Dokumentation empfiehlt bei privaten Setups ausdrücklich, die Sichtbarkeit öffentlicher Räume restriktiv zu halten; Synapse hat die Standardregeln für Room-Directory-Publikation in neueren Versionen auch bewusst verschärft. citeturn17search6turn35view0
Ein subtiler, aber wichtiger Punkt ist die Trennung von **MAS Admin** und **Synapse Admin**. Offiziell ist `urn:mas:admin` für automatisierte `client_credentials`-Tools dokumentiert. Für `urn:synapse:admin:*` beschreibt die Scope-Referenz dagegen ein benutzergebundenes Modell; außerdem braucht Synapse-Admin zusätzlich die Matrix-API-Scopes. Daraus folgt als belastbare Betriebsregel: **Reine Maschinenautomation sollte primär MAS Admin API nutzen; Synapse-Admin-Aktionen entweder über Auto-Join, über ein Synapse-Modul oder über einen echten Service-User mit benutzergebundenem Admin-Token**. citeturn20view1turn32search0turn32search1
## Tests, Rollout und Recovery
Der Rollout sollte nicht mit echten Einladungen beginnen, sondern mit einem **vollständigen Dry-Run auf Staging oder einem Testkonto**. Zuerst reconcile-st du Flux, dann prüfst du das HelmRelease und die gerenderte MAS-Konfiguration. Danach testest du die MAS Admin API, erzeugst ein kurzes Einmal-Token, registrierst einen neuen Testnutzer, überprüfst `times_used`/`valid`, kontrollierst die Raum-/Space-Mitgliedschaften und widerrufst übrige Tokens. Damit deckst du sowohl die ESS-/MAS-Seite als auch die Synapse-Onboarding-Seite einmal komplett ab. citeturn20view1turn12view0turn16view0turn27view0
Die fachliche Checkliste dafür ist kurz, aber strikt:
- **Konfiguration vorhanden:** `matrixAuthenticationService.additional` und `synapse.additional` sind im gerenderten Config-Output sichtbar. Wegen des offenen ESS-Issues zu `additional.*` solltest du das aktiv prüfen. citeturn31view1turn38view0
- **MAS Admin API erreichbar:** `/api/spec.json` bzw. das Anlegen eines Tokens funktioniert mit `urn:mas:admin`. citeturn20view1turn10view0
- **Token-Lebenszyklus korrekt:** neues Token erscheint als `valid`, nach Nutzung steigt `times_used`, bei `usage_limit: 1` ist es anschließend nicht mehr gültig. citeturn12view0turn37view2
- **Onboarding korrekt:** Testnutzer landet im Haupt-Space, in Welcome/Announcements und falls aktiviert in weiteren Zielräumen. citeturn16view0turn27view0
- **Missbrauchsschutz greift:** Ablaufzeit, CAPTCHA, Rate-Limits und Policy-Regeln sind aktiv. citeturn3view1turn3view2turn20view0
Die wichtigsten Failure Modes und ihre Recovery-Schritte sind diese:
| Symptom | Wahrscheinliche Ursache | Recovery |
|---|---|---|
| Registrierung fordert trotzdem E-Mail-Verifikation | `password_registration_email_required` ist noch `true` oder falsches MAS-Configfile aktiv | Gerendertes MAS-Configfile prüfen, Werte korrigieren, neu deployen citeturn2view4turn1view2turn38view0 |
| `403` bei Token-Erzeugung | OAuth-Client nicht in `policy.data.admin_clients` oder falscher Scope | Client-/Policy-Fragment korrigieren, neuen Access Token holen citeturn20view1turn23view3 |
| `404` auf `/api/admin/v1/...` | `adminapi` nicht in `http.listeners.resources` aktiviert | Listener-Block korrigieren und Redeploy citeturn20view1 |
| User landet nicht im Space | Space existiert nicht, Space wurde nicht separat angelegt, oder `auto_join_mxid_localpart`-User kann nicht einladen | Space vorab anlegen, `system`-User joinen lassen, Rechte prüfen; Spaces werden nicht automatisch erstellt citeturn16view0turn16view1turn16view2 |
| Feingranulare Raumzuweisung klappt nicht | Du versuchst Membership über Claim-Mapping zu lösen | Membership über Auto-Join, Provisioner oder Synapse-Modul abbilden citeturn21search1turn34view0 |
| “Groups” lassen sich nicht mehr sinnvoll zuweisen | Groups/Communities sind im aktuellen Synapse-Modell entfernt | Auf Spaces + Rooms umstellen citeturn17search0turn17search2 |
Wenn ein Invite-Token versehentlich verschickt wurde, ist der saubere Recovery-Schritt **nicht** das HelmRelease zu verändern, sondern das Token per MAS Admin API zu **revoken** und bei Bedarf ein neues zu erzeugen. Wenn ein Benutzer zwar registriert wurde, aber Raumzuweisungen fehlen, ist die schnellste operative Korrektur ein nachgelagerter Join über den Synapse-Admin-Endpunkt. Wenn ein Synapse-Modul dafür verantwortlich ist, beachte die Worker-Eigenschaft von `on_user_registration`. citeturn13view0turn27view0turn35view0
## Quellenbasis und offene Punkte
Die belastbarsten Primärquellen für dieses Design sind die offiziellen Dokumentationen zu ESS, MAS, Synapse, Element Web und LiveKit. Für den Vergleichspfad “Authentik Invitations” ist die offizielle Authentik-Doku hinzugezogen worden.
Die Priorisierung war dabei:
- ESS Advanced-Doku zur Einbindung zusätzlicher Konfigurationsdateien für MAS, Synapse, Element Web und MatrixRTC. citeturn1view2
- ESS Chart-Values zur Bestätigung, dass `matrixAuthenticationService.additional`/`synapse.additional`/`elementWeb.additional` offizielle Wertepfade sind. citeturn31view1turn31view4
- MAS-Konfigurationsreferenz für `account.*`, `captcha`, `policy`, `rate_limiting`, `email`, `clients`, `admin_clients` und HTTP-Listener. citeturn2view4turn20view0turn22view0turn23view0
- MAS Admin API und OpenAPI-Schema für Token-Erzeugung, Update, Revoke, Validitätsbegriff und Automationsmodell. citeturn20view1turn12view0turn13view0turn37view1turn37view2
- MAS Scope- und Access-Token-Doku für den Unterschied zwischen `urn:mas:admin` und benutzergebundenem Synapse-Admin-Zugriff. citeturn32search0turn32search1
- Synapse-Konfigurationsmanual für `auto_join_rooms`, Space-Aliasse, `autocreate_auto_join_rooms` und `auto_join_mxid_localpart`. citeturn16view0turn16view1turn16view2
- Synapse-Admin- und Modul-Doku für Raumzuweisung per API und Callback-Punkte `on_user_registration` / `on_user_login`. citeturn27view0turn34view0turn35view0
- Element-Web-Konfiguration für Welcome-/Branding-/OIDC-nahe UX-Optionen. citeturn24search0
- LiveKit-/Element-Call-Doku als optionale, vom Registrierungsfluss getrennte RTC-Schicht. citeturn25search0turn25search13
- Authentik-Invitationsdoku nur für den Vergleich innerhalb der Optionen-Tabelle. citeturn36search0turn36search1
Offen beziehungsweise bewusst konservativ behandelt bleiben drei Punkte. Erstens beschreibt die offizielle MAS-Dokumentation nach dem hier ausgewerteten Stand **keinen stabil dokumentierten Invite-Link-Parameter**, mit dem ein Registration Token sicher per URL in die MAS-UI vorbefüllt wird; deshalb empfehle ich eine eigene Landing-Page oder Token-Übermittlung im Mailtext. Zweitens ist **client_credentials** sauber für die **MAS Admin API** dokumentiert, nicht aber als Standardmuster für **Synapse-Admin-Automation**; für Synapse-Onboarding ist deshalb `auto_join_rooms` oder ein user-/modulbasierter Pfad robuster. Drittens gibt es aktuell ein offenes ESS-Helm-Issue zu `matrixAuthenticationService.additional.*`; deshalb solltest du das gerenderte MAS-Configfile im Deployment immer verifizieren, bevor du produktive Einladungen versendest. citeturn20view1turn32search0turn38view0

296
docs/ops-configmap-sync.md Normal file
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+

View File

@ -0,0 +1,206 @@
# Element Desktop Setup Scripts
Automatische Konfiguration und Installation von Element Desktop mit Custom Themes für aXion1337.Chat
## 📋 Systemanforderungen
- **Windows 10/11**
- **macOS 10.13+**
- **Linux** (Ubuntu, Debian, Fedora, Arch, openSUSE, etc.)
---
## 🪟 Windows
### Installation
1. **Lade die Datei herunter**: `element-setup-windows.cmd`
2. **Doppelklick** auf die Datei
3. Das Skript wird automatisch:
- ✅ Die config.json erstellen
- ✅ Element Desktop installieren (falls nötig)
- ✅ Element starten
**Oder manuell:**
```cmd
element-setup-windows.cmd
```
### Voraussetzungen
Das Skript versucht automatisch, Element zu installieren über:
- Windows Store (Microsoft Store)
- WinGet (Windows Package Manager)
- Chocolatey
Falls nichts davon vorhanden ist, installiere Element manuell:
https://element.io/download
---
## 🍎 macOS
### Installation
1. **Lade die Datei herunter**: `element-setup-macos.command`
2. **Doppelklick** im Finder
3. Das Skript wird automatisch:
- ✅ Die config.json erstellen
- ✅ Element Desktop installieren (über Homebrew falls nötig)
- ✅ Element starten
**Oder im Terminal:**
```bash
chmod +x element-setup-macos.command
./element-setup-macos.command
```
### Voraussetzungen
Das Skript nutzt **Homebrew** (falls vorhanden):
```bash
/bin/bash -c "$(curl -fsSL https://raw.githubusercontent.com/Homebrew/install/HEAD/install.sh)"
```
Oder installiere Element manuell:
https://element.io/download
---
## 🐧 Linux
### Installation
1. **Lade die Datei herunter**: `element-setup-linux.sh`
2. **Im Terminal:**
```bash
chmod +x element-setup-linux.sh
./element-setup-linux.sh
```
3. Das Skript wird automatisch:
- ✅ Die config.json erstellen
- ✅ Element Desktop installieren (über apt/dnf/pacman/zypper)
- ✅ Element starten
### Unterstützte Distributionen
- **Ubuntu/Debian**: `apt`
- **Fedora/RHEL**: `dnf`
- **Arch Linux**: `pacman`
- **openSUSE**: `zypper`
---
## ✅ Was die Skripte machen
Alle Skripte führen diese Schritte aus:
1. **config.json erstellen** im richtigen Verzeichnis:
- **Windows**: `%APPDATA%\Element\config.json`
- **macOS**: `~/Library/Application Support/Element/config.json`
- **Linux**: `~/.config/Element/config.json`
2. **Automatische Konfiguration**:
```json
{
"configUrl": "https://axion1337.chat/config.json",
"brand": "aXion1337.Chat",
"default_theme": "aXion1337 Dark",
"show_labs_settings": true,
"features": {
"feature_qr_code_login": true
}
}
```
3. **Element Desktop installieren** (falls nicht vorhanden)
4. **Element starten** und deine Custom Themes laden
---
## 🎨 Themes nach Setup
Nach dem Setup hat dein Element Desktop:
1. **Automatisch geladene Themes** von: `https://axion1337.chat/config.json`
2. **Standard Theme**: aXion1337 Dark
3. **Verfügbare Themes**:
- aXion1337 Dark
- Deep Purple
- Discord Dark
- Electric Blue
- Everforest dark hard
- Gruvbox Dark
- Wal
---
## ⚙️ Manuelle Konfiguration (falls Skript nicht funktioniert)
Falls die Skripte nicht funktionieren, erstelle manuell die config.json:
### Windows
```
%APPDATA%\Element\config.json
```
### macOS
```
~/Library/Application Support/Element/config.json
```
### Linux
```
~/.config/Element/config.json
```
**Inhalt** (copy-paste):
```json
{
"configUrl": "https://axion1337.chat/config.json",
"brand": "aXion1337.Chat",
"default_theme": "aXion1337 Dark",
"show_labs_settings": true,
"features": {
"feature_qr_code_login": true
},
"setting_defaults": {
"custom_themes": []
}
}
```
---
## 🆘 Troubleshooting
### Element startet nicht
- Stelle sicher, dass Element Desktop installiert ist
- Überprüfe den Installationspfad
- Starten manuell: `element` (Terminal/CMD)
### config.json wird nicht geladen
- Überprüfe, dass die Datei im richtigen Verzeichnis ist
- Beende Element vollständig (auch in der Taskbar)
- Starte Element neu
### Themes nicht sichtbar
- Überprüfe Internetverbindung
- `https://axion1337.chat/config.json` sollte erreichbar sein
- Öffne Settings > Appearance > Theme und wähle manuell
---
## 📞 Support
Bei Fragen oder Problemen:
- https://element.io/help
- https://axion1337.chat
---
**Version**: 1.0
**Letztes Update**: 2026-04-23
**Kompatibilität**: Element Desktop 1.11+

114
docs/setup/element-setup-linux.sh Executable file
View File

@ -0,0 +1,114 @@
#!/bin/bash
# Element Desktop Setup Script for Linux
# Ausführung: chmod +x element-setup-linux.sh && ./element-setup-linux.sh
echo "========================================"
echo "Element Desktop Konfiguration Setup"
echo "========================================"
echo ""
# Erkenne Linux Distribution
if [ -f /etc/os-release ]; then
. /etc/os-release
OS=$ID
else
OS=$(uname -s)
fi
# Config-Verzeichnis
CONFIG_DIR="$HOME/.config/Element"
CONFIG_FILE="$CONFIG_DIR/config.json"
# Erstelle Verzeichnis falls nicht vorhanden
if [ ! -d "$CONFIG_DIR" ]; then
echo "Erstelle Element Verzeichnis..."
mkdir -p "$CONFIG_DIR"
fi
# Erstelle config.json
echo "Erstelle config.json..."
cat > "$CONFIG_FILE" << 'EOF'
{
"configUrl": "https://axion1337.chat/config.json",
"brand": "aXion1337.Chat",
"default_theme": "aXion1337 Dark",
"show_labs_settings": true,
"features": {
"feature_qr_code_login": true
},
"setting_defaults": {
"custom_themes": []
}
}
EOF
echo "✅ Config erstellt: $CONFIG_FILE"
echo ""
# Versuche Element zu starten/installieren
echo "Überprüfe Element Desktop Installation..."
# Methode 1: Element ist bereits installiert
if command -v element &> /dev/null; then
echo "Element gefunden. Starte Element..."
element &
sleep 2
exit 0
fi
# Methode 2: Apt (Debian/Ubuntu)
if command -v apt &> /dev/null; then
echo ""
echo "Installiere Element über apt..."
sudo apt update
sudo apt install -y element-desktop
echo "Starte Element..."
element &
exit 0
fi
# Methode 3: Pacman (Arch Linux)
if command -v pacman &> /dev/null; then
echo ""
echo "Installiere Element über pacman..."
sudo pacman -S --noconfirm element-web
echo "Starte Element..."
element &
exit 0
fi
# Methode 4: DNF (Fedora/RHEL)
if command -v dnf &> /dev/null; then
echo ""
echo "Installiere Element über dnf..."
sudo dnf install -y element-desktop
echo "Starte Element..."
element &
exit 0
fi
# Methode 5: Zypper (openSUSE)
if command -v zypper &> /dev/null; then
echo ""
echo "Installiere Element über zypper..."
sudo zypper install -y element-desktop
echo "Starte Element..."
element &
exit 0
fi
# Fallback
echo ""
echo "⚠️ Element Desktop konnte nicht automatisch installiert werden."
echo ""
echo "Bitte installiere Element Desktop manuell:"
echo " Ubuntu/Debian: sudo apt install element-desktop"
echo " Fedora/RHEL: sudo dnf install element-desktop"
echo " Arch: sudo pacman -S element-web"
echo " openSUSE: sudo zypper install element-desktop"
echo ""
echo "Oder: https://element.io/download"
echo ""
echo "✅ Deine config.json wurde erstellt unter:"
echo "$CONFIG_FILE"
echo ""

View File

@ -0,0 +1,84 @@
#!/bin/bash
# Element Desktop Setup Script for macOS
# Doppelklick im Finder zum Ausführen
echo "========================================"
echo "Element Desktop Konfiguration Setup"
echo "========================================"
echo ""
# Config-Verzeichnis
CONFIG_DIR="$HOME/Library/Application Support/Element"
CONFIG_FILE="$CONFIG_DIR/config.json"
# Erstelle Verzeichnis falls nicht vorhanden
if [ ! -d "$CONFIG_DIR" ]; then
echo "Erstelle Element Verzeichnis..."
mkdir -p "$CONFIG_DIR"
fi
# Erstelle config.json
echo "Erstelle config.json..."
cat > "$CONFIG_FILE" << 'EOF'
{
"configUrl": "https://axion1337.chat/config.json",
"brand": "aXion1337.Chat",
"default_theme": "aXion1337 Dark",
"show_labs_settings": true,
"features": {
"feature_qr_code_login": true
},
"setting_defaults": {
"custom_themes": []
}
}
EOF
echo "Config erstellt: $CONFIG_FILE"
echo ""
# Versuche Element zu installieren/starten
echo "Überprüfe Element Desktop Installation..."
# Methode 1: Über Homebrew (falls installiert)
if command -v brew &> /dev/null; then
if brew list element &> /dev/null; then
echo "Element über Homebrew gefunden. Starte Element..."
open -a Element
sleep 2
exit 0
fi
fi
# Methode 2: Direkte App im Applications Folder
if [ -d "/Applications/Element.app" ]; then
echo "Element im Applications Folder gefunden. Starte Element..."
open -a Element
sleep 2
exit 0
fi
# Methode 3: Homebrew Installation
if command -v brew &> /dev/null; then
echo ""
echo "Installiere Element über Homebrew..."
brew install element --cask
echo "Starte Element..."
sleep 2
open -a Element
exit 0
else
echo ""
echo "⚠️ Homebrew nicht gefunden. Bitte installiere zuerst:"
echo "https://brew.sh"
echo ""
echo "Oder installiere Element manuell:"
echo "https://element.io/download"
echo ""
echo "✅ Deine config.json wurde erstellt unter:"
echo "$CONFIG_FILE"
echo ""
fi
# Warte auf Benutzer-Input vor dem Schließen
read -p "Drücke Enter zum Beenden..."

View File

@ -0,0 +1,89 @@
@echo off
REM Element Desktop Setup Script for Windows
REM Doppelklick zum Ausführen
setlocal enabledelayedexpansion
echo ========================================
echo Element Desktop Konfiguration Setup
echo ========================================
echo.
REM Config-Verzeichnis
set APPDATA_PATH=%APPDATA%\Element
set CONFIG_FILE=%APPDATA_PATH%\config.json
REM Erstelle Verzeichnis falls nicht vorhanden
if not exist "%APPDATA_PATH%" (
echo Erstelle Element Verzeichnis...
mkdir "%APPDATA_PATH%"
)
REM Erstelle config.json
echo Erstelle config.json...
(
echo {
echo "configUrl": "https://axion1337.chat/config.json",
echo "brand": "aXion1337.Chat",
echo "default_theme": "aXion1337 Dark",
echo "show_labs_settings": true,
echo "features": {
echo "feature_qr_code_login": true
echo },
echo "setting_defaults": {
echo "custom_themes": []
echo }
echo }
) > "%CONFIG_FILE%"
echo Config erstellt: %CONFIG_FILE%
echo.
REM Versuche Element zu installieren/starten
echo Überprüfe Element Desktop Installation...
REM Methode 1: Über Microsoft Store (wenn verfügbar)
where element >nul 2>nul
if %ERRORLEVEL% == 0 (
echo Starte Element Desktop...
start element
timeout /t 2 >nul
echo Done!
pause
exit /b 0
)
REM Methode 2: WinGet (Falls installiert)
winget list --name "Element" >nul 2>nul
if %ERRORLEVEL% == 0 (
echo WinGet gefunden. Installiere Element...
winget install Element.Element --silent
echo Starte Element...
timeout /t 3 >nul
start element
pause
exit /b 0
)
REM Methode 3: Chocolatey (Falls installiert)
choco list element >nul 2>nul
if %ERRORLEVEL% == 0 (
echo Chocolatey gefunden. Installiere Element...
choco install element -y
echo Starte Element...
timeout /t 3 >nul
start element
pause
exit /b 0
)
REM Fallback: Manueller Download
echo.
echo Element Desktop konnte nicht automatisch installiert werden.
echo Bitte installiere Element Desktop manuell:
echo https://element.io/download
echo.
echo Deine config.json wurde erstellt unter:
echo %CONFIG_FILE%
echo.
pause