Skip to content

部署开源的聊天服务

有的时候公司内网无法使用QQ/微信, 或者单纯想部署个聊天服务器和朋友一起玩...

  • memble
  • matrix

memble

一些即时性很强的游戏, 比如打 CS 开黑报点, 需要和朋友在一起玩游戏, 但是又不在一起, 需要长时间语音通话的就可以使用 Mumble 这个软件可以说是 teamspeak 的开源替代品, 功能强大UI简洁, 项目主页

为什么不直接用微信/QQ语音?

因为用微信语音的总感觉有点延迟, 而且没有做降噪处理, 可能会有杂音, 另外可能会占线

使用 Mumble 的优缺点?

  • 开源, 轻量级, 低延迟, 声音会做降噪理, 可完美平替 teamspeak
  • 功能就只有语音通话, 没有文字聊天等功能

客户端

client-settings

服务端

yaml
services:
  mumble-server:
    image: mumblevoip/mumble-server:latest
    container_name: mumble-server
    hostname: mumble-server
    restart: always
    ports:
      - 64738:64738
      - 64738:64738/udp
    environment:
      MUMBLE_SUPERUSER_PASSWORD: "super_user_password" # 超级管理员密码(注意修改)

matrix

matrix 是一个标准的聊天协议, 因此社区有很多用不同语言实现的服务端和客户端, 可以客户端都可以连接到遵循 matrix 协议的服务

开源服务端实现

开源客户端实现

快速开始(http协议)

  • 服务端
  • web 客户端

使用 http 协议的话, 无法使用语音和视频通话, 只能使用文字聊天, 因为语音是视频都是通过 webrtc 实现的, 而 webrtc 只能在 https 的环境下使用 因此在 http 协议的情况下, 无法 webrtc 来进行语音通话

yaml
services:
  # matrix server
  # 当然你也可以使用其他的实现, 如: https://github.com/element-hq/synapse
  # 我这里使用的是 matrix-conduit, 是因为他是 rust 编写的, 我想要测试一下它
  # 文档: https://docs.conduit.rs/
  matrix-server:
    image: matrixconduit/matrix-conduit:latest
    restart: unless-stopped
    ports:
      - 8080:6167
    volumes:
      - ./db:/var/lib/matrix-conduit/
    environment:
      CONDUIT_SERVER_NAME: example.matrix.com # 使用你自己的域名或 ip
      CONDUIT_DATABASE_PATH: /var/lib/matrix-conduit/ # 数据库保存目录
      CONDUIT_DATABASE_BACKEND: rocksdb  # 数据库类型
      CONDUIT_PORT: 6167                 # 监听端口
      CONDUIT_MAX_REQUEST_SIZE: 20000000 # in bytes, ~20 MB
      CONDUIT_ALLOW_REGISTRATION: "true" # 是否允许注册
      CONDUIT_REGISTRATION_TOKEN: "register-token-string" # 注册需要填入的密钥
      CONDUIT_ALLOW_CHECK_FOR_UPDATES: "true" # 允许检查更新
      CONDUIT_TRUSTED_SERVERS: '["matrix.org"]'
      CONDUIT_MAX_CONCURRENT_REQUESTS: 100
      CONDUIT_ADDRESS: 0.0.0.0
      CONDUIT_CONFIG: ""

  # matrix webui client
  # 当然你也可以使用其他客户端, 我这里为了方便测试所以顺便部署了一个 web 版 ui 客户端
  # docs: https://github.com/vector-im/element-web/blob/develop/docs/config.md
  element-webui-client:
    image: vectorim/element-web:latest
    restart: unless-stopped
    ports:
      - 8081:80
    depends_on:
      - matrix-server
    # volumes:
    #   - ./element_config.json:/app/config.json

TURN/STUN 服务器

coturn 是一个开源的 TURN/STUN 服务器 主要用于解决实时通信(如 WebRTC 音视频通话)中的 NAT 穿透问题,帮助设备在复杂网络环境下建立直接连接

  • TURN: NAT 穿透中继
  • STUN: 公网地址发现
  • 多网络协议支持 TCP/UDP/TLS/DTLS 兼容 ipv4/ipv6

当然 coturn 也是支持 docker 部署在线测试 coturn 服务是否部署成功

yaml
services:
  # coturn-server
  turn-server:
    container_name: coturn-server
    image: docker.io/coturn/coturn
    restart: unless-stopped
    network_mode: "host"
    volumes:
      - ./coturn.conf:/etc/coturn/turnserver.conf
sh
# 默认配置文件参考 github 源码:
# https://github.com/coturn/coturn/blob/master/docker/coturn/turnserver.conf
# 注意: 使用 docker 部署时, 最好删除所有注释防止奇怪的错误导致 coturn 无法启动

