部署落地:HAProxy 统一入口(RTMPS/HTTP分流) + 8445拉流弹幕口 + hooks 公网化 + 部署文档

- conf/haproxy: 18443 TLS终结+SNI选证+首字节嗅探,RTMPS→1935,HTTP→8445
- conf/nginx:   8445 明文口承载 tsk 双域名 /live/ 与 /danmaku
- conf/certs:   pem 构建脚本(接入 acme.sh 续期钩子)
- run.sh:       修正为当前部署相对路径
- srs.conf:     http_hooks 恢复并指向 api.rrrosmontis.icu (bj live_monitor)
- DEPLOYMENT.md: 完整部署记忆(架构/证书/通知链路/重建步骤/已知坑)
This commit is contained in:
RRRosmontis
2026-09-03 11:24:33 +08:00
parent 41b5da7c7e
commit 359c1c6ead
7 changed files with 240 additions and 3 deletions
+4
View File
@@ -5,3 +5,7 @@ __pycache__/
trunk/objs/
trunk/3rdparty/
*.flv
# 部署运行时产物
danmaku/venv/
*.log
+107
View File
@@ -0,0 +1,107 @@
# 部署记忆文档 — srs-and-danmaku-linux
> 部署位置:**cf 服务器**(Celestial-Fulcrum,Ubuntu 24.04,本仓库即部署目录 `/home/srs`)
> 部署日期:2026-09-01 ~ 09-03
> 上游:https://git.rrrosmontis.icu/RoyirinRosmontis/srs-and-danmaku-linux(本仓库)
## 1. 总体架构
```
外网 443(Sakura Frp HTTPS 隧道 ×2,TLS 透传到本机)
├── srs_oversea: tsk.aeolianchi.me (frp-age 节点) ──┐
└── srs_cn: tsk.rrrosmontis.icu (frp-hip 节点) ─┴→ 本机 :18443
│
HAProxy [TLS终结 + 按SNI选证 + 首字节嗅探]
├── 解密后 0x03 (RTMPS 推流) → 127.0.0.1:1935 (SRS)
└── HTTP (拉流/弹幕) → 127.0.0.1:8445 (nginx)
├── /live/ → 127.0.0.1:8080 (SRS HTTP-FLV/HLS)
└── /danmaku → 127.0.0.1:55556 (弹幕 WebSocket)
```
- **推流**:`rtmps://tsk.aeolianchi.me:443/live/room_<房间号>` 或 `rtmps://tsk.rrrosmontis.icu:443/live/room_<房间号>`(OBS / ffmpeg 均可)
- **拉流**:`https://tsk.rrrosmontis.icu/live/room_<房间号>.flv`(或 `.m3u8`,me 域名同)
- **弹幕**:`wss://tsk.rrrosmontis.icu/danmaku`
- 设计要点:全部业务共用 443 对外端口;推流用 **RTMPS**(裸 RTMP 无 SNI 无法过 HTTPS 隧道);nginx stream ssl_preread 分不开「同 SNI 的 RTMPS/HTTPS」,故用 **HAProxy 先终结 TLS 再嗅探首字节**(RTMP 握手恒为 0x03,HTTP 以方法字符开头)。
## 2. 本机组件与路径
| 组件 | 路径 | 说明 |
|---|---|---|
| SRS 源码+编译产物 | `/home/srs/trunk/` | SRS 6.0.172(上游 tag v6.0-b0),二进制 `trunk/objs/srs` |
| 弹幕后端 | `/home/srs/danmaku/danmaku_backend.py` | FastAPI + uvicorn,端口 55556,venv 在 `danmaku/venv/`(gitignore) |
| HAProxy 配置 | `conf/haproxy/haproxy.cfg` | 软链 → `/etc/haproxy/haproxy.cfg` |
| nginx 8445 口 | `conf/nginx/srs-https-8445.conf` | 软链 → `/etc/nginx/sites-enabled/srs-https-8445.conf`(明文 HTTP,TLS 已在 HAProxy 终结) |
| 证书 pem 构建脚本 | `conf/certs/build-pems.sh` | 生成 `/etc/haproxy/certs/*.pem`(cert+key 合一;**私钥不入库**,pem 只在 /etc 下) |
| 主配置 | `trunk/conf/srs.conf` | RTMP 1935 / API 1985 / HTTP 8080 / WebRTC 8000(UDP) |
### systemd 服务(均 enabled 开机自启)
| 服务 | 启动 | 日志 |
|---|---|---|
| `srs-server.service` | `trunk/run.sh`(`./objs/srs -c ./conf/srs.conf`,WorkingDirectory=/home/srs/trunk) | `journalctl -u srs-server -f` |
| `srs-danmaku.service` | `danmaku/venv/bin/python danmaku_backend.py` | `journalctl -u srs-danmaku -f` |
| `haproxy.service` | `/etc/haproxy/haproxy.cfg`(软链至 conf/) | `journalctl -u haproxy -f` |
## 3. 证书与续期
- `tsk.aeolianchi.me`:acme.sh(阿里云 DNS API,ecc),装于 `/etc/nginx/cert/tsk.aeolianchi.me/`
- `tsk.rrrosmontis.icu`:复用 acme.sh 泛域名证书 `*.rrrosmontis.icu`(`/home/server/cert/extra/rrrosmontis.icu/`)
- **续期钩子**:两张证书的 `--reloadcmd` 均为 `conf/certs/build-pems.sh && systemctl reload nginx && systemctl reload haproxy`,续期后自动重拼 pem 并重载,无需人工干预
## 4. 开播通知链路(http_hooks)
```
SRS on_publish/on_unpublish
→ https://api.rrrosmontis.icu/v1/live/publish/local/on_publish (bj nginx 公网入口)
→ bj:1986 /remote_srs/local/on_publish (live_monitor.py, napcat 伴生 Flask)
→ 按 record.json 关注列表发 QQ 通知;返回 {"code":0} 放行推流
```
- SRS 6.0 的 http_hooks 原生支持 https 回调(源码 http client 带 TLS)
- **流名必须为 `room_<房间号>`** 才会被识别为房间;hook 失败 SRS 会拒绝推流
- 主站(aliyun)走 `/remote_srs/on_publish`(site=1),本机为副站(`/remote_srs/local/...`,site=2)
## 5. 前端页面(hk 服务器)
- `https://lfr.aeolianchi.me` → hk:/home/srs-frontend(index.html + js/hls、mpegts 播放库)
- 页面内副站地址已改为 `tsk.rrrosmontis.icu`(拉流 base + 弹幕 wss)
- hk nginx:`/etc/nginx/conf.d/lfr.aeolianchi.me.conf`(80 跳转 + 443 静态,证书 webroot HTTP-01 自动续期)
## 6. 从零重建步骤(换机/重装备忘)
1. `git clone` 本仓库到部署目录(如 `/home/srs`)
2. 补编译依赖:`apt install -y automake autoconf libtool pkg-config tclsh cmake`(另需 gcc/g++/make)
3. **补齐 `trunk/3rdparty/`**(仓库 .gitignore 排除了它,裸仓库无法编译):从官方 `ossrs/srs` tag `v6.0-b0` 稀疏克隆 `trunk/3rdparty` 拷入——版本号必须与本仓库 `trunk/src/core/srs_core_version6.hpp` 的 `VERSION_REVISION` 一致(当前 172)
4. 编译:`cd trunk && ./configure && make -j$(nproc)`(大任务放 tmux)
5. 弹幕后端:`python3 -m venv danmaku/venv && danmaku/venv/bin/pip install fastapi 'uvicorn[standard]'`
6. 软链配置:`conf/haproxy/haproxy.cfg → /etc/haproxy/haproxy.cfg`、`conf/nginx/srs-https-8445.conf → /etc/nginx/sites-enabled/`
7. 证书签发(acme.sh dns_ali)+ `build-pems.sh` + 续期钩子(见第 3 节)
8. systemd:创建 `srs-server.service` / `srs-danmaku.service`(见第 2 节),`daemon-reload && enable --now`
9. Sakura Frp:两条 HTTPS 隧道绑定各自域名,本地目标 `127.0.0.1:18443`
## 7. 已知行为与坑
- **SRS 对不在线流的 .flv 请求会挂住连接等流出现**(不是 404)——拉流方需自行设置超时;测试时推流建立延迟会造成"拉到 0 字节"的假象
- `srs.conf` 中 `rtc_server.candidate = 39.97.55.150`(bj 公网 IP):WebRTC 播放需 UDP 8000 能路由到该地址,当前未配转发,WebRTC 播放未打通(HTTP-FLV/HLS 不受影响)
- `daemon off` + 控制台日志是配合 systemd 的刻意配置,非调试残留
- 免费版 Sakura 节点偶发新连接抖动,客户端重试即可
- `run.sh` 依赖 systemd 的 `WorkingDirectory=/home/srs/trunk`(内用相对路径),改路径两处同步
## 8. 本仓库相对上游的变更
| 文件 | 变更 |
|---|---|
| `trunk/run.sh` | 修正旧绝对路径(srs-server-6.0-b0 → 当前部署路径),改为相对路径 |
| `trunk/conf/srs.conf` | http_hooks 指向 api.rrrosmontis.icu 公网入口(bj live_monitor) |
| `conf/` | 新增:HAProxy 分流配置、nginx 8445 拉流/弹幕口、pem 构建脚本 |
| `.gitignore` | 追加 `danmaku/venv/`、`*.log` |
| `DEPLOYMENT.md` | 本文档 |
## 9. 快速运维
```bash
systemctl restart srs-server srs-danmaku # 重启业务
journalctl -u srs-server -f # 看 SRS 日志(含 hook 回调记录)
/home/srs/conf/certs/build-pems.sh # 手动重建 HAProxy pem
tmux attach -t <会话> # 编译类长任务用 tmux(单字母命名惯例)
```
+12
View File
@@ -0,0 +1,12 @@
#!/bin/bash
# 重建 HAProxy 用的 pem(cert+key 合一),由 acme.sh 续期钩子调用
set -e
mkdir -p /etc/haproxy/certs
cat /etc/nginx/cert/tsk.aeolianchi.me/fullchain.pem \
/etc/nginx/cert/tsk.aeolianchi.me/privkey.pem \
> /etc/haproxy/certs/tsk.aeolianchi.me.pem
cat /home/server/cert/extra/rrrosmontis.icu/fullchain.pem \
/home/server/cert/extra/rrrosmontis.icu/key.pem \
> /etc/haproxy/certs/tsk.rrrosmontis.icu.pem
chmod 600 /etc/haproxy/certs/*.pem
echo "pems rebuilt: $(date)"
+41
View File
@@ -0,0 +1,41 @@
# HAProxy — SRS 统一入口(HTTPS 隧道 443 -> 本机 18443)
# TLS终结 + 首字节嗅探:
# RTMPS (解密后首字节 0x03) -> 127.0.0.1:1935 (SRS 推流)
# HTTP (拉流 /danmaku) -> 127.0.0.1:8445 (nginx 明文口)
# 证书: /etc/haproxy/certs/*.pem (由 /home/srs/conf/certs/build-pems.sh 生成)
global
log /dev/log local0
log /dev/log local1 notice
chroot /var/lib/haproxy
stats socket /run/haproxy/admin.sock mode 660 level admin
stats timeout 30s
user haproxy
group haproxy
daemon
defaults
log global
mode tcp
option tcplog
option dontlognull
timeout connect 5s
timeout client 3600s
timeout server 3600s
frontend srs_18443
bind *:18443 ssl crt /etc/haproxy/certs/tsk.aeolianchi.me.pem crt /etc/haproxy/certs/tsk.rrrosmontis.icu.pem
tcp-request inspect-delay 5s
# RTMP C0 握手首字节固定 0x03
acl is_rtmp req.payload(0,1) -m bin 03
tcp-request content accept if is_rtmp
tcp-request content accept if HTTP
tcp-request content reject
use_backend srs_rtmp if is_rtmp
default_backend srs_http
backend srs_rtmp
server srs 127.0.0.1:1935 maxconn 100
backend srs_http
server nginx 127.0.0.1:8445 maxconn 1000
+70
View File
@@ -0,0 +1,70 @@
# SRS 拉流 + 弹幕 HTTP 口(127.0.0.1:8445,TLS 已由 HAProxy 在 18443 终结)
# 软链: /etc/nginx/sites-enabled/srs-https-8445.conf -> 本文件
# tsk.aeolianchi.me
server {
listen 127.0.0.1:8445;
server_name tsk.aeolianchi.me;
location /live/ {
proxy_pass http://127.0.0.1:8080;
proxy_http_version 1.1;
proxy_set_header Connection "";
proxy_set_header Host $host;
proxy_set_header X-Real-IP $remote_addr;
proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;
proxy_set_header X-Forwarded-Proto https;
proxy_buffering off;
proxy_request_buffering off;
proxy_cache off;
proxy_read_timeout 3600s;
proxy_send_timeout 3600s;
}
location /danmaku {
proxy_pass http://127.0.0.1:55556;
proxy_http_version 1.1;
proxy_set_header Upgrade $http_upgrade;
proxy_set_header Connection "upgrade";
proxy_set_header Host $host;
proxy_set_header X-Real-IP $remote_addr;
proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;
proxy_set_header X-Forwarded-Proto https;
proxy_read_timeout 3600s;
proxy_send_timeout 3600s;
}
}
# tsk.rrrosmontis.icu
server {
listen 127.0.0.1:8445;
server_name tsk.rrrosmontis.icu;
location /live/ {
proxy_pass http://127.0.0.1:8080;
proxy_http_version 1.1;
proxy_set_header Connection "";
proxy_set_header Host $host;
proxy_set_header X-Real-IP $remote_addr;
proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;
proxy_set_header X-Forwarded-Proto https;
proxy_buffering off;
proxy_request_buffering off;
proxy_cache off;
proxy_read_timeout 3600s;
proxy_send_timeout 3600s;
}
location /danmaku {
proxy_pass http://127.0.0.1:55556;
proxy_http_version 1.1;
proxy_set_header Upgrade $http_upgrade;
proxy_set_header Connection "upgrade";
proxy_set_header Host $host;
proxy_set_header X-Real-IP $remote_addr;
proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;
proxy_set_header X-Forwarded-Proto https;
proxy_read_timeout 3600s;
proxy_send_timeout 3600s;
}
}
+4 -2
View File
@@ -49,9 +49,11 @@ vhost __defaultVhost__ {
hls_cleanup on; # 自动清理过期切片
}
# http_hooks 指向 bj 的 live_monitor(副站回调),经 api.rrrosmontis.icu 公网入口
# 2026-09-01 恢复:SRS 6.0 支持 https hooks;流名需为 room_<房间号> 才触发 QQ 通知
http_hooks {
enabled on;
on_publish http://127.0.0.1:1986/remote_srs/local/on_publish;
on_unpublish http://127.0.0.1:1986/remote_srs/local/on_unpublish;
on_publish https://api.rrrosmontis.icu/v1/live/publish/local/on_publish;
on_unpublish https://api.rrrosmontis.icu/v1/live/publish/local/on_unpublish;
}
}
+2 -1
View File
@@ -1,3 +1,4 @@
#!/bin/bash
/home/srs/srs-server-6.0-b0/trunk/objs/srs -c /home/srs/srs-server-6.0-b0/trunk/conf/srs.conf
cd "$(dirname "$0")"
./objs/srs -c ./conf/srs.conf