自建 Piik 屏幕共享节点:从 Docker 到 HTTPS 的完整踩坑记录
本文最后更新于21 天前,其中的信息可能已经过时,如有错误请发送邮件到[email protected]

一、目标

Piik 是一个可自托管的网页屏幕共享 / 房间工具:网页与信令由服务器提供,画面走 WebRTC(默认 P2P,可选 SFU 兜底)。官方 demo 和 App 的公网邀请模式只有 P2P,遇到严格 NAT 容易出现「网页能开、画面连不上」。所以我决定在自己的 VPS 上搭一个专属节点,并预留 SFU 兜底端口。

服务器雨云 Ubuntu x64(公网 IP 38.246.253.12)
面板宝塔(Nginx 反向代理)
DNSCloudflare(忆水.xyz,punycode:xn--45tq0z.xyz)
部署方式Docker Compose,镜像 ghcr.io/tntcrafthim/piik:latest
证书Let’s Encrypt(acme.sh + Cloudflare DNS 验证)

二、部署本身很简单

cd /root
# compose.yaml 与 .env 放在同一目录
docker compose run --rm piik --check-config   # config=ok
docker compose up -d
docker compose logs --tail=20

看到下面这行就说明服务起来了:

msg="Piik server is listening" version=v1.9.2 host=0.0.0.0 port=8787
publicUrl=https://xn--45tq0z.xyz sqlite=true sfu=false

关键端口(Compose 会自动映射):

127.0.0.1:8787  网页 / 信令(只对本机开放,由 Nginx 反代出去)
3478-3480/udp   STUN(P2P 打洞必需)
7882/udp        SFU 媒体兜底(可选)

三、Nginx 反向代理

宝塔里用「反向代理项目」没有成功,最后手工写 vhost(/www/server/panel/vhost/nginx/xn--45tq0z.xyz.conf)反而最稳:

server {
    listen 80;
    server_name xn--45tq0z.xyz www.xn--45tq0z.xyz;

    location / {
        proxy_pass http://127.0.0.1:8787;
        proxy_http_version 1.1;
        proxy_set_header Upgrade $http_upgrade;      # WebSocket 必需
        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 $scheme;
        proxy_read_timeout 3600s;
        proxy_send_timeout 3600s;
    }
}

重要:中文域名在浏览器里发出去的是 punycode 形式的 Host,所以 server_name 必须写 xn--45tq0z.xyz,写中文匹配不上。

四、踩过的坑(重点)

现象真正原因解决
curl 返回 status=000(连响应都没有)Nginx 根本没起来:旧 vhost 里有个 listen 8787,而 8787 已被 Piik 占用 → [emerg] bind() to 0.0.0.0:8787 failed删掉或改掉那个 vhost,然后 service nginx restart
反代配了还是 Nginx 404宝塔「反向代理项目」生成的 conf 没绑定成站点,nginx -T 里查不到对应 server_name手工写 vhost,或先在宝塔「添加站点」,再进站点内加反代
域名打不开,getaddrinfo ENOTFOUNDCloudflare 里只有 www 和 * 记录,通配符不覆盖根域名补一条 @ 的 A 记录
网页能开,建房报 403 Origin not allowedPUBLIC_BASE_URL 写的是 https://…,实际却用 http://… 访问,来源不匹配让 PUBLIC_BASE_URL 等于浏览器实际访问的地址(含协议);多地址用英文逗号写进 ALLOWED_ORIGINS
Cloudflare 橙云 + Full 模式回源 404CF 用 443 回源,而源站 443 上没有该域名的 server 块要么切 Flexible(80 回源),要么给源站配好证书后用 Full
acme.sh 卡在 Could not get nonce它默认用 ZeroSSL,国内服务器连不上加 --server letsencrypt 重签,立刻成功
观众看不到画面Cloudflare 代理不转发 UDP,STUN 打洞失败stun 子域必须设成 DNS only(灰云),并放行 UDP 3478-3480
浏览器选不了屏幕浏览器屏幕采集要求 HTTPS 或 localhost给源站签真证书,改用 HTTPS 访问

五、HTTPS:acme.sh + Cloudflare DNS 验证

用 DNS 验证签证书,不需要占用 80 端口:

