在 Archlinux 服务器上安装 dendrite

本文最后更新于 2022年7月5日 凌晨

摘自维基百科:

Matrix是一种用于实时通信的开放协议。它允许拥有一个通信服务提供商帐户的用户与不同服务提供商的用户进行网络聊天IP语音视频通话。也就是说,它旨在使不同服务提供商之间的实时通信无缝工作,就像使用电子邮件一样。采用该协议的软件有Element.io等。

最近我一直想部署一个 Matrix 服务端。然后就了解到了 Dendrite.

Dendrite 是基于 Go 的第二代 Matrix 客户端,性能比用Python编写的Synapse服务器强。

本文参考了官方的部署教程.

安装

总共三个步骤:

  1. 安装 nats-server
  2. 安装 postgresql
  3. 安装 dendrite

安装 nats-server

本步骤可以省略,dendrite 会使用内置的 nats-server

1
yay -S nats-server

然后编辑 nats-serverservice 文件

1
sudo systemctl edit --full nats-server.service

ExecStart 行修改为(加上 -js)

1
ExecStart=/usr/bin/nats-server -js --pid /run/nats-server.pid --syslog --http_port 8222

然后启动 nats-server并加入开机自启。

1
sudo systemctl enable --now nats-server

安装 PostgreSQL

直接用 yay 安装数据库

1
yay -S postgresql

接着初始化数据库

1
sudo su - postgres -c "initdb --locale en_US.UTF-8 -D '/var/lib/postgres/data'"

启动 postgresql 服务

1
sudo systemctl enable --now postgresql

