Matrix-Dendrite-Monolith + Sliding mit Docker-Compose

Matrix-Dendrite-Monolith + Sliding mit Docker-Compose

Dies ist das erste Setup, welches Funktioniert. Es werden zwei Subdomains benötigt, einer für den Dendrite-Container hier immer benannt als matrix.domain.com und einer für die Elements-weboberfläche, hier benannt als elements.domain.com.

Im jeweiligen Deploy-Ordner brauchen wir einen .config-Ordner:

mkdir -p ./config

Zunächst die docker-compose.yaml:

services:
  postgres:
    hostname: postgres
    image: postgres:16-alpine
    restart: always
    volumes:
      # This will create a docker volume to persist the database files in.
      # If you prefer those files to be outside of docker, you'll need to change this.
      - dendrite_postgres_data:/var/lib/postgresql/data
    environment:
      POSTGRES_PASSWORD: itsasecret
      POSTGRES_USER: dendrite
      POSTGRES_DATABASE: dendrite
    healthcheck:
      test:
        - CMD-SHELL
        - pg_isready -U dendrite
      interval: 5s
      timeout: 5s
      retries: 5
    networks:
      - internal
  monolith:
    hostname: monolith
    image: matrixdotorg/dendrite-monolith:latest
    ports:
      - 8008:8008
      - 8448:8448
    volumes:
      - ./config:/etc/dendrite
      - dendrite_media:/var/dendrite/media
      - dendrite_jetstream:/var/dendrite/jetstream
      - dendrite_search_index:/var/dendrite/searchindex
    depends_on:
      postgres:
        condition: service_healthy
    networks:
      - internal
    restart: unless-stopped
  element-web:
    image: vectorim/element-web:latest
    restart: always
    container_name: element-web
    depends_on:
      - monolith
    volumes:
      - ./element-web/config.json:/app/config.json:ro
    ports:
      - 8449:80
      - 8450:433
    networks:
      - internal
networks:
  internal:
    attachable: true
volumes:
  dendrite_postgres_data: null
  dendrite_media: null
  dendrite_jetstream: null
  dendrite_search_index: null

Der erste Start wird scheitern, was nicht schlimm ist, denn so wird wenigstens die gewünschte Ordnerstruktur angelegt.
Damit die Container reibungslos starten benötigen wir noch zwei config Dateien und müssen zwei docker Befehle ausführen, als erstes wird ein Key erstellt:

docker run --rm --entrypoint="/usr/bin/generate-keys" \
  -v $(pwd)/config:/mnt \
  matrixdotorg/dendrite-monolith:latest \
  -private-key /mnt/matrix_key.pem

Und eine Standard config hinterlegt:

docker run --rm --entrypoint="/bin/sh" \
  -v $(pwd)/config:/mnt \
  matrixdotorg/dendrite-monolith:latest \
  -c "/usr/bin/generate-config \
    -dir /var/dendrite/ \
    -db postgres://dendrite:itsasecret@postgres/dendrite?sslmode=disable \
    -server YourDomainHere > /mnt/dendrite.yaml"

Auch elements web benötigt eine config.json. Anmerkung: bei mir wurde versehentlich die Datei config.json als Ordner angelegt, dieser muss entfernt werden und als Datei angelegt werden.

{
    "default_server_name": "matrix.domain.com",
    "default_server_config": {
        "m.homeserver": {
            "base_url": "https://matrix.domain.com"
        },
        "m.identity_server": {
            "base_url": "https://vector.im"
        }
    },
    "brand": "Element",
    "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",
        "https://scalar-staging.vector.im/_matrix/integrations/v1>
        "https://scalar-staging.vector.im/api",
        "https://scalar-staging.riot.im/scalar/api"
    ],
    "bug_report_endpoint_url": "https://element.io/bugreports/sub>
    "uisi_autorageshake_app": "element-auto-uisi",
    "show_labs_settings": false,
    "room_directory": {
        "servers": ["matrix.org", "gitter.im", "libera.chat"]
    },
    "enable_presence_by_hs_url": {
        "https://matrix.org": false,
        "https://matrix-client.matrix.org": false
    },
    "terms_and_conditions_links": [
        {
            "url": "https://element.io/privacy",
            "text": "Privacy Policy"
        },
        {
            "url": "https://element.io/cookie-policy",
            "text": "Cookie Policy"
        }
    ],
    "posthog": {
        "project_api_key": "phc_Jzsm6DTm6V2705zeU5dcNvQDlonOR68Xv>
        "api_host": "https://posthog.element.io"
    },
    "privacy_policy_url": "https://element.io/cookie-policy",
    "map_style_url": "https://api.maptiler.com/maps/streets/style>
    "setting_defaults": {
        "RustCrypto.staged_rollout_percent": 30
    }
}

