SSD Nodes Learn 🎉 VPS $5.50/月起
指南 Matt Connor作者: Matt Connor

Matrix Synapse VPS 自托管与长期运维指南

了解在 VPS 上稳定运行 Matrix Synapse 的实际要求,包括 1 vCPU 和 2 GB 内存的适用范围、Postgres、媒体清理、注册防护与双数据备份。

保持 Matrix Synapse 主服务器持续运行所需的工作

Matrix Synapse 易于安装,也容易被忽略。安装过程只需要添加一个 apt 软件源、一个配置文件、一个反向代理配置块和一条 DNS 记录。要让主服务器稳定运行一年,则需要完成不同的工作:使用真正的数据库、定期清理媒体存储、禁止陌生人使用注册功能,以及创建同时包含服务器两部分数据的备份。

本指南面向 Ubuntu 24.04 LTS,并从 matrix.org apt 软件源安装 Synapse。该软件源由 Synapse 项目为 Debian 和 Ubuntu 维护。软件包版本每隔几周就会更新,因此本文不指定版本号。以下所有路径和选项均来自当前 Synapse 文档。

容量评估:1 vCPU 和 2 GB RAM 实际能满足什么需求

截至 2026 年 8 月,已发布的容量评估页面通常建议为 Synapse homeserver 配置 1 vCPU 和 2 GB RAM。对于以下场景,这个配置是合理的:私有服务器、少量用户、小型房间,且没有活跃的公共房间。Synapse 文档明确说明了另一种情况。文档要求:“如果要加入大型公共房间,例如 #matrix:matrix.org,至少需要 1GB 可用 RAM。”这里的可用 RAM 是在 Python、Postgres 和内核占用之外的内存。

一个房间就可能改变容量需求,因为加入房间的过程会产生持续负载。本地用户加入房间后,您的 homeserver 会成为该房间的完整参与者。它会从房间中的其他服务器接收该房间的每个事件,验证每个事件的签名,并在本地存储房间状态。大型公共房间可能有数千名成员,分布在数百台服务器上。因此,无论用户之后是否再次打开该房间,您的服务器都会持续执行这些操作。之后离开房间也不会删除已经存储的历史记录。

Synapse 的大部分 RAM 用于缓存。caches 部分包含一个 global_factor,可同时调整所有缓存;SYNAPSE_CACHE_FACTOR 环境变量也用于设置相同的值。提高该值会消耗更多 RAM,以减少数据库查询。降低该值会增加 CPU 和 Postgres 的负载,以节省 RAM。Postgres 也需要自己的内存,因此在 2 GB 服务器上,两者会竞争同一部分内存。

对于小型方案,请遵循两条实际建议。添加 swap:swap 不会让 Synapse 运行更快,但可以避免内核在执行大型加入操作期间终止该进程。然后从第一周开始监控磁盘,因为媒体存储和房间状态表会持续增长,没有固定上限,并且两者都存储在磁盘上。

为什么选择 Postgres,以及 SQLite 为什么不再适用

Debian 软件包默认使用 SQLite。这适合首次启动,但不适合供其他人使用的服务器。SQLite 同时只允许一个写入者。联邦流量和客户端请求会在同一时间执行写入,因此一个简单请求可能需要等待较慢的请求完成。用户看到的现象就是应用随机卡顿几秒。

第二个原因在于架构。Synapse 的 worker 进程是使用多个 CPU 核心的受支持方式,而 worker 要求使用 Postgres。继续使用 SQLite 不仅会牺牲性能,也会放弃后续的扩展路径。

之后再迁移仍受支持,但迁移期间需要停机,因此应在有用户之前完成。Synapse 自带 synapse_port_db,可将 SQLite 数据库复制到已准备好的 Postgres 数据库中:

synapse_port_db --sqlite-database homeserver.db --postgres-config homeserver-postgres.yaml

