Tuwunel Docker Compose 部署指南

Tuwunel v1.9.3 的 Docker Compose 快速部署方案,含数据持久化、开放注册配置、Matrix 协议端点全链路验证,附录含社区 Helm chart k8s 部署参考。

TuwunelTuwunelChat2026/10/27

Tuwunel Docker Compose 部署指南

目标:在单台服务器上通过 Docker Compose 快速部署 Tuwunel v1.9.3 homeserver,含数据持久化、开放注册、Matrix 协议端点验证、以及社区 Helm chart 部署参考。已在 Ubuntu 22.04 LTS + Docker 29.8.0 实测通过。

一、环境信息

项值
Tuwunel 版本v1.9.3
Docker 引擎Docker Engine 29.8.0(compose plugin v2)
基础镜像ghcr.io/matrix-construct/tuwunel:v1.9.3(约 33MB)
服务器系统Ubuntu 22.04 LTS / 任意支持 Docker 的发行版
Matrix 客户端端口8008(容器内)→ 宿主映射(示例 8130)
Federation 端口8448(容器内)
数据持久化Docker volume tuwunel-data → /var/lib/tuwunel
配置格式TOML(环境变量前缀 TUWUNEL_ + TOML key 覆盖)

二、镜像选型说明

镜像维护方说明
ghcr.io/matrix-construct/tuwunel:v1.9.3官方(matrix-construct)首选,发布节奏与源码同步,含二进制 + 默认配置
ghcr.io/spnngl/images/tuwunel社区(spnngl)硬化镜像(distroless、non-root、无 shell),用于社区 Helm chart

官方镜像为 基于 Debian slim 的标准镜像,包含完整 tuwunel 二进制 + tuwunel-example.toml 示例配置文件,容器默认以 tuwunel 非 root 用户运行。

三、前置条件

  1. Docker Engine ≥ 24.0(含 compose plugin v2)——docker compose version 确认
  2. 开放端口 8008(客户端 API)和 8448(Federation)——用于外部客户端接入和跨服务器联邦互联
  3. DNS 解析:
    • chat.example.com A 记录指向服务器 IP(server_name)
    • 如使用 federation,_matrix._tcp.chat.example.com SRV 记录(可选,也可用 /.well-known/matrix/server)
  4. 网络代理(可选):如无法直连 GHCR,配置 Docker daemon registry-mirrors 或代理

四、部署步骤

4.1 创建项目目录与 Compose 文件

mkdir -p /opt/quzuo-tuwunel && cd /opt/quzuo-tuwunel

创建 docker-compose.yml:

name: tuwunel-1-9-3-stack
services:
  tuwunel:
    image: ghcr.io/matrix-construct/tuwunel:v1.9.3
    container_name: tuwunel-1-9-3
    restart: unless-stopped
    ports:
      - "8008:8008"
      - "8448:8448"
    environment:
      # === 必需:服务器名(一经选定不可修改,数据库绑定) ===
      - TUWUNEL_SERVER_NAME=chat.example.com
      # === 必需:数据目录 ===
      - TUWUNEL_DATABASE_PATH=/var/lib/tuwunel
      # === 必需:监听 0.0.0.0 才能被宿主机访问 ===
      - TUWUNEL_ADDRESS=0.0.0.0
      - TUWUNEL_PORT=8008
      # === 可选:启用开放注册(生产环境建议改用 token 模式) ===
      - TUWUNEL_ALLOW_REGISTRATION=true
      - TUWUNEL_YES_I_AM_VERY_VERY_SURE_I_WANT_AN_OPEN_REGISTRATION_SERVER_PRONE_TO_ABUSE=true
      # === 可选:日志级别 ===
      - TUWUNEL_LOG_LEVELS=info
      # === 可选:管理注册共享密钥(启用 _synapse/admin/v1/register) ===
      - TUWUNEL_REGISTRATION_SHARED_SECRET=please-change-this-to-a-long-random-string
    volumes:
      - tuwunel-data:/var/lib/tuwunel
    networks:
      - tuwunel-net

volumes:
  tuwunel-data:

networks:
  tuwunel-net:
    driver: bridge

⚠️ 注意:server_name 设置后不可更改——它写入 RocksDB 数据库,绑定了所有用户 ID(@user:server_name)和房间 ID。如需更改必须清空数据库(删除 volume tuwunel-data 后重新初始化)。

4.2 启动服务

