CyTube 配置参数详解

CyTube 3.86.1 配置体系逐段详解:config.yaml 全参数(mysql/listen/http/https/io/站务限制/频道行为/播放队列/ffmpeg/service-socket 等)与 conf/ 四个扩展文件(camo/captcha/email/prometheus),关键参数附改值+重启+生效回显实测:站点标题改值、update-interval 采样 2.00s、聊天长度截断行为、保留名正则五组对比、channel_data 落库与 prometheus /metrics。

CyTubeCyTube流媒体自托管2026/10/29

CyTube 配置参数详解

目标:把 CyTube 3.86.1 的配置体系彻底讲透。以官方模板 config.template.yaml(217 行,注释即文档)为底本逐段拆解每个配置项的含义、默认值与取值注意点,再补上 conf/ 目录下的四个扩展配置(camo/captcha/email/prometheus)。关键参数全部附"改值 → 重启 → 生效回显"的实测闭环,回显逐行照抄自真实部署现场。部署过程见《CyTube Docker Compose 部署实战》,日常运维见《CyTube 常用命令与运维实战(核心篇)》。

一、配置体系总览

CyTube 的配置由两层组成:主配置 config.yaml(YAML,位于应用运行目录)与 conf/ 目录下的扩展配置(TOML,按功能拆文件)。主配置负责站点骨架(数据库、监听端口、站务限制),扩展配置负责可选能力(验证码、邮件、指标暴露、图片代理)——不放文件就是关闭,应用启动时逐个探测并在日志里报告探测结果。

实测启动日志的配置加载段(docker logs 逐行照抄):

[INFO] config: Loaded configuration from config.yaml
[INFO] config: No camo configuration found, chat images will not be proxied.
[INFO] config: Loaded prometheus configuration from conf/prometheus.toml.  Prometheus listener is ENABLED
[INFO] config: No email configuration found, defaulting to disabled
[INFO] config: No captcha configuration found, defaulting to disabled

四行 config: 日志就是配置体系的自述:主配置已加载;conf/camo.toml 不存在 → 图片代理关闭;conf/prometheus.toml 存在且启用 → 指标监听开启;邮件、验证码未配置 → 默认关闭。排障第一步永远是看这段日志。

此外,CyTube 启动时会对配置做一致性自检,用管理命令行触发一次完整的 WARN 清单(回显逐行照抄):

[WARN] config: Detected 127.0.0.1 or localhost in root-domain 'localhost'.  This server will not work from other computers!  Set root-domain to the domain the website will be accessed from (e.g. example.com)
[WARN] config: socket.io is bound to localhost, this server will be inaccessible from other computers!
[WARN] config: No YouTube v3 API key set.  YouTube links will not work.  See youtube-v3-key in config.template.yaml and https://developers.google.com/youtube/registering_an_application for information on registering an API key.
[WARN] config: No Twitch Client ID set.  Twitch VOD links will not work.  See twitch-client-id in config.template.yaml and https://github.com/justintv/Twitch-API/blob/master/authentication.md#developer-setupfor more information on registering a client ID

这四条 WARN 覆盖了新手最常踩的四个坑:域名写 localhost(外部无法访问)、实时通道绑本地、缺 YouTube API Key(站内搜不到 YouTube 视频)、缺 Twitch Client ID(VOD 查询失效)。真实上线前逐条消除即可。

💡 技术拓展:CyTube 的配置校验是"宽松加载"策略——未知键、缺失键都不报错,缺失项回落到源码 src/config.js 里的内置默认值(与 config.template.yaml 的数值一致)。因此配置文件里没写的参数也在生效,逐段核对模板文件是确认默认行为的唯一可靠途径。

二、数据库连接(mysql 段)

模板默认:

mysql:
  server: 'localhost'
  port: 3306
  database: 'cytube3'
  user: 'cytube3'
  password: ''
  pool-size: 10
参数说明
server数据库地址,域名、IP 或 UNIX 套接字路径(套接字写法 unix:/path/to/sock.sock)
port端口,默认 3306
database / user / password库名与账号;官方要求 MySQL/MariaDB ≥ 5.5.3 且字符集 utf8mb4
pool-size连接池大小,默认 10;频道多、Socket 并发高时可加大