如果您希望在 Synapse 旁边的容器中运行数据库,请参阅在 Docker 中或主机上运行数据库,了解其中的取舍。

在 Ubuntu 24.04 上安装 Synapse

sudo apt install -y lsb-release wget apt-transport-https
sudo wget -O /usr/share/keyrings/matrix-org-archive-keyring.gpg https://packages.matrix.org/debian/matrix-org-archive-keyring.gpg
echo "deb [signed-by=/usr/share/keyrings/matrix-org-archive-keyring.gpg] https://packages.matrix.org/debian/ $(lsb_release -cs) main" | sudo tee /etc/apt/sources.list.d/matrix-org.list
sudo apt update
sudo apt install matrix-synapse-py3

在 Ubuntu 24.04 上,lsb_release -cs 的输出为 noble,而 matrix.org 软件源发布的是 noble 套件。不要使用 Ubuntu 自带软件仓库中的 matrix-synapse 软件包。Synapse 项目明确要求不要这样做,因为这些构建版本落后于其正式发布版本,并且存在已知安全漏洞。

安装程序会询问服务器名称,并将答案写入 /etc/matrix-synapse/conf.d/server_name.yaml。请谨慎填写。server_name 是每个用户 ID(@alice:example.com)中冒号后的部分,也会嵌入服务器创建的每个房间中。之后更改该值不会迁移任何内容,而是生成另一个主服务器。请使用不带前缀的域名 example.com,即使 Synapse 实际运行在 matrix.example.com 上。委派配置会连接这两者,下一节将介绍该配置。

该软件包以 matrix-synapse 用户身份运行 Synapse,将数据保存在 /var/lib/matrix-synapse 下,并读取 /etc/matrix-synapse/homeserver.yaml,随后读取 /etc/matrix-synapse/conf.d/ 中的每个文件。请将自定义设置写入 conf.d 下的小型文件中。软件包升级不会修改这些文件。

sudo systemctl restart matrix-synapse
systemctl status matrix-synapse
sudo journalctl -u matrix-synapse -n 100 --no-pager

正常启动后,监听器会启动,随后服务不再输出日志。systemd 单元会在服务退出几秒后重新启动它,因此,如果 Synapse 拒绝某项配置,该单元会表现为反复启动并退出。日志的最后几行会指出它拒绝的配置项。

将 Synapse 指向 Postgres

sudo apt install -y postgresql
sudo -u postgres createuser --pwprompt synapse_user
sudo -u postgres createdb --encoding=UTF8 --locale=C --template=template0 --owner=synapse_user synapse

区域设置不是无关紧要的细节。如果数据库创建时使用的 COLLATECTYPE 值不同,Synapse 将拒绝连接并启动,除非在数据库配置中设置 allow_unsafe_locale。文档规定的后续修复方法是将数据转储后重新加载到正确创建的数据库中。首次创建时就应使用正确的设置。

database:
  name: psycopg2
  txn_limit: 10000
  args:
    user: synapse_user
    password: secretpassword
    dbname: synapse
    host: localhost
    port: 5432
    cp_min: 5
    cp_max: 10

在所有配置文件中仅保留一个 database: 密钥。替换 homeserver.yaml 内的 SQLite 配置块,不要在 conf.d 下再添加一份副本,这样就不会无法确定实际生效的是哪一份配置。重启,然后确认 Synapse 确实使用了 Postgres:

sudo -u postgres psql synapse -c "SELECT count(*) FROM users;"

返回数字表示 Synapse 已在此数据库中创建架构。若出现缺少关系的错误,表示它仍在写入 SQLite 文件,因此你编辑的配置文件并不是实际读取的文件。

反向代理、TLS 与 federation 所需的 .well-known 文件

Synapse 在 localhost 上绑定并监听 8008 端口的纯 HTTP。TLS 和公网端口由前置的反向代理负责。

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