use-auth-secret
static-auth-secret=05839f80-a3a2-4ab0-a364-79aae4bfb794 # 注意修改, 使用自己的密码
realm=example.coturn.com # 注意修改, 使用指向自己服务器的域名

https 支持

这个实现方式有很多, 比如直接使用 caddy 来做反向代理, 当然也可以使用其他的, 比如手动配置 nginx, 或者直接使用 nginx-proxy-manager 为了简单和方便记录笔记, 我这里使用 caddy 来做反向代理, 并且将所有服务全部都加入同一个 docker 网络

yaml
services:
  caddy:
    image: caddy:latest
    container_name: caddy
    restart: always
    ports:
      - "80:80"
      - "443:443"
    networks:
      - app_network
    volumes:
      - ./caddy_etc:/etc/caddy # 在 Caddyfile 中配置反向代理
      - ./caddy_data:/data
      - ./caddy_config:/config

  element-webui-client:
    image: vectorim/element-web
    restart: always
    container_name: element-webui-client
    # 不需要再暴露端口了, 因为直接走 caddy 代理了,
    # 由于在同一网络下(app_network), 直接通过 docker 网络访问即可
    # prots:
    #   - 80:80
    networks:
      - app_network

networks:
  app_network:
txt
# 反向代理的目标域名
element.example.com {
    # container_name:port -> element-webui-client:80
    reverse_proxy element-webui-client:80
}

快速生成所有配置文件的脚本

由于配置文件比较多, 而且需要不同的文件保持同步, 这就很容易出错, 所以我写了一个脚本来自动生成配置文件

bash
#!/bin/bash

### 注意一定要在执行之前修改以下变量, 生成完之后再修改某个文件
### 就可能导致忘记改其他需要同步的配置文件

### variables
matrix_host="matrix.yourdomain.com" # 服务域名
matrix_register_token="register-token-string" # 注册密钥
element_host="element.yourdomain.com"
coturn_host="coturn.yourdomain.com" # 须开放 3478 端口的 udp 和 tcp
coturn_secret="your-coturn-secrets" # coturn 中继服务器链接密码

### docker-compose
docker_compose_content=$(cat <<EOF
networks:
  app_network:

services:
  # docs: https://github.com/coturn/coturn
  coturn-server:
    container_name: coturn-server
    image: coturn/coturn:latest
    restart: unless-stopped
    network_mode: "host"
    ports:
      - 3478:3478
      - 3478:3478/udp
    volumes:
      - ./coturn.conf:/etc/coturn/turnserver.conf

  # docs: https://hub.docker.com/_/caddy
  caddy-server:
    container_name: caddy-server
    image: caddy:latest
    restart: unless-stopped
    networks:
      - app_network
    ports:
      - 80:80
      - 443:443
    volumes:
      - ./caddy_etc:/etc/caddy
      - ./caddy_data:/data
      - ./caddy_config:/config

  # docs: https://docs.conduit.rs/deploying/docker.html
  matrix-server:
    image: matrixconduit/matrix-conduit:latest
    restart: unless-stopped
    container_name: matrix-server
    networks:
      - app_network
    depends_on:
      - coturn-server
    volumes:
      - ./db:/var/lib/matrix-conduit/
    environment:
      CONDUIT_SERVER_NAME: ${matrix_host}
      CONDUIT_DATABASE_PATH: /var/lib/matrix-conduit/
      CONDUIT_DATABASE_BACKEND: rocksdb
      CONDUIT_PORT: 6167
      CONDUIT_MAX_REQUEST_SIZE: 20000000 # in bytes, ~20 MB
      CONDUIT_ALLOW_REGISTRATION: "true"
      CONDUIT_REGISTRATION_TOKEN: "$matrix_register_token"
      CONDUIT_ALLOW_CHECK_FOR_UPDATES: "true"
      CONDUIT_TRUSTED_SERVERS: '["matrix.org"]'
      CONDUIT_MAX_CONCURRENT_REQUESTS: 100
      CONDUIT_ADDRESS: 0.0.0.0
      CONDUIT_CONFIG: ""
      CONDUIT_TURN_URIS: '["turn:${coturn_host}?transport=udp", "turn:${coturn_host}?transport=tcp"]'
      CONDUIT_TURN_SECRET: "${coturn_secret}"

  # docs: https://github.com/element-hq/element-web/blob/develop/docs/config.md
  element-webui-client:
    image: vectorim/element-web:latest
    container_name: element-webui-client
    restart: unless-stopped
    environment:
      VIRTUAL_HOST: ${element_host}
    networks:
      - app_network
    depends_on:
      - matrix-server
    volumes:
      - ./element_web.config.json:/app/config.json
EOF
)

