前情提要

20240924更新:推荐使用客户端:FluffyChat,地址:https://fluffychat.im/ (安卓不要下载Element!!!)

之前部署了 Tailchat,但是我没找到官方对于加密方式和安全性这方面的说明,所以又发现了一个 Matrix,这个也是开源的,并且支持 E2E 加密,会更安全

https://blog.imbhj.com/archives/qbm6zs6S

部署

首先拉取镜像:

建议先拉取镜像,等会还得生成配置文件,会方便一点。

docker pull docker.io/matrixdotorg/synapse:latest
docker pull docker.io/postgres:12-alpine
docker pull docker.io/vectorim/element-web:latest

docker-compose.yaml

# This compose file is compatible with Compose itself, it might need some
# adjustments to run properly with stack.

# version: '3'

services:

  synapse:
    # build:
    #   context: ../..
    #   dockerfile: docker/Dockerfile
    image: docker.io/matrixdotorg/synapse:latest
    # Since synapse does not retry to connect to the database, restart upon
    # failure
    restart: unless-stopped
    # See the readme for a full documentation of the environment settings
    # NOTE: You must edit homeserver.yaml to use postgres, it defaults to sqlite
    environment:
      - SYNAPSE_CONFIG_PATH=/data/homeserver.yaml
    volumes:
      # You may either store all the files in a local folder
      - ./files:/data
      # - ./homeserver.yaml:/data/homeserver.yaml
      # .. or you may split this between different storage points
      # - ./files:/data
      # - /path/to/ssd:/data/uploads
      # - /path/to/large_hdd:/data/media
    depends_on:
      - db
      - element
    # In order to expose Synapse, remove one of the following, you might for
    # instance expose the TLS port directly:
    ports:
    #  - 8448:8448
    # ... or use a reverse proxy, here is an example for traefik:
      - 8080:8008
    labels:
      # The following lines are valid for Traefik version 1.x:
    #   - traefik.enable=true
    #   - traefik.frontend.rule=Host:my.matrix.Host
    #   - traefik.port=8008
      # Alternatively, for Traefik version 2.0:
      - traefik.enable=true
      - traefik.http.routers.http-synapse.entryPoints=http
      - traefik.http.routers.http-synapse.rule=Host(`e2e.imbhj.com`)
      - traefik.http.middlewares.https_redirect.redirectscheme.scheme=https
      - traefik.http.middlewares.https_redirect.redirectscheme.permanent=true
      - traefik.http.routers.http-synapse.middlewares=https_redirect
      - traefik.http.routers.https-synapse.entryPoints=https
      - traefik.http.routers.https-synapse.rule=Host(`e2e.imbhj.com`)
      - traefik.http.routers.https-synapse.service=synapse
      - traefik.http.routers.https-synapse.tls=true
      - traefik.http.services.synapse.loadbalancer.server.port=8008
      - traefik.http.routers.https-synapse.tls.certResolver=le-ssl

  db:
    image: docker.io/postgres:12-alpine
    # Change that password, of course!
    ports:
      - 5432:5432
    environment:
      - POSTGRES_USER=synapse
      - POSTGRES_PASSWORD=xxxxxxxxx
      # ensure the database gets created correctly
      # https://element-hq.github.io/synapse/latest/postgres.html#set-up-database
      - POSTGRES_INITDB_ARGS=--encoding=UTF-8 --lc-collate=C --lc-ctype=C
    volumes:
      # You may store the database tables in a local folder..
      - ./schemas:/var/lib/postgresql/data
      # .. or store them on some high performance storage for better results
      # - /path/to/ssd/storage:/var/lib/postgresql/data

  element:
    image: docker.io/vectorim/element-web:latest
    ports:
      - 8888:80
    volumes:
      - ./element-web/config.json:/app/config.json

注意更改数据库密码以及对应的配置项里的 服务域名或 IP 地址

然后在当前目录下执行:

docker-compose run --rm -e SYNAPSE_SERVER_NAME=my.matrix.host -e SYNAPSE_REPORT_STATS=no synapse generate

my.matrix.host 要更改为自己要部署的域名或 IP 地址,不带 http 前缀。

生成完毕之后,进入 ./files 目录下,找到 homeserver.yaml 文件,修改:

