私有化端到端加密的即时通信平台部署并实现消息定期清空

私有化端到端加密的即时通信平台部署并实现消息定期清空

_

其实大部分人似乎也不需要一个这样的平台,就算需要也已经有现成的了,比如某✈️,虽然处于某些因素国内无法正常使用。

至于这是什么,本文不会过多赘述。

image.webp
Element Web 界面效果

关系

本文围绕 MatrixSynapseElement 展开,三者分别对应 协议实现客户端 的角色。

组件名称 角色 / 定位 具体描述 电子邮件类比 Web 网页类比
Matrix 协议 (Protocol) 一个开源、去中心化的实时通信开放标准和规则。它定义了消息如何发送、端到端加密如何工作以及服务器之间如何互联(联邦)。 SMTP / IMAP 协议 HTTP / HTTPS 协议
Synapse 服务端 (Server) Matrix 协议的官方参考服务器软件(用 Python 编写)。你需要把它部署在服务器上,它负责实际存储你的聊天记录、处理账号登录,并与其他服务器交换数据。 邮件服务器软件 (如 Exchange, Postfix) Web 服务器软件 (如 Nginx, Apache)
Element 客户端 (Client) 目前最流行的 Matrix 用户界面/APP(原名 Riot)。它有网页版、手机端和电脑端。你通过它来打字聊天、语音通话和管理群组。 邮件客户端应用 (如 Outlook, Foxmail) 浏览器 (如 Chrome, Edge)

matrix-org 项目的控制权和开源协议发生了重大变更,代码库被整体迁移到了 Element 公司的 GitHub 组织下,并且更换到了更严格的传染性开源协议 AGPLv3。

如果你不想自己部署的话也可以使用公开的 Matrix 服务器,具体需自行搜索,本文仅作私有化部署记录。

另外 Matrix 协议及其 Synapse 服务器实现了去中心化、联邦式的即时通讯体验,也就是说你可以可以自己搭建服务器,并与使用其他服务器的用户自由通信,而无需依赖单一的中心化服务商。

部署

如果你觉得 Synapse 使用 Python 开发太重了,可以使用由 Go 语言开发的 dendrite

本文仅记录 Docker 部署方式

  1. 创建并进入容器编排目录,执行以下命令生成配置文件。

docker run -it --rm \
    -v $(pwd)/synapse:/data \
    -e SYNAPSE_SERVER_NAME=你的域名 \
    -e SYNAPSE_REPORT_STATS=no \
    -e UID=1000 \ # 可选:如果是非 root 环境
    -e GID=1000 \ # 可选:如果是非 root 环境
    ghcr.io/element-hq/synapse:latest generate
  1. 默认是使用 SQLite 作为数据库,如果需要更换为 PostgreSQL 的话就把配置文件(homeserver.yaml)中的 database 区域修改为如下。

database:
  name: psycopg2
  txn_limit: 10000
  args:
    user: 数据库用户名
    password: 密码
    dbname: 数据库名称
    host: postgres
    port: 5432
    cp_min: 5
    cp_max: 10
  1. 可搭配 Redis 使用

redis:
  enabled: true
  host: redis
  port: 6379
  dbid: 0
  1. Synapse 以及 Element Web 编排 (注意修改持久化目录)

version: "3.3"

services:
  synapse:
    image: "matrixdotorg/synapse:latest"
    container_name: "matrix_synapse"
    restart: unless-stopped
    ports:
      - 8008:8008
    volumes:
      - "/docker/matrix/data:/data"
    environment:
      VIRTUAL_HOST: 你的域名
      VIRTUAL_PORT: 8008
      LETSENCRYPT_HOST: 你的域名
      SYNAPSE_REPORT_STATS: "yes"
  element-web:
    ports:
      - 8009:80
    volumes:
      - "/docker/element-web/config.json:/app/config.json"
    image: vectorim/element-web
    restart: unless-stopped

element-web/config.json 文件你需要提前创建好,否则 docker 会创建一个 config.json 文件夹导致报错。