实测要点:server 写编排栈内的服务名即可(同网络内服务名即主机名),本实验为 cytube-3.86.1-mariadb。库与账号由 MariaDB 初始化变量自动创建,首启迁移自动建 14 张表(实测 show tables; 回显见《CyTube Docker Compose 部署实战》4.2 节)。

三、监听端口(listen 数组)

模板默认与注释要点:

listen:
  - ip: ''
    port: 8080
    http: true
  - ip: ''
    port: 1337
    io: true

规则(源自模板注释原文):

  1. 每个条目必须给出 ip 和 port,ip 留空字符串表示绑定全部网卡;
  2. 每个条目用 http / https / io 三个布尔值声明该端口承载的服务;http+io(或 https+io)可以合并到一个端口;但 http 与 https 同时声明时只有 https 生效;
  3. 可用 url 键为该端口指定对外的完整地址(反代场景用)。

本实验的监听配置(实测生效):8080 承载 http(页面/接口),1337 承载 io(实时通道),分别对外映射为 8129/8130。实时通道探活实测:

curl -s "http://localhost:8130/socket.io/?EIO=4&transport=polling" | head -c 60

实测回显:

0{"sid":"lvJnPptR3Zw1-Vxb","upgrades":["websocket"],...

💡 技术拓展:官方 Wiki 附录的生产建议是"反代只转发 HTTP,WebSocket 走 8443 的 HTTPS 端口直连"——即 listen 中再加一个 https: true, io: true 的 8443 条目(同时打开 https.enabled 并配好证书)。这是因为许多反代对长连接 WebSocket 的超时/缓冲处理不佳,直连 TLS 端口更稳。

四、HTTP 服务(http 段)

模板全量:

http:
  default-port: 8080
  root-domain: 'localhost'
  alt-domains:
    - '127.0.0.1'
  minify: false
  max-age: '7d'
  gzip: true
  gzip-threshold: 1024
  cookie-secret: 'change-me'
  index:
    max-entries: 50
  trust-proxies: ['loopback']
参数默认说明
default-port8080生成链接时使用的默认 HTTP 端口
root-domainlocalhost登录 Cookie 的绑定根域;多子域站点(a.example.com/b.example.com)填 example.com
alt-domains['127.0.0.1']额外允许签发登录 Cookie 的域名/主机名列表
minifyfalse是否压缩 CSS/JS(express-minify)
max-age'7d'静态资源缓存时长(ms 模块格式,0 禁用)
gzip / gzip-thresholdtrue / 1024gzip 开关与触发阈值(字节),启动日志 webserver: Enabled gzip compression 即此参数回显
cookie-secretchange-meCookie 签名密钥,必须改成随机长串;泄露等于可伪造登录态
index.max-entries50首页公开频道列表最多展示条数
trust-proxies['loopback']信任的代理地址段(proxy-addr 语法),用于把 X-Forwarded-For 映射为真实客户端 IP——IP 限流、封禁、别名记录都依赖真实 IP,反代场景必配

实测:改 html-template.title 验证配置生效链路(html-template 段与 http 段同属页面呈现,此处一并实测)。把标题从 CyTube 改为 CyTube 实验室:

sed -i "s/title: 'CyTube'/title: 'CyTube 实验室'/" conf/config.yaml
docker restart cytube-3.86.1-app
sleep 6 && curl -s http://localhost:8129/ | grep -o '<title>[^<]*</title>'

实测回显:

cytube-3.86.1-app
<title>CyTube 实验室</title>

页面 <title> 已变为新值——主配置改值 → 服务重启 → 页面回显的生效链路验证通过。

五、HTTPS 服务(https 段)

模板默认(全部关闭态):

https:
  enabled: false
  default-port: 8443
  domain: 'https://localhost'
  keyfile: 'localhost.key'
  passphrase: ''
  certfile: 'localhost.cert'
  cafile: ''
  ciphers: 'HIGH:!DSS:!aNULL@STRENGTH'
参数说明
enabled总开关;开启后还需在 listen 数组加 https: true 的条目才真正监听
default-port / domain生成 HTTPS 链接的默认端口与域名前缀
keyfile / certfile / cafile / passphrase证书私钥、证书、CA 链与私钥口令(相对应用运行目录)
ciphersOpenSSL 加密套件表达式,默认即禁用 DSS/无认证套件

本实验未启用 HTTPS(隔离内网直连 HTTP)。上生产必须启用:直链视频与登录 Cookie 都受浏览器安全策略约束,全站 HTTPS 是硬要求。

六、页面模板与实时通道(html-template / io 段)

html-template:
  title: 'Sync'
  description: 'Free, open source synchtube'

io:
  domain: 'http://localhost'
  default-port: 1337
  ip-connection-limit: 10
  cors:
    allowed-origins: []
  • html-template.title:页面左上角站点名与 <title>(实测改值见第四节);
  • html-template.description:<meta> 描述;
  • io.domain:Socket.IO 对外的根地址。模板注释原文警告:此域的根必须与 HTTP 域的根一致(或 HTTPS 域),否则登录不生效——Cookie 按 http.root-domain 签发,实时通道按 io.domain 连接,两域根不一致时跨域不带 Cookie;
  • io.default-port:生成 Socket.IO 连接地址的默认端口;
  • io.ip-connection-limit: 10:单 IP 并发实时连接上限(防一个 IP 开几十个标签页刷连接);
  • io.cors.allowed-origins:额外放行的跨域来源列表(io.domain/https.domain 隐式包含)。

💡 技术拓展:cookie-secret、root-domain、io.domain 三者构成"登录铁三角"。实测排障案例:用 127.0.0.1 访问而 root-domain 为 localhost 时,服务端根本不下发 Cookie,注册/登录一律 403 Invalid Session(完整现象与处置见《CyTube Docker Compose 部署实战》8.1 节)。

七、第三方平台密钥

youtube-v3-key: ''
twitch-client-id: null
  • youtube-v3-key:YouTube Data API v3 密钥。不配则 YouTube 链接无法解析(启动 WARN 明说)。模板注释给出完整的申请步骤与自测命令:
export YOUTUBE_API_KEY="your key here"
curl "https://www.googleapis.com/youtube/v3/search?key=$YOUTUBE_API_KEY&part=id&maxResults=1&q=test+video&type=video"
  • twitch-client-id:Twitch 数据 API 的 Client ID,用于 VOD(回放)查询;不配则 Twitch 直播链接可用但 VOD 链接解析失败。

两个密钥都是"站点级"的:配一次全站所有频道受益。

八、注册与站务限制

模板默认:

max-channels-per-user: 5
max-accounts-per-ip: 5
guest-login-delay: 60
max-chat-message-length: 320
参数默认说明
max-channels-per-user5每个账号可注册的频道数上限
max-accounts-per-ip5每 IP 可注册账号数上限(防批量小号)
guest-login-delay60同 IP 两次游客登录的最小间隔(秒)
max-chat-message-length320单条聊天消息最大字符数,源码硬顶 1000

实测一:游客登录限流(guest-login-delay: 60)。同 IP 第二次游客登录时服务端直接拒绝,实测回显:

[15:42:37] [B(viewer)] <== login: {"success":false,"error":"Guest logins are restricted to one per IP address per 60 seconds."}

实测二:改 max-chat-message-length: 20 验证行为。配置改值重启后,经 Socket.IO 发送 24 个汉字:

[16:03:02] 发送 24 字消息(上限 20)
[16:03:02] [A(admin)] ==> chatMsg {"msg":"一二三四五六七八九十甲乙丙丁戊己庚辛壬癸子丑寅卯"}
[16:03:02] [A(admin)] <== chatMsg: {"username":"admin","msg":"一二三四五六七八九十甲乙丙丁戊己庚辛壬癸","meta":{},"time":1793203382732}

24 字消息被服务端截断为 20 字后照常广播(对照:发送 10 字消息原样通过)。这是一个容易被误解的行为——超长消息不是整条拒绝而是截断放行。

九、频道行为参数

9.1 频道路径与黑名单

channel-path: 'r'
channel-blacklist: []
  • channel-path:频道 URL 路径段,http://localhost/r/频道名 中的 r;允许字符为字母、数字、下划线、连字符;
  • channel-blacklist:频道名黑名单数组,命中者加入即被踢(配合运维篇的封禁命令使用)。

9.2 频道快照周期(channel-save-interval)

channel-save-interval: 5

注释原文:频道状态落盘的周期(分钟),默认 5。实测改为 1 后的完整行为链(改值 → 重启 → 加频道并修改 MOTD → 观察落库):

[INFO] bgtask: Saving channels with delay 60000
[INFO] bgtask: Saved /r/movie-night

随后查库确认频道状态真的落了库(7 个模块各一行):

*************************** 5. row ***************************
channel_id: 1
       key: motd
value_head: "运维篇实测:频道状态保存验证 MOTD"
*************************** 6. row ***************************
channel_id: 1
       key: playlist
value_head: {"pl":[{"media":{"id":"https://10.89.60.1:8133/cytube-test.mp4","title":"CytubeLab 同步测试片","seconds":

三个实测结论:

  1. 3.x 的频道状态存在数据库 channel_data 表(按模块分行:motd、playlist、chatbuffer、css、js 等),模板注释里的"落盘"指的是写库,chandump/ 目录是 2.x 文件存储的遗留路径(源码明确 file 类型已抛异常弃用);
  2. 周期保存只处理有在线观众的频道(源码 bgtask.js 中 chan.users.length > 0 条件),空频道不写;
  3. 保存走脏标记:只有发生变更的模块才写库(源码 dbstore.js 中 rowCount === 0 直接返回),所以只进频道不改动时 channel_data 不会新增内容。

9.3 保留名规则(reserved-names)

模板默认:

reserved-names:
  usernames:
    - '^(.*?[-_])?admin(istrator)?([-_].*)?$'
    - '^(.*?[-_])?owner([-_].*)?$'
  channels:
    - '^(.*?[-_])?admin(istrator)?([-_].*)?$'
    - '^(.*?[-_])?owner([-_].*)?$'
  pagetitles: []

数组里的每一项都是正则,多规则按"或"合并、不区分大小写。默认规则保留 admin/owner 前后缀变形(d-admin、admin_x 命中;dadmin 不命中——模板注释原话)。命中后的注册报错(实测回显):

That username is reserved.

实测对比矩阵(改值重启后逐个注册验证,回显取页面 alert 文案):

测试用户名配置状态结果
co-admin规则被改为 ['(?!)', '(?!)'](永不匹配的占位正则)Registration Successful
x-admin恢复默认两条正则That username is reserved.
the-owner恢复默认两条正则That username is reserved.
dadmin恢复默认两条正则Registration Successful
co-admin2(尾缀数字)恢复默认两条正则Registration Successful

两个实用结论:(?!) 是"全部放行"的合法写法(本实验室本地环境即用它跳过保留名限制);默认正则只匹配 admin/owner 与分隔符紧邻的变形,co-admin2 这类尾缀数字不在保护范围内,需要更严保护就自己加正则。

十、别名清理与播放队列

10.1 别名清理(aliases)

aliases:
  purge-interval: 3600000
  max-age: 2592000000

CyTube 会记录每个账号用过的历史用户名(别名,aliases 表),便于识别"改名的小号"。purge-interval 是清扫周期(毫秒,默认 1 小时),max-age 是别名最长保留期(毫秒,默认 30 天)。两个值都只影响清理节奏,不影响功能。

10.2 播放队列(playlist)

playlist:
  max-items: 4000
  update-interval: 5
  • max-items:播放队列最大条目数,默认 4000;
  • update-interval:播放进度广播周期(秒),即《CyTube Docker Compose 部署实战》第七节里两端逐位一致的 mediaUpdate 的发送频率。

实测:把 update-interval 改为 2 后采样 20 秒(Socket.IO 客户端记录 mediaUpdate 到达时刻,相邻间隔):

[16:03:02] 采样结果:共 10 帧,相邻间隔(秒)=2.00, 2.00, 4.00, 1.00, 2.00, 2.00, 2.00, 2.00, 2.00

采样主频 2.00 秒与配置完全吻合(个别 4.00/1.00 是 30 秒短片循环重播时边界重叠所致)。改小可让进度校准更"跟手",代价是实时通道广播量增大;默认 5 秒对绝大多数场景足够。

十一、性能与媒体处理

11.1 垃圾回收与降权(aggressive-gc / setuid)

aggressive-gc: false
setuid:
  enabled: false
  group: 'users'
  user: 'user'
  timeout: 15
  • aggressive-gc:开启后周期限流器清理时立即触发一次 GC,要求以 node --expose-gc index.js 启动,否则无效(模板注释原文)。默认关闭即可;
  • setuid:以 root 启动后延迟降权到普通用户(timeout 为降权前等待毫秒数)。本实验室在构建期直接用专用普通用户运行,此段保持关闭。

11.2 直链媒体支持(ffmpeg)

ffmpeg:
  enabled: false
  ffprobe-exec: 'ffprobe'

开启后支持 HTTPS 直链视频(服务端用 ffprobe 探测时长/编码再全房间同步)。本实验实测开启(enabled: true),30 秒 MP4 直链入队后的元数据回显:

<== playlist: [{"media":{"id":"https://10.89.60.1:8133/cytube-test.mp4","title":"CytubeLab 同步测试片","seconds":30,"duration":"00:30","type":"fi","meta":{"codec":"mov/h264","bitrate":839.586}},...

seconds: 30 / meta.codec: mov/h264 就是 ffprobe 的探测结果。Debian/Ubuntu 若用 libav 发行版,ffprobe-exec 需改为 avprobe(模板注释原文)。

link-domain-blacklist: []
vimeo-workaround: false
service-socket:
  enabled: false
  socket: 'service.sock'
poll:
  max-options: 50
  • link-domain-blacklist:聊天/队列里禁止出现的域名黑名单;
  • vimeo-workaround:Vimeo 对作者域名屏蔽的兼容开关,一般保持 false;
  • service-socket:开启后在应用运行目录创建 UNIX 套接字 service.sock,外部服务可连上去发管理命令(/gc、/globalban、/unloadchan 等,完整命令清单与实战见《CyTube 常用命令与运维实战(核心篇)》)。模板注释点明用途:stdin 不可用的托管场景(如 PM2)下的管理通道。本实验室实测开启(启动日志 main: Opening service socket),且 bin/admin.js 依赖它;
  • poll.max-options:频道投票最大选项数,默认 50。

十二、扩展配置 conf/example 逐个详解

conf/example/ 目录下有四个扩展配置模板,复制到 conf/(去掉 .example 路径形态)即启用。四个文件实测均已在本地环境验证加载行为。

12.1 camo.toml(聊天图片代理)

[camo]
enabled = true
server = 'https://my-camo-server'
key = 'ABCDEFGH'
whitelisted-domains = [
    'i.imgur.com',
    'i.4cdn.org'
]
encoding = 'url'

把聊天里的图片 URL 重写到 camo 代理服务器(防止聊天图片泄露观众 IP / 混入恶意内容)。key 必须与代理侧的 CAMO_KEY 环境变量一致;whitelisted-domains 放行可信域名不走代理;encoding 选 url 或 hex 编码目标地址。未配置时启动日志提示 No camo configuration found, chat images will not be proxied.(图片直出)。

12.2 captcha.toml(hCaptcha 验证码)

[hcaptcha]
site-key = "10000000-ffff-ffff-ffff-000000000001"
secret = "0x0000000000000000000000000000000000000000"

[register]
enabled = true

注册页启用 hCaptcha。模板默认值是 hCaptcha 官方本地测试假密钥(恒通过),上生产必须换真密钥。[register] enabled = true 表示注册需要验证码。本实验室未配置此文件,注册接口实测可直连提交(回显见部署篇 5.1 节)。

12.3 email.toml(密码重置与账号删除邮件)

[smtp]
host = 'smtp.gmail.com'
port = 465
secure = true
user = 'some-user@example.com'
password = 'secretpassword'

[password-reset]
enabled = true
html-template = """...$user$...$url$..."""
text-template = """..."""
from = "Example Website <website@example.com>"
subject = "Password reset request"

[delete-account]
enabled = true
html-template = """..."""
text-template = """..."""

配 SMTP 后解锁两个能力:密码自助重置([password-reset],邮件模板中 $user$/$url$ 会被替换为用户名与 24 小时有效的重置链接)与账号删除([delete-account],提交后 7 天自动删除)。HTML 与纯文本双模板都要配,邮件客户端按能力二选一渲染。未配置时启动日志 No email configuration found, defaulting to disabled,忘记密码只能找管理员改库。

12.4 prometheus.toml(指标暴露)

[prometheus]
enabled = true
host = '127.0.0.1'
port = 19820
path = '/metrics'

独立于主 HTTP 服务的指标监听(默认 127.0.0.1:19820,端口刻意选了避开常见 exporter 的 19820)。模板注释说明:除 path 外的任何路径一律 400。本实验室把 host 改为 0.0.0.0 以便从宿主抓取,实测回显:

curl -s http://localhost:19820/metrics | head -6
# HELP cytube_media_cache_result_age_seconds Age (in seconds) of cached record
# TYPE cytube_media_cache_result_age_seconds summary

# HELP cytube_db_query_duration_seconds DB query latency (including time spent acquiring connections)
# TYPE cytube_db_query_duration_seconds summary
cytube_db_query_duration_seconds{quantile="0.01"} 0

可用指标包括数据库查询延迟分位数、频道状态加载/保存行数字节计数、活跃频道数等,接入 Prometheus 后可做"观影室负载"面板。

十三、参数速查表

最后浓缩一张全参数速查表(默认值全部取自 3.86.1 模板,打 ✅ 的为本实验室实测验证过生效链路的参数):

配置段参数默认值一句话说明
mysqlserver/port/database/user/password/pool-sizelocalhost/3306/cytube3/cytube3/空/10数据库连接与连接池
listen(数组)ip/port/http/https/io/url8080 http + 1337 io监听端口与服务标志
httpdefault-port8080生成链接的默认端口
httproot-domain / alt-domainslocalhost / ['127.0.0.1']Cookie 绑定域 ✅(排障验证)
httpcookie-secretchange-meCookie 签名密钥
httpminify / max-age / gzip / gzip-thresholdfalse / 7d / true / 1024静态资源压缩缓存 ✅(gzip 日志回显)
httpindex.max-entries50首页公开频道列表上限
httptrust-proxies['loopback']反代真实 IP 透传
httpsenabled 等falseTLS 全套(生产必开)
html-templatetitle / descriptionSync / Free, open source synchtube站点名与描述 ✅
iodomain / default-porthttp://localhost / 1337实时通道对外地址
ioip-connection-limit10单 IP 并发连接上限
iocors.allowed-origins[]额外跨域来源
—youtube-v3-key空YouTube Data API 密钥
—twitch-client-idnullTwitch VOD 查询密钥
—max-channels-per-user5每账号频道注册上限
—max-accounts-per-ip5每 IP 注册账号上限
—guest-login-delay60游客登录限流(秒)✅
—max-chat-message-length320聊天消息长度上限,硬顶 1000 ✅(截断行为)
—channel-pathr频道 URL 路径段 ✅
—channel-blacklist[]频道名黑名单
—channel-save-interval5频道状态保存周期(分钟)✅
aliasespurge-interval / max-age3600000 / 2592000000别名清扫周期/保留期(毫秒)
—vimeo-workaroundfalseVimeo 屏蔽兼容
reserved-namesusernames/channels/pagetitlesadmin、owner 变形正则保留名规则 ✅(五组对比)
playlistmax-items / update-interval4000 / 5队列上限 / 进度广播周期(秒)✅
—aggressive-gcfalse主动 GC(需 --expose-gc)
ffmpegenabled / ffprobe-execfalse / ffprobe直链视频探测 ✅
—link-domain-blacklist[]链接域名黑名单
setuidenabled 等falseroot 启动降权
service-socketenabled / socketfalse / service.sock管理命令套接字 ✅
—poll.max-options50投票选项上限
conf/camo.toml([camo])未配置聊天图片代理 ✅(未配置日志)
conf/captcha.toml([hcaptcha]/[register])未配置注册验证码 ✅(未配置日志)
conf/email.toml([smtp]/[password-reset]/[delete-account])未配置邮件能力 ✅(未配置日志)
conf/prometheus.toml([prometheus])未配置指标暴露 ✅(/metrics 回显)

十四、参考链接