2022-11-22 / @syui

matrix , fly / fly

dendriteをupgradeしてみた

matrix

micro-blogのmastodonがtwitterに似ているのなら、chatのmatrixはslackに似ています。

mastodon, matrixの類似点は分散であるところです。

matrixのaddressは@user:example.comとなります。

matrixには様々なclientがあり、とくにwebのclientが手軽です。

例えば、elementがそれに当たります。自分が使っているserverを指定します。

https://app.element.io/

matrixは、serverからのapiとclientの組み合わせで使います。

mastodonとの違いはserverがui(html)を提供しないところです。これは、clientがui(html)を提供します。

やり取りは主にchat形式になります。roomが存在し、気に入ったroomに入り、投稿と閲覧を行います。

dmも可能です。この場合も通常はroomが作成されます。

dendrite

前回、matrixのdendrite-serverを立てたのですが、今回はdendriteのupgradeを試みてわかったことを書きます。

dendriteは、goで書かれたmatrix-serverです。

monolith, polylithがあり、polylithは大規模用です。single-userはmonolithを選択しましょう。

まず、DBですが、postgresql(pgsql)を使用しましょう。sqliteは正常に動作しません。

https://matrix-org.github.io/dendrite/installation/database

latestもpgsqlならconfig(v2)で動作します。v1との違いはdatabasejetstreamあたりです。

latest config

flyでdomainの$app.fly.devをcertしておいてください。

version: 2

global:
  server_name: xxx.fly.dev
  #well_known_server_name: "syui.cf:443"
  private_key: /etc/dendrite/matrix_key.pem
  key_validity_period: 168h0m0s
  trusted_third_party_id_servers:
  - matrix.org
  - vector.im

  database:
    connection_string: postgres://db.internal:5432/?sslmode=disable
    max_open_conns: 100
    max_idle_conns: 5
    conn_max_lifetime: -1

  jetstream:
    in_memory: false
    storage_path: /data/
    topic_prefix: Dendrite    

  metrics:
    enabled: false
    basic_auth:
      username: metrics
      password: metrics

  dns_cache:
    enabled: true
    cache_size: 4000
    cache_lifetime: 300

app_service_api:
  database:
    connection_string: postgres://db.internal:5432/?sslmode=disable
    max_open_conns: 10
    max_idle_conns: 2
    conn_max_lifetime: -1
  config_files: []

client_api:
  registration_disabled: true
  registration_shared_secret: ""
  enable_registration_captcha: false
  recaptcha_public_key: ""
  recaptcha_private_key: ""
  recaptcha_bypass_secret: ""
  recaptcha_siteverify_api: ""

  turn:
    turn_user_lifetime: ""
    turn_uris: []
    turn_shared_secret: ""
    turn_username: ""
    turn_password: ""

  rate_limiting:
    enabled: true
    threshold: 5
    cooloff_ms: 500

edu_server:

federation_api:
  federation_certificates: []

federation_sender:
  database:
    connection_string: postgres://db.internal:5432/?sslmode=disable
    max_open_conns: 10
    max_idle_conns: 2
    conn_max_lifetime: -1
  send_max_retries: 16
  disable_tls_validation: false

  proxy_outbound:
    enabled: true
    protocol: http
    host: localhost
    port: 8008

key_server:
  database:
    connection_string: postgres://db.internal:5432/?sslmode=disable
    max_open_conns: 10
    max_idle_conns: 2
    conn_max_lifetime: -1

media_api:
  database:
    connection_string: postgres://db.internal:5432/?sslmode=disable
    max_open_conns: 10
    max_idle_conns: 2
    conn_max_lifetime: -1
  base_path: /data/media
  max_file_size_bytes: 10485760
  dynamic_thumbnails: false
  max_thumbnail_generators: 10
  thumbnail_sizes:
  - width: 32
    height: 32
    method: crop
  - width: 96
    height: 96
    method: crop
  - width: 640
    height: 480
    method: scale

room_server:
  database:
    connection_string: postgres://db.internal:5432/?sslmode=disable
    max_open_conns: 10
    max_idle_conns: 2
    conn_max_lifetime: -1

signing_key_server:
  database:
    connection_string: postgres://db.internal:5432/?sslmode=disable
    max_open_conns: 10
    max_idle_conns: 2
    conn_max_lifetime: -1

  key_perspectives:
  - server_name: matrix.org
    keys:
    - key_id: ed25519:auto
      public_key: Noi6WqcDj0QmPxCNQqgezwTlBKrfqehY1u2FyWP9uYw
    - key_id: ed25519:a_RXGa
      public_key: l8Hft5qXKn1vfHrg3p4+W8gELQVo8N13JkluMfmn2sQ

  prefer_direct_fetch: false

sync_api:
  database:
    connection_string: postgres://db.internal:5432/?sslmode=disable
    max_open_conns: 10
    max_idle_conns: 2
    conn_max_lifetime: -1