config.example.json 文件,可在 element-hq/element-web 找到,将 m.homeserver.base_url 修改为你的 Synapse 服务器地址,如果你想固定为你的服务器地址并且不可修改的话可以将 disable_custom_urls 改为 true,修改 default_country_code 为 CN 可以使网页默认为中文,其余参数可以去看项目文档。

{
    "default_server_config": {
        "m.homeserver": {
            "base_url": "https://matrix-client.matrix.org",
            "server_name": "matrix.org"
        },
        "m.identity_server": {
            "base_url": "https://vector.im"
        }
    },
    "disable_custom_urls": false,
    "disable_guests": false,
    "disable_login_language_selector": false,
    "disable_3pid_login": false,
    "force_verification": false,
    "brand": "Element",
    "integrations_ui_url": "https://scalar.vector.im/",
    "integrations_rest_url": "https://scalar.vector.im/api",
    "integrations_widgets_urls": [
        "https://scalar.vector.im/_matrix/integrations/v1",
        "https://scalar.vector.im/api",
        "https://scalar-staging.vector.im/_matrix/integrations/v1",
        "https://scalar-staging.vector.im/api"
    ],
    "default_widget_container_height": 280,
    "default_country_code": "GB",
    "show_labs_settings": false,
    "features": {},
    "default_federate": true,
    "default_theme": "light",
    "room_directory": {
        "servers": ["matrix.org"]
    },
    "enable_presence_by_hs_url": {
        "https://matrix.org": false,
        "https://matrix-client.matrix.org": false
    },
    "setting_defaults": {
        "breadcrumbs": true
    },
    "jitsi": {
        "preferred_domain": "meet.element.io"
    },
    "element_call": {
        "url": "https://call.element.io",
        "brand": "Element Call"
    },
    "map_style_url": "https://api.maptiler.com/maps/streets/style.json?key=fU3vlMsMn4Jb6dnEIFsx"
}

容器启动成功后就可以通过 8008 端口访问 Synapse,8009 端口访问 Element Web 客户端了,再用 Nginx 反代一下即可使用域名访问。

  1. 创建管理员账户

docker exec -it synapse-matrix(Synapse 容器名称) \
register_new_matrix_user \
http://localhost:8008 \
-c /data/homeserver.yaml \
-a -u 管理员用户名 -p 密码

管理后台

管理后台我使用的开源项目 etkecc/ketesa,你可以自部署,也可以直接使用作者部署好的,需要注意 CORS 跨域问题。

你可以直接将 Synapse 服务器域名的 CORS 跨域设置为 *

消息定期清空

有两种方式实现,推荐两种一起使用,因为实测发现服务端自动删除后客户端仍然可以显示,原因是客户端会缓存消息到本地。

服务端自动删除

在 Synapse 配置文件(homeserver.yaml) 中新增一节:

retention:
  enabled: true
  
  default_policy:
    min_lifetime: 3d
    max_lifetime: 3d
    
  allowed_lifetime:
    min: 3d
    max: 3d

即可实现每 3 天清空一次消息。

房间单独配置

  1. 打开开发者工具: 进入房间,在聊天框输入/devtools指令 -> -> 弹出开发者工具

  2. 发送自定义事件: 在工具箱中点击 发送自定义时间线事件

  3. 填写事件内容:

    • Event Type (事件类型): m.room.retention

    • Event Content (事件内容) (数字以毫秒为单位,以下为1小时示例):

    {
      "max_lifetime": 3600000
    }

机器人自动删除

机器人删除首先需要去搭建 maubot 平台,项目地址: https://github.com/maubot/maubot,另外也有许多开源的插件,参见 https://plugins.mau.bot/

创建并进入 maubot 容器的持久化目录,简易部署指南如下:

  1. 获取配置文件

docker run --rm -v $PWD:/data:z dock.mau.dev/maubot/maubot:latest
  1. 在 root 账户后添加一个你要登录的账户,如下:

admins:
    root: ''
    admin: 'password'
  1. 部署容器

