Tinode 0.25.3 配置参数详解

Tinode 0.25.3 服务端配置文件 tinode.conf 全参数详解:26 个顶层分区逐项说明(入口与传输、密钥与安全、数据库适配器、账号策略、凭据验证、推送通知、可观测),关键参数均带修改-验证闭环实测(端口切换、uid_key 非法值、数据库字段名错误、最短用户名 422、验证码调试回执、stdout 推送启停),并汇总排障实录。全部命令与回显来自真实服务器实测。

Tinode即时通讯Tinode2026/10/26

Tinode 0.25.3 配置参数详解

目标:把 Tinode v0.25.3 唯一的配置文件 tinode.conf 讲透——先给出 26 个顶层分区的全景地图,再按「入口与传输、安全与密钥、数据库、账号策略、凭据验证、消息策略、推送、可观测」逐项解释含义与默认值,关键参数附上「修改 → 重启 → 验证」的实测闭环与踩坑实录。本文所有命令与回显均来自真实服务器实测(Ubuntu 22.04 + MySQL 8)。

一、环境信息

本文的配置实验在以下环境完成(与安装篇同一台服务器,版本自证取自服务启动日志):

项目实测值
操作系统Ubuntu 22.04.5 LTS
服务端Tinode v0.25.3(启动日志 Server v0.25:/opt/tinode-app/tinode:v0.25.3)
配置文件/opt/tinode-app/tinode.conf(705 行,JSON 带注释)
数据库MySQL 8.0.46(适配器 schema 版本 116)
服务托管systemd(单元 tinode.service)

配置文件全文行数实测:

wc -l /opt/tinode-app/tinode.conf
705 /opt/tinode-app/tinode.conf

二、配置文件总览

2.1 文件位置与加载方式

Tinode 的全部配置集中在一个 JSON 文件中,由启动参数 -config 指定(systemd 单元中的 ExecStart=/opt/tinode-app/tinode -config /opt/tinode-app/tinode.conf)。格式是「带 // 注释的 JSON」——官方在文件首行就提醒注释语法较为脆弱(// The JSON comments are somewhat brittle. Don't try anything too fancy.),手工编辑时不要添加尾注释或调整引号风格。

所有配置项均在启动时读取,修改后必须重启服务才生效。这是本文每个修改-验证闭环的固定动作:systemctl restart tinode 后用 systemctl is-active tinode(预期 active)与 journalctl -u tinode 确认。

2.2 顶层分区全景

用 grep 列出全部顶层键(实测回显):