docker compose up -d

实测输出:

[+] Pulling image "ghcr.io/matrix-construct/tuwunel:v1.9.3"
ghcr.io/matrix-construct/tuwunel:v1.9.3 Pulled
[+] Running 3/3
 ✔ Network tuwunel-net      Created
 ✔ Volume tuwunel-data      Created
 ✔ Container tuwunel-1-9-3  Started

4.3 查看启动日志

docker logs tuwunel-1-9-3 --tail 30

实测输出节选:

2026-10-27T06:50:33.286372Z  INFO tuwunel::server: 1.9.3 server_name=chat.example.com database_path="/var/lib/tuwunel" log_levels=info
2026-10-27T06:50:33.397724Z  INFO main: start: open: tuwunel_database::engine::open: Opened database. columns=135 sequence=0 time=88.176649ms
2026-10-27T06:50:33.401960Z  WARN main: start: tuwunel_service::migrations: Created new RocksDB database with version 17
2026-10-27T06:50:33.404991Z  INFO tuwunel_router::serve: Listening on ["tcp:0.0.0.0:8008"]

关键行解读:

  • 1.9.3:版本正确
  • columns=135:RocksDB 数据库初始化完成,135 个列族
  • Listening on ["tcp:0.0.0.0:8008"]:HTTP 服务监听就绪
  • WARN ... Created new RocksDB database with version 17:首次启动正常告警(新项目)

4.4 验证 Matrix 协议端点

客户端版本:

curl -s http://localhost:8008/_matrix/client/versions | python3 -m json.tool | head -15

实测输出:

{
    "versions": [
        "r0.0.1", "r0.1.0", "r0.2.0", "r0.3.0", "r0.4.0", "r0.5.0", "r0.6.0",
        "r0.6.1", "v1.1", "v1.2", "v1.3", "v1.4", "v1.5", "v1.6", "v1.7",
        "v1.8", "v1.9", "v1.10", "v1.11", "v1.12", "v1.13", "v1.14",
        "v1.15", "v1.16", "v1.17", "v1.18", "v1.19"
    ],
    "unstable_features": {
        "org.matrix.msc2732": true,
        "org.matrix.msc3715": true,
        "org.matrix.msc3882": true,
        "org.matrix.msc3575": true
    }
}

登录流程:

curl -s http://localhost:8008/_matrix/client/v3/login | python3 -m json.tool

实测输出:

{
    "flows": [
        {"type": "m.login.application_service"},
        {"type": "m.login.token", "get_login_token": true},
        {"type": "m.login.password"}
    ]
}

注册测试用户:

# Step 1: 发起注册,获取 session
RESP=$(curl -s -X POST http://localhost:8008/_matrix/client/v3/register \
  -H 'Content-Type: application/json' \
  -d '{"username":"admin","password":"q1w2e3r4","initial_device_display_name":"CLI"}')
SESSION=$(echo "$RESP" | python3 -c "import sys,json; print(json.load(sys.stdin)['session'])")
echo "Session: $SESSION"

# Step 2: 完成 dummy auth stage
curl -s -X POST http://localhost:8008/_matrix/client/v3/register \
  -H 'Content-Type: application/json' \
  -d "{\"username\":\"admin\",\"password\":\"q1w2e3r4\",\"initial_device_display_name\":\"CLI\",\"auth\":{\"type\":\"m.login.dummy\",\"session\":\"$SESSION\"}}" | python3 -m json.tool

实测输出:

{
    "access_token": "XrAr9IHjxOaSBdQoz7GsWaqhJAzoRlec",
    "user_id": "@admin:chat.example.com",
    "device_id": "z34EjhmALZ",
    "home_server": "chat.example.com"
}

创建测试房间并发消息:

TOKEN="XrAr9IHjxOaSBdQoz7GsWaqhJAzoRlec"
ROOM_ID=$(curl -s -X POST http://localhost:8008/_matrix/client/v3/createRoom \
  -H "Authorization: Bearer $TOKEN" \
  -H 'Content-Type: application/json' \
  -d '{"room_alias_name":"test-room","name":"Test Room","visibility":"public"}' | python3 -c "import sys,json; print(json.load(sys.stdin)['room_id'])")
echo "Room ID: $ROOM_ID"