# Configuration file for Synapse.
#
# This is a YAML file: see [1] for a quick introduction. Note in particular
# that *indentation is important*: all the elements of a list or dictionary
# should have the same indentation.
#
# [1] https://docs.ansible.com/ansible/latest/reference_appendices/YAMLSyntax.html
#
# For more information on how to configure Synapse, including a complete accounting of
# each option, go to docs/usage/configuration/config_documentation.md or
# https://element-hq.github.io/synapse/latest/usage/configuration/config_documentation.html
server_name: "e2e.imbhj.com"
pid_file: /data/homeserver.pid
listeners:
  - port: 8080
    tls: false
    type: http
    x_forwarded: true
    resources:
      - names: [client, federation]
        compress: false
database:
  name: psycopg2
  args:
    # database: /data/homeserver.db
    user: synapse
    password: xxxxxxxxx
    dbname: synapse
    host: x.x.x.x
    cp_min: 5
    cp_max: 10
    # seconds of inactivity after which TCP should send a keepalive message to the server
    keepalives_idle: 10
    # the number of seconds after which a TCP keepalive message that is not
    # acknowledged by the server should be retransmitted
    keepalives_interval: 10
    # the number of TCP keepalives that can be lost before the client's connection
    # to the server is considered dead
    keepalives_count: 3
log_config: "/data/自动生成.log.config"
media_store_path: /data/media_store
registration_shared_secret: "自动生成"
enable_registration: true       # 是否允许注册
registration_requires_token: true  # 注册是否需要token
report_stats: false
macaroon_secret_key: "自动生成"
form_secret: "自动生成"
signing_key_path: "/data/自动生成.signing.key"
trusted_key_servers:
  - server_name: "matrix.org"


# vim:ft=yaml

自动生成 的部分不用管,记得修改数据库用户/密码和 docker-compose.yml 文件一致,设置好数据库 IP,如果是本地就填本地 IP 即可。

回到项目根目录,创建 ./element-web/config.json 文件,写入:

{
    "default_server_name": "imbhj.com",
    "default_server_config": {
        "m.homeserver": {
            "base_url": "https://e2e.imbhj.com"
        },
        "m.identity_server": {
            "base_url": "https://vector.im"
        }
    }
}

注意修改自己的域名即可,服务域名和 element 的客户端域名是不同的

然后执行 docker-compose up -d 启动容器

创建管理员账户

容器启动起来之后,执行命令:

docker exec -it synapse register_new_matrix_user http://localhost:8008 -c /data/homeserver.yaml --help

如果使用 1panel 面板进入容器终端,则可忽略命令前缀 docker exec -it synapse

注意修改地址为自己的服务地址。

这是命令帮助,提示你如何操作,接下来这一行才是生成管理员账户的操作:

docker exec -it synapse register_new_matrix_user http://localhost:8008 -c /data/homeserver.yaml -a

执行之后会在终端提示你输入管理员的用户名及密码,创建完毕。

注册普通账户

首先确保 homeserver.yaml 文件中开启了下面两个配置:

enable_registration: true       # 是否允许注册
registration_requires_token: true  # 注册是否需要token

之后我们需要生成一个 token,以便其他用户注册时作为校验。synapse 服务端提供了一个 admin api 用来生成 token,但实际使用上略微麻烦。经过查找发现已经有人将 admin api 封装成了页面管理端 synapse-admin

这个管理端只是一个前端,其已经部署了一个到 GitHub Pages 上,我们在填入我们的管理员用户名、密码以及我们服务的地址后就可以直接使用了。

仓库地址:

https://github.com/Awesome-Technologies/synapse-admin

直接访问地址:

https://awesome-technologies.github.io/synapse-admin/

20240923215921.png

然后使用刚才在终端创建的用户名和密码登录

创建 token :

20240923220108.png

  • Token,这里填入我们想创建的 token 内容,允许为空。

  • Length,在 Token 字段为空的情况下,需要填入 Length,会自动生成一个指定长度的随机 token 值。

  • Uses allowed,允许 token 使用多少次,填 null(不填)则是无限次。

  • Expiry time,token 的过期时间,填 null(不填)则是没有过期时间。

然后就可以访问 element 客户端进行注册了,注册时填入这个 token 即可。

本文中部署的是 element-web 客户端,还有其他很多客户端,如下:

https://matrix.org/ecosystem/clients/

推荐使用客户端:FluffyChat,地址:https://fluffychat.im/

当用户第一次注册并登录后,客户端会提示备份密钥。这里非常建议将密钥导出并备份下来。