x_forwarded: true 会告知 Synapse 信任代理设置的 X-Forwarded-For 请求头。如果没有该配置,所有客户端看起来都来自 127.0.0.1,速率限制会将其视为一个非常繁忙的本地用户,并统一限制所有客户端。

location ~ ^(/_matrix|/_synapse/client) {
    proxy_pass http://localhost:8008;
    proxy_set_header X-Forwarded-For $remote_addr;
    proxy_set_header X-Forwarded-Proto $scheme;
    proxy_set_header Host $host:$server_port;
    client_max_body_size 50M;
    proxy_http_version 1.1;
}

Synapse 文档对这个代码块有一项警告,很多人因此浪费数天时间。不要在 proxy_pass 的端口后添加路径,即使只是单个 / 也不行。nginx 随后会规范化 URI,导致发送服务器签名的字节发生变化。这样 federation 请求会无法通过签名验证,但普通客户端请求仍可正常工作。

client_max_body_size 必须至少与 Synapse 的 max_upload_size 一样大。如果 nginx 设置了更小的值,超过该限制的上传会先被 nginx 以 413 Request Entity Too Large 拒绝,Synapse 根本看不到这些请求,因此其日志中不会有任何错误信息可供排查。

证书配置请参考 在 Ubuntu 24.04 上使用 Certbot 和 Let's Encrypt。如果还未确定使用哪种代理,请参阅 反向代理对比,了解由哪种代理负责 TLS。

委派可以让 server_name 保持为 example.com,同时让 Synapse 运行在 matrix.example.com。请从裸域提供以下两个文件:

location /.well-known/matrix/server {
    default_type application/json;
    return 200 '{"m.server": "matrix.example.com:443"}';
}

location /.well-known/matrix/client {
    default_type application/json;
    add_header Access-Control-Allow-Origin '*';
    return 200 '{"m.homeserver": {"base_url": "https://matrix.example.com"}}';
}

服务器文件会告知其他 homeserver 将 federation 流量发送到哪里。这使 federation 可以通过 443 运行,而不是使用默认的 8448 端口。客户端文件会告知 Matrix 客户端哪个 URL 提供 @alice:example.com。客户端文件中的 Access-Control-Allow-Origin 请求头很重要,因为基于浏览器的客户端会跨源获取该文件。如果没有此请求头,浏览器会阻止响应,客户端会报告找不到您的 homeserver。

两个文件都必须由 example.com 本身通过有效的 TLS 提供。先检查文件,再检查外部网络实际看到的内容:

curl -s https://example.com/.well-known/matrix/server
curl -s https://matrix.example.com/_matrix/federation/v1/version

第一个命令会返回您编写的 JSON。第二个命令会返回一个 JSON 对象,其中包含服务器实现及其版本,从而证明代理可以通过 federation 路径连接到 Synapse。然后通过 https://federationtester.matrix.org 中的 Matrix federation tester 检查该域名。该工具会沿着真实远程服务器使用的相同路径进行访问。

决定是否启用联邦:必须明确选择

联邦是 Matrix 的核心功能,也是主要成本来源。启用联邦的 homeserver 会接受来自陌生服务器的连接,接收它们的事件,缓存它们的媒体,并存储用户访问的每个房间的状态。这是威胁模型决策,不应默认启用。

如果用户需要联系其他 homeserver 上的用户,或选择 Matrix 的原因是需要可迁移的身份,则应启用联邦。如果服务器只服务于一个团队,且其中所有账户都由您管理,则不应启用联邦。封闭服务器存储的数据更少、接收的内容更少,也更不容易成为滥用目标。

如需限制联邦而不是完全禁用,Synapse 支持使用允许列表:

federation_domain_whitelist:
- lon.example.com
- nyc.example.com

文档还建议在防火墙中限制联邦监听器,使不需要的流量在网络层被阻止,而不是进入 Python。要完全关闭联邦,请从监听器 resources 列表中移除 federation,不要发布 /.well-known/matrix/server,并保持 8448 端口关闭。