user_api:
  account_database:
    connection_string: postgres://db.internal:5432/?sslmode=disable
    max_open_conns: 10
    max_idle_conns: 2
    conn_max_lifetime: -1
  device_database:
    connection_string: postgres://db.internal:5432/?sslmode=disable
    max_open_conns: 10
    max_idle_conns: 2
    conn_max_lifetime: -1

tracing:
  enabled: false
  jaeger:
    serviceName: ""
    disabled: false
    rpc_metrics: false
    tags: []
    sampler: null
    reporter: null
    headers: null
    baggage_restrictions: null
    throttler: null

logging:
- type: file
  level: info
  params:
    path: /var/log/dendrite

old config

version: 1

global:
  server_name: <my-matrix.domain>

  private_key: /etc/dendrite/matrix_key.pem
  key_validity_period: 168h0m0s
  trusted_third_party_id_servers:
  - matrix.org
  - vector.im

  kafka:
    addresses:
      - kafka:9092

    topic_prefix: Dendrite

    use_naffka: true

    naffka_database:
      connection_string: file:///data/dendrite.db
      max_open_conns: 10
      max_idle_conns: 2
      conn_max_lifetime: -1

  metrics:
    enabled: false

    basic_auth:
      username: metrics
      password: metrics

  dns_cache:
    enabled: false

    cache_size: 256
    cache_lifetime: 300

app_service_api:
  internal_api:
    listen: http://0.0.0.0:7777
    connect: http://appservice_api:7777
  database:
    connection_string: file:///data/dendrite.db
    max_open_conns: 10
    max_idle_conns: 2
    conn_max_lifetime: -1

  config_files: []

client_api:
  internal_api:
    listen: http://0.0.0.0:7771
    connect: http://client_api:7771
  external_api:
    listen: http://0.0.0.0:8071

  registration_disabled: false

  registration_shared_secret: ""

  enable_registration_captcha: false

  recaptcha_public_key: ""
  recaptcha_private_key: ""
  recaptcha_bypass_secret: ""
  recaptcha_siteverify_api: ""

  turn:
    turn_user_lifetime: ""
    turn_uris: []
    turn_shared_secret: ""
    turn_username: ""
    turn_password: ""

  rate_limiting:
    enabled: true
    threshold: 5
    cooloff_ms: 500

edu_server:
  internal_api:
    listen: http://0.0.0.0:7778
    connect: http://edu_server:7778

federation_api:
  internal_api:
    listen: http://0.0.0.0:7772
    connect: http://federation_api:7772
  external_api:
    listen: http://0.0.0.0:8072

  federation_certificates: []

federation_sender:
  internal_api:
    listen: http://0.0.0.0:7775
    connect: http://federation_sender:7775
  database:
    connection_string: file:///data/dendrite.db
    max_open_conns: 10
    max_idle_conns: 2
    conn_max_lifetime: -1

  send_max_retries: 16

  disable_tls_validation: false

  proxy_outbound:
    enabled: false
    protocol: http
    host: localhost
    port: 8080

key_server:
  internal_api:
    listen: http://0.0.0.0:7779
    connect: http://key_server:7779
  database:
    connection_string: file:///data/dendrite.db
    max_open_conns: 10
    max_idle_conns: 2
    conn_max_lifetime: -1

media_api:
  internal_api:
    listen: http://0.0.0.0:7774
    connect: http://media_api:7774
  external_api:
    listen: http://0.0.0.0:8074
  database:
    connection_string: file:///data/dendrite.db
    max_open_conns: 10
    max_idle_conns: 2
    conn_max_lifetime: -1

  base_path: /data/media

  max_file_size_bytes: 10485760

  dynamic_thumbnails: false

  max_thumbnail_generators: 10

  thumbnail_sizes:
  - width: 32
    height: 32
    method: crop
  - width: 96
    height: 96
    method: crop
  - width: 640
    height: 480
    method: scale

room_server:
  internal_api:
    listen: http://0.0.0.0:7770
    connect: http://room_server:7770
  database:
    connection_string: file:///data/dendrite.db
    max_open_conns: 10
    max_idle_conns: 2
    conn_max_lifetime: -1

signing_key_server:
  internal_api:
    listen: http://0.0.0.0:7780
    connect: http://signing_key_server:7780
  database:
    connection_string: file:///data/dendrite.db
    max_open_conns: 10
    max_idle_conns: 2
    conn_max_lifetime: -1

  key_perspectives:
  - server_name: matrix.org
    keys:
    - key_id: ed25519:auto
      public_key: Noi6WqcDj0QmPxCNQqgezwTlBKrfqehY1u2FyWP9uYw
    - key_id: ed25519:a_RXGa
      public_key: l8Hft5qXKn1vfHrg3p4+W8gELQVo8N13JkluMfmn2sQ

  prefer_direct_fetch: false