curl https://get.acme.sh | sh -s email=你的邮箱@gmail.com
export CF_Token="CF的API令牌"       # 权限:Zone → DNS → Edit
~/.acme.sh/acme.sh --issue --dns dns_cf --server letsencrypt \
  -d xn--45tq0z.xyz -d www.xn--45tq0z.xyz

# 装到 Nginx 使用的路径并自动重载
~/.acme.sh/acme.sh --install-cert -d xn--45tq0z.xyz \
  --key-file       /www/server/panel/vhost/cert/xn--45tq0z.xyz/privkey.pem \
  --fullchain-file /www/server/panel/vhost/cert/xn--45tq0z.xyz/fullchain.pem \
  --reloadcmd      "service nginx restart"

再补一个 443 的 server 块(listen 443 ssl; + http2 on; + 上面两个证书路径 + 同一份 proxy 配置),然后把站点地址统一成 https:

cd /root
sed -i 's|^PUBLIC_BASE_URL=.*|PUBLIC_BASE_URL=https://xn--45tq0z.xyz|' .env
docker compose up -d

自动续期(acme.sh 装 cron 失败时,用宝塔「计划任务」加一条 Shell 脚本):

"/root/.acme.sh"/acme.sh --cron --home "/root/.acme.sh" > /dev/null

六、验收清单

curl -s http://127.0.0.1:8787/healthz      # {"status":"ok"}
curl -s https://xn--45tq0z.xyz/healthz     # {"status":"ok"}
ss -lntp | grep -E ':80|:443|8787'         # nginx 听 80/443,Piik 听 8787
docker compose ps                          # 容器 Up
systemctl is-enabled docker                # enabled(开机自启)
docker inspect piik-piik-1 --format '{{.HostConfig.RestartPolicy.Name}}'   # unless-stopped

浏览器打开 https://xn--45tq0z.xyz:无证书警告、能建房;把链接发给朋友,手机用流量加入,画面和声音都正常,收工。

七、几条经验

  1. status=000 不是 404。 前者是「连接被直接关掉」(服务没在监听)。排查顺序永远是:进程 → 监听端口 → vhost 匹配 → 上游服务。
  2. 排查要分层。 本机 127.0.0.1:8787 → 本机带 Host 头 → 公网 IP 带 Host 头 → 域名。每层都拿到结论,不要跳步。
  3. 中文域名记得用 punycode(忆水.xyz = xn--45tq0z.xyz)。Nginx 的 server_name、客户端填的节点地址都建议用 punycode。
  4. Cloudflare 免费版不转发 UDP。 凡是 STUN、游戏加速这类服务,相关子域一定要设成 DNS only(灰云)。
  5. 证书必须和实际访问的协议一致,否则就是各种 403 / 526;改完 .env 记得 docker compose up -d 重建容器才生效。
文末附加内容
暂无评论

发送评论 编辑评论


				
|´・ω・)ノ
ヾ(≧∇≦*)ゝ
(☆ω☆)
(╯‵□′)╯︵┴─┴
 ̄﹃ ̄
(/ω\)
∠( ᐛ 」∠)_
(๑•̀ㅁ•́ฅ)
→_→
୧(๑•̀⌄•́๑)૭
٩(ˊᗜˋ*)و
(ノ°ο°)ノ
(´இ皿இ`)
⌇●﹏●⌇
(ฅ´ω`ฅ)
(╯°A°)╯︵○○○
φ( ̄∇ ̄o)
ヾ(´・ ・`。)ノ"
( ง ᵒ̌皿ᵒ̌)ง⁼³₌₃
(ó﹏ò。)
Σ(っ °Д °;)っ
( ,,´・ω・)ノ"(´っω・`。)
╮(╯▽╰)╭
o(*////▽////*)q
>﹏<
( ๑´•ω•) "(ㆆᴗㆆ)
😂
😀
😅
😊
🙂
🙃
😌
😍
😘
😜
😝
😏
😒
🙄
😳
😡
😔
😫
😱
😭
💩
👻
🙌
🖕
👍
👫
👬
👭
🌚
🌝
🙈
💊
😶
🙏
🍦
🍉
😣
Source: github.com/k4yt3x/flowerhd
颜文字
Emoji
小恐龙
花!
上一篇