echo "$docker_compose_content" > ./docker-compose.yml

### caddy
if [[ ! -d "./caddy_etc" ]]; then
    mkdir -p ./caddy_etc
fi

caddyfile_content=$(cat <<EOF
# caddy online docs: https://caddyserver.com/docs/caddyfile
${matrix_host} {
	reverse_proxy matrix-server:6167 {
		health_interval 10s
		health_timeout 5s
	}
}
${element_host} {
	reverse_proxy element-webui-client:80 {
		health_interval 10s
		health_timeout 5s
	}
}
EOF
)
echo "$caddyfile_content" > ./caddy_etc/Caddyfile

### coturn
coturn_conf_content=$(cat <<EOF
use-auth-secret
static-auth-secret=${coturn_secret}
realm=${coturn_host}
EOF
)
echo "$coturn_conf_content" > ./coturn.conf


### element-web, for webui default server
element_web_config_content=$(cat <<EOF
{
  "default_server_config": {
    "m.homeserver": {
      "base_url": "https://${matrix_host}"
    }
  }
}
EOF
)
echo "$element_web_config_content" > ./element_web.config.json

最后

所有配置文件汇总

txt
.
├── caddy_etc
│   └── Caddyfile
├── coturn.conf
├── docker-compose.yml
├── element_web.config.json
└── installer.sh # 生成配置文件的脚本文件

2 directories, 5 files
txt
# caddy online docs: https://caddyserver.com/docs/caddyfile
matrix.yourdomain.com {
	reverse_proxy matrix-server:6167 {
		health_interval 10s
		health_timeout 5s
	}
}
element.yourdomain.com {
	reverse_proxy element-webui-client:80 {
		health_interval 10s
		health_timeout 5s
	}
}
yaml
networks:
  app_network:

services:
  # docs: https://github.com/coturn/coturn
  coturn-server:
    container_name: coturn-server
    image: coturn/coturn:latest
    restart: unless-stopped
    network_mode: "host"
    ports:
      - 3478:3478
      - 3478:3478/udp
    volumes:
      - ./coturn.conf:/etc/coturn/turnserver.conf

  # docs: https://hub.docker.com/_/caddy
  caddy-server:
    container_name: caddy-server
    image: caddy:latest
    restart: unless-stopped
    networks:
      - app_network
    ports:
      - 80:80
      - 443:443
    volumes:
      - ./caddy_etc:/etc/caddy
      - ./caddy_data:/data
      - ./caddy_config:/config

  # docs: https://docs.conduit.rs/deploying/docker.html
  matrix-server:
    image: matrixconduit/matrix-conduit:latest
    restart: unless-stopped
    container_name: matrix-server
    networks:
      - app_network
    depends_on:
      - coturn-server
    volumes:
      - ./db:/var/lib/matrix-conduit/
    environment:
      CONDUIT_SERVER_NAME: matrix.yourdomain.com
      CONDUIT_DATABASE_PATH: /var/lib/matrix-conduit/
      CONDUIT_DATABASE_BACKEND: rocksdb
      CONDUIT_PORT: 6167
      CONDUIT_MAX_REQUEST_SIZE: 20000000 # in bytes, ~20 MB
      CONDUIT_ALLOW_REGISTRATION: "true"
      CONDUIT_REGISTRATION_TOKEN: "register-token-string"
      CONDUIT_ALLOW_CHECK_FOR_UPDATES: "true"
      CONDUIT_TRUSTED_SERVERS: '["matrix.org"]'
      CONDUIT_MAX_CONCURRENT_REQUESTS: 100
      CONDUIT_ADDRESS: 0.0.0.0
      CONDUIT_CONFIG: ""
      CONDUIT_TURN_URIS: '["turn:coturn.yourdomain.com?transport=udp", "turn:coturn.yourdomain.com?transport=tcp"]'
      CONDUIT_TURN_SECRET: "your-secret-strings"

  # docs: https://github.com/element-hq/element-web/blob/develop/docs/config.md
  element-webui-client:
    image: vectorim/element-web:latest
    container_name: element-webui-client
    restart: unless-stopped
    environment:
      VIRTUAL_HOST: element.yourdomain.com
    networks:
      - app_network
    depends_on:
      - matrix-server
    volumes:
      - ./element_web.config.json:/app/config.json
sh
use-auth-secret
static-auth-secret=your-secret-strings
realm=coturn.yourdomain.com
json
{
  "default_server_config": {
    "m.homeserver": {
      "base_url": "https://matrix.yourdomain.com"
    }
  }
}

Released under the MIT License.