如果运行 Matrix 的原因是提供私有团队聊天,而联邦从未属于需求的一部分,请在决定使用 Synapse 前,将运行成本与其他自托管 Slack 替代方案进行比较。使用 Docker Compose 部署 Rocket.Chat可以在配置更低的机器上提供团队聊天,因为它无需存储其他组织的房间状态。

媒体存储库会悄悄占满磁盘

您自己的用户上传的文件会永久保存在磁盘上。其他主服务器上的用户发布文件后,只要您的某个客户端显示这些文件,Synapse 就会将其获取并缓存到磁盘上。Synapse 还会为图像生成缩略图,因此一张照片会变成多个文件。默认情况下,这些内容都不会过期。

找到存储路径并测量其大小:

grep media_store_path /etc/matrix-synapse/homeserver.yaml
sudo du -sh /var/lib/matrix-synapse/media_store

测量您自己的配置输出的路径。Debian 软件包会将 Synapse 数据保存在 /var/lib/matrix-synapse 下,因此存储通常位于该路径。然后在 conf.d 中设置保留策略:

media_retention:
  local_media_lifetime: 90d
  remote_media_lifetime: 14d

仔细查看这两行,因为它们不是同一类型的设置。remote_media_lifetime 会使缓存过期,删除的内容可以从拥有该文件的服务器重新获取。local_media_lifetime 会在达到指定期限后永久删除您自己的用户上传的媒体文件。如果团队在聊天中共享文档,并希望明年还能找到这些文档,就会丢失它们。许多服务器只设置远程媒体的保留期限。

如需执行一次性清理,管理 API 接受以毫秒为单位的 Unix 时间戳:

BEFORE_TS=$(date -d '30 days ago' +%s%3N)
curl -X POST -H "Authorization: Bearer $ADMIN_TOKEN" \
  "https://matrix.example.com/_synapse/admin/v1/purge_media_cache?before_ts=$BEFORE_TS"

POST /_synapse/admin/v1/purge_media_cache 会删除最后访问时间早于该时间戳的远程媒体缓存。POST /_synapse/admin/v1/media/delete?before_ts=<ms> 会根据相同规则删除本地媒体。先执行远程清理,再次测量,因为在启用联邦的服务器上,远程缓存通常占较大部分。

以下两个设置都会影响同一块磁盘空间。max_upload_size 限制单个上传文件的大小,并且必须与 nginx 中的 client_max_body_size 保持一致。url_preview_enabled: true 会让服务器获取远程页面,使客户端能够显示链接预览,同时会占用带宽并存储您自己未上传内容的缩略图。

在有人发现您的 homeserver 前关闭注册

扫描器几天内就能发现开放的 homeserver。只要允许自由创建账户,您的服务器就会成为其联邦连接的每个房间中的垃圾信息来源,另一端的管理员还会封禁您的整个域名。这种声誉损害会持续到清理工作完成之后,因为封禁列表由人工维护。

Synapse 默认关闭注册。enable_registration 默认为 falseregistration_requires_token 默认为 false。如果启用注册却未配置验证步骤,Synapse 也会拒绝启动,除非您另外设置 enable_registration_without_verification: true。这是有意设计的保护机制,因此不要仅为消除启动错误就启用它。

手动创建所需账户:

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

该命令会提示您输入用户名、密码,以及是否将该账户设为服务器管理员。它会从通过 -c 传入的配置中读取 registration_shared_secret;如果提示找不到共享密钥,请将 -c 指向包含该密钥的文件。

当手动创建账户无法继续扩展时,可以使用注册令牌。注册令牌是新用户注册时必须提供的字符串,每个令牌还可以设置可使用的次数上限:

enable_registration: true
registration_requires_token: true
curl -X POST -H "Authorization: Bearer $ADMIN_TOKEN" \
  -H "Content-Type: application/json" \
  -d '{"uses_allowed": 1}' \
  https://matrix.example.com/_synapse/admin/v1/registration_tokens/new

