25ed765a03
6 Wochen uncommittete Arbeit (Voice-Channels, LiveKit-Manager, Settings-Modal u.v.m.) als ein WIP-Commit gesichert, damit nichts verloren geht und der Pi den aktuellen Stand klonen kann. Thematische Aufarbeitung: siehe ROADMAP M0. Co-Authored-By: Claude Fable 5 <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_01CPrAGBxBT6GfPXzeWQ4AXb
438 lines
15 KiB
Markdown
438 lines
15 KiB
Markdown
# 13 — Server-Administration: Continuwuity
|
|
|
|
> **Gilt für:** Continuwuity 0.5.x (Fork von Conduwuit, welches ein Fork von Conduit ist)
|
|
> **Homeserver:** `steggi-matrix.work`
|
|
> **WICHTIG:** Continuwuity hat KEINE Synapse Admin API (`/_synapse/admin/` existiert nicht!)
|
|
|
|
---
|
|
|
|
## Inhaltsverzeichnis
|
|
- [Server-Admin vs. Room Power Level](#server-admin-vs-room-power-level)
|
|
- [Admin Room — Befehle](#admin-room--befehle)
|
|
- [Continuwuity Admin HTTP API](#continuwuity-admin-http-api)
|
|
- [Power Level in Räumen erzwingen (als Server-Admin)](#power-level-in-räumen-erzwingen)
|
|
- [MSC3083: Restricted Join Rules auf Continuwuity](#msc3083-restricted-join-rules-auf-continuwuity)
|
|
- [Diagnose: Warum M_FORBIDDEN?](#diagnose-warum-m_forbidden)
|
|
- [User-Admin-Status prüfen/setzen](#user-admin-status-prüfensetzen)
|
|
- [Raum-Administration via Matrix API](#raum-administration-via-matrix-api)
|
|
- [Wichtige Unterschiede: Continuwuity vs. Synapse](#wichtige-unterschiede-continuwuity-vs-synapse)
|
|
- [Continuwuity `homeserver.yaml` — relevante Einstellungen](#continuwuity-homeserveryaml--relevante-einstellungen)
|
|
|
|
---
|
|
|
|
## Server-Admin vs. Room Power Level
|
|
|
|
```
|
|
Continuwuity Server-Admin
|
|
├── Ermöglicht: Admin-Room-Befehle, Server-API
|
|
├── Ermöglicht: User deaktivieren, Räume löschen (Server-Level)
|
|
└── NICHT: Automatisch PL 100 in jedem Matrix-Raum!
|
|
|
|
Matrix Room Power Level 100
|
|
├── Gilt pro Raum (in m.room.power_levels State-Event gespeichert)
|
|
├── Ermöglicht: Name/Topic/Avatar setzen, Join-Rules ändern, User kicken/bannen
|
|
└── Unabhängig vom Server-Admin-Status
|
|
```
|
|
|
|
**Beispiel-Problem:**
|
|
- Du bist Server-Admin auf `steggi-matrix.work` ✅
|
|
- Du hast PL 100 im Space `!xyz:steggi-matrix.work` ✅
|
|
- Du erstellst einen neuen Channel → Server gibt dir PL 100 als Ersteller ✅
|
|
- Du versuchst `join_rules: restricted` zu setzen → M_FORBIDDEN ❌
|
|
- **Grund:** Continuwuity 0.5.x unterstützt MSC3083 möglicherweise nicht vollständig
|
|
|
|
---
|
|
|
|
## Admin Room — Befehle
|
|
|
|
Continuwuity hat einen speziellen Admin-Raum. Als Server-Admin kannst du dort Befehle eingeben:
|
|
|
|
```
|
|
# Admin-Raum beitreten (normalerweise automatisch eingeladen)
|
|
# Raum-Alias: #admins:steggi-matrix.work
|
|
|
|
# Befehle im Admin-Raum (als Nachricht senden):
|
|
|
|
!admin help # Alle Befehle anzeigen
|
|
|
|
!admin make_user_admin @user:server # User zu Server-Admin machen
|
|
!admin deactivate_user @user:server # User deaktivieren
|
|
!admin list_users # Alle User auflisten
|
|
|
|
!admin get_room_state !roomId:server # Room-State anzeigen
|
|
!admin delete_room !roomId:server # Raum löschen
|
|
|
|
!admin get_mem_usage # Server-Speicherverbrauch
|
|
!admin server_version # Server-Version
|
|
```
|
|
|
|
```bash
|
|
# Als curl (Admin-Token erforderlich):
|
|
# Admin-Room-ID herausfinden:
|
|
curl -s "https://steggi-matrix.work/_matrix/client/v3/directory/room/%23admins%3Asteggi-matrix.work" \
|
|
-H "Authorization: Bearer J5laxTz5Zte9oRB5x8QsyYRQ6b0hAuXI"
|
|
# → {"room_id": "!adminRoomId:steggi-matrix.work", ...}
|
|
```
|
|
|
|
---
|
|
|
|
## Continuwuity Admin HTTP API
|
|
|
|
```bash
|
|
# Basis-URL: https://steggi-matrix.work/_conduwuit/admin/v1/
|
|
# (Nicht /_synapse/admin/ — das ist Synapse-only!)
|
|
|
|
# User zu Server-Admin machen
|
|
curl -X POST "https://steggi-matrix.work/_conduwuit/admin/v1/make_user_admin" \
|
|
-H "Authorization: Bearer J5laxTz5Zte9oRB5x8QsyYRQ6b0hAuXI" \
|
|
-H "Content-Type: application/json" \
|
|
-d '{"user_id": "@todesneutron:steggi-matrix.work"}'
|
|
|
|
# Server-Status abfragen
|
|
curl "https://steggi-matrix.work/_conduwuit/server/version" \
|
|
-H "Authorization: Bearer J5laxTz5Zte9oRB5x8QsyYRQ6b0hAuXI"
|
|
|
|
# Alternativ — Standard Matrix-Whoami (prüft ob Token gültig):
|
|
curl "https://steggi-matrix.work/_matrix/client/v3/account/whoami" \
|
|
-H "Authorization: Bearer J5laxTz5Zte9oRB5x8QsyYRQ6b0hAuXI"
|
|
# → {"user_id": "@todesneutron:steggi-matrix.work", "is_guest": false}
|
|
|
|
# Prüfen ob User Server-Admin ist (Conduwuit-spezifisch):
|
|
curl "https://steggi-matrix.work/_conduwuit/admin/v1/users/@todesneutron:steggi-matrix.work" \
|
|
-H "Authorization: Bearer J5laxTz5Zte9oRB5x8QsyYRQ6b0hAuXI"
|
|
```
|
|
|
|
---
|
|
|
|
## Power Level in Räumen erzwingen (als Server-Admin)
|
|
|
|
Als Server-Admin kannst du via Matrix Client API Power Levels in jedem Raum setzen,
|
|
**auch wenn du kein Mitglied bist** (Continuwuity erlaubt das für Server-Admins):
|
|
|
|
```bash
|
|
# Schritt 1: Aktuelles Power-Level-Event lesen
|
|
ROOM_ID="!raumId:steggi-matrix.work"
|
|
TOKEN="J5laxTz5Zte9oRB5x8QsyYRQ6b0hAuXI"
|
|
SERVER="https://steggi-matrix.work"
|
|
|
|
curl "${SERVER}/_matrix/client/v3/rooms/${ROOM_ID}/state/m.room.power_levels/" \
|
|
-H "Authorization: Bearer ${TOKEN}"
|
|
|
|
# Schritt 2: Power Level setzen (users-Map ändern)
|
|
curl -X PUT "${SERVER}/_matrix/client/v3/rooms/${ROOM_ID}/state/m.room.power_levels/" \
|
|
-H "Authorization: Bearer ${TOKEN}" \
|
|
-H "Content-Type: application/json" \
|
|
-d '{
|
|
"users": {
|
|
"@todesneutron:steggi-matrix.work": 100
|
|
},
|
|
"users_default": 0,
|
|
"events_default": 0,
|
|
"state_default": 50,
|
|
"ban": 50,
|
|
"kick": 50,
|
|
"invite": 0,
|
|
"redact": 50
|
|
}'
|
|
```
|
|
|
|
```dart
|
|
// In Flutter / Dart (mit Admin-Token):
|
|
// Zuerst aktuellen PL-State lesen:
|
|
final currentPl = await client.getRoomStateWithKey(
|
|
roomId,
|
|
EventTypes.RoomPowerLevels,
|
|
'',
|
|
);
|
|
|
|
// Users-Map erweitern und zurückschreiben:
|
|
final users = Map<String, dynamic>.from(
|
|
(currentPl['users'] as Map?)?.cast<String, dynamic>() ?? {},
|
|
);
|
|
users['@todesneutron:steggi-matrix.work'] = 100;
|
|
|
|
await client.setRoomStateWithKey(
|
|
roomId,
|
|
EventTypes.RoomPowerLevels,
|
|
'',
|
|
{
|
|
...currentPl,
|
|
'users': users,
|
|
},
|
|
);
|
|
```
|
|
|
|
---
|
|
|
|
## MSC3083: Restricted Join Rules auf Continuwuity
|
|
|
|
`join_rules: restricted` (MSC3083) erlaubt Räumen, nur Space-Mitglieder beizutreten.
|
|
**Continuwuity 0.5.x unterstützt MSC3083 möglicherweise nicht vollständig.**
|
|
|
|
```bash
|
|
# Testen ob restricted join rules funktionieren:
|
|
ROOM_ID="!testRaum:steggi-matrix.work"
|
|
TOKEN="J5laxTz5Zte9oRB5x8QsyYRQ6b0hAuXI"
|
|
SPACE_ID="!spaceId:steggi-matrix.work"
|
|
|
|
curl -X PUT "https://steggi-matrix.work/_matrix/client/v3/rooms/${ROOM_ID}/state/m.room.join_rules/" \
|
|
-H "Authorization: Bearer ${TOKEN}" \
|
|
-H "Content-Type: application/json" \
|
|
-d '{
|
|
"join_rule": "restricted",
|
|
"allow": [
|
|
{
|
|
"type": "m.room_membership",
|
|
"room_id": "'"${SPACE_ID}"'"
|
|
}
|
|
]
|
|
}'
|
|
# → 200 OK: Unterstützt!
|
|
# → M_FORBIDDEN oder M_UNRECOGNIZED: Nicht unterstützt oder PL zu niedrig
|
|
```
|
|
|
|
**Workaround wenn restricted nicht funktioniert:**
|
|
```bash
|
|
# Fallback: invite-only (explizit jeden User einladen)
|
|
curl -X PUT "https://steggi-matrix.work/_matrix/client/v3/rooms/${ROOM_ID}/state/m.room.join_rules/" \
|
|
-H "Authorization: Bearer ${TOKEN}" \
|
|
-H "Content-Type: application/json" \
|
|
-d '{"join_rule": "invite"}'
|
|
```
|
|
|
|
```dart
|
|
// In space_admin_dialog.dart — Fallback wenn restricted nicht supported:
|
|
try {
|
|
await room.setJoinRules(
|
|
JoinRules.restricted,
|
|
allow: [
|
|
SpaceRoomJoinRulesAllowInner(
|
|
roomId: spaceId,
|
|
type: SpaceRoomJoinRulesAllowInnerType.mRoomMembership,
|
|
),
|
|
],
|
|
);
|
|
} on MatrixException catch (e) {
|
|
if (e.error == MatrixError.M_FORBIDDEN || e.error == MatrixError.M_UNKNOWN) {
|
|
// Continuwuity unterstützt restricted join rules nicht
|
|
// Fallback zu invite-only:
|
|
await room.setJoinRules(JoinRules.invite);
|
|
} else {
|
|
rethrow;
|
|
}
|
|
}
|
|
```
|
|
|
|
---
|
|
|
|
## Diagnose: Warum M_FORBIDDEN?
|
|
|
|
```bash
|
|
# 1. Prüfen: Welchen Power Level hat mein User in diesem Raum?
|
|
ROOM_ID="!raumId:steggi-matrix.work"
|
|
TOKEN="J5laxTz5Zte9oRB5x8QsyYRQ6b0hAuXI"
|
|
|
|
curl "https://steggi-matrix.work/_matrix/client/v3/rooms/${ROOM_ID}/state/m.room.power_levels/" \
|
|
-H "Authorization: Bearer ${TOKEN}"
|
|
# Antwort zeigt 'users' Map — prüfen ob '@todesneutron:steggi-matrix.work' drin ist
|
|
|
|
# 2. Prüfen: Was ist state_default?
|
|
# Im Antwort-JSON: "state_default": 50 bedeutet: PL 50 nötig für State-Events
|
|
# "m.room.join_rules": 100 in events-Map = PL 100 für Join-Rule-Änderung
|
|
|
|
# 3. Prüfen: Bin ich Mitglied des Raums?
|
|
curl "https://steggi-matrix.work/_matrix/client/v3/rooms/${ROOM_ID}/state/m.room.member/%40todesneutron%3Asteggi-matrix.work/" \
|
|
-H "Authorization: Bearer ${TOKEN}"
|
|
# → {"membership": "join"} = Mitglied ✅
|
|
# → {"errcode": "M_NOT_FOUND"} = Nicht Mitglied ❌ (Server-Admin kann trotzdem State setzen)
|
|
|
|
# 4. Prüfen: Unterstützt der Server restricted join rules?
|
|
curl "https://steggi-matrix.work/_matrix/client/v3/capabilities" \
|
|
-H "Authorization: Bearer ${TOKEN}"
|
|
# Antwort: capabilities-Objekt — MSC3083 ist nicht explizit gelistet (kein Standard-Capability)
|
|
```
|
|
|
|
**Häufige Ursachen und Lösungen:**
|
|
|
|
| Fehler | Ursache | Lösung |
|
|
|---|---|---|
|
|
| M_FORBIDDEN beim State-Event | PL zu niedrig im Raum | Power Level via curl erhöhen (s.o.) |
|
|
| M_FORBIDDEN bei join_rules: restricted | MSC3083 nicht unterstützt | Fallback zu `invite` nutzen |
|
|
| M_FORBIDDEN beim Channel erstellen | Bug in space_admin_dialog.dart | Raum manuell erstellen, dann Space-Child setzen |
|
|
| M_NOT_FOUND | Raum nicht bekannt | Raum beitreten oder Admin-Join |
|
|
| M_FORBIDDEN bei Power-Level-Änderung | PL darf nur gleich/höher gesetzt werden | Als Ersteller oder via Admin-API |
|
|
|
|
---
|
|
|
|
## User-Admin-Status prüfen/setzen
|
|
|
|
```bash
|
|
# Prüfen ob User Server-Admin ist:
|
|
curl "https://steggi-matrix.work/_matrix/client/v3/account/whoami" \
|
|
-H "Authorization: Bearer J5laxTz5Zte9oRB5x8QsyYRQ6b0hAuXI"
|
|
|
|
# Auf Pi (SSH): User-Datenbank direkt abfragen (Conduwuit/Continuwuity nutzt RocksDB)
|
|
# Alternativ: Über Admin-Room-Befehl
|
|
# (Im Admin-Room als Nachricht senden:)
|
|
# !admin make_user_admin @todesneutron:steggi-matrix.work
|
|
|
|
# Über HTTP (Conduwuit Admin-Endpoint):
|
|
curl -X POST "https://steggi-matrix.work/_conduwuit/admin/v1/make_user_admin" \
|
|
-H "Authorization: Bearer J5laxTz5Zte9oRB5x8QsyYRQ6b0hAuXI" \
|
|
-H "Content-Type: application/json" \
|
|
-d '{"user_id": "@todesneutron:steggi-matrix.work"}'
|
|
```
|
|
|
|
---
|
|
|
|
## Raum-Administration via Matrix API
|
|
|
|
Da kein Synapse-Admin-API existiert, nutze die Standard-Matrix-Client-API mit Admin-Token:
|
|
|
|
```bash
|
|
# Raum beitreten (als Admin, auch wenn invite-only):
|
|
curl -X POST "https://steggi-matrix.work/_matrix/client/v3/join/!roomId%3Asteggi-matrix.work" \
|
|
-H "Authorization: Bearer J5laxTz5Zte9oRB5x8QsyYRQ6b0hAuXI" \
|
|
-H "Content-Type: application/json" \
|
|
-d '{}'
|
|
|
|
# User in Raum einladen:
|
|
curl -X POST "https://steggi-matrix.work/_matrix/client/v3/rooms/!roomId%3Asteggi-matrix.work/invite" \
|
|
-H "Authorization: Bearer J5laxTz5Zte9oRB5x8QsyYRQ6b0hAuXI" \
|
|
-H "Content-Type: application/json" \
|
|
-d '{"user_id": "@user:steggi-matrix.work"}'
|
|
|
|
# Space-Child-Relation setzen (Channel einem Space hinzufügen):
|
|
curl -X PUT "https://steggi-matrix.work/_matrix/client/v3/rooms/!spaceId%3Asteggi-matrix.work/state/m.space.child/!channelId%3Asteggi-matrix.work/" \
|
|
-H "Authorization: Bearer J5laxTz5Zte9oRB5x8QsyYRQ6b0hAuXI" \
|
|
-H "Content-Type: application/json" \
|
|
-d '{
|
|
"via": ["steggi-matrix.work"],
|
|
"suggested": false
|
|
}'
|
|
|
|
# Space-Parent-Relation setzen (im Channel-Raum):
|
|
curl -X PUT "https://steggi-matrix.work/_matrix/client/v3/rooms/!channelId%3Asteggi-matrix.work/state/m.space.parent/!spaceId%3Asteggi-matrix.work/" \
|
|
-H "Authorization: Bearer J5laxTz5Zte9oRB5x8QsyYRQ6b0hAuXI" \
|
|
-H "Content-Type: application/json" \
|
|
-d '{
|
|
"via": ["steggi-matrix.work"],
|
|
"canonical": true
|
|
}'
|
|
|
|
# Alle Mitglieder eines Raums auflisten:
|
|
curl "https://steggi-matrix.work/_matrix/client/v3/rooms/!roomId%3Asteggi-matrix.work/members" \
|
|
-H "Authorization: Bearer J5laxTz5Zte9oRB5x8QsyYRQ6b0hAuXI"
|
|
|
|
# Raum verlassen (als User, nicht löschen):
|
|
curl -X POST "https://steggi-matrix.work/_matrix/client/v3/rooms/!roomId%3Asteggi-matrix.work/leave" \
|
|
-H "Authorization: Bearer J5laxTz5Zte9oRB5x8QsyYRQ6b0hAuXI" \
|
|
-H "Content-Type: application/json" \
|
|
-d '{}'
|
|
```
|
|
|
|
---
|
|
|
|
## Wichtige Unterschiede: Continuwuity vs. Synapse
|
|
|
|
| Feature | Synapse | Continuwuity 0.5.x |
|
|
|---|---|---|
|
|
| Admin API URL | `/_synapse/admin/v1/` | `/_conduwuit/admin/v1/` |
|
|
| Admin Room | Optional | Standard |
|
|
| MSC3083 (restricted join rules) | ✅ Vollständig | ⚠️ Teilweise / experimentell |
|
|
| Spaces (MSC1772) | ✅ | ✅ Grundfunktionen |
|
|
| MatrixRTC / MSC3401 | ✅ (Element Call) | ⚠️ Eingeschränkt |
|
|
| Push-Gateway | ✅ | ✅ |
|
|
| Server-side search | ✅ | ✅ Grundfunktionen |
|
|
| E2EE / Cross-Signing | ✅ | ✅ |
|
|
| Presence | ✅ | ✅ |
|
|
| Account Deactivation | Admin API | Admin Room / API |
|
|
| Room Deletion/Purge | Admin API | Admin Room / API |
|
|
| User Listing | Admin API | Admin Room / API |
|
|
| Federation | ✅ | ✅ |
|
|
| Application Services | ✅ | ⚠️ Eingeschränkt |
|
|
|
|
---
|
|
|
|
## Continuwuity `homeserver.yaml` — relevante Einstellungen
|
|
|
|
```yaml
|
|
# /etc/continuwuity/homeserver.yaml (oder /etc/conduwuit/conduwuit.toml je nach Version)
|
|
|
|
# Matrix-RTC / LiveKit
|
|
# MSC3266: Room Summary
|
|
# MSC3401: MatrixRTC
|
|
allow_unstable_room_versions: true
|
|
|
|
# Federation (für Multi-Server-Calls nötig)
|
|
allow_federation: true
|
|
allow_public_room_directory_without_auth: false
|
|
|
|
# Push (für Notifications)
|
|
# Kein spezieller Config — nutzt Standard-Matrix-Push-API
|
|
|
|
# TURN-Server für WebRTC
|
|
turn_uris:
|
|
- "turn:steggi-matrix.work:3478?transport=udp"
|
|
- "turn:steggi-matrix.work:3478?transport=tcp"
|
|
turn_secret: "dein-turn-secret"
|
|
turn_username: "" # leer = HMAC-basiert
|
|
turn_password: ""
|
|
turn_ttl: 86400
|
|
|
|
# Registrierung
|
|
allow_registration: false # Kein offener Signup
|
|
registration_token: "dein-token" # Oder token-basiert
|
|
|
|
# Log-Level
|
|
log: "warn,conduwuit=info"
|
|
|
|
# Performance
|
|
rocksdb_parallelism_threads: 4 # Pi 5 hat 4 Cores
|
|
|
|
# Unter Continuwuity: Admin-User beim ersten Start setzen
|
|
# Erster registrierter User wird automatisch Server-Admin
|
|
```
|
|
|
|
```bash
|
|
# Auf dem Pi: Config-Datei editieren
|
|
ssh steggi@192.168.178.71
|
|
sudo nano /etc/continuwuity/homeserver.yaml
|
|
# oder:
|
|
sudo nano /etc/conduwuit/conduwuit.toml # Falls TOML-Format
|
|
|
|
# Service neu starten:
|
|
sudo systemctl restart continuwuity
|
|
# oder:
|
|
sudo systemctl restart conduwuit
|
|
|
|
# Logs prüfen:
|
|
sudo journalctl -u continuwuity -f
|
|
```
|
|
|
|
---
|
|
|
|
## Schnell-Diagnose Checkliste
|
|
|
|
Wenn du M_FORBIDDEN bekommst:
|
|
|
|
```bash
|
|
# 1. Token gültig?
|
|
curl "https://steggi-matrix.work/_matrix/client/v3/account/whoami" \
|
|
-H "Authorization: Bearer J5laxTz5Zte9oRB5x8QsyYRQ6b0hAuXI"
|
|
|
|
# 2. PL im betroffenen Raum prüfen:
|
|
curl "https://steggi-matrix.work/_matrix/client/v3/rooms/!ROOM_ID/state/m.room.power_levels/" \
|
|
-H "Authorization: Bearer J5laxTz5Zte9oRB5x8QsyYRQ6b0hAuXI"
|
|
|
|
# 3. Mitglied des Raums?
|
|
curl "https://steggi-matrix.work/_matrix/client/v3/rooms/!ROOM_ID/state/m.room.member/%40todesneutron%3Asteggi-matrix.work/" \
|
|
-H "Authorization: Bearer J5laxTz5Zte9oRB5x8QsyYRQ6b0hAuXI"
|
|
|
|
# 4. Was genau schlägt fehl? (Antwort-Body lesen!)
|
|
# M_FORBIDDEN + "Power level too low" → PL erhöhen
|
|
# M_FORBIDDEN + "Not a member" → Raum beitreten
|
|
# M_UNRECOGNIZED → Feature nicht unterstützt
|
|
# M_FORBIDDEN + "..." → join_rules restricted Problem
|
|
```
|