Jetzt müssten die Container korrekt starten. Somit fehlt lediglich noch der caddy proxy Eintrag:

matrix.domain.com {
  reverse_proxy /_matrix/* localhost:8008
  reverse_proxy /_synapse/client/* localhost:8008

  header {
    X-Content-Type-Options nosniff
    Referrer-Policy  strict-origin-when-cross-origin
    Strict-Transport-Security "max-age=63072000; includeSubDomain>
    Permissions-Policy "accelerometer=(), camera=(), geolocation=>
    X-Frame-Options SAMEORIGIN
    X-XSS-Protection 1
    X-Robots-Tag none
    -server
  }
}

element.piriot.de {
  encode zstd gzip
  reverse_proxy localhost:8449

  header {
    X-Content-Type-Options nosniff
    Referrer-Policy  strict-origin-when-cross-origin
    Strict-Transport-Security "max-age=63072000; includeSubDomain>
    Permissions-Policy "accelerometer=(), camera=(), geolocation=>
    X-Frame-Options SAMEORIGIN
    X-XSS-Protection 1
    X-Robots-Tag none
    -server
  }
}

Als letzter Schritt werden die User nur über die Kommandozeile erstellt:

So erfährt man den Containernamen:

docker ps --format "{{.Names}}"

Adminaccount:

docker exec -it CONTAINERNAME /usr/bin/create-account -config /path/to/dendrite.yaml -username USERNAME -admin

Anmerkung: Für einen selbst reicht auch ein normaler Account, ich konnte mit dem Adminaccount keine Pushnachrichten empfangen.

Useraccount:

docker exec -it CONTAINERNAME /usr/bin/create-account -config /path/to/dendrite.yaml -username USERNAME

Damit die Kommandozeilen Anmeldung funktioniert wird ein shared-secret benötigt in der dendrite.yaml dies darf irgendein Buchstaben wirrwarr sein:

client_api:
  # ...
  registration_shared_secret: "YourSecret"

Das Ergebnis ist ein funktionsfähiger Matrix Server der deföderiert und eigenständig läuft es fehlt ein integrationsserver, bedeutet User können nur über die Suche des korrekten Tags "@user:matrix.example.dom" gefunden werden. Auch ein Turn-Server fehlt, bedeutet Anrufe über Voice oder Video funktioniert ebenfalls nicht.

Bonus:

Um Apps wie Element X zu verwenden benötigen wir einen weitere Kombination aus Containern, welche hier ebenfalls als Docker Compose zu finden ist:

services:
  sliding-sync:
    image: ghcr.io/matrix-org/sliding-sync:v0.99.1
    restart: unless-stopped
    ports:
      - 8881:8881
    environment:
      - SYNCV3_SECRET=somerandomsecret
      - SYNCV3_SERVER=https://matrix.domain.com
      - SYNCV3_DB=user=syncv3 dbname=syncv3 sslmode=disable
        host=sliding-postgres password=itsasecret
      - SYNCV3_BINDADDR=0.0.0.0:8881
    depends_on:
      - sliding-postgres
  sliding-postgres:
    image: postgres:16-alpine
    restart: unless-stopped
    environment:
      - POSTGRES_USER=syncv3
      - POSTGRES_PASSWORD=itsasecret
      - POSTGRES_DB=syncv3
    volumes:
      - sliding_db_data:/var/lib/postgresql/data
volumes:
  sliding_db_data: null
networks: {}

Dies ist allerdings optional.