省略 token 后,Synapse 会生成令牌并返回。GET /_synapse/admin/v1/registration_tokens 会列出当前有效的令牌。两个调用都需要服务器管理员账户的访问令牌。您可以使用上文创建的管理员用户登录来获取该令牌。

如果组织已在其他位置管理账户,则可以完全跳过本地密码,因为 Synapse 支持将登录委托给 OIDC(OpenID Connect)提供商,例如 作为自托管 SSO 提供商的 Authentik。这样,用户加入和离开组织都可在同一位置处理。

可真正重建服务器的备份

Synapse 备份包含 3 个部分,缺少其中任何一个,恢复出的服务器都无法使用。

  • Postgres 数据库,其中保存所有事件、账户和房间。
  • 媒体存储目录,其中保存所有上传的文件。
  • /etc/matrix-synapse,其中保存配置和服务器的签名密钥。

签名密钥最容易被遗忘。它是 homeserver 用于签署事件的私钥,远程服务器会使用匹配的公钥验证这些事件。运行 grep signing_key_path /etc/matrix-synapse/homeserver.yaml 查看密钥的存储位置。如果丢失该密钥,恢复出的服务器就无法证明自己仍是房间已知的那台服务器。

sudo -u postgres pg_dump --format=custom --file=/var/backups/synapse-$(date +%F).dump synapse
sudo tar czf /var/backups/synapse-etc-$(date +%F).tgz -C /etc matrix-synapse

先转储数据库,再复制媒体存储。媒体文件只会写入一次,并通过 ID 引用,因此在转储后执行媒体复制,最多只会多包含文件,不会漏掉文件。反过来操作时,恢复出的数据库可能会引用备份中没有捕获的文件。

将这 3 个部分全部发送到 VPS 之外的位置。使用具有异地快照的 restic 很适合这种备份结构,因为媒体存储占据较大空间,但运行之间几乎不会变化,去重功能可以让每个快照保持较小。

然后演练恢复流程,因为从未恢复过的备份只能算作假设。创建第二台 VPS,安装相同的软件包,恢复配置,使用相同的编码和区域设置创建数据库,将转储 pg_restore 到数据库中,复制回媒体存储,然后登录。记录整个过程耗时。这个时间就是实际恢复时间。

状态表增长后的处理:压缩

Synapse 将房间状态存储为状态组。在联邦服务器上,state_groups_state 通常会成为数据库中最大的对象。修改任何设置前,先进行测量:

sudo -u postgres psql synapse -c "SELECT pg_size_pretty(pg_database_size('synapse'));"
sudo -u postgres psql synapse -c "SELECT pg_size_pretty(pg_total_relation_size('state_groups_state'));"

如果该表占据了数据库的大部分空间,项目提供了用于压缩它的工具 rust-synapse-compress-state。该工具会将状态组层次结构重写为更少的行,但不会改变任何房间状态的含义。它使用 Rust 构建:

sudo apt install -y build-essential libssl-dev pkg-config git
curl --proto '=https' --tlsv1.2 -sSf https://sh.rustup.rs | sh
git clone https://github.com/matrix-org/rust-synapse-compress-state.git
cd rust-synapse-compress-state/synapse_auto_compressor
cargo build --release
./target/release/synapse_auto_compressor -p postgresql://synapse_user:secretpassword@localhost/synapse -c 500 -n 100

-c 表示每次处理的状态组数量,-n 表示本次运行处理的分块数量。自动压缩器会记录处理进度,因此下一次运行会从上次停止的位置继续。这使它适合安排为定时任务。其文档说明,修改会在针对追加式表的事务中应用,因此可以在 Synapse 运行期间执行。无论如何,首次运行前都应备份数据库。