sync_api:
  internal_api:
    listen: http://0.0.0.0:7773
    connect: http://sync_api:7773
  external_api:
      listen: http://0.0.0.0:8073
  database:
    connection_string: file:///data/dendrite.db
    max_open_conns: 10
    max_idle_conns: 2
    conn_max_lifetime: -1

user_api:
  internal_api:
    listen: http://0.0.0.0:7781
    connect: http://user_api:7781
  account_database:
    connection_string: file:///data/dendrite.db
    max_open_conns: 10
    max_idle_conns: 2
    conn_max_lifetime: -1
  device_database:
    connection_string: file:///data/dendrite.db
    max_open_conns: 10
    max_idle_conns: 2
    conn_max_lifetime: -1

tracing:
  enabled: false
  jaeger:
    serviceName: ""
    disabled: false
    rpc_metrics: false
    tags: []
    sampler: null
    reporter: null
    headers: null
    baggage_restrictions: null
    throttler: null

logging:
- type: file
  level: info
  params:
    path: /var/log/dendrite

ref : https://codeberg.org/gerald/dendrite-on-flyio/src/branch/main/dendrite-example.yaml

registration_shared_secret

registration_disabledがtrueの場合、create-accountコマンドでaccoutが作成できません。registration_shared_secretが必要です。

config(v1)のv0.5.0までなかったようですが、config(v2)のv0.6.0から追加されました。spam対策のようですが、非常に厄介です。

client_api:
  registration_disabled: false
  guests_disabled: true
  registration_shared_secret: ""
  enable_registration_captcha: false
  recaptcha_public_key: ""
  recaptcha_private_key: ""
  recaptcha_bypass_secret: ""
$ curl localhost:8008/_synapse/admin/v1/register
$ fly ssh console
$ /usr/bin/create-account -config /etc/dendrite/dendrite.yaml -username xxx -password xxx -admin

IMPORTANT: Process file descriptor limit is currently 1024

FROM matrixdotorg/dendrite-monolith

COPY ./entrypoint.sh /entrypoint.sh
ENTRYPOINT ["/entrypoint.sh"]
#!/bin/sh
ulimit -n 65535
ulimit -u 4096
exec /usr/bin/dendrite-monolith-server --tls-cert /etc/dendrite/server.crt --tls-key /etc/dendrite/server.key --config /etc/dendrite/dendrite.yaml

https://matrix-org.github.io/dendrite/installation/start/optimisation

https://fly.io/laravel-bytes/integrating-the-elastic-stack-elk-into-a-laravel-app-on-fly/

fly cretificate

$ flyctl ips list
$ flyctl certs create example.com
$ flyctl certs show example.com

https://fly.io/docs/app-guides/custom-domains-with-fly/#teaching-your-app-about-custom-domains

domain

https://example.com/.well-known/matrix/server

{
    "m.server": "matrix.example.com:8448"
}

.well-known$app.fly.devを使用したほうがいいかもしれません。

global:
  server_name: example.com
  well_known_server_name: "example.com:443"

fly cret+cloudflareで連携したdomainが通らなかった。

panic

様々な問題を解決してもpanic(golang)で動かないことがあります。これは、fly.ioのcpu, memoryの問題っぽい気がしますが、planをupgradeすれば解決するかもしれません。

遅い

遅い、とにかく遅い…。

matrix.orgとsyui.cfでやり取りしてみたのですが、非常に遅かったので、今後、高速化をやっていきたいのですが、fly.ioのplanを上げるしかないのか、あるいは、dendrite-configとかでなんとかなるものなのか、わかりません。

注釈

正確には、matrixはprotocolで、dendriteがserver、elementがclientです。

しかし、matrixをserverと表現することがあります。なぜなら、そのほうが伝わりやすいからです。

例えばここでdendrite-serverは…と書いてもなんのことかわかりません。

ですが、matrix-serverと書くと「ああ、あのchatのserverか」とわかりますよね。

これは、mastodonを紹介するときにもよくあることです。

例えば、mastodonを紹介するとき、mastodonをprotocolのように扱ってしまうことがあるのです。

mastodonはserver, clientであり、protocolではありません。

mastodonは昔、ostatusというprotocolで動いていましたが、すぐにactivitypubに移行して、それからずっとactivitypubです。

しかし、mastodonは広く認知されているので、protocolのように扱い、そのように表現してしまうことが多々あるような気がしています。

mastodonのように広がり、繋がるsnsという場合、厳密には、activitypub等のprotocolで繋がっているのであって、mastodon自体は単なるserverでありclientです。

protocolより遥かに狭いものなのですが、mastodonは有名なので、protocolのように広い概念のようなものとして表現し、扱ってしまうことがあります。あまり気にしていませんが。

とは言え、ここで書かれていることは、正確ではないため、注釈しておくことにします。