From bace26c084611d50adc791cd42fa4d8d3fa32fde Mon Sep 17 00:00:00 2001 From: florianfederspiel Date: Tue, 19 May 2026 18:49:04 +0200 Subject: [PATCH] KI-AGENT: Vereinfache Matrix Selfhost auf eine Domain --- .env.example | 13 ++--- README.md | 15 ++--- .../migrations/0043_communication_rooms.sql | 58 +++++++++++++++++++ backend/db/migrations/meta/_journal.json | 7 +++ docker-compose.selfhost.yml | 22 +++---- matrix/selfhost/element-config.json | 6 +- 6 files changed, 91 insertions(+), 30 deletions(-) create mode 100644 backend/db/migrations/0043_communication_rooms.sql diff --git a/.env.example b/.env.example index 77176b7..13d3d52 100644 --- a/.env.example +++ b/.env.example @@ -68,11 +68,7 @@ FEDEO_BOOTSTRAP_TENANT_SHORT=MEIN # gelesen, wenn das Profil "matrix" genutzt wird. Für produktive Systeme # müssen alle Geheimnisse ersetzt werden. -MATRIX_SERVER_NAME=fedeo.de -MATRIX_HOMESERVER_HOST=matrix.fedeo.de -MATRIX_RTC_HOST=call.fedeo.de -MATRIX_TURN_HOST=turn.fedeo.de -MATRIX_ELEMENT_HOST=element.fedeo.de +MATRIX_SERVER_NAME=app.example.com MATRIX_POSTGRES_DB=synapse MATRIX_POSTGRES_USER=synapse @@ -85,11 +81,12 @@ LIVEKIT_SECRET=change-this-livekit-secret-please-replace # Backend-Integration im Selfhost-Stack MATRIX_HOMESERVER_URL=http://matrix-synapse:8008 -MATRIX_RTC_JWT_URL=https://call.fedeo.de/livekit/jwt -MATRIX_LIVEKIT_URL=wss://call.fedeo.de/livekit/sfu +MATRIX_RTC_HOST=app.example.com +MATRIX_RTC_JWT_URL=https://app.example.com/livekit/jwt +MATRIX_LIVEKIT_URL=wss://app.example.com/livekit/sfu MATRIX_REGISTRATION_SHARED_SECRET=copy-from-matrix-synapse-homeserver-yaml MATRIX_SERVICE_USER_LOCALPART=fedeo_service -NUXT_PUBLIC_MATRIX_ELEMENT_URL=https://element.fedeo.de +NUXT_PUBLIC_MATRIX_ELEMENT_URL=https://app.example.com/element # Lokale Matrix-Entwicklung MATRIX_DEV_SYNAPSE_PORT=8008 diff --git a/README.md b/README.md index e2df459..67b6793 100644 --- a/README.md +++ b/README.md @@ -192,23 +192,20 @@ FEDEO_BOOTSTRAP_ADMIN_LAST_NAME=Benutzer FEDEO_BOOTSTRAP_TENANT_NAME=Mein Unternehmen FEDEO_BOOTSTRAP_TENANT_SHORT=MEIN -MATRIX_SERVER_NAME=example.com -MATRIX_HOMESERVER_HOST=matrix.example.com -MATRIX_RTC_HOST=call.example.com -MATRIX_TURN_HOST=turn.example.com -MATRIX_ELEMENT_HOST=element.example.com +MATRIX_SERVER_NAME=app.example.com MATRIX_POSTGRES_DB=synapse MATRIX_POSTGRES_USER=synapse MATRIX_POSTGRES_PASSWORD=change-this-matrix-db-password MATRIX_TURN_SHARED_SECRET=change-this-turn-secret MATRIX_HOMESERVER_URL=http://matrix-synapse:8008 -MATRIX_RTC_JWT_URL=https://call.example.com/livekit/jwt -MATRIX_LIVEKIT_URL=wss://call.example.com/livekit/sfu +MATRIX_RTC_HOST=app.example.com +MATRIX_RTC_JWT_URL=https://app.example.com/livekit/jwt +MATRIX_LIVEKIT_URL=wss://app.example.com/livekit/sfu MATRIX_REGISTRATION_SHARED_SECRET=copy-from-matrix-synapse-homeserver-yaml MATRIX_SERVICE_USER_LOCALPART=fedeo_service LIVEKIT_KEY=fedeo-livekit LIVEKIT_SECRET=change-this-livekit-secret-please-replace -NUXT_PUBLIC_MATRIX_ELEMENT_URL=https://element.example.com +NUXT_PUBLIC_MATRIX_ELEMENT_URL=https://app.example.com/element ``` Die `FEDEO_BOOTSTRAP_*`-Werte sind für den ersten Start gedacht. Wenn `FEDEO_BOOTSTRAP_ADMIN_EMAIL` und `FEDEO_BOOTSTRAP_ADMIN_PASSWORD` gesetzt sind, legt das Backend idempotent einen Admin-Benutzer, einen ersten Mandanten, eine Administrator-Rolle und grundlegende Stammdaten an. Nach erfolgreichem Erstzugriff solltest du das Bootstrap-Passwort aus der `.env` entfernen oder ändern. @@ -217,7 +214,7 @@ Die `FEDEO_BOOTSTRAP_*`-Werte sind für den ersten Start gedacht. Wenn `FEDEO_BO Die Selfhost-Konfiguration liegt in `docker-compose.selfhost.yml`. Sie startet MinIO standardmäßig mit. Wenn du stattdessen AWS S3, Hetzner Object Storage, Backblaze B2 S3 oder einen anderen externen S3-Dienst nutzen willst, kannst du die Services `minio` und `createbuckets` entfernen und nur die entsprechenden S3-Umgebungsvariablen auf den externen Anbieter zeigen lassen. -Der Matrix-Stack ist im Selfhost-Compose als optionales Profil `matrix` enthalten. Er umfasst Synapse, eine eigene PostgreSQL-Datenbank für Synapse, Redis, `.well-known/matrix`, coturn, LiveKit, den LiveKit-JWT-Service und Element Web. Vor dem ersten Start musst du `matrix/synapse/homeserver.yaml` erzeugen und `matrix/selfhost/element-config.json` sowie `matrix/well-known/*` auf deine Domains anpassen. +Der Matrix-Stack ist im Selfhost-Compose als optionales Profil `matrix` enthalten. Er umfasst Synapse, eine eigene PostgreSQL-Datenbank für Synapse, Redis, `.well-known/matrix`, coturn, LiveKit, den LiveKit-JWT-Service und Element Web. Das einfache Selfhost-Setup nutzt nur `DOMAIN`: Synapse läuft unter `https://DOMAIN/_matrix`, Matrix-Well-Known unter `https://DOMAIN/.well-known/matrix`, LiveKit unter `https://DOMAIN/livekit/sfu`, der JWT-Service unter `https://DOMAIN/livekit/jwt` und Element Web unter `https://DOMAIN/element`. Vor dem ersten Start musst du `matrix/synapse/homeserver.yaml` erzeugen und `matrix/selfhost/element-config.json` auf deine Domain anpassen. Das Backend führt beim Containerstart standardmäßig `npm run migrate` aus. Setze `FEDEO_RUN_MIGRATIONS=false`, wenn du Migrationen bewusst manuell ausführen möchtest. diff --git a/backend/db/migrations/0043_communication_rooms.sql b/backend/db/migrations/0043_communication_rooms.sql new file mode 100644 index 0000000..ad6eea9 --- /dev/null +++ b/backend/db/migrations/0043_communication_rooms.sql @@ -0,0 +1,58 @@ +CREATE TABLE IF NOT EXISTS "communication_rooms" ( + "id" uuid PRIMARY KEY DEFAULT gen_random_uuid() NOT NULL, + "tenant_id" bigint NOT NULL, + "key" text NOT NULL, + "name" text NOT NULL, + "topic" text, + "type" text DEFAULT 'room' NOT NULL, + "entity_type" text, + "entity_id" bigint, + "entity_uuid" uuid, + "matrix_room_id" text, + "matrix_alias" text, + "parent_space_room_id" text, + "archived" boolean DEFAULT false NOT NULL, + "created_at" timestamp with time zone DEFAULT now() NOT NULL, + "updated_at" timestamp with time zone, + "created_by" uuid, + "updated_by" uuid +); + +DO $$ +BEGIN + IF NOT EXISTS ( + SELECT 1 FROM pg_constraint WHERE conname = 'communication_rooms_tenant_id_tenants_id_fk' + ) THEN + ALTER TABLE "communication_rooms" + ADD CONSTRAINT "communication_rooms_tenant_id_tenants_id_fk" + FOREIGN KEY ("tenant_id") REFERENCES "public"."tenants"("id") + ON DELETE cascade ON UPDATE no action; + END IF; + + IF NOT EXISTS ( + SELECT 1 FROM pg_constraint WHERE conname = 'communication_rooms_created_by_auth_users_id_fk' + ) THEN + ALTER TABLE "communication_rooms" + ADD CONSTRAINT "communication_rooms_created_by_auth_users_id_fk" + FOREIGN KEY ("created_by") REFERENCES "public"."auth_users"("id") + ON DELETE no action ON UPDATE no action; + END IF; + + IF NOT EXISTS ( + SELECT 1 FROM pg_constraint WHERE conname = 'communication_rooms_updated_by_auth_users_id_fk' + ) THEN + ALTER TABLE "communication_rooms" + ADD CONSTRAINT "communication_rooms_updated_by_auth_users_id_fk" + FOREIGN KEY ("updated_by") REFERENCES "public"."auth_users"("id") + ON DELETE no action ON UPDATE no action; + END IF; +END $$; + +CREATE UNIQUE INDEX IF NOT EXISTS "communication_rooms_tenant_key_idx" + ON "communication_rooms" USING btree ("tenant_id", "key"); + +CREATE INDEX IF NOT EXISTS "communication_rooms_tenant_idx" + ON "communication_rooms" USING btree ("tenant_id"); + +CREATE INDEX IF NOT EXISTS "communication_rooms_entity_idx" + ON "communication_rooms" USING btree ("tenant_id", "entity_type", "entity_id", "entity_uuid"); diff --git a/backend/db/migrations/meta/_journal.json b/backend/db/migrations/meta/_journal.json index fa13103..7055a4d 100644 --- a/backend/db/migrations/meta/_journal.json +++ b/backend/db/migrations/meta/_journal.json @@ -302,6 +302,13 @@ "when": 1780153200000, "tag": "0042_profile_availability_note", "breakpoints": true + }, + { + "idx": 43, + "version": "7", + "when": 1780156800000, + "tag": "0043_communication_rooms", + "breakpoints": true } ] } diff --git a/docker-compose.selfhost.yml b/docker-compose.selfhost.yml index 278fff2..559be29 100644 --- a/docker-compose.selfhost.yml +++ b/docker-compose.selfhost.yml @@ -131,8 +131,8 @@ services: FEDEO_BOOTSTRAP_TENANT_NAME: ${FEDEO_BOOTSTRAP_TENANT_NAME:-FEDEO} FEDEO_BOOTSTRAP_TENANT_SHORT: ${FEDEO_BOOTSTRAP_TENANT_SHORT:-FEDEO} MATRIX_HOMESERVER_URL: ${MATRIX_HOMESERVER_URL:-http://matrix-synapse:8008} - MATRIX_SERVER_NAME: ${MATRIX_SERVER_NAME:-fedeo.de} - MATRIX_RTC_HOST: ${MATRIX_RTC_HOST:-call.fedeo.de} + MATRIX_SERVER_NAME: ${MATRIX_SERVER_NAME:-${DOMAIN}} + MATRIX_RTC_HOST: ${MATRIX_RTC_HOST:-${DOMAIN}} MATRIX_RTC_JWT_URL: ${MATRIX_RTC_JWT_URL:-} MATRIX_LIVEKIT_URL: ${MATRIX_LIVEKIT_URL:-} MATRIX_REGISTRATION_SHARED_SECRET: ${MATRIX_REGISTRATION_SHARED_SECRET:-} @@ -221,7 +221,7 @@ services: - ./matrix/synapse:/data labels: - traefik.enable=true - - traefik.http.routers.fedeo-matrix.rule=Host(`${MATRIX_HOMESERVER_HOST:-matrix.fedeo.de}`) && PathPrefix(`/_matrix`) + - traefik.http.routers.fedeo-matrix.rule=Host(`${DOMAIN}`) && PathPrefix(`/_matrix`) - traefik.http.routers.fedeo-matrix.entrypoints=websecure - traefik.http.routers.fedeo-matrix.tls.certresolver=letsencrypt - traefik.http.services.fedeo-matrix.loadbalancer.server.port=8008 @@ -243,7 +243,7 @@ services: - traefik.http.middlewares.fedeo-matrix-well-known-cors.headers.accesscontrolalloworiginlist=* - traefik.http.middlewares.fedeo-matrix-well-known-cors.headers.accesscontrolallowmethods=GET,OPTIONS - traefik.http.middlewares.fedeo-matrix-well-known-cors.headers.accesscontrolallowheaders=Content-Type,Authorization - - traefik.http.routers.fedeo-matrix-well-known.rule=Host(`${MATRIX_SERVER_NAME:-fedeo.de}`) && PathPrefix(`/.well-known/matrix`) + - traefik.http.routers.fedeo-matrix-well-known.rule=Host(`${DOMAIN}`) && PathPrefix(`/.well-known/matrix`) - traefik.http.routers.fedeo-matrix-well-known.entrypoints=websecure - traefik.http.routers.fedeo-matrix-well-known.tls.certresolver=letsencrypt - traefik.http.routers.fedeo-matrix-well-known.middlewares=fedeo-matrix-well-known-cors @@ -262,7 +262,7 @@ services: - --fingerprint - --use-auth-secret - --static-auth-secret=${MATRIX_TURN_SHARED_SECRET:-change-this-turn-secret} - - --realm=${MATRIX_SERVER_NAME:-fedeo.de} + - --realm=${MATRIX_SERVER_NAME:-${DOMAIN}} - --listening-port=3478 - --tls-listening-port=5349 - --min-port=49160 @@ -311,7 +311,7 @@ services: labels: - traefik.enable=true - traefik.http.middlewares.fedeo-matrix-livekit-strip.stripprefix.prefixes=/livekit/sfu - - traefik.http.routers.fedeo-matrix-livekit.rule=Host(`${MATRIX_RTC_HOST:-call.fedeo.de}`) && PathPrefix(`/livekit/sfu`) + - traefik.http.routers.fedeo-matrix-livekit.rule=Host(`${DOMAIN}`) && PathPrefix(`/livekit/sfu`) - traefik.http.routers.fedeo-matrix-livekit.entrypoints=websecure - traefik.http.routers.fedeo-matrix-livekit.tls.certresolver=letsencrypt - traefik.http.routers.fedeo-matrix-livekit.middlewares=fedeo-matrix-livekit-strip @@ -331,15 +331,15 @@ services: - matrix-livekit - matrix-synapse environment: - LIVEKIT_URL: wss://${MATRIX_RTC_HOST:-call.fedeo.de}/livekit/sfu + LIVEKIT_URL: wss://${DOMAIN}/livekit/sfu LIVEKIT_KEY: ${LIVEKIT_KEY:-fedeo-livekit} LIVEKIT_SECRET: ${LIVEKIT_SECRET:-change-this-livekit-secret-please-replace} - LIVEKIT_FULL_ACCESS_HOMESERVERS: ${MATRIX_SERVER_NAME:-fedeo.de} + LIVEKIT_FULL_ACCESS_HOMESERVERS: ${MATRIX_SERVER_NAME:-${DOMAIN}} LIVEKIT_JWT_BIND: :8080 labels: - traefik.enable=true - traefik.http.middlewares.fedeo-matrix-rtc-jwt-strip.stripprefix.prefixes=/livekit/jwt - - traefik.http.routers.fedeo-matrix-rtc-jwt.rule=Host(`${MATRIX_RTC_HOST:-call.fedeo.de}`) && PathPrefix(`/livekit/jwt`) + - traefik.http.routers.fedeo-matrix-rtc-jwt.rule=Host(`${DOMAIN}`) && PathPrefix(`/livekit/jwt`) - traefik.http.routers.fedeo-matrix-rtc-jwt.entrypoints=websecure - traefik.http.routers.fedeo-matrix-rtc-jwt.tls.certresolver=letsencrypt - traefik.http.routers.fedeo-matrix-rtc-jwt.middlewares=fedeo-matrix-rtc-jwt-strip @@ -359,9 +359,11 @@ services: - ./matrix/selfhost/element-config.json:/app/config.json:ro labels: - traefik.enable=true - - traefik.http.routers.fedeo-matrix-element.rule=Host(`${MATRIX_ELEMENT_HOST:-element.fedeo.de}`) + - traefik.http.routers.fedeo-matrix-element.rule=Host(`${DOMAIN}`) && PathPrefix(`/element`) - traefik.http.routers.fedeo-matrix-element.entrypoints=websecure - traefik.http.routers.fedeo-matrix-element.tls.certresolver=letsencrypt + - traefik.http.middlewares.fedeo-matrix-element-strip.stripprefix.prefixes=/element + - traefik.http.routers.fedeo-matrix-element.middlewares=fedeo-matrix-element-strip - traefik.http.services.fedeo-matrix-element.loadbalancer.server.port=80 - traefik.docker.network=fedeo_web networks: diff --git a/matrix/selfhost/element-config.json b/matrix/selfhost/element-config.json index 5a7e17e..d3ac100 100644 --- a/matrix/selfhost/element-config.json +++ b/matrix/selfhost/element-config.json @@ -1,14 +1,14 @@ { "default_server_config": { "m.homeserver": { - "base_url": "https://matrix.fedeo.de", - "server_name": "fedeo.de" + "base_url": "https://app.example.com", + "server_name": "app.example.com" } }, "org.matrix.msc4143.rtc_foci": [ { "type": "livekit", - "livekit_service_url": "https://call.fedeo.de/livekit/jwt" + "livekit_service_url": "https://app.example.com/livekit/jwt" } ], "disable_custom_urls": false,