# 发送消息
curl -s -X PUT "http://localhost:8008/_matrix/client/v3/rooms/$ROOM_ID/send/m.room.message/1" \
  -H "Authorization: Bearer $TOKEN" \
  -H 'Content-Type: application/json' \
  -d '{"msgtype":"m.text","body":"Hello from Tuwunel!"}' | python3 -m json.tool

实测输出:

{
    "event_id": "$2edlN78wEgstO30UelVlHhIezG4J6hGchPctZlOYhpI"
}

五、数据持久化说明

Tuwunel 使用 RocksDB 嵌入式数据库 + 本地媒体存储。在 Compose 部署中,数据统一存放在 /var/lib/tuwunel:

路径内容说明
/var/lib/tuwunel/db/RocksDB 数据库文件135 列族、LSM-Tree 结构
/var/lib/tuwunel/media/用户上传的图片/视频/文件默认本地存储
/var/lib/tuwunel/media_cache/远程媒体缓存跨服务器 federation 时的缓存

备份方式:

# 停止容器
docker compose stop tuwunel
# 备份 volume(方式 1:直接用 volume 名称)
docker run --rm -v tuwunel-data:/data -v $(pwd):/backup alpine tar czf /backup/tuwunel-backup-$(date +%F).tar.gz -C /data .
# 方式 2:Tuwunel 在线备份(需配置 database_backup_path)
docker exec tuwunel-1-9-3 tuwunel --help | grep -i backup

💡 技术拓展:Matrix homeserver 数据库架构对比——

Homeserver数据库备份方式
TuwunelRocksDB(LSM-Tree 嵌入式)database_backup_path 在线备份 + 文件系统快照
SynapsePostgreSQL(WAL + pg_basebackup)pg_dump / pg_basebackup
DendritePostgreSQL 或 SQLite同 Synapse 或 SQLite .backup

本文/本方案实际采用 Tuwunel 的 RocksDB 在线备份(需配置 database_backup_path),理由:零停机、无需外部数据库组件。

六、环境变量表

Tuwunel 通过环境变量覆盖 TOML 配置文件中的值。格式为 TUWUNEL_ 前缀 + TOML key 大写化(点号也转为下划线)。

TOML key环境变量名默认值必需说明
global.server_nameTUWUNEL_SERVER_NAME—✅服务器名,绑定到用户 ID(改前需清库)
global.database_pathTUWUNEL_DATABASE_PATH/var/lib/tuwunel✅数据目录
global.addressTUWUNEL_ADDRESS["127.0.0.1","::1"]Docker 用需改 0.0.0.0监听地址
global.portTUWUNEL_PORT8008—监听端口
global.log_levelsTUWUNEL_LOG_LEVELSinfo—日志级别(debug/info/warn/error)
global.allow_registrationTUWUNEL_ALLOW_REGISTRATIONfalse注册需开允许新用户注册
global.yes_i_am_very_very_sure...TUWUNEL_YES_I_AM_VERY_VERY_SURE_I_WANT_AN_OPEN_REGISTRATION_SERVER_PRONE_TO_ABUSEfalse开放注册需开无 token 的开放注册警告确认
global.registration_tokenTUWUNEL_REGISTRATION_TOKEN—推荐注册令牌
global.registration_shared_secretTUWUNEL_REGISTRATION_SHARED_SECRET——Synapse admin register 端点密钥
global.database_backup_pathTUWUNEL_DATABASE_BACKUP_PATH——RocksDB 在线备份目录
global.cache_capacity_modifierTUWUNEL_CACHE_CAPACITY_MODIFIER1.0—LRU 缓存倍数(内存多可调大)
global.db_cache_capacity_mbTUWUNEL_DB_CACHE_CAPACITY_MB自动—RocksDB 读缓存 MB
global.db_write_buffer_capacity_mbTUWUNEL_DB_WRITE_BUFFER_CAPACITY_MB自动—RocksDB 写缓冲 MB

七、配置文件挂载

对于复杂配置(LDAP、OIDC、Storage Provider、Application Service 等),推荐挂载 TOML 配置文件:

services:
  tuwunel:
    volumes:
      - tuwunel-data:/var/lib/tuwunel
      - ./config/tuwunel.toml:/etc/tuwunel/tuwunel.toml:ro
    command: ["tuwunel", "-c", "/etc/tuwunel/tuwunel.toml"]

Tuwunel 支持 TOML 文件 + 环境变量叠加:文件定义基础配置,环境变量覆盖文件中同名项(冲突以环境变量为准)。