基于 matrix 协议的通信是端对端加密的,即除了你和对方外,整个链路上的所有人都无法看到你们交流的消息。要解密消息便需要这个密钥,如果这个密钥丢失,那么新登录的客户端将无法解密历史的所有消息数据。同样,如果这个密钥泄露,掌握服务器的人也可以通过这个密钥解密你的所有消息。

在对应的客户端的设置里都可以进行密钥的导出或者备份,务必保管好自己的密钥。

Element安卓端无法登录

如图所示:

20240923223826.png

不要慌,这不是配置有问题,单纯的网络问题,多刷新几次,多登陆几次就可以了

element-web 端也是,如果打开是白屏,那么只是网络问题导致资源没加载出来,刷新一下就好了。

20240926更新

需要跨服聊天,那么必须在 homeserver.yamldocker-compose.yaml 文件中使用 8448 端口以及 https 协议

本文是内网穿透部署,但是解决跨服聊天的思路是一样的,官方的配置说明中,跨服聊天要么直接访问 server_name:8448 端口走 https 协议,要么使用 .well-known/matrix/server 重新定向到 443 端口走 https 协议

建议使用第二种,需要在 homeserver.yaml 文件中开启选项 serve_server_wellknown: true ,下面会放出整个配置文件

对于移动端的跨服聊天,如果自己私服的服务器配置不行,或者 IP 纯净度不够(国内情况),

  • 可能会导致聊天记录拉取非常慢,或者失败

  • 可能会网络波动导致丢失部分聊天记录,无法解密

  • 可能会网络波动导致房间或者私聊无法验证双方加密设备是否可靠

客户端、web 端如果要邀请、搜索用户,必须直接粘贴完整的 ID,否则会导致搜索不到,完整的 ID 例如:

用户:@luobo:e2e.imbhj.com

聊天室:#test:e2e.imbhj.com

当然,只是概率性问题,我实测是可以跨服邀请、私聊、公共聊天频道的,但是目前这种部署方式无法实现语音通话和视频通话,官方文档里说需要部署中转服务器,后续再慢慢解决吧

最后放上我自己踩坑更新后的配置文件:

homeserver.yaml

# Configuration file for Synapse.
#
# This is a YAML file: see [1] for a quick introduction. Note in particular
# that *indentation is important*: all the elements of a list or dictionary
# should have the same indentation.
#
# [1] https://docs.ansible.com/ansible/latest/reference_appendices/YAMLSyntax.html
#
# For more information on how to configure Synapse, including a complete accounting of
# each option, go to docs/usage/configuration/config_documentation.md or
# https://element-hq.github.io/synapse/latest/usage/configuration/config_documentation.html
server_name: "e2e.imbhj.com"
pid_file: /data/homeserver.pid
listeners:
  - port: 8448
    tls: false
    type: http
    x_forwarded: true
    resources:
      - names: [client, federation]
        compress: false
# database:
#   name: sqlite3
#   args:
#     database: /data/homeserver.db
database:
  name: psycopg2
  args:
    # database: /data/homeserver.db
    user: synapse
    password: xxxxxxxxx
    dbname: synapse
    host: x.x.x.x
    cp_min: 5
    cp_max: 10
    # seconds of inactivity after which TCP should send a keepalive message to the server
    keepalives_idle: 10
    # the number of seconds after which a TCP keepalive message that is not
    # acknowledged by the server should be retransmitted
    keepalives_interval: 10
    # the number of TCP keepalives that can be lost before the client's connection
    # to the server is considered dead
    keepalives_count: 3
# 是否允许注册
enable_registration: true
# 注册是否需要token
registration_requires_token: true
# 生成 /.well-known/matrix/server
serve_server_wellknown: true
# 客户端 URL
public_baseurl: https://ele.imbhj.com/
log_config: "/data/e2e.imbhj.com.log.config"
media_store_path: /data/media_store
registration_shared_secret: "Pk0V0E4q,^JnzgV+;.1;rDBt*w1fdroi1A#w,6-2HmYRXYG6PG"
report_stats: false
macaroon_secret_key: ".8TyqH#v656P7j6#lP2SO*I4iCTkbe2LSIt;tBDQy5wNsM+Ssl"
form_secret: "Qr=0K:eomNyjE;R6Rbaoa41WIrgQ~&EPqyUedBYIe=8uo3ZPMs"
signing_key_path: "/data/e2e.imbhj.com.signing.key"
trusted_key_servers:
  - server_name: "matrix.org"
  - server_name: "mozilla.org"


# vim:ft=yaml

docker-compose.yaml

