十二个构建

一个联邦真正可用的 Matrix 主服务器

在小 Ryzen 实例上的 Synapse,使用 Postgres,通过 well-known 文件而不是 SRV 记录进行委派,以及可达其他服务器的验证。

构建内容

一台位于 example.com 的家用服务器,运行在 matrix.example.com 上,与其他所有服务器正确联邦。底层使用 Postgres,前端使用 nginx,委派由两个小型 JSON 文件处理,并且关闭注册,使你的服务器不会在一周内成为别人的免费中继。

联邦是这些安装通常失败的地方,而且几乎从不是因为 Synapse。服务器运行正常,本地消息正常,但外部消息无法到达。实际上,原因几乎总是委派:服务器的身份和其所在地址是两个不同的东西,连接它们的机制很容易出现细微错误。

开始之前

  • 一台 R-4 足够服务几十个用户。Synapse 更消耗内存而非 CPU,加入大型联邦房间是唯一会使其吃力的操作。
  • DNS 中的两个名称:example.com 是服务器的身份,出现在每个用户 ID 中;matrix.example.com 是软件实际监听的地址。
  • 两者的证书。第一个仅需提供两个静态文件。

1. 数据库,使用正确的排序规则

apt update && apt install -y postgresql matrix-synapse nginx certbot
sudo -u postgres psql -c "CREATE USER synapse_user WITH PASSWORD '<a long password>';"
sudo -u postgres psql -c "CREATE DATABASE synapse ENCODING 'UTF8' LC_COLLATE='C' LC_CTYPE='C' TEMPLATE=template0 OWNER synapse_user;"

排序规则不是细节。Synapse 拒绝在创建时使用除 C 以外的任何排序规则的数据库上启动,并且当你搞错时,它打印的错误会在你已经导入数据后才出现。现在正确地做一次,彻底做好。

2. 家服务器配置

Debian 的软件包在安装时询问服务器名称;回答 example.com,而不是机器的主机名。这个答案将成为服务器上每个用户 ID 和房间 ID 的一部分,事后无法更改,除非放弃服务器。

然后编辑 /etc/matrix-synapse/homeserver.yaml

server_name: "example.com"
public_baseurl: "https://matrix.example.com/"
pid_file: /run/matrix-synapse.pid

listeners:
  - port: 8008
    tls: false
    type: http
    x_forwarded: true
    bind_addresses: ['127.0.0.1']
    resources:
      - names: [client, federation]
        compress: false

database:
  name: psycopg2
  args:
    user: synapse_user
    password: "<a long password>"
    database: synapse
    host: 127.0.0.1
    cp_min: 5
    cp_max: 10

enable_registration: false
registration_shared_secret: "<a long random string>"
report_stats: false
suppress_key_server_warning: true
url_preview_enabled: false

media_store_path: /var/lib/matrix-synapse/media
max_upload_size: 100M
media_retention:
  remote_media_lifetime: 30d

rc_message:
  per_second: 0.5
  burst_count: 15

其中两个设置会节省你的磁盘和烦恼。远程媒体保留在一个月后丢弃其他服务器文件的缓存副本,没有它,媒体存储会随着你不曾要求的内容不断增长。URL 预览已关闭,因为它使你的服务器代表任何能发布链接的人抓取任意地址,这是一个带聊天界面的请求伪造引擎。

x_forwarded: true 也很重要:没有它,Synapse 会将世界上的每个用户都视为一个客户端进行速率限制,因为每个请求看起来都来自 nginx。

3. 委派

你的身份是 example.com,你的服务器位于 matrix.example.com。两个文件弥合差距。从 example.com 通过 HTTPS 提供它们,并设置正确的内容类型。

/.well-known/matrix/server

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

/.well-known/matrix/client

{ "m.homeserver": { "base_url": "https://matrix.example.com" } }

第一个文件中的端口是必需的。省略它,其他服务器会回退到端口 8448,发现没有监听,然后静默放弃;之后你的用户会报告联邦故障,而你机器上的每个日志看起来都非常健康。

server {
  listen 443 ssl;
  server_name example.com;
  ssl_certificate     /etc/letsencrypt/live/example.com/fullchain.pem;
  ssl_certificate_key /etc/letsencrypt/live/example.com/privkey.pem;

  location /.well-known/matrix/ {
    root /var/www/wellknown;
    default_type application/json;
    add_header Access-Control-Allow-Origin *;
  }
}

server {
  listen 443 ssl;
  listen [::]:443 ssl;
  server_name matrix.example.com;
  ssl_certificate     /etc/letsencrypt/live/matrix.example.com/fullchain.pem;
  ssl_certificate_key /etc/letsencrypt/live/matrix.example.com/privkey.pem;
  client_max_body_size 100m;

  location ~ ^(/_matrix|/_synapse/client) {
    proxy_pass http://127.0.0.1:8008;
    proxy_set_header X-Forwarded-For $remote_addr;
    proxy_set_header X-Forwarded-Proto $scheme;
    proxy_set_header Host $host;
  }
}

well-known 位置上的 Access-Control-Allow-Origin 头是 Web 客户端所必需的,但几乎所有人都忘记了。没有它,桌面客户端可以正常工作,而浏览器客户端则完全无法找到你的服务器。

mkdir -p /var/www/wellknown/.well-known/matrix
systemctl restart matrix-synapse nginx

4. 创建用户

register_new_matrix_user -c /etc/matrix-synapse/homeserver.yaml http://127.0.0.1:8008

回答提示,将第一个账户设为管理员,并保持开放注册关闭。一个开放注册的家服务器几天内就会成为垃圾邮件来源,其他服务器会在你注意到之前很久就开始拒绝你的流量。

验证它

由内而外。首先,软件是否有响应:

curl -s https://matrix.example.com/_matrix/client/versions | head -c 200
curl -s https://matrix.example.com/_matrix/federation/v1/version

然后,委派是否正确提供,端口存在且内容类型正确:

curl -si https://example.com/.well-known/matrix/server | grep -E "content-type|m.server"
curl -s https://example.com/.well-known/matrix/client

然后,你的签名密钥是否能解析。其他服务器在与你通信之前会先获取它:

curl -s https://matrix.example.com/_matrix/key/v2/server | head -c 300

最后,唯一重要的测试。使用客户端登录,加入一个托管在非你服务器的公共房间,发送消息。然后使用客户端在设置中显示的访问令牌,从管理 API 读取联邦状态:

curl -s -H "Authorization: Bearer <admin token>" \
  "https://matrix.example.com/_synapse/admin/v1/federation/destinations" | head -c 400

每个目的地都应显示最近的成功事务且无重试间隔。目的地中 retry_interval 不断增长的是你无法到达的服务器;如果每个目的地都是这样,问题在于委派而不是网络,步骤三是应该检查的地方。

journalctl -u matrix-synapse --since "10 min ago" | grep -i "federation" | tail -20

之后

第一次加入非常大的房间会占用一个核心几分钟,并引入大量状态。这是正常的,每个房间只发生一次,这是人们认为 Synapse 慢的主要原因。语音和视频需要与此并列的 TURN 服务器;同一实例上的 coturn 可以服务一个小型社区,尽管它希望在防火墙中有自己的 UDP 端口范围。联邦是双向聊天的,这在选择站点时值得记住:我们的 位置索引 列出了我们自己测量的往返时间。

随时恭候

选择城市,选择大小,用加密货币支付。

无需填写关于您的身份信息的表格,无需等待人工审批,无需电话验证。账单结清后,凭证将发送到您的邮箱。