docker run --restart unless-stopped -p 29316:29316 -v $PWD:/data:z dock.mau.dev/maubot/maubot:latest
  1. Synapse 服务器后台中添加一个账户用来作为 Bot

  2. 进入 maubot 容器内

docker exec -it <容器ID或名称> /bin/sh
  1. CLI 登录 maubot

mbc login
  1. 登录刚才创建的 Bot账号

mbc auth
  1. 访问 maubot web 控制台登录第 2 步添加的账户

  2. 点击左边 Clients 的 "+" 添加在管理后台生成的机器人账户

    image (1).webp
    添加机器人 Client
  3. 点击左边 Plugins 的 "+" 上传插件,消息自动清除插件仓库地址: https://github.com/williamkray/maubot-expiringmessages,下载后需解压重新打个压缩包,需将文件放在压缩包根目录,不然 maubot 无法识别。

  4. 点击左边 Instances 的 "+" 创建一个实例,id 随便,Primary user 选刚刚创建的 client,Type 选刚刚上传的插件。

image (2).webp
添加机器人实例
  1. 将机器人拉入你的房间

机器人指令如下:

  • 设置消息自动删除的期限: !expire set <duration>

  • 日: d (e.g., 1d)

  • 小时: h (e.g., 24h)

  • 分钟: m (e.g., 30m)

  • 秒钟: s (e.g., 60s)

可以混合使用,例如: !expire set 1d2h30m。

  • 取消自动删除: !expire unset

  • 显示当前设置: !expire show

定期清空 媒体文件/附件

虽然聊天记录都定期清空了,但是上传的文件都还会存在硬盘上,可以通过配置文件中添加如下配置项实现:

media_retention:
  # 本地用户上传的媒体,超过多久后删除(例如:90天)
  local_media_lifetime: 90d
  # 远程服务器用户发送、被本地用户缓存的媒体,超过多久后删除(例如:30天)
  remote_media_lifetime: 30d

但这样会产生一个问题,用户以及群聊的头像也会被删除,所以此处提供另外一种方法,通过调用 Synapse API 实现删除头像资源以外的文件。

将以下 shell 直接丢给 crontab 定时执行即可。

#!/bin/bash

# --- 配置项 ---
SYNAPSE_URL="https://example.com"  # Matrix Synapse 访问地址
SERVER_NAME="example.com"        # 你的 Matrix Synapse 服务器域名
ACCESS_TOKEN="token" # 拥有管理员权限的 Token

# 获取 3 天前的 Unix 时间戳(单位:毫秒)
TIMESTAMP=$(date -d '3 days ago' +%s000)

# 1. 清理本地媒体文件 (keep_profiles=true 默认生效,自动阻止删除头像)
curl -X POST "${SYNAPSE_URL}/_synapse/admin/v1/media/${SERVER_NAME}/delete?before_ts=${TIMESTAMP}&keep_profiles=true" \
     -H "Authorization: Bearer ${ACCESS_TOKEN}"

# 2. 清理远程服务器缓存在本地的媒体文件
curl -X POST "${SYNAPSE_URL}/_synapse/admin/v1/purge_media_cache?before_ts=${TIMESTAMP}" \
     -H "Authorization: Bearer ${ACCESS_TOKEN}"

ACCESS_TOKEN 可以在 Element Web 中点击头像 -> 关于 中获取。

image (3).webp
Element Web 获取 Access Token

注意事项

  • 登录账号后记得保存你的 Recovery Key,这是你解密聊天记录的密钥,如果没有这个密钥,你在其他设备登录可能无法显示历史聊天记录。

  • 由于 PostgreSQL 以及 Synapse 项目本身的原因,中文搜索支持度可以说是为 0,若想实现中文搜索请参考: https://nigzu.com/matrix-synapse-add-chinese-seearch/

结语

就到这了,我也刚开始用,先慢慢体验,文章临时写了下做记录用,不是很规范。

派大星_StarPatrick-1

VMware 虚拟机去虚拟化标识 2026-05-05