# This compose file is compatible with Compose itself, it might need some
# adjustments to run properly with stack.

# version: '3'

services:

  synapse:
    # build:
    #   context: ../..
    #   dockerfile: docker/Dockerfile
    image: docker.io/matrixdotorg/synapse:latest
    # Since synapse does not retry to connect to the database, restart upon
    # failure
    restart: unless-stopped
    # See the readme for a full documentation of the environment settings
    # NOTE: You must edit homeserver.yaml to use postgres, it defaults to sqlite
    environment:
      - SYNAPSE_CONFIG_PATH=/data/homeserver.yaml
    volumes:
      # You may either store all the files in a local folder
      - ./files:/data
      # - ./homeserver.yaml:/data/homeserver.yaml
      # .. or you may split this between different storage points
      # - ./files:/data
      # - /path/to/ssd:/data/uploads
      # - /path/to/large_hdd:/data/media
    depends_on:
      - db
      - element
    # In order to expose Synapse, remove one of the following, you might for
    # instance expose the TLS port directly:
    ports:
      - 9448:8448
      # - 8080:8008
    # ... or use a reverse proxy, here is an example for traefik:
    # labels:
      # The following lines are valid for Traefik version 1.x:
      # - traefik.enable=true
      # - traefik.frontend.rule=Host:e2e.imbhj.com
      # - traefik.port=8008
      # Alternatively, for Traefik version 2.0:
      # - traefik.enable=true
      # - traefik.http.routers.http-synapse.entryPoints=http
      # - traefik.http.routers.http-synapse.rule=Host(`e2e.imbhj.com`)
      # - traefik.http.middlewares.https_redirect.redirectscheme.scheme=https
      # - traefik.http.middlewares.https_redirect.redirectscheme.permanent=true
      # - traefik.http.routers.http-synapse.middlewares=https_redirect
      # - traefik.http.routers.https-synapse.entryPoints=https
      # - traefik.http.routers.https-synapse.rule=Host(`e2e.imbhj.com`)
      # - traefik.http.routers.https-synapse.service=synapse
      # - traefik.http.routers.https-synapse.tls=true
      # - traefik.http.services.synapse.loadbalancer.server.port=8008
      # - traefik.http.routers.https-synapse.tls.certResolver=le-ssl

  db:
    image: docker.io/postgres:12-alpine
    # Change that password, of course!
    ports:
      - 5432:5432
    environment:
      - POSTGRES_USER=synapse
      - POSTGRES_PASSWORD=xxxxxxxxx
      # ensure the database gets created correctly
      # https://element-hq.github.io/synapse/latest/postgres.html#set-up-database
      - POSTGRES_INITDB_ARGS=--encoding=UTF-8 --lc-collate=C --lc-ctype=C
    volumes:
      # You may store the database tables in a local folder..
      - ./schemas:/var/lib/postgresql/data
      # .. or store them on some high performance storage for better results
      # - /path/to/ssd/storage:/var/lib/postgresql/data

  element:
    image: docker.io/vectorim/element-web:latest
    ports:
      - 8888:80
    volumes:
      - ./element-web/config.json:/app/config.json

config.json

{
    "default_server_name": "imbhj.com",
    "default_server_config": {
        "m.homeserver": {
            "base_url": "https://e2e.imbhj.com"
        },
        "m.identity_server": {
            "base_url": "https://vector.im"
        }
    }
}

注意修改数据库密码,服务端域名,客户端域名

参考资料

官方 GitHub 仓库:

https://github.com/element-hq/synapse

官方安装文档:

https://element-hq.github.io/synapse/latest/setup/installation.html

官方 docker-compose 文件:

https://github.com/element-hq/synapse/blob/develop/contrib/docker/docker-compose.yml

官方 docker 安装说明:

https://github.com/element-hq/synapse/tree/develop/contrib/docker

官方 docker 配置说明:

https://github.com/element-hq/synapse/blob/develop/docker/README.md

官方 postgres 数据库连接说明:

https://github.com/element-hq/synapse/blob/develop/docs/postgres.md

参考的大佬博客-任意的Blog:

https://renyili.org/post/%E8%87%AA%E5%BB%BAmatrix%E6%9C%8D%E5%8A%A1

element-web 的安装说明:

https://github.com/element-hq/element-web/blob/develop/docs/install.md

element-web 的配置说明:

https://github.com/element-hq/element-web/blob/develop/docs/config.md

element-web 的配置示例:

https://app.element.io/config.json