完整配置参考官方示例 4314 行文件:tuwunel-example.toml,详解见 《Tuwunel v1.9.3 配置参数详解》。

八、等价 docker run

不用 Compose,纯 Docker 命令启动:

docker run -d \
  --name tuwunel-1-9-3 \
  --restart unless-stopped \
  -p 8008:8008 -p 8448:8448 \
  -e TUWUNEL_SERVER_NAME=chat.example.com \
  -e TUWUNEL_DATABASE_PATH=/var/lib/tuwunel \
  -e TUWUNEL_ADDRESS=0.0.0.0 \
  -e TUWUNEL_PORT=8008 \
  -e TUWUNEL_ALLOW_REGISTRATION=true \
  -e TUWUNEL_YES_I_AM_VERY_VERY_SURE_I_WANT_AN_OPEN_REGISTRATION_SERVER_PRONE_TO_ABUSE=true \
  -v tuwunel-data:/var/lib/tuwunel \
  ghcr.io/matrix-construct/tuwunel:v1.9.3

九、常用运维命令

# 查看容器状态
docker ps --filter name=tuwunel-1-9-3 --format "table {{.Names}}\t{{.Status}}\t{{.Ports}}"

# 实时日志
docker logs -f tuwunel-1-9-3

# 进入容器
docker exec -it tuwunel-1-9-3 sh

# Tuwunel 健康检查
docker exec tuwunel-1-9-3 tuwunel --health-check

# 数据库在线备份(需先配 database_backup_path)
docker exec tuwunel-1-9-3 tuwunel --maintenance

# 停机维护(拒绝新连接但保持运行)
docker exec tuwunel-1-9-3 tuwunel --read-only

# 重启
docker compose restart tuwunel

# 停止(保留数据)
docker compose down

# 停止+删除数据(⚠️ 清空数据库,不可恢复)
docker compose down -v

十、附录:社区 Helm Chart k8s 部署参考(Tier3)

💡 Tuwunel 目前无 matrix-org 官方 Helm chart。社区 chart 由 spnngl/charts 维护,版本迭代活跃(0.1.0 → 0.1.1 间隔 1 天)。以下为 2026-10-27 实查数据,k8s 集群实测将于 K1 批次进行(本波为实查成文)。

10.1 Chart 基本信息

项值
Chart 名称tuwunel
Chart 仓库https://ghcr.io/spnngl/charts(OCI)
Chart 版本0.1.1(2026-10-25)
App 版本1.9.4(注:比官方 10-27 实测 v1.9.3 略新)
K8s 版本要求>= 1.33.0-0
Kubernetes APIv1 / apps/v1 / networking.k8s.io
Workload单副本 StatefulSet(RocksDB 嵌入式数据库,不可多主写入)
镜像ghcr.io/spnngl/images/tuwunel(distroless non-root)
可选组件Cinny Web 客户端、LiveKit Media SFU(语音视频)、LK JWT Service
存储storage: true → PVC(dataStorageSize 默认 10Gi)
许可证Apache-2.0

10.2 安装步骤(k8s 集群实测待 K1 批次)

# 添加 OCI 仓库(Helm 3.8+ 支持 OCI)
helm pull oci://ghcr.io/spnngl/charts/tuwunel --version 0.1.1

# 或直接安装
helm install tuwunel oci://ghcr.io/spnngl/charts/tuwunel \
  --namespace tuwunel --create-namespace \
  --set serverName=chat.example.com \
  --set image.tag=1.9.4

10.3 values.yaml 关键配置项

以下为 values.yaml 中最常修改的字段(chart v0.1.1 实查):

# --- 核心必填 ---
serverName: example.com          # 服务器名,数据库首次启动后不可改

# --- 镜像 ---
image:
  repository: ghcr.io/spnngl/images/tuwunel
  tag: ""                        # 空则取 chart 注解,或指定如 "1.9.4"
  pullPolicy: IfNotPresent
imagePullSecrets: []

# --- Tuwunel TOML 配置覆盖(schema 校验)---
# 注意:只能设 TOML key(不能设 server_name, database_path, address, port 这四个由 chart 固定)
settings:
  # 注册
  allow_registration: true
  registration_token: ""
  yes_i_am_very_very_sure_i_want_an_open_registration_server_prone_to_abuse: false
  # 缓存调优
  cache_capacity_modifier: 1.0
  # Federation
  allow_federation: true
  # 日志
  log_levels: info

