服务器运维
管理与设置
管理页面、注册验证码的发送(短信和电子邮件)、服务器设置值、备份与安全——面向运营方的参考。
服务器内置了一个用浏览器打开的管理页面。你可以在这里查看服务器状态,决定如何发送注册和登录验证码,并管理用户和机器人。本文档把管理页面和服务器设置值集中整理在一处,供查阅。如果需要先安装,请参阅服务器安装。
打开管理页面
管理页面位于管理 HTTP 端口(生产配置中为 8080)的 /admin/,只能在服务器本机(127.0.0.1)上打开。运营方通过 SSH 隧道进入。
# 在自己的电脑上执行(保持运行)
ssh -N -L 8080:127.0.0.1:8080 <用户>@<服务器>
# 浏览器:http://localhost:8080/admin/
# 令牌(在服务器上查看)
sudo cat /srv/pabal/pabal_server/data/admin-token
输入令牌后点打开(열기)。浏览器会记住令牌,可以用右上角的清除令牌(토큰 지우기)将其清除。如果要自行设定令牌,请设置 TELEGRAM_ADMIN_TOKEN(至少 16 个字符)——这样就不会写入文件。
各标签页显示的内容
| 标签页 | 内容 | 刷新 |
|---|---|---|
| 仪表盘(대시보드) | 当前在线的用户、会话和连接,用户、机器人、群组、消息、照片和文件的数量,运行时间、端口、数据库,JVM,状态检查。测试号码开启时会显示警告横幅 | 5 秒 |
| 注册验证码(가입 코드) | 等待中的验证码(号码、发送方式、发送状态、验证码、剩余时间、输错次数)和最近记录。可以复制或取消验证码 | 3 秒 |
| 用户(사용자) | 所有账号——手机号码、登录邮箱(可编辑)、是否在线、登录设备数、消息数。退出所有设备(모든 기기 로그아웃)、封禁号码(번호 차단)、删除账号(계정 삭제,需附上核实本人身份的备注——删除后只留下账号 id 和备注) | 10 秒 |
| 机器人(봇) | 用 BotFather 创建的机器人——创建者、命令菜单、连接方式(MTProto · HTTP 轮询 · Webhook 地址及失败原因)、等待中的更新数量 | 10 秒 |
| 语音(음성) | 语音机器人——网关、中继和隐私政策的状态、紧急停止开关、正式开放、允许文字记录、正在进行的通话及挂断、允许和暂停机器人、测试者、限额(见下文) | 5 秒 |
| 举报(신고) | 通过应用中的“举报”提交的内容——举报时内容的副本(发送者删除后也能查看)。删除(对话双方;如果是群组,则从所有成员处删除)、停用账号(退出所有设备,无法再登录或注册)、已停用账号的列表。在停用状态下注销的账号,其号码在注销后 1 年内(默认)不能重新注册——可在停用时延长,或之后在列表的限制重新注册(재가입 막기)中延长到更晚的截止日期(以 1 年和所选日期中较晚者为准,不会缩短)或无限期(管理 API:POST /admin/api/reports/<id>/suspend {"userId": …, "blockSignupUntil": "2028-01-01"} 或 "blockSignupForever": true;之后修改用 POST /admin/api/suspensions/<id>/block-signup,请求体为空则恢复默认)。已处理的举报也能查看。已处理的举报自处理之日起满 3 年后连同副本一并删除(卡片上显示该日期);如出现纠纷、调查或诉讼,保留(보존)会一直保存到解除为止(管理 API:POST /admin/api/reports/<id>/hold,解除用 /release) | 10 秒 |
| 客服中心(고객센터) | 发给 @PabalSupport 的对话。选中对话回复后,会以客服机器人的名义发到该对话中 | 10 秒 |
| 设置(설정) | 注册和登录规则、应用审核账号、短信、电子邮件(SMTP)、封禁手机号码、网站上显示的运营方信息 | 手动保存 |
| 保留用户名(예약 아이디) | 预先封住、谁都不能占用的用户名——搜索、添加、下载列表(.txt)、服务器默认封住的用户名。已被别人使用的名称,保留后也不会被收回 | 打开时一次 |
| 存储(저장소) | 数据目录和数据库地址(密码会被隐藏)、照片和文件的数量与容量、按类型统计的存储流数量 | 10 秒 |
危险的操作(退出登录、封禁、取消验证码)需要点击两次才会执行。
注册和登录验证码
用户在应用中输入手机号码后,服务器会生成验证码,并通过在设置(설정)标签页中选定的方式发送出去。
| 发送方式 | 验证码的去向 | 应用界面 |
|---|---|---|
| 管理页面(관리 화면) | 注册验证码(가입 코드)标签页。由运营方复制后直接告知用户 | 号码 → “验证码已发送” → 验证码(新号码还要输入名字) |
| SMS | 通过 Twilio · Solapi · Webhook 之一发送短信 | 与管理页面方式相同 |
| 电子邮件(이메일) | 通过 SMTP 发送邮件 | 号码 → 输入电子邮件 → “验证码已发送到电子邮件” → 验证码 |
- 在电子邮件方式下,新注册可以使用任意地址,该地址会成为账号的登录邮箱(로그인 이메일)。已有账号只能通过已登记的登录邮箱接收——这是为了防止有人在别人的号码上填入自己的地址来登录。没有登录邮箱的已有账号,会改用短信(如已设置)或管理页面发送。可以在用户标签页中为其填入登录邮箱。
- 发送在后台进行,应用会直接进入输入验证码的界面。发送结果(成功或失败及原因)会显示在注册验证码标签页中。
- 注册(输入名字)只有在验证码输入正确之后才能进行。错误的验证码只接受允许的次数,超过之后,即使输入正确的验证码也会被拒绝。
- 更换号码(应用的设置 → 电话号码)默认关闭,应用会显示错误。打开允许更换号码后,无论采用哪种发送方式,验证码都只通过短信发到新号码(即使打开了显示验证码,注册验证码标签页也不会显示它——在那里拿到验证码的人未必是该号码的主人),并使用短信设置中专门的更换号码文本(번호 바꾸기 문구,默认
[파발] 번호 바꾸기 확인 코드: {code})。重新发送间隔和每日上限同时适用于新号码和账号;被封禁或被停用的号码,以及其他账号正在使用的号码,在索取验证码时和更换时都会被拒绝。验证码只对该账号和该号码有效,且只能使用一次;正在等待该号码的他人的登录验证码保持不变。更换之后,旧号码不能再登录这个账号。
设置——注册和登录
| 项目 | 含义 | 默认值 |
|---|---|---|
| 允许新注册(새 가입 허용) | 关闭后只有已有账号可以登录。新号码会以“号码无效”被拒绝 | 开启 |
| 验证码发送方式(코드 전달 방식) | 管理页面 / 短信 / 电子邮件 | 管理页面 |
| 在管理页面显示验证码(관리 화면에 코드 표시) | 在短信和电子邮件方式下,也在注册验证码标签页中显示验证码(以防发送失败) | 开启 |
| 测试号码 +99966…(테스트 번호) | 按服务器设置 / 开启 / 关闭。生产环境中请关闭 | 按服务器设置 |
| 验证码位数 · 有效时间(코드 자릿수 · 코드 유효 시간) | 5~6 位 · 1~60 分钟 | 5 位 · 5 分钟 |
| 重新请求间隔 · 每日上限(재요청 간격 · 번호당 하루 최대 요청) | 同一号码再次获取验证码前需等待的秒数(0~3600)· 24 小时内的最多次数(1~1000) | 60 秒 · 10 次 |
| 允许输错次数(틀린 입력 허용 횟수) | 超过后该验证码会被锁定(1~20) | 5 次 |
| 允许更换号码(번호 바꾸기 허용) | 已登录的账号可以用应用的“更换号码”换到另一个号码。只有设置好短信之后才能打开 | 关闭 |
设置——SMS
| 服务商 | 要填写的值 | 备注 |
|---|---|---|
| Webhook(웹훅) | 接收地址(웹훅 주소,https://…)、Authorization 请求头(可选) | 服务器会发送 POST {"phone":"+8210…","code":"12345","text":"…"}。返回 2xx 即视为成功。适用于连接自建的短信服务器或其他服务 |
| Twilio | Account SID、Auth Token、发送号码(발신 번호)或 Messaging Service SID | 包括海外号码在内,覆盖全球 |
| Solapi(原 CoolSMS) | API Key、API Secret、发送号码 | 韩国国内短信。发送号码必须是在 Solapi 预先登记的号码。+82 号码会以 010… 的格式发送 |
文本(문구)中可以使用 {code}(验证码)和 {minutes}(有效时间)。默认值:[파발] 인증 코드: {code}(意为“[Pabal] 验证码:{code}”)。保存后,请用测试发送(테스트 발송)进行确认。
设置——电子邮件(SMTP)
| 服务 | 服务器 · 端口 · 安全(SMTP 서버 · 포트 · 보안) | 用户名 · 密码(사용자명 · 비밀번호) |
|---|---|---|
| Gmail | smtp.gmail.com · 587 · STARTTLS | Gmail 地址 · 应用专用密码(Google 账号 → 安全性 → 两步验证 → 应用专用密码) |
| Naver | smtp.naver.com · 587 · STARTTLS | 账号 ID · 密码(在邮件设置中开启 POP3/SMTP) |
| 公司内部邮件中继 | 中继地址 · 25 · 无(없음) | 留空 |
发件地址(보내는 주소)必须是该 SMTP 账号有权发送的地址。主题(제목)和正文(본문)中也可以使用 {code}、{minutes}。
用户管理
- 退出所有设备(모든 기기 로그아웃):断开该账号的所有登录(授权密钥)。用于丢失了设备的用户。
- 封禁号码(번호 차단):该号码将无法接收验证码,该号码的账号会立即在所有设备上退出登录。与设置标签页中的封禁手机号码(전화번호 차단)列表相同。
- 登录邮箱(로그인 이메일):在电子邮件方式下,已有账号要通过电子邮件登录时需要它。
- 删除账号(계정 삭제):用户请求删除账号时,在确认是本人之后使用。删除的内容与应用内的删除账号完全相同,且无法撤销。需要再次输入该账号的 ID 或手机号码,并写下请求从哪里来、如何确认本人的备注,才会执行。备注会与 ID、日期一起保留(其中的手机号码、邮箱地址以及该账号的名字和用户名会被去掉)。如果邮件请求不是从该账号登记的登录邮箱发来的,可在同一窗口向该账号的手机号码发送短信验证码,再填入请求人通过邮件回复的验证码进行确认。机器人和服务器自身的账号不能在这里删除。
- @BotFather 是服务器内置的机器人,不能对它执行退出登录。
机器人管理
在机器人(봇)标签页中可以查看每个机器人的连接方式——是否通过 MTProto 连接,最近 1 分钟内是否通过 HTTP 调用过 getUpdates,Webhook 地址是什么以及当前是否正在失败(包括原因)。如果等待中的更新数持续增加,说明机器人程序已经停止,或者 Webhook 正在失败。删除机器人和重新签发令牌,由创建该机器人的人在 @BotFather 中操作。
语音标签页
这里用于运营语音机器人(有人打电话时由 AI 语音模型接听的机器人,语音机器人)。即使服务器上没有开启语音,这个标签页也会显示,状态栏会告诉你缺少什么。开启方法见服务器安装——语音机器人。每 5 秒刷新一次。
| 栏目 | 显示的内容和可以进行的操作 |
|---|---|
| 最上方的数字 | 正在进行的通话 · 今天已用的时长(服务器的每日限额,通话中预留的时长) · 已连接的网关 · 开启了语音的机器人(已允许的机器人) · 测试者(是否已正式开放) |
| 状态 | 网关链路(地址,或“关闭(没有链路机密值)”(꺼짐 (링크 비밀 없음)))、通话中继(TURN;没有时显示“所有机器人通话都是忙音”(모든 봇 통화가 통화 중))、隐私政策中是否有 bot-calls 一节(没有时显示“任何机器人都不接听”(어떤 봇도 받지 않음))、等待中的同意,以及以忙音结束的电话按原因统计的次数(例如 워치가 못 거는 모드(手表无法拨打的模式)——用 Apple Watch 给使用工具、MCP、自有密钥、音频流模式或所有者文字记录的机器人打电话的情况,WATCH_NOT_YET) |
| 紧急停止开关 | 停止所有语音通话(모든 음성 통화 멈추기):按下的那一刻就在这台服务器上生效,所有正在进行的机器人通话都会结束,不再接听新通话,任何机器人都不再显示通话按钮。随后会被保存,服务器重启后依然有效(保存失败时会有警告)。用重新开放语音通话(음성 통화 다시 열기)解除 |
| 正式开放 | 正式开放前,只有下面的测试者可以给语音机器人打电话。要向所有人开放,请在输入框中原样输入 공개합니다(意为“我要公开”)并点向所有人开放(모두에게 공개)(如果服务器的接收方键 TELEGRAM_VOICE_RECIPIENTS 是尚未确定处理地区的 …@unset,则会被拒绝——必须先发布写入了地区的应用版本)。用恢复为仅限测试者(시험자만으로 되돌리기)撤回。正式开放前是否已完成法律审查并取得提供商(Google)的书面答复,由运营方判断——代码不会阻止 |
| 网关 | 每个已连接网关的 id、承担的通话数/容量、声音发送的去向(google.vertex.gemini-live@us-central1 等)、功能(tools·byok·transcripts·stream …)、引擎、boot |
| 文字记录 · 自有密钥 | 允许文字记录:在输入框中输入 대화 기록을 허용합니다(意为“我允许文字记录”)并点允许文字记录(대화 기록 허용)。完成法律审查之前请不要允许。关闭后立即生效,并会丢弃正在进行的通话以及机器人尚未取走的对话文字。来电者选择的保存对话与这项允许无关,管理页面上也没有它的开关——由隐私政策中的 bot-calls-keep-text 一节开启(服务器安装——保存对话)。自有密钥:是否接受及不接受的原因、主密钥 id、有密钥的机器人数量(密钥本身不会出现在任何地方) |
| 正在进行的通话 | 通话 id、机器人、来电者(名字和 id)、状态、已用时长/最长时长、网关、未完成的工具查询数。挂断(끊기)(需点击两次才执行) |
| 语音机器人 | 可以使用语音的机器人:仅限已允许的机器人(허용한 봇만)(默认)或用 @BotFather 创建的所有机器人(@BotFather 로 만든 모든 봇)。按机器人 id 或 @用户名允许(허용)。表格:机器人、创建者、状态(开启/关闭、能否接听及原因、暂停、音频流模式下声音发送的地址、工具及回答/错误/超时次数)、音色和语言、限额、今天的通话。可以进行的操作:允许(허용)·取消允许(허용 취소)、检查后再次允许(확인하고 다시 허용)、暂停(멈추기)(必须填写原因,200 个字符,会显示给机器人所有者,正在进行的通话会结束)·恢复(다시 열기)、查看设置(설정 보기) |
| 查看机器人的设置 | 指令和问候语的原文(供审查)、工具定义以及各工具的响应时间(p50·p95)、工具查询的去向、同意的规则版本、冒充检查的适用和豁免、最近的变更,以及每月的通话、时长、未接和拒绝 |
| 测试者 | 按人的 id 或 @用户名(@ 可有可无,不区分大小写)加为测试者(시험자로 넣기)·移除(빼기)(机器人和服务器自身的账号不行)。通过服务器设置 TELEGRAM_VOICE_TESTERS 加入的人显示为“服务器”(서버),不能在这里移除 |
| 限额 | 下表 + 加入冒充检查的名字(사칭 검사에 더할 이름)(每行一个)。保存时会告诉你哪些机器人因此无法再接听电话 |
| 机器人打来的电话 | 全局开关:在框中原样输入 봇이 거는 전화를 켭니다 后开启——只能在法律审查之后(许可窗口文字的 callme.legal_review 不是 done 时会被拒绝;开发和测试服务器的例外是 TELEGRAM_VOICE_CALLME_UNREVIEWED)。关闭后新请求立即返回 503。国家(默认 82,999 仅限测试服务器)、限额(生产服务器不会保存比下限更宽松的值)、所有者已开启的机器人列表(审核状态、令牌暂停、自动停止、今天的请求),以及在机器人详情(名称、@用户名、照片、指令、问候语、工具、音色、语言、模式、目的、所有者姓名及其 outboundReviewHash)中许可、撤回许可,自动停止的解除,各判定阶段的拒绝次数 |
允许就是审查。在“仅限已允许的机器人”模式下允许一个机器人,就等于允许了它当前的指令、问候语和工具(音频流模式下是音频流地址)。如果机器人所有者修改了其中任何一项,机器人表格中会显示“指令·问候语已更改——检查后再次允许才会接听电话”(지시문·인사말이 바뀜 — 확인하고 다시 허용해야 전화를 받습니다),在你点检查后再次允许(확인하고 다시 허용)之前,该机器人不会接听电话。机器人语言不是韩语或英语的机器人,即使在“用 @BotFather 创建的所有机器人”模式下也是如此——因为保存时的自动规则检查只能读懂韩语和英语。这类机器人的表格中会显示“韩语、英语以外的机器人(自动规则检查读不懂):请阅读指令和问候语——检查后再次允许才会接听电话”(한국어·영어가 아닌 봇 (자동 규칙 검사가 읽지 못함): 지시문·인사말을 읽어 주세요 — 확인하고 다시 허용해야 전화를 받습니다),请让能读懂该语言的人阅读指令和问候语后再允许。
| 限额 | 默认 | 范围 |
|---|---|---|
| 一通电话的最长时间(秒) | 600 | 60~3600,不超过服务器设置 TELEGRAM_VOICE_MAX_SECONDS |
| 单个机器人的同时通话数 | 2 | 1~100,不超过服务器设置 TELEGRAM_VOICE_BOT_CONCURRENCY |
| 每人每小时的通话次数 | 20 | 1~200 |
| 每人每天的通话(分钟) | 60 | 1~600 |
| 单个机器人每天的通话(分钟) | 60 | 1~6000 |
| 单个机器人所有者每天的通话(分钟) | 120 | 1~6000 |
| 整个服务器每天的通话(分钟) | 300 | 1~100000 |
| 接听的最短通话(秒) | 60 | 30~300——剩余时长少于这个值时不接听 |
| 新账号限制(天) | 7 | 0~90(0 = 关闭)——测试者,以及机器人一天以前给其发过消息的人除外 |
- “一天”以服务器的时区为准(
TELEGRAM_VOICE_TIME_ZONE,默认Asia/Seoul)。接听通话时,在当天剩余时长内确定最长时间,并在所有限额中预留;结束后只按服务器时钟的实际秒数计费。用机器人所有者的自有密钥接听的通话,只占用来电者的限额。 - 机器人所有者只能在这些限额以内设定自己机器人的通话时长(默认 300 秒)和同时通话数。
- 所有操作(紧急停止开关、正式开放、允许、暂停、挂断、限额 …)都会以
음성: …(意为“语音:…”)记录在注册验证码标签页的活动记录中。 - 语音通话的质量数据(到第一声的时间、插话时停下所需的时间、工具的响应时间等)不在这个标签页中,只在管理端口的
/metrics中(JSON 中以voice.开头,Prometheus 格式/metrics?format=prometheus中以voice_开头的名称)。其中不含人、机器人或话语,只有合计值。
同样的操作也可以通过管理 API 完成(均需 Authorization: Bearer <令牌>):GET /admin/api/voice、GET /admin/api/voice/bots/<id>,以及用 POST 调用 voice/kill {"on": true}、voice/launch {"launched": true, "confirm": "…"}、voice/transcripts {"allowed": true, "confirm": "…"}、voice/testers·voice/testers/remove {"userId": …}、voice/gate {"botGate": "ALLOWLIST"}、voice/bots/allow·voice/bots/disallow {"botId": …}、voice/bots/<id>/suspend {"reason": "…"}·…/lift·…/name-exempt、voice/calls/<id>/end,限额则用 /admin/api/settings/voice。机器人打电话:voice/outbound {"on": true, "confirm": "…"}、voice/outbound/settings {"countries": […], "limits": {…}}、GET /admin/api/voice/outbound/bots/<id>、voice/outbound/bots/allow {"botId": …, "expect": "<outboundReviewHash>"}·voice/outbound/bots/disallow、voice/outbound/bots/<id>/lift。
环境变量
服务器先读取配置文件(server-config.json),然后用环境变量覆盖。生产环境的 Compose 文件会设定下列值,因此通常只需修改 .env。
| 变量 | 含义 | 生产 Compose 中的值 |
|---|---|---|
TELEGRAM_PORT | MTProto 端口 | MTPROTO_PORT(8443) |
TELEGRAM_HOST | MTProto 监听的地址 | 0.0.0.0 |
TELEGRAM_PUBLIC_HOST | 告知应用的服务器地址(help.getConfig) | PUBLIC_IP |
TELEGRAM_WEB_PORT | 网站、文档、Bot API、管理页面的端口 | 8080 |
TELEGRAM_WEB_HOST | 该端口监听的地址。默认为 127.0.0.1 | 0.0.0.0(容器内。在主机上只以 127.0.0.1 公开) |
TELEGRAM_PUBLIC_URL | 网站地址。用于链接(me_url_prefix)、邀请链接、文档示例、预览图片 | https://DOMAIN/ |
TELEGRAM_DATA_DIR | 照片、文件、admin-token、operations.json 的位置 | /app/data |
TELEGRAM_RSA_KEY | 服务器 RSA 私钥的路径(不存在时首次启动会生成,公钥为 .pub) | /app/keys/private.pem |
TELEGRAM_DC_ID | 这台服务器的 DC 编号。必须与应用作为主 DC 使用的编号一致(所有 Telegram 应用都是 2)——否则照片和文件的下载不会开始 | DC_ID(2) |
TELEGRAM_DB_TYPE | memory · h2 · postgresql | postgresql |
TELEGRAM_DB_URL, TELEGRAM_DB_USERNAME, TELEGRAM_DB_PASSWORD | JDBC 连接 | jdbc:postgresql://pabal-postgres:5432/pabal, pabal, POSTGRES_PASSWORD |
TELEGRAM_DB_MAX_POOL_SIZE | 数据库连接数 | 20 |
TELEGRAM_ADMIN_TOKEN | 管理页面令牌(留空时在 data/admin-token 中生成) | ADMIN_TOKEN |
TELEGRAM_MAX_FILE_SIZE | 可以发送的最大文件(2GB·512MB·字节数)。分片会随到随写入磁盘,因此受到限制的是磁盘而不是内存 | MAX_FILE_SIZE(2GB) |
TELEGRAM_TEST_NUMBERS | +99966… 测试号码。仅限开发 | false |
TELEGRAM_WEBHOOK_ALLOW_LOCAL | 允许机器人 Webhook 使用 http:// 和内部地址。仅限开发 | (未设置 = false) |
TELEGRAM_FCM_CREDENTIALS | Android 推送用的 Firebase 服务账号密钥文件路径。留空则关闭推送(服务器安装——第 10 步) | FCM_CREDENTIALS(空) |
TELEGRAM_FCM_PROJECT_ID | 仅当要发送到密钥文件中 project_id 以外的 Firebase 项目时 | FCM_PROJECT_ID(空) |
TELEGRAM_PUSH_PREVIEWS | 设为 false 时,推送通知中不含消息内容,只显示发送者 | PUSH_PREVIEWS(true) |
TELEGRAM_TURN_HOST、TELEGRAM_TURN_PORT、TELEGRAM_TURN_SECRET | 通话中继(TURN)——位于不同网络的两个应用会合的地方。机密值为空时只有直连(服务器安装——通话中继) | TURN_HOST(为空则用 DOMAIN)、TURN_PORT(3478)、TURN_SECRET(为空) |
TELEGRAM_APNS_KEY、TELEGRAM_APNS_KEY_ID、TELEGRAM_APNS_TEAM_ID、TELEGRAM_APNS_TOPIC、TELEGRAM_APNS_MIN_BUILD、TELEGRAM_APNS_VOIP_MIN_BUILD | iPhone 推送(APNs)——密钥文件路径、密钥 ID(为空则从文件名读取)、为应用签名的团队、Bundle ID、推送的最低版本号、使用 CallKit 通话界面的第一个版本号。没有密钥时 iPhone 推送关闭(服务器安装——第 11 步) | APNS_*(无密钥、为空——从文件名读取、4Z8R468M2D、me.pabal.ios、4、为空) |
TELEGRAM_STATIC_MAPS_KEY、TELEGRAM_STATIC_MAPS_PER_DAY、TELEGRAM_STATIC_MAPS_PER_USER_HOUR | 位置消息中的地图图片——Google Maps Static API 密钥、每天新获取的图片数、一个人每小时能让服务器新获取的图片数。没有密钥时地图图片关闭(服务器安装——地图图片) | STATIC_MAPS_*(无密钥、300、120) |
JAVA_OPTS | JVM 选项(内存) | .env 中的值 |
环境变量——语音机器人
在生产环境中,附加文件 deploy/docker-compose.voice.yml 会用 .env 中的值设置其中的链路、中继、时区、限额、测试者和最低版本,其余的按功能分别审查后再加(服务器安装——语音机器人)。网关(pabal-voice)的 VOICE_* 设置在代码仓库的 voice/README.md 中。
| 变量 | 默认 | 含义 |
|---|---|---|
TELEGRAM_VOICE_LINK_SECRET_FILE | — | 与网关相同的 32 字节链路机密值(64 位 hex)。不存在或有误时语音关闭 |
TELEGRAM_VOICE_LINK_HOST, TELEGRAM_VOICE_LINK_PORT | 127.0.0.1, 8095 | 链路监听的位置。不是回环地址时需要 TELEGRAM_VOICE_LINK_ANY_ADDRESS=true,公网地址总是被拒绝 |
TELEGRAM_VOICE_LINK_ANY_ADDRESS | — | 声明“这个网络只有服务器和网关使用” |
TELEGRAM_VOICE_TURN_HOST, TELEGRAM_VOICE_TURN_PORT | — | 交给网关的中继地址(服务器的局域网地址)。是回环地址时忽略 |
TELEGRAM_VOICE_MAX_SECONDS | 600 | 这台服务器允许的最长通话(60~3600) |
TELEGRAM_VOICE_BOT_CONCURRENCY | 2 | 单个机器人同时通话数的上限(运营方和机器人所有者只能调低) |
TELEGRAM_VOICE_TIME_ZONE | Asia/Seoul | 每日、每月限额的基准 |
TELEGRAM_VOICE_TESTERS | — | 测试者用户 id 列表(与管理页面的列表合并)。* 只用于测试服务器 |
TELEGRAM_VOICE_RECIPIENTS | google.vertex.gemini-live@us-central1 | 应用确认窗口所说的接收方。必须与网关的相同,通话才能接通 |
TELEGRAM_VOICE_MIN_BUILD_DESKTOP, _ANDROID, _IOS, _WATCHOS | 1, 62151, 5, 1 | 真正包含确认窗口的第一个应用版本(桌面版是标记 pabal-bc 后面的数字)。接收方变化时,发布新版本并调高这些值。桌面版在首次批准韩语、英语以外的确认窗口时调高到 2 |
TELEGRAM_VOICE_MIN_SHEET_VERSION | 1 | 接受的最低确认窗口版本 |
TELEGRAM_VOICE_TOOL_RESULT_BYTES | 16384 | 工具回答的最大大小(1024~16384) |
TELEGRAM_VOICE_KEYS_MASTER_FILE, TELEGRAM_VOICE_KEYS_PREVIOUS_MASTER_FILE | — | 封装自有密钥和音频流机密值的主密钥,以及更换期间的旧密钥。放在备份之外权限为 700 的文件夹中 |
TELEGRAM_VOICE_OWN_KEYS_APPS_READY | — | 只有在应用显示了自有密钥机器人的确认窗口(第 2 版)之后才设为 true。在此之前不接受自有密钥 |
TELEGRAM_VOICE_OWN_KEY_MIN_SHEET_VERSION, TELEGRAM_VOICE_TRANSCRIPT_MIN_SHEET_VERSION | 2, 1 | 自有密钥通话和文字记录提示所需的确认窗口版本(生产服务器不会把自有密钥的版本降到 2 以下) |
TELEGRAM_VOICE_STREAM_MIN_BUILD_DESKTOP, _ANDROID, _IOS | 0(无) | 包含音频流确认窗口的第一个应用版本。为 0 时谁都不能给音频流机器人打电话 |
TELEGRAM_VOICE_STREAM_MIN_SHEET_VERSION | 2 | 音频流确认窗口的版本 |
TELEGRAM_VOICE_STREAM_DENY_ADDRESSES | — | 音频流地址不得访问的本部署地址(公开主机和网站主机会自动包含) |
TELEGRAM_WATCH_API_PORT, _HOST, _ANY_ADDRESS, TELEGRAM_WATCH_AUDIO_URL, TELEGRAM_WATCH_ALLOW_PLAIN, TELEGRAM_WATCH_SESSION_DAYS, TELEGRAM_WATCH_AUTH_PER_MINUTE | —, 127.0.0.1, —, —, —, 7, 30 | Apple Watch API 和音频入口的地址(服务器安装——Apple Watch 入口)。ALLOW_PLAIN 仅限开发 |
TELEGRAM_VOICE_EVIDENCE_KEY_DIR | — | 机器人打电话的许可记录(HMAC 证据)所用密钥的文件夹。700,放在会被备份的文件夹之外。用 scripts/voice-evidence-key.py 创建和更换。没有它,谁都不能开启许可。使用 Docker Compose 时,只写在 .env 里不会传到服务器——开启机器人打来的电话时,把它加到 deploy/docker-compose.voice.yml 中 pabal-server 的 environment(容器内的路径)和 volumes(主机上的那个文件夹) |
TELEGRAM_VOICE_OUTBOUND_MIN_BUILD_DESKTOP、_ANDROID、_IOS、_WATCHOS | 0(无) | 带许可窗口的第一个应用版本。更旧的版本不能开启许可,机器人的来电也不会让它响铃。0 表示该平台没有 |
TELEGRAM_VOICE_CALLME_DEVICE_AGE_SECONDS | 86400 | 设备登录后多久才能开启许可(秒)。只有测试服务器可以更改(生产服务器会警告并忽略) |
TELEGRAM_VOICE_KEEP_TEXT_UNREVIEWED | — | 在法律审查之前就把保存对话复选框的文案显示在手表上。仅限内部测试服务器 |
TELEGRAM_MCP_*, TELEGRAM_MCP_APPS_READY | — | MCP 组件(由 deploy/docker-compose.mcp.yml 填入)。即使不使用 MCP,TELEGRAM_MCP_EGRESS_OWN_ADDRESSES(Pabal 的公网地址)也会用来防止 Webhook 和工具请求发往 Pabal 自身 |
TELEGRAM_VOICE_BOTS, TELEGRAM_VOICE_NOTICE_CHECK=off, TELEGRAM_VOICE_STREAM_ALLOW_PRIVATE | — | 仅限测试服务器(只在 TELEGRAM_TEST_NUMBERS=true 时):允许列出的机器人(id 或 @用户名,* 为所有机器人) · 跳过法律条款检查 · 音频流地址可以使用私有地址 |
TELEGRAM_VOICE_CALLME_UNREVIEWED, TELEGRAM_VOICE_DEV_ECHO_OUTBOUND, TELEGRAM_VOICE_TEST_DIAL, TELEGRAM_VOICE_TEST_DIAL_USERS | — | 仅限测试和开发服务器:可以在法律审查前打开机器人打电话的开关(开发和测试服务器)· 由回声网关拨打机器人的电话(开发服务器,TELEGRAM_TEST_MODE)· 管理 API 的测试拨号及其可拨打的账号(+99966 测试号码之外最多 20 个,测试服务器)。生产服务器会警告并忽略 |
数据文件
| 文件 | 内容 | 权限 |
|---|---|---|
keys/private.pem | 服务器 RSA 私钥。绝不外传 | 600 |
keys/private.pem.pub | 公钥。用于构建应用和 /docs/server-key.pem | — |
keys/firebase-service-account.json | (可选)Android 推送用的 Firebase 私钥。泄露时在 Firebase 控制台中删除并重新获取 | 600 |
data/admin-token | 管理页面令牌 | 600 |
data/operations.json | 设置标签页中的值——注册规则、短信和 SMTP 的机密值、封禁的号码,以及语音标签页的设置(紧急停止开关、正式开放、测试者、已允许的机器人、限额) | 600 |
keys/voice-link.secret | (语音机器人)与网关相同的链路机密值 | 400 |
/etc/pabal/voice/voice-master.key | (语音机器人)封装机器人所有者自有密钥和音频流机密值的主密钥。放在数据文件夹之外,不放进备份 | 600(文件夹 700) |
data/media/ | 照片和文件的原始文件 | — |
PostgreSQL events 表 | 账号、对话、消息、登录、机器人、Webhook 设置——所有变更的记录 | — |
安全须知
- 不要把管理端口直接开放到互联网上。生产配置中的 Caddy 会以 404 拦截
/admin、/health、/metrics等管理路径。 - 所有管理数据请求都需要
Authorization: Bearer <令牌>,其他网站的页面无法读取这些数据。 - 短信和 SMTP 的机密值只保存在
operations.json中,界面和 API 只会告知“已保存”。机密值输入框留空保存时,会保留原来的值。 - 令牌和机密值不会写入日志,日志中的手机号码会做遮盖处理。Bot API 地址(包含令牌)也不会写入日志。
- 推送通知的设备令牌在日志中只以指纹形式记录,Firebase 密钥文件的内容和通知内容都不会写入日志。
- 授权密钥保存在数据库中,因此能够访问数据库的人就能解密用户流量。请像保护 RSA 密钥一样保护数据库和备份。
已知限制
- 等待中的验证码和最近记录保存在内存中,服务器重启后会丢失(在应用中重新请求即可)。
- 短信服务商的实际发送效果,需要用各服务商的账号来确认。服务器按照各服务商的文档来构造请求。
- 尚未提供的功能:强制删除机器人、查看消息、查看日志、图表、推送通知统计(推送情况请通过服务器日志确认)。