grep -nP '^\t"[a-z_]+"' /opt/tinode-app/tinode.conf
9:	"listen": ":6060",
13:	"api_path": "/",
16:	"cache_control": 39600,
20:	"ws_compression_disabled": false,
23:	"static_mount": "/",
28:	"grpc_listen": ":16060",
32:	"grpc_keepalive_enabled": true,
36:	"api_key_salt": "T713/rYYgW7g4m3vG6zGRh7+FM1t0T8j13koXScOAj4=",
43:	"max_message_size": 131072,
50:	"max_subscriber_count": 128,
53:	"max_tag_count": 16,
56:	"permanent_accounts": false,
60:	"expvar": "/debug/vars",
70:	"use_x_forwarded_for": true,
74:	"x_frame_options": "SAMEORIGIN",
79:	"default_country_code": "",
92:	"msg_delete_age": 600,
96:	"alias_tag": "alias",
99:	"media": {
155:	"tls": {
188:	"auth_config": {
245:	"store_config": {
387:	"acc_validation": {
506:	"acc_gc_config": {
517:	"push": [
618:	"webrtc": {
650:	"cluster_config": {
678:	"plugins": [

26 个顶层键按职能分为四类:

分区键职能
入口与传输listen、api_path、cache_control、ws_compression_disabled、static_mount、grpc_listen、grpc_keepalive_enabled三种通道的监听与 Web 静态托管
全局策略max_message_size、max_subscriber_count、max_tag_count、permanent_accounts、msg_delete_age、alias_tag、default_country_code消息与主题的硬限制
安全api_key_salt、tls、use_x_forwarded_for、x_frame_optionsAPI key 签名、TLS、反代头
子配置块media、auth_config、store_config、acc_validation、acc_gc_config、push、webrtc、cluster_config、plugins、expvar各子系统独立配置

其中 expvar(第 60 行)虽是标量键,本质是可观测开关:运行时统计暴露在 /debug/vars 路径,留空或设为 - 即关闭。本章第三至十节按上述顺序展开,每个关键参数给出「含义、默认值、修改-验证实测」。

三、服务入口与传输参数

3.1 listen:客户端入口端口(修改-验证实测)

listen(第 9 行,默认 :6060)是 HTTP/WebSocket/长轮询三通道共用的监听地址,Web 控制台静态托管也走这里。支持 host:port、:port、:https 服务名或 unix:/path/to/socket.sock 套接字形式;留空时无 TLS 默认 :80,有 TLS 默认 :443。命令行 --listen 可覆盖。

修改-验证实测:把端口从 6060 改为 6160,重启后验证新端口、随后改回:

sed -i 's/"listen": ":6060"/"listen": ":6160"/' /opt/tinode-app/tinode.conf
systemctl restart tinode
systemctl is-active tinode
curl -sI http://localhost:6160/ | head -1
active
HTTP/1.1 200 OK

改回 6060 并重启后 curl -sI http://localhost:6060/ | head -1 再次回显 HTTP/1.1 200 OK。这演示了配置修改的通用闭环:改文件 → restart → is-active + curl 验证。

3.2 其余传输参数逐项

键(行号)默认值含义与要点
api_path(13)/流式通道与大文件 API 的 URL 前缀;命令行 --api_path 可覆盖
cache_control(16)39600静态资源 Cache-Control 秒数(39600 = 11 小时;安装篇 Web 验证回显中的 max-age=39600 即来源于此)
ws_compression_disabled(20)false是否禁用 WebSocket 逐消息压缩(RFC 7692.4);官方注释:反向代理为 MSFT IIS 时应设 true
static_mount(23)/静态文件挂载路径,默认用服务端直接托管 Web 控制台
grpc_listen(28):16060gRPC 通道监听;留空则禁用 gRPC
grpc_keepalive_enabled(32)truegRPC keepalive,把 KEEPALIVE_TIME 从默认 2 小时缩到 60 秒

验证 gRPC 入口的方法是看启动日志(实测回显,来自 journalctl -u tinode):

Oct 26 12:23:26 tinode-sys tinode[5744]: I2026/10/26 12:23:26 gRPC/1.82.0 server is registered at [:16060]
Oct 26 12:23:26 tinode-sys tinode[5744]: I2026/10/26 12:23:26 Listening for client HTTP connections on [:6060]

static_mount 生效的证据是启动行 Serving static content from '/opt/tinode-app/static' at '/'。

四、安全与密钥参数

4.1 api_key_salt 与 keygen 配对(第 36 行)

api_key_salt 是 API key 的签名盐(32 字节 base64),与发行包内 keygen 工具生成的 key 成对使用。keygen 实测输出:

cd /opt/tinode-app && ./keygen
API key v1 seq1 [ordinary]: AQAAAAABAABb1lv6-dWoYXC4M6VO5gY9
HMAC salt: XxCVzrVjlX84Urtke1MuW+6DzuqchOYPkYlUgJAz+m8=

验证方法:salt 与 key 不配对时,所有客户端请求会被拒。本环境 salt/key 配对时 LP 会话创建正常返回(实测回显):

curl -s -X POST "http://localhost:6060/v0/channels/lp?apikey=AQAAAAABAAAoeOI7tA3HsYvdzDhYhZJy"
{"ctrl":{"params":{"sid":"aX06iiNwxZs"},"code":201,"text":"created","ts":"2026-10-26T13:04:32.448Z"}}

要点:每次 keygen 输出全新一对;替换 salt 后必须重启,且客户端侧的 key 要同步换成同一对,否则 201 变 403。

4.2 uid_key:UID 生成密钥(排障实录实测)

uid_key 位于 store_config 内(第 249 行,本环境值 6cTXIXgdxO8qxObF30+1hg==),是用户 UID 加密生成器(snowflake + XTEA)的 16 字节 base64 密钥。它的正确性在启动时强校验——改成非法 base64(33 个字符)实测:服务直接启动失败,journald 回显:

E2026/10/26 12:53:19 Failed to connect to DB: store: failed to parse config: illegal base64 data at input byte 32({

错误信息在 illegal base64 data at input byte 32( 之后原样回显了整段 store_config JSON(含 mysql/postgres/rethinkdb/mongodb 各段,多行输出),systemd 层面表现为 Main process exited, code=exited, status=1/FAILURE。修复:恢复 16 字节 base64 值后 systemctl restart tinode,is-active 回显 active。

⚠️ uid_key 的运维纪律:它决定 UID 的编解码。一旦库里有用户数据,此值绝不可再改——换了 key,既有 UID 全部无法解析。全新部署可在首次 init-db 前自定义。

4.3 tls / use_x_forwarded_for / x_frame_options

  • tls(第 155 行):内嵌 TLS 配置块,配置证书后 listen 可直接服务 HTTPS;不配则前面挂 Nginx/Caddy 反代。
  • use_x_forwarded_for(第 70 行,默认 true):从 X-Forwarded-For 头取客户端真实 IP。注意安全语义:直连暴露时应确认不会被伪造头污染。
  • x_frame_options(第 74 行,默认 SAMEORIGIN):Web 控制台的防点击劫持响应头。

五、数据库参数(store_config,第 245 行起)

5.1 use_adapter 与适配器段

store_config.use_adapter(第 256 行)从 alldbs 发行包内置的四个适配器中选一个(本文 mysql)。每个适配器在 store_config.adapters 下有独立配置段。store_config.max_results 限制单次查询返回上限;uid_key 见 4.2 节。

5.2 mysql 连接参数(排障实录实测)

本环境 mysql 段仅显式配置了两项(实测回显):

sed -n '/"mysql": {/,/}/p' /opt/tinode-app/tinode.conf | grep -E 'User|Passwd'
				"User": "tinode",
				"Passwd": "q1w2e3r4",

其余连接参数(本机实例、库名 tinode)沿用适配器默认值。字段名必须逐字符正确——把 Passwd 误写成 Password 的实测后果:JSON 解析对未知字段不报错、静默忽略,等效于空密码连接,服务反复重启失败:

Oct 26 12:52:25 tinode-sys tinode[5975]: E2026/10/26 12:52:25 Failed to connect to DB: Error 1045 (28000): Access denied for user 'tinode'@'localhost' (using password: NO)
Oct 26 12:52:25 tinode-sys systemd[1]: tinode.service: Main process exited, code=exited, status=1/FAILURE

using password: NO 是空密码特征,遇到它优先怀疑字段名拼错而非密码本身。改正字段名重启后 is-active 回显 active 恢复。

六、账号与鉴权策略(auth_config,第 188 行起)

6.1 basic 段:最短用户名/密码(422 边界实测)

发行包默认的 basic 鉴权配置实测原文(第 196-206 行):

		// Basic (login + password) authentication.
		"basic": {
			// Add 'auth-name:username' to tags making user discoverable by username.
			"add_to_tags": true,
			// The minimum length of a login in unicode runes, i.e. "登录" is length 2, not 6.
			// The maximum length is 32 and it cannot be changed.
			"min_login_length": 4,
			// The minimum length of a password in unicode runes, "пароль" is length 6, not 12.
			// There is no limit on maximum length, but MySQL & PgSQL adapters have a limit of 32 bytes.
			"min_password_length": 6
		},

逐项说明:add_to_tags: true 把 basic:用户名 加入用户可搜索标签(按用户名搜索用户的前提);min_login_length: 4(按 Unicode 字符计,最大 32 固定不可改);min_password_length: 6(无上限,但 MySQL/PgSQL 适配器单字段限 32 字节)。

修改-验证实测:在 min_login_length: 4 生效的服务器上注册 3 字符用户名 bob(实测回显):

{"ctrl":{"id":"2","params":{"what":"auth"},"code":422,"text":"policy violation","ts":"2026-10-26T12:37:30.071Z"}}

422 policy violation 且 params.what:"auth" 指向鉴权策略不满足。同节实测的姊妹边界:注册时完全不提供 email 凭据,同样 422 但参数指向凭据(params.creds:["email"]),对应 7.1 节的注册策略:

{"ctrl":{"id":"3","params":{"creds":["email"]},"code":422,"text":"policy violation","ts":"2026-10-26T12:37:30.08Z"}}

6.2 token 段

token 鉴权器(第 209 行起)控制登录令牌:expire_in: 1209600(2 周有效期)、serial_num: 1(序列号,整体 +1 可一次性作废全部已发令牌)、以及令牌签名用的 HMAC 盐(官方注释要求自生成并保密)。实测佐证:登录成功响应中 expires 恰为 2 周后(2026-10-26T12:18:29 登录,expires 2026-11-09T12:18:29)。

七、注册凭据验证(acc_validation,第 387 行起)

7.1 email 验证器与 debug_response

acc_validation 定义注册时要求的凭据与验证方式。发行包默认启用了调试回执(实测位置与原文):

grep -n -B2 'debug_response' /opt/tinode-app/tinode.conf | head -6
456-				// REMOVE IN PRODUCTION!!! Otherwise anyone will be able to register
457-				// with fake emails.
458:				"debug_response": "123456"

含义:未配置真实 SMTP 出口时,邮箱验证码固定为 123456(第 498 行为手机号验证的同类默认值)。官方注释明确生产必须删除。修改-验证闭环:注册 tina 时先收到 300 validate credentials(响应含临时 token 与 cred:["email"]),再用验证码 123456 登录成功(实测回显):

{"ctrl":{"id":"2","params":{"authlvl":"auth","cred":["email"],"desc":{"created":"2026-10-26T12:18:29.413Z","updated":"2026-10-26T12:18:29.413Z","defacs":{"auth":"JRWPASD","anon":"N"}},"expires":"2026-11-09T12:18:29.466Z","token":"8Y/EkEKfpugVuvFqFAABAAAAQvhB+rA5MyV/S4WOCW7LA6p1I96hHx0jQAzuu/ZYDt0=","user":"usr8Y_EkEKfpug"},"code":300,"text":"validate credentials","ts":"2026-10-26T12:18:29.41Z"}}
{"ctrl":{"id":"3","params":{"authlvl":"auth","expires":"2026-11-09T12:18:29.531Z","token":"8Y/EkEKfpugVuvFqFAABAAEAnYMLpmuWIaVG4LSgn77ADpt2BgKOpQ2GZXKGV4X7n+k=","user":"usr8Y_EkEKfpug"},"code":200,"text":"ok","ts":"2026-10-26T12:18:29.481Z"}}

生产化路径:在对应验证器配置中填入真实发信参数(SMTP 令牌等)并删除 debug_response,验证码改为真实下发后凭 resp 完成登录。

八、消息与主题策略

键(行号)默认值含义与验证方式
max_message_size(43)131072单条消息最大字节数(128KB);超限大文件走 out-of-band 上传(maxFileUploadSize 上限 8388608 = 8MB)。验证:hi 握手响应 params.maxMessageSize:131072
max_subscriber_count(50)128群组话题可配置专属权限的订阅者上限(频道读者不受限)。验证:hi 响应 maxSubscriberCount:128
max_tag_count(53)16每话题/用户可索引标签数上限。验证:hi 响应 maxTagCount:16
permanent_accounts(56)false为 true 时普通用户不可注销账号
msg_delete_age(92)600已删除消息的硬删除延迟(分钟);验证:hi 响应 msgDelAge:600
alias_tag(96)"alias"别名标签命名空间;验证:启动日志 Alias tag: alias
default_country_code(79)""手机号注册缺省国家码

这些上限值都会随 hi 握手一次性下发(实测回显节选):

"params":{"build":"mysql:v0.25.3","maxFileUploadSize":8388608,"maxMessageSize":131072,"maxSubscriberCount":128,"maxTagCount":16,"maxTagLength":96,"minTagLength":2,"msgDelAge":600,...}

修改任一项后重启,再发一次 hi 即可看到新值,这是最省事的「改配置-看生效」验证通道。

九、推送通知参数(push,第 517 行起)

9.1 stdout 推送启停(修改-验证实测)

push 是数组配置,每个元素是一个通知器。发行包默认仅含 stdout 通知器且关闭(第 518-525 行实测原文):

		{
			// Notificator which writes to STDOUT. Useful for debugging.
			"name":"stdout",
			"config": {
				// Disabled.
				"enabled": false
			}
		},

把 enabled 改为 true 并重启后,启动日志从 Push handlers configured: [](关闭态实测)变为:

Oct 26 12:23:26 tinode-sys tinode[5744]: I2026/10/26 12:23:26 Push handlers configured: [stdout]

推送效果实测:注册 derek 并向 tina 发消息后,journald 中出现 stdout 通知器的 Receipt 结构体输出(两条:sub 订阅通知与 msg 消息通知,map 内是各接收者与未读计数):

&{map[1iHXaDZ-kxI:{0 [] 0 false}]  {sub false usrJ83MPZorA1g 2026-10-26 12:53:24.209 +0000 UTC usrJ83MPZorA1g 0  <nil>  false  JRWPAD JRWPAD}}
&{map[1iHXaDZ-kxI:{0 [] 1 true} J83MPZorA1g:{1 [] 0 false}]  {msg false p2p1iHXaDZ-kxInzcw9misDWA 2026-10-26 12:53:24.216 +0000 UTC usrJ83MPZorA1g 1 text/plain stdout push test  false  N N}}

msg 通知中可见接收方(未读 +1)、在线发送者自身({1 [] 0 false},在线则静默)、P2P 话题名 p2p1iHXaDZ-kxInzcw9misDWA 与消息内容 stdout push test。stdout 通知器官方定位就是调试用;生产环境在此数组中加入 fcm(Google 推送)或 tnpg 等元素并配置对应凭据。

十、运行时可观测(expvar)

expvar(第 60 行,默认 /debug/vars)暴露运行时统计。实测:

curl -s http://localhost:6060/debug/vars | head -c 300

输出为 JSON 计数器集合,其中 CtrlCodesTotal2xx 等键累计了各协议状态码计数(实测值 140 起,随请求增长)。不需要时把该键置为空串或 - 即关闭暴露,重新启动后 /debug/vars 不再可访问。

十一、修改配置的通用方法与排障实录汇总

11.1 通用方法

每个配置项的验证都遵循同一闭环,实测步骤模板:

vi /opt/tinode-app/tinode.conf
systemctl restart tinode
systemctl is-active tinode
journalctl -u tinode --no-pager -n 20

三条验证判据:is-active 回显 active;journald 出现完整启动行序列(Listening for client HTTP connections on [:6060] 等);对应功能的业务验证通过(如端口改动后 curl 新端口 200、推送改动后出现 Receipt 行)。建议每次改前备份(cp tinode.conf tinode.conf.bak),本文三处故障实测均以备份一键恢复。

11.2 排障实录汇总

本文实测复现的三类配置错误及其指纹:

故障实测指纹(journald 关键行)根因解决
mysql 密码字段名写成 PasswordFailed to connect to DB: Error 1045 (28000): Access denied ... (using password: NO)JSON 未知字段静默忽略,等效空密码字段名改回 Passwd
uid_key 非法 base64Failed to connect to DB: store: failed to parse config: illegal base64 data at input byte 32({...整段 store_config 回显密钥格式强校验失败恢复 16 字节 base64
注册用户名过短接口返回 {"code":422,"text":"policy violation","params":{"what":"auth"}}min_login_length=4 策略用户名加长或调小该值(下限受 32 上限约束)

共同规律:配置错误一律表现为启动失败(journald 里的 E 级错误行)或接口 4xx,绝不会静默半生效;定位入口就是 journalctl -u tinode 的错误行原文。

十二、参考链接