From 557bfb5ee10d65cb6496703c4df5f696a1304a68 Mon Sep 17 00:00:00 2001 From: Apple Date: Wed, 26 Nov 2025 11:56:39 -0800 Subject: [PATCH] feat: Add Matrix infrastructure (Synapse + Element Web) - Synapse homeserver.yaml configuration - Element Web config.json - PostgreSQL init script for synapse DB - Nginx gateway configuration - Docker Compose for Matrix stack - README_MATRIX.md documentation --- infra/matrix/README_MATRIX.md | 152 +++++++++++++++++++++++++ infra/matrix/docker-compose.matrix.yml | 75 ++++++++++++ infra/matrix/element-web/config.json | 57 ++++++++++ infra/matrix/gateway/matrix.conf | 64 +++++++++++ infra/matrix/postgres/init.sql | 27 +++++ infra/matrix/synapse/homeserver.yaml | 93 +++++++++++++++ infra/matrix/synapse/log.config | 21 ++++ 7 files changed, 489 insertions(+) create mode 100644 infra/matrix/README_MATRIX.md create mode 100644 infra/matrix/docker-compose.matrix.yml create mode 100644 infra/matrix/element-web/config.json create mode 100644 infra/matrix/gateway/matrix.conf create mode 100644 infra/matrix/postgres/init.sql create mode 100644 infra/matrix/synapse/homeserver.yaml create mode 100644 infra/matrix/synapse/log.config diff --git a/infra/matrix/README_MATRIX.md b/infra/matrix/README_MATRIX.md new file mode 100644 index 00000000..6859a5c8 --- /dev/null +++ b/infra/matrix/README_MATRIX.md @@ -0,0 +1,152 @@ +# Matrix Integration for DAARION.city + +## Overview + +Matrix забезпечує децентралізований real-time чат для DAARION.city: +- **Synapse** — Matrix homeserver +- **Element Web** — веб-клієнт +- **DAARION Bridge** (майбутнє) — інтеграція з City Rooms та Agents + +## Architecture + +``` +┌─────────────────────────────────────────────────────────┐ +│ DAARION.city │ +├─────────────────────────────────────────────────────────┤ +│ ┌─────────────┐ ┌─────────────┐ ┌─────────────────┐ │ +│ │ Element Web │ │ Synapse │ │ DAARION Auth │ │ +│ │ (8088) │→ │ (8008) │← │ (7020) │ │ +│ └─────────────┘ └─────────────┘ └─────────────────┘ │ +│ │ │ │ │ +│ └───────────────┼───────────────────┘ │ +│ ↓ │ +│ ┌───────────┐ │ +│ │ PostgreSQL│ │ +│ │ (synapse)│ │ +│ └───────────┘ │ +└─────────────────────────────────────────────────────────┘ +``` + +## URLs + +| Service | Internal | External | +|---------|----------|----------| +| Synapse API | http://127.0.0.1:8008 | https://matrix.daarion.space/_matrix/ | +| Element Web | http://127.0.0.1:8088 | https://matrix.daarion.space/element/ | +| Well-known | - | https://matrix.daarion.space/.well-known/matrix/* | + +## Deployment Phases + +### Phase 1: Base Synapse (Current) +- [x] Конфігурація homeserver.yaml +- [x] PostgreSQL schema +- [x] Docker Compose +- [ ] Deploy на NODE1 +- [ ] SSL/DNS для matrix.daarion.space + +### Phase 2: Element Web +- [x] config.json +- [ ] Deploy Element +- [ ] Nginx routing /element/ + +### Phase 3: DAARION Auth Integration +- [ ] User provisioning при реєстрації +- [ ] SSO через DAARION JWT +- [ ] Sync user profiles + +### Phase 4: City Rooms Bridge +- [ ] Маппінг City Rooms → Matrix Rooms +- [ ] Agent messages → Matrix events +- [ ] Presence sync + +### Phase 5: Federation (Optional) +- [ ] DNS SRV records +- [ ] Federation keys +- [ ] Multi-node setup + +## Configuration + +### Environment Variables + +```bash +# Required +SYNAPSE_DB_PASSWORD=your_secure_password +SYNAPSE_REGISTRATION_SECRET=your_registration_secret +TURN_SHARED_SECRET=your_turn_secret + +# Optional +SYNAPSE_SERVER_NAME=daarion.space +``` + +### DNS Records + +``` +matrix.daarion.space A 144.76.224.179 +_matrix._tcp.daarion.space SRV 10 5 443 matrix.daarion.space +``` + +## User Registration + +Реєстрація через API (для інтеграції з DAARION Auth): + +```bash +# Register user via admin API +curl -X POST "http://localhost:8008/_synapse/admin/v1/register" \ + -H "Content-Type: application/json" \ + -d '{ + "nonce": "...", + "username": "user123", + "password": "...", + "admin": false + }' +``` + +## Security + +1. **Registration disabled** — користувачі створюються тільки через DAARION Auth +2. **Admin API** — обмежений доступ +3. **Rate limiting** — налаштовано в homeserver.yaml +4. **E2EE** — підтримується Element Web + +## Monitoring + +Метрики доступні на порту 9000: +- `/_synapse/metrics` — Prometheus метрики + +## Troubleshooting + +### Synapse не стартує +```bash +docker logs daarion-synapse +# Перевірити signing.key +docker exec daarion-synapse ls -la /data/ +``` + +### Database connection failed +```bash +# Перевірити PostgreSQL +docker exec -it dagi-postgres psql -U postgres -c "\l" +``` + +### Element не підключається +1. Перевірити CORS headers +2. Перевірити .well-known endpoints +3. Перевірити config.json base_url + +## Files + +``` +infra/matrix/ +├── synapse/ +│ ├── homeserver.yaml # Main config +│ └── log.config # Logging config +├── postgres/ +│ └── init.sql # DB initialization +├── element-web/ +│ └── config.json # Element config +├── gateway/ +│ └── matrix.conf # Nginx config +├── docker-compose.matrix.yml +└── README_MATRIX.md +``` + diff --git a/infra/matrix/docker-compose.matrix.yml b/infra/matrix/docker-compose.matrix.yml new file mode 100644 index 00000000..c9e789d0 --- /dev/null +++ b/infra/matrix/docker-compose.matrix.yml @@ -0,0 +1,75 @@ +version: '3.8' + +# Matrix Stack for DAARION.city +# Includes: Synapse homeserver + Element Web + +services: + synapse: + image: matrixdotorg/synapse:latest + container_name: daarion-synapse + restart: unless-stopped + environment: + - SYNAPSE_CONFIG_PATH=/data/homeserver.yaml + - SYNAPSE_DB_PASSWORD=${SYNAPSE_DB_PASSWORD:-synapse_password} + - SYNAPSE_REGISTRATION_SECRET=${SYNAPSE_REGISTRATION_SECRET:-registration_secret_change_me} + - TURN_SHARED_SECRET=${TURN_SHARED_SECRET:-turn_secret_change_me} + volumes: + - ./synapse/homeserver.yaml:/data/homeserver.yaml:ro + - ./synapse/log.config:/data/log.config:ro + - synapse_data:/data + ports: + - "8008:8008" + - "9000:9000" # Metrics + networks: + - dagi-network + depends_on: + - synapse-init + healthcheck: + test: ["CMD", "curl", "-f", "http://localhost:8008/health"] + interval: 30s + timeout: 10s + retries: 3 + + synapse-init: + image: matrixdotorg/synapse:latest + container_name: daarion-synapse-init + entrypoint: /bin/sh + command: > + -c " + if [ ! -f /data/signing.key ]; then + echo 'Generating signing key...' + python -m synapse.app.homeserver --config-path /data/homeserver.yaml --generate-keys + fi + echo 'Synapse initialized' + " + environment: + - SYNAPSE_CONFIG_PATH=/data/homeserver.yaml + volumes: + - ./synapse/homeserver.yaml:/data/homeserver.yaml:ro + - synapse_data:/data + networks: + - dagi-network + + element-web: + image: vectorim/element-web:latest + container_name: daarion-element + restart: unless-stopped + volumes: + - ./element-web/config.json:/app/config.json:ro + ports: + - "8088:80" + networks: + - dagi-network + healthcheck: + test: ["CMD", "wget", "-q", "--spider", "http://localhost:80"] + interval: 30s + timeout: 10s + retries: 3 + +volumes: + synapse_data: + +networks: + dagi-network: + external: true + diff --git a/infra/matrix/element-web/config.json b/infra/matrix/element-web/config.json new file mode 100644 index 00000000..1516755e --- /dev/null +++ b/infra/matrix/element-web/config.json @@ -0,0 +1,57 @@ +{ + "default_server_config": { + "m.homeserver": { + "base_url": "https://matrix.daarion.space", + "server_name": "daarion.space" + }, + "m.identity_server": { + "base_url": "https://vector.im" + } + }, + "brand": "DAARION", + "integrations_ui_url": "https://scalar.vector.im/", + "integrations_rest_url": "https://scalar.vector.im/api", + "integrations_widgets_urls": [ + "https://scalar.vector.im/_matrix/integrations/v1", + "https://scalar.vector.im/api" + ], + "bug_report_endpoint_url": null, + "uisi_autorageshake_app": "element-auto-uisi", + "show_labs_settings": true, + "room_directory": { + "servers": [ + "daarion.space" + ] + }, + "enable_presence_by_hs_url": { + "https://matrix.daarion.space": true + }, + "setting_defaults": { + "breadcrumbs": true, + "MessageComposerInput.showStickersButton": false + }, + "features": { + "feature_spotlight": true + }, + "default_country_code": "UA", + "default_theme": "dark", + "disable_custom_urls": false, + "disable_guests": true, + "disable_login_language_selector": false, + "disable_3pid_login": false, + "branding": { + "welcome_background_url": null, + "auth_header_logo_url": null, + "auth_footer_links": [ + { + "text": "DAARION.city", + "url": "https://app.daarion.space" + } + ] + }, + "embedded_pages": { + "welcome_url": null + }, + "map_style_url": "https://api.maptiler.com/maps/streets/style.json?key=fU3vlMsMn4Jb6dnEIFsx" +} + diff --git a/infra/matrix/gateway/matrix.conf b/infra/matrix/gateway/matrix.conf new file mode 100644 index 00000000..6dab34bc --- /dev/null +++ b/infra/matrix/gateway/matrix.conf @@ -0,0 +1,64 @@ +# Nginx configuration for Matrix (Synapse + Element) +# Add to /etc/nginx/conf.d/ on NODE1 + +# Matrix Synapse API +location /_matrix/ { + proxy_pass http://127.0.0.1:8008; + proxy_http_version 1.1; + proxy_set_header Host $host; + proxy_set_header X-Real-IP $remote_addr; + proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for; + proxy_set_header X-Forwarded-Proto $scheme; + + # WebSocket support + proxy_set_header Upgrade $http_upgrade; + proxy_set_header Connection "upgrade"; + + # Increase timeouts for long-polling + proxy_read_timeout 600s; + proxy_send_timeout 600s; + + # Increase body size for media uploads + client_max_body_size 50M; +} + +# Synapse admin API (restrict access!) +location /_synapse/ { + proxy_pass http://127.0.0.1:8008; + proxy_http_version 1.1; + proxy_set_header Host $host; + proxy_set_header X-Real-IP $remote_addr; + proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for; + proxy_set_header X-Forwarded-Proto $scheme; + + # Restrict to internal only + # allow 127.0.0.1; + # deny all; +} + +# Element Web UI +location /element/ { + alias /var/www/element/; + index index.html; + try_files $uri $uri/ /element/index.html; + + # Cache static assets + location ~* \.(js|css|png|jpg|jpeg|gif|ico|svg|woff|woff2)$ { + expires 1y; + add_header Cache-Control "public, immutable"; + } +} + +# .well-known for Matrix federation +location /.well-known/matrix/server { + default_type application/json; + add_header Access-Control-Allow-Origin *; + return 200 '{"m.server": "matrix.daarion.space:443"}'; +} + +location /.well-known/matrix/client { + default_type application/json; + add_header Access-Control-Allow-Origin *; + return 200 '{"m.homeserver": {"base_url": "https://matrix.daarion.space"}, "m.identity_server": {"base_url": "https://vector.im"}}'; +} + diff --git a/infra/matrix/postgres/init.sql b/infra/matrix/postgres/init.sql new file mode 100644 index 00000000..e8255a61 --- /dev/null +++ b/infra/matrix/postgres/init.sql @@ -0,0 +1,27 @@ +-- Matrix Synapse PostgreSQL initialization +-- Run this on the existing dagi-postgres instance + +-- Create synapse database +CREATE DATABASE synapse + ENCODING 'UTF8' + LC_COLLATE='C' + LC_CTYPE='C' + template=template0; + +-- Create synapse user (password should be set via env variable) +CREATE USER synapse WITH ENCRYPTED PASSWORD 'CHANGE_ME_IN_PRODUCTION'; + +-- Grant privileges +GRANT ALL PRIVILEGES ON DATABASE synapse TO synapse; + +-- Connect to synapse database and set up extensions +\c synapse + +-- Required extensions for Synapse +CREATE EXTENSION IF NOT EXISTS pg_trgm; + +-- Grant schema permissions +GRANT ALL ON SCHEMA public TO synapse; +ALTER DEFAULT PRIVILEGES IN SCHEMA public GRANT ALL ON TABLES TO synapse; +ALTER DEFAULT PRIVILEGES IN SCHEMA public GRANT ALL ON SEQUENCES TO synapse; + diff --git a/infra/matrix/synapse/homeserver.yaml b/infra/matrix/synapse/homeserver.yaml new file mode 100644 index 00000000..68134728 --- /dev/null +++ b/infra/matrix/synapse/homeserver.yaml @@ -0,0 +1,93 @@ +# Synapse Homeserver Configuration for DAARION.city +# Version: 1.0.0 +# +# ВАЖЛИВО: Замініть всі значення перед запуском! + +server_name: "daarion.space" +public_baseurl: "https://matrix.daarion.space/" +pid_file: /data/homeserver.pid + +# Database configuration +database: + name: psycopg2 + args: + user: synapse + password: "${SYNAPSE_DB_PASSWORD}" + database: synapse + host: dagi-postgres + port: 5432 + cp_min: 5 + cp_max: 10 + +# Listeners +listeners: + - port: 8008 + tls: false + type: http + x_forwarded: true + bind_addresses: ['0.0.0.0'] + resources: + - names: [client, federation] + compress: false + +# Registration +enable_registration: false +registration_shared_secret: "${SYNAPSE_REGISTRATION_SECRET}" + +# Allow registration via DAARION Auth +enable_registration_without_verification: false + +# Media storage +media_store_path: /data/media_store +max_upload_size: 50M +url_preview_enabled: true + +# Signing keys +signing_key_path: /data/signing.key + +# Logging +log_config: /data/log.config + +# Rate limiting +rc_messages_per_second: 0.2 +rc_message_burst_count: 10 +rc_registration: + per_second: 0.17 + burst_count: 3 + +# Federation (disabled for MVP, enable in Phase 7) +# federation_domain_whitelist: +# - daarion.space + +# Trusted key servers +trusted_key_servers: + - server_name: "matrix.org" + +# Metrics (optional, for monitoring) +enable_metrics: true +metrics_port: 9000 + +# TURN server (for voice/video calls) +turn_uris: + - "turn:turn.daarion.space:3478?transport=udp" + - "turn:turn.daarion.space:3478?transport=tcp" +turn_shared_secret: "${TURN_SHARED_SECRET}" +turn_user_lifetime: 86400000 +turn_allow_guests: false + +# Room settings +default_room_version: "10" + +# Presence +presence: + enabled: true + +# Application services (for future DAARION Bridge) +# app_service_config_files: +# - /data/appservices/daarion-bridge.yaml + +# Experimental features +experimental_features: + msc2716_enabled: false # Message history import + msc3202_device_masquerading: false + diff --git a/infra/matrix/synapse/log.config b/infra/matrix/synapse/log.config new file mode 100644 index 00000000..aa3f4f11 --- /dev/null +++ b/infra/matrix/synapse/log.config @@ -0,0 +1,21 @@ +version: 1 + +formatters: + precise: + format: '%(asctime)s - %(name)s - %(lineno)d - %(levelname)s - %(request)s - %(message)s' + +handlers: + console: + class: logging.StreamHandler + formatter: precise + +loggers: + synapse.storage.SQL: + level: WARNING + +root: + level: INFO + handlers: [console] + +disable_existing_loggers: false +