# --- 部署拓扑 ---
# Tuwunel 是单 writer 的 StatefulSet;replicas 固定 1(chart 不允许多副本)
replicaCount: 1

# --- 存储 ---
storage: true
dataStorageSize: 10Gi
# dataStorageClass: ""          # 指定 StorageClass

# --- Service ---
service:
  type: ClusterIP
  port: 8008

# --- Ingress ---
ingress:
  enabled: true
  className: ""
  annotations: {}
  hosts:
    - host: chat.example.com
      paths:
        - path: /
          pathType: Prefix

# --- well-known 委托 ---
# Matrix Federation 需要 _matrix._tcp SRV 或 /.well-known/matrix/server
ingress.wellKnown:
  enabled: true

# --- 可选组件 ---
cinny:
  enabled: true                 # 启用 Cinny Web 客户端(端口 80)
livekit:
  enabled: true                 # 启用 LiveKit RTC 后端
lkjwtService:
  enabled: true                 # 启用 LiveKit JWT 签发服务

# --- 资源 ---
resources:
  requests:
    cpu: 100m
    memory: 256Mi
  limits:
    cpu: 1000m
    memory: 512Mi

# --- 现有 Secret 挂载 ---
existingSecret:
  name: ""                      # 如指定,则挂载到 /etc/tuwunel/secrets
                                # 用于 registration_token_file, smtp_password_file 等

10.4 Helm 与 Compose 核心差异

维度Docker ComposeHelm Chart (社区)
拓扑单容器 + optional 网络StatefulSet + 可选 Ingress + 可选 Cinny/LiveKit/LKJWT
数据库内嵌 RocksDB volume内嵌 RocksDB PVC
多节点不支持不支持(单 writer StatefulSet)
存储类Docker volumePVC(需集群 StorageClass)
配置管理环境变量 + 可选 TOML 挂载values.yaml settings + 可选 existingSecret
镜像来源官方 ghcr.io/matrix-construct社区 ghcr.io/spnngl/images
升级docker compose pull && uphelm upgrade
生产就绪✅ 完全可用⚠️ 社区维护、迭代频繁

十一、常见问题

Q1: 容器启动时提示 "Config parameter X is unknown to tuwunel"?

A: 环境变量名必须精确匹配 TOML key(大小写、下划线)。错误如 log_level → 正确应为 log_levels。完整 TOML key 列表参考配置文件详解篇。

Q2: 注册返回 M_FORBIDDEN "Registration has been disabled"?

A: Tuwunel 默认 allow_registration = false。需设 TUWUNEL_ALLOW_REGISTRATION=true,无 token 时还需额外设开放注册确认标志(两个一起开)。

Q3: 联邦互联不通(其他 homeserver 无法发现我)?

A: 检查 DNS——至少满足以下其一:(1)chat.example.com:8448 直接可达;(2)_matrix._tcp.chat.example.com SRV 记录指向 chat.example.com:8448;(3)https://chat.example.com/.well-known/matrix/server 返回 {"m.server":"chat.example.com:8448"}。

Q4: server_name 填错了可以改吗?

A: 不能。server_name 写入 RocksDB 后绑定所有用户/房间 ID。要改必须:docker compose down -v 删数据卷 → 改环境变量 → docker compose up -d。

Q5: 想启用邮箱验证注册怎么做?

A: 挂载 TOML 配置文件,在 [global.smtp] 下配置 SMTP 服务器,同时设 require_email_for_registration = true。详见配置参数详解篇。

Q6: 社区 Helm chart 安全扫描有 8 个漏洞(1 high / 6 medium),敢用吗?

A: 根据 ArtifactHub 报告(2026-10-27),漏洞来自 spnngl/images 的基础镜像。建议生产环境使用官方 Docker 镜像自建 K8s deployment,或等社区 chart 更新基础镜像。

十二、参考链接

资源URL
Tuwunel Docker 镜像https://github.com/matrix-construct/tuwunel/pkgs/container/tuwunel
社区 Helm charthttps://artifacthub.io/packages/helm/spnngl-tuwunel/tuwunel
Helm chart 源码https://github.com/spnngl/charts/tree/main/charts/tuwunel
Tuwunel 配置详解https://matrix-construct.github.io/tuwunel/configuration.html
Matrix 协议规范https://spec.matrix.org/latest/
Federation 配置文档https://matrix-construct.github.io/tuwunel/deploying/generic.html