再创建 dendrite 使用的数据库用户,并输入密码(假设叫 PASSWORD),记得密码不要包含特殊字符,比如(#),否则会导致 config.yaml 解析出错。然后顺便创建对应的数据库。

1
2
sudo -u postgres createuser -P dendrite
sudo -u postgres createdb -O dendrite dendrite

安装 Dendrite

每一个 dendrite 安装都需要

  • 一个唯一的 Matrix 签名私钥
  • 一个有效、被信任的TLS证书和私钥

安装 dendrite

1
yay -S dendrite

首先我们生成一个 Matrix 签名私钥

1
dendrite-generate-keys --private-key matrix_key.pem

注意: 保管好这个私钥,在同一个域名下重新安装 dendrite(或者其他 Matrix 服务端) 的时候,你会需要这个 key。如果失去了这个 key, 你在加入federated rooms 的时候会遇到问题。

TLS 证书那条没看懂,先忽略。

之后就是生成配置文件,如果你是一个熟练工的话,我建议你将/etc/dendrite/config-example.yaml复制为 /etc/dendrite/config.yaml,而不是使用 dendrite-generate-config

如果你是一个新手,Archlinux 有个很棒的脚本叫做 dendrite-generate-config,我们看一下它的用法

1
dendrite-generate-config -h
1
2
3
4
5
6
7
Usage of dendrite-generate-config:
-ci
sane defaults for CI testing
-db string
The DB URI to use for all components if not SQLite files
-server string
The domain name of the server if not 'localhost'

因此,我们用如下命令来生成配置文件,注意把 PASSWORD 替换为你的 dendrite 数据库用户密码。把 askk.cc 替换为你准备用来提供服务的域名。

1
dendrite-generate-config -db 'postgres://dendrite:PASSWORD@localhost/dendrite?sslmode=disable' -server askk.cc >config.yaml

然后我们看一下默认的配置, 运行 cat config.yaml (如果你想使用完整的配置进行修改,参考 dendrite sample config)

然后将配置文件复制到 /etc/dendrite,私钥复制到 /var/lib/dendrite, 并修正权限

1
2
3
sudo cp config.yaml /etc/dendrite
sudo cp matrix_key.pem /var/lib/dendrite
sudo chown -R dendrite:dendrite /var/lib/dendrite

接着添加其他的 key_perspectives 找到对应的行,直接修改,注意缩进。进行这一步是因为默认的 matrix.org 连不上,但是 archlinux.orgmozilla.org 是可以从国内连上的。

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
key_perspectives:
- server_name: matrix.org
keys:
- key_id: ed25519:auto
public_key: Noi6WqcDj0QmPxCNQqgezwTlBKrfqehY1u2FyWP9uYw
- key_id: ed25519:a_RXGa
public_key: l8Hft5qXKn1vfHrg3p4+W8gELQVo8N13JkluMfmn2sQ
- server_name: archlinux.org
keys:
- key_id: ed25519:a_KKNB
public_key: eO1SdnG7CjsIQ/bPaD7k5kwD8CSvYkzHNdhot4gp1Xg
- server_name: mozilla.org
keys:
- key_id: ed25519:0
public_key: RsDggkM9GntoPcYySc8AsjvGoD0LVz5Ru/B/o5hV9h4
prefer_direct_fetch: true

如果你想添加其他的 服务器,需要自己获取 public_key 方式如下

访问 Matrix Federation Tester, 输入 你想添加的域名,比如 matrix.org, 测试完成后找到最下面的 View the json report.

在新打开的页面你就能够找到 verify_keys 那里就有你需要的 public_key 以及 key_id.

附上一个我的配置。各种密码已经隐掉,Github gist.

然后就可以开启自启动并立即启动啦。

1
sudo systemctl enable --now dendrite

看一下是否启动成功

1
systemctl status dendrite

成功的话,会有类似如下的输出

1
2
3
4
5
6
7
8
9
10
Feb 28 23:26:45 tencent-arch dendrite[961838]: [961838] [INF]
Feb 28 23:26:45 tencent-arch dendrite[961838]: [961838] [INF] ---------------- JETSTREAM ----------------
Feb 28 23:26:45 tencent-arch dendrite[961838]: [961838] [INF] Max Memory: 2.87 GB
Feb 28 23:26:45 tencent-arch dendrite[961838]: [961838] [INF] Max Storage: 41.82 GB
Feb 28 23:26:45 tencent-arch dendrite[961838]: [961838] [INF] Store Directory: "/var/cache/dendrite/jetstream"
Feb 28 23:26:45 tencent-arch dendrite[961838]: [961838] [INF] -------------------------------------------
Feb 28 23:26:45 tencent-arch dendrite[961838]: [961838] [INF] Server is ready
Feb 28 23:26:45 tencent-arch dendrite[961838]: time="2022-02-28T15:26:45.596884493Z" level=info msg="Enabled perspective key fetcher" num_public_keys=2 se>
Feb 28 23:26:45 tencent-arch dendrite[961838]: time="2022-02-28T15:26:45.623562213Z" level=info msg="Enabling server notices at /_synapse/admin/v1/send_se>
Feb 28 23:26:45 tencent-arch dendrite[961838]: time="2022-02-28T15:26:45.664262183Z" level=info msg="Starting external Monolith listener on :8008"

Dendrite 走代理

假设你已经在服务器上配置好了代理,比如说 v2raya, 但是你显然不想进行透明代理,只想代理 dendrite,这时候,我们为 dendrite 的 systemd 服务添加环境变量即可。

1
sudo systemctl edit --full dendrite

[service] 部分添加 Environment 开头的两行。

1
2
3
4
5
6
[Service]
User=dendrite
Environment=https_proxy=127.0.0.1:20172
Environment=http_proxy=127.0.0.1:20172
ExecStart=/usr/bin/dendrite --config=/etc/dendrite/config.yaml
WorkingDirectory=/var/lib/dendrite/

改好之后重载 systemd 服务文件并重启 dendrite,运行

1
2
sudo systemctl daemon-reload
sudo systemctl restart dendrite

添加 Nginx 配置

Github 的说明真是不够详细,nginx 的配置还要自己找。

我们先进入 Nginx 存放配置的文件夹 (没有的话可以先创建)

1
cd /etc/nginx/conf.d

写入配置文件

1
sudo vim dendrite.conf

写入以下内容 (粘贴自 monolith-sample.conf ), 注意修改域名为你自己的域名,比如我的 matrix.askk.cc, ssl 那四行删除掉,待会我们用 certbot 来生成证书。
在这里, matrix.askk.cc 是我的 well-known server, askk.cchomeserver,如果你不区分两者,直接将它们改成你在 dendrite 的配置文件里面写的就可以了。 # managed by Certbot 表示是由certbot 生成的部分,可以不用全部自己写,但是最少要写一个 listen 80;certbot 会帮你改成下面那样子。

注意: 我添加了那两行 default_type application/json;

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
upstream monolith {
server 127.0.0.1:8008;
}
server {
server_name matrix.askk.cc;
listen [::]:443 ssl; # IPv6

proxy_set_header Host $host;
proxy_set_header X-Real-IP $remote_addr;
proxy_read_timeout 600;

location /.well-known/matrix/server {
default_type application/json;
return 200 '{ "m.server": "matrix.askk.cc:443" }';
}
location /.well-known/matrix/client {
# If your sever_name here doesn't match your matrix homeserver URL
# (e.g. hostname.com as server_name and matrix.hostname.com as homeserver URL)
default_type application/json;
add_header Access-Control-Allow-Origin '*'; # 如果你 well-known server 与 homeserver 不同,就需要这行。
return 200 '{ "m.homeserver": { "base_url": "https://askk.cc" } }';
}

location /_matrix {
proxy_pass http://monolith;
}

listen 443 ssl; # managed by Certbot
ssl_certificate /etc/letsencrypt/live/matrix.askk.cc/fullchain.pem; # managed by Certbot
ssl_certificate_key /etc/letsencrypt/live/matrix.askk.cc/privkey.pem; # managed by Certbot
include /etc/letsencrypt/options-ssl-nginx.conf; # managed by Certbot
ssl_dhparam /etc/letsencrypt/ssl-dhparams.pem; # managed by Certbot
}

server {
if ($host = matrix.askk.cc) {
return 301 https://$host$request_uri;
} # managed by Certbot
server_name matrix.askk.cc;
listen 80;
return 404; # managed by Certbot
}

接下来安排 ssl, 首先安装 certbot

1
yay -S certbot

运行 certbot

1
sudo certbot

输入对应你域名的序号,回车。看到类似如下的输出就说明成功了

1
2
3
4
5
6
7
8
9
10
11
12
Successfully received certificate.
Certificate is saved at: /etc/letsencrypt/live/askk.cc/fullchain.pem
Key is saved at: /etc/letsencrypt/live/askk.cc/privkey.pem
This certificate expires on 2022-05-30.
These files will be updated when the certificate renews.

Deploying certificate
Successfully deployed certificate for askk.cc to /etc/nginx/conf.d/dendrite.conf
Congratulations! You have successfully enabled HTTPS on https://askk.cc

NEXT STEPS:
- The certificate will need to be renewed before it expires. Certbot can automatically renew the certificate in the background, but you may need to take steps to enable that functionality. See https://certbot.org/renewal-setup for instructions.

检查一下 dendrite.conf

1
cat nginx.conf

你会发现末尾多了两行

1
2
ssl_certificate /etc/letsencrypt/live/askk.cc/fullchain.pem; # managed by Certbot
ssl_certificate_key /etc/letsencrypt/live/askk.cc/privkey.pem; # managed by Certbot

但是!我们的示例配置里明明有三行,我们还要生成另一个文件(这里参考 certbot using weak diffie hellman encryption)

执行

1
sudo openssl  dhparam -out  /etc/letsencrypt/dhparams.pem 2048

然后在 编辑dendrite.conf

1
sudo vim dendrite.conf

在前两行 ssl 下面加入

1
ssl_dhparam /etc/letsencrypt/dhparams.pem;

最后检查 dendrite.conf

1
cat dendrite.conf

你的 dendrite.conf 看起来像这样 (注意最后三行。)

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
#change IP to location of monolith server
upstream monolith{
server 127.0.0.1:8008;
}
server {
listen 443 ssl; # IPv4
listen [::]:443 ssl; # IPv6
server_name askk.cc;


proxy_set_header Host $host;
proxy_set_header X-Real-IP $remote_addr;
proxy_read_timeout 600;

location /.well-known/matrix/server {
return 200 '{ "m.server": "askk.cc:443" }';
}

location /.well-known/matrix/client {
# If your sever_name here doesn't match your matrix homeserver URL
# (e.g. hostname.com as server_name and matrix.hostname.com as homeserver URL)
# add_header Access-Control-Allow-Origin '*';
return 200 '{ "m.homeserver": { "base_url": "https://askk.cc" } }';
}

location /_matrix {
proxy_pass http://monolith;
}

ssl_certificate /etc/letsencrypt/live/askk.cc/fullchain.pem; # managed by Certbot
ssl_certificate_key /etc/letsencrypt/live/askk.cc/privkey.pem; # managed by Certbot
ssl_dhparam /etc/letsencrypt/dhparams.pem;
}

现在我们就算设置好了,重启 nginx 然后看下是否成功

1
2
sudo systemctl restart nginx
sudo systemctl status nginx

如果有 绿色的 Active: active (running) 字样说明可以了。

使用不同于 homeserver 的 well known server

这件事的意义在于这里,由于我的 homeserver 叫 matrix.askk.cc , 所以在我的服务器注册的用户都会叫做 @xxx:matrix.askk.cc 这样其实不是很方便,我们也许希望用户叫做 @xxx:askk.cc. 但是我们可能已经把 askk.cc 拿来搭建网站了(44380已经被使用了。所以要使用其他的 well known server )

下面我们假设我的 homeserver 叫 askk.cc(即注册用户叫 @xxx:askk.cc), well known server 叫 matrix.askk.cc


如果你想要使用的 homeserver 与 well-know-server不同(说人话就是 matrix.org 的 well known server 是 matrix-federation.matrix.org

你需要修改 /etc/dendrite/config.yaml,比如我希望 well know server 是 matrix.askk.cc

1
well_known_server_name: "matrix.askk.cc"

同时你需要修改 nginx 的页面配置为如下的部分(只放了主要的部分,删除了 ssl 等配置,自己补上)。

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
server
{
server_name matrix.askk.cc;
listen 443 ssl; # IPv6
listen [::]:443 ssl; # IPv6


proxy_set_header Host $host;
proxy_set_header X-Real-IP $remote_addr;
proxy_read_timeout 600;

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

location /.well-known/matrix/client
{
# If your sever_name here doesn't match your matrix homeserver URL
# (e.g. hostname.com as server_name and matrix.hostname.com as homeserver URL)
default_type application/json;
add_header Access-Control-Allow-Origin '*';
return 200 '{ "m.homeserver": { "base_url": "https://askk.cc" } }';
}
# 访问 / 手动返回404
location /
{
return 404;
}

同时我们给 askk.cc 的 nginx 的配置文件加上如下片段

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
server{
# 其他部分
## matrix
listen 8448 ssl;
listen [::]:8448 ssl;
location /_matrix {
proxy_pass http://matrix.askk.cc:8008;
#proxy_pass http://127.0.0.1:8008;
proxy_set_header X-Forwarded-For $remote_addr;
}
location /.well-known/matrix/server {
default_type application/json;
return 200 '{ "m.server": "matrix.askk.cc:443" }';
}

location /.well-known/matrix/client {
# If your sever_name here doesn't match your matrix homeserver URL
# (e.g. hostname.com as server_name and matrix.hostname.com as homeserver URL)
default_type application/json;
add_header Access-Control-Allow-Origin '*';
return 200 '{ "m.homeserver": { "base_url": "https://askk.cc" } }';
}
# 其他部分
}

测试结果

https://federationtester.matrix.org/ 输入自己的的域名(askk.cc) 测试一下

如果 checks 显示緑色的 Success 就说明成功啦!

备份与迁移

由于国内的服务器连接不到 matrix.org, 我在服务器上面挂了代理,但是 Nick Cao 老师建议部署到 境外的服务器上。于是我就开始迁移到 Oracle 的服务器上。

系统还是arch, 所以照常安装。不过 matrix_key.pem 用之前的就是。数据库密码也尽量用一样的。部署好之后导入 postgresql 的数据库就行,原本的用户也还在。

postgresql 可以不用跟着迁移,只要在新服务器上改下对应的 dendrite 配置文件的连接密码即可,但是这样的话,我们需要对 postgresql 进行一些配置,参见

Configure PostgreSQL to be accessible from remote hosts

先在旧服务器上导出数据。先停止 dendrite, 然后切到 root 来导出数据。

1
2
3
sudo systemctl disable --now dendrite
sudo su
pg_dump -U postgres -F c dendrite > db1.tar

把旧服务器上的数据库传到本地

1
rsync -chavzP -e "ssh -p 3456 -i ~/.ssh/tencent-arch" sukanka@a.sukanka.com:~/db1.tar /tmp/www

把本地的数据库传到新服务器上。

1
rsync -chavzP -e "ssh -p 1234 -i ~/.ssh/oracle" /tmp/www  sukanka@oarch.sukanka.com:~/db1.tar

在新服务器上面停止 Dendrite,然后切到 postgres.运行

1
2
3
4
sudo systemctl stop dendrite
sudo su
su postgres
dropdb dendrite

退回到普通用户,恢复数据

1
pg_restore -U postgres -d dendrite -1  db1.tar

还要备份旧服务器上缓存的媒体文件,并恢复到新服务器上,不然新服务器上会找不到有的媒体文件。

下面是在旧服务器上的操作

1
2
3
sudo su
cd /var/lib/dendrite
tar -czvf /home/sukanka/media.tar.gz media_store

然后在把压缩包下载到本地服务器并上传到新服务器

1
2
rsync -chavzP -e "ssh -p 3456 -i ~/.ssh/tencent-arch" sukanka@a.sukanka.com:~/media.tar.gz /tmp/media.tar.gz
rsync -chavzP -e "ssh -p 1234 -i ~/.ssh/oracle" /tmp/media.tar.gz sukanka@oarch.sukanka.com:~/media.tar.gz

在新服务器上恢复数据

1
2
3
4
sudo su
cp media.tar.gz /var/lib/dendrite
cd /var/lib/dendrite
tar -xvf media.tar.gz media_store

新服务器上重新启动 dendrite

1
sudo systemctl start dendrite

注意

如果你同时搞了 bridge, 记得把桥的数据库也备份下来。

桥接 tg

安装 AUR 上的 mautrix-telegram 包,改好配置文件。另外记得把 dendrite 加入到 mautrix-telegram 组。

1
usermod -a -G mautrix-telegram dendrite

首先我们还是要为 mautrix-telegram 创建一个 postgres 用户与数据库

1
2
sudo -u postgres createuser -P mautrix-telegram
sudo -u postgres createdb -O mautrix-telegram mautrix-telegram

创建用户的时候,密码与 dendrite 用户的一样就行。

然后把数据库链接写入配置文件。

改配置文件的时候记得 address 填 well-known server, domainhomeserver, 例如我的 homeserveraskk.cc(即用户为 @user:askk.cc), 但是 well-known server 为 matrix.askk.cc,则按照如下填写。

1
2
3
4
# The address that this appservice can use to connect to the homeserver.
address: https://matrix.askk.cc
# The domain of the homeserver (for MXIDs, etc).
domain: askk.cc

改好配置文件之后,运行下面的命令,生成 registration.yaml

1
2
cd /etc/mautrix-telegram
sudo -u mautrix-telegram python -m mautrix_telegram -g

如果你服务器在国内,可能你还需要为它设置代理,修改mautrix-telegramconfig.yaml,这部分改成如下的样子(直接搜索 proxy), 然后端口这些根据你的情况自己填。同时记得安装 PySocks

1
2
3
4
5
6
7
8
9
...
proxy:
# Allowed types: disabled, socks4, socks5, http, mtproxy
type: socks5
# Proxy IP address and port.
address: 127.0.0.1
port: 20170
...

1
yay -S python-pysocks

记得重新生成 registration.yaml

最后修改 dendrite 的配置文件(在 /etc/dendrite/config.yaml),加入最下面一行。最后重启 dendritemautrix-telegram 即可。

1
2
3
4
5
6
7
8
9
10
11
12
app_service_api:
internal_api:
listen: http://localhost:7777
connect: http://localhost:7777
database:
connection_string: postgres://dendrite:E3f4zM4fMhWvsv@localhost/dendrite?sslmode=disable
max_open_conns: 5
max_idle_conns: 2
conn_max_lifetime: -1
disable_tls_validation: false
config_files:
- /etc/mautrix-telegram/registration.yaml

与 mastodon 共用主域名

与在另一个服务器上的 mastodon 共用同一个主域名,参见 在同一域名下部署 mastodon 与 matrix


在 Archlinux 服务器上安装 dendrite
https://blog.askk.cc/2022/02/28/deploy-dendrite/
作者
sukanka
发布于
2022年2月28日
许可协议