这里有一个容易让人意外的 Postgres 细节。删除行后,释放的空间会返回给 Postgres 供其重用,而不会返回给文件系统。因此,大规模压缩后,df 可能完全不会变小。VACUUM FULL 才会将空间返还给文件系统,但它会对表加排他锁,并且需要大约等于该表大小的可用磁盘空间。因此,应将其安排在维护时段执行,而不要临时运行。

判断服务器是否健康的检查

systemctl status matrix-synapse
curl -s https://example.com/.well-known/matrix/server
curl -s https://matrix.example.com/_matrix/federation/v1/version
sudo -u postgres psql synapse -c "SELECT pg_size_pretty(pg_database_size('synapse'));"
sudo du -sh /var/lib/matrix-synapse/media_store

健康状态是指单元处于 active 状态且未反复重启,delegation 文件返回您的 m.server 值,联邦版本端点返回 JSON,并且可以将两个大小数值与上个月的数值进行比较。大小检查最容易被忽略,而磁盘空间耗尽会在没有任何警告的情况下导致 Synapse 服务器停止运行:卷空间用尽后,Postgres 无法继续写入,随后 Synapse 处理每个需要访问数据库的请求时都会失败。

FAQ

Matrix Synapse 服务器需要多少 RAM?

对于只有少量用户、使用小型房间且没有大型公共房间的私有 homeserver,2 GB 通常够用。截至 2026 年 8 月,大多数已发布的容量规划页面都建议使用这一配置。如果用户要加入 #matrix:matrix.org 等大型公共房间,Synapse 文档要求在其他内存需求之外,至少额外保留 1 GB 空闲 RAM,因为服务器需要存储该房间的状态并持续处理其流量。在 2 GB 方案上添加 swap,避免某个大型加入操作导致内核终止该进程。

我必须使用 PostgreSQL,而不能使用 SQLite 吗?

当用户超过少数几人后,是的。SQLite 一次只能有一个写入者,因此负载升高时,联邦流量和客户端请求会相互阻塞,请求可能每次挂起数秒。Synapse 的 worker 进程是使用多个 CPU 核心的受支持方式,而它要求使用 Postgres。之后再迁移可以使用 synapse_port_db,但需要停机,因此应在创建用户前通过 --encoding=UTF8 --locale=C --template=template0 创建数据库。

为什么我的 Synapse 磁盘使用量一直增长?

主要涉及一个目录和一张表。媒体存储会保留服务器所在房间中上传的每个文件,包括远程用户媒体的缓存副本和生成的缩略图;除非设置 media_retention,否则这些内容不会过期。对于启用联邦的服务器,state_groups_state 表会随着房间状态增长,而 rust-synapse-compress-state 可以减小其大小。在决定处理哪一项之前,先使用 du -sh 检查 media_store_path,并使用 SELECT pg_size_pretty(pg_total_relation_size('state_groups_state')); 检查两者的占用量。

如何阻止陌生人在我的 homeserver 上注册?

enable_registration 保持为默认值 false,并使用 register_new_matrix_user 创建账户。无法继续扩展时,同时设置 enable_registration: trueregistration_requires_token: true,并分发通过 POST /_synapse/admin/v1/registration_tokens/new 创建的令牌。不要仅为绕过 Synapse 启动时的拒绝而设置 enable_registration_without_verification: true,因为开放的 homeserver 会成为垃圾邮件来源,其他管理员可能因此屏蔽你的整个域名。

我的 homeserver 应该启用联邦吗?

联邦是一个关于暴露范围的决定,不应默认启用。如果用户需要联系其他 homeserver 上的用户,则启用联邦。如果服务器只服务于一个团队,则关闭联邦,因为非联邦服务器存储的数据更少、接收的流量更少,也更不容易受到滥用。在两者之间,可以使用 federation_domain_whitelist 将联邦限制为指定的合作伙伴域名。Synapse 文档还建议通过防火墙限制联邦监听器,而不要只依赖应用层检查。

#matrix#synapse#自托管#postgresql#federation