
最近在折腾自托管先是把 Bitwarden 自托管部署搞到报错卡在证书那步一下午后来又动了在 Windows 上搭 Sentry 的念头一查内存要求直接劝退。不断试错的过程中就发现了一个冷门但很有意思的项目Neko一个可以多人协同的自托管网页浏览器。简单说它把浏览器跑在服务器容器里大家通过网页就能同时看到同一个浏览器画面还能轮流操作鼠标键盘。这篇文章我就用实际体验来聊聊 Neko 的部署、玩法、性能表现以及踩过的坑。1. Neko 到底是个什么东西1.1 一句话理解 Neko 的原理Neko 的官方定位是“self-hosted virtual browser”也就是自托管的虚拟浏览器。它没有走传统的远程桌面协议比如 RDP、VNC而是用 WebRTC 来做画面传输。服务器上跑一个 Docker 容器容器里是一个完整的 Chromium 浏览器页面内容在服务器端渲染然后通过 WebRTC 把画面实时编码成视频流推给各个浏览器端。反过来你本地的鼠标移动、点击、键盘输入会通过 WebRTC DataChannel 传回服务器驱动容器里的浏览器执行操作。这个思路和云游戏很像算是一种“浏览器即服务”的玩法。好处在于所有访客不需要安装任何客户端打开浏览器就能加入坏处也明显它本质上是流式传输对服务器带宽和 CPU 编码性能有硬性要求。对比一下其他远程访问方案方案传输内容客户端要求多人协作部署复杂度VNC整个桌面画面需要 VNC 客户端弱单向观看居多低RustDesk整个桌面画面需要客户端或 Web一般中Neko容器内浏览器画面仅需现代浏览器强多人可轮流操作中如果你只需要远程打开一个网页截图、跑个自动化脚本或者给别人演示某个网站Neko 比全桌面远程控制更轻量、更聚焦。如果目的是远程管理整台服务器那还是老老实实用传统的远程桌面方案更合适。1.2 为什么多人协同的场景需要它Neko 解决的核心痛点是“一群人对着同一个网页进行协作”。我一直觉得在线会议里的共享屏幕体验一直不算好主要问题是共享者一个人操作其他人只能被动看想上手点两下还要开远程控制权限一来一回特别费劲。Neko 把这套逻辑反过来——浏览器是公用的谁有权限谁就能操作。常用于这么几种场景远程答疑和教学老师打开一个页面学生加入后可以直接在浏览器里操作老师能看到全过程比截图描述问题效率高太多。多人测试和验收几个人同时看同一个后台系统谁发现问题谁直接操作演示不需要反复切屏。一起刷剧看视频没错这可能是 Neko 最受欢迎的使用场景。容器里的浏览器播放视频所有加入的人同步看到同一个画面延迟很低相当于一个自建的在线放映室。隔离环境下的网页访问因为浏览器是跑在服务器容器里的访客本机不接触网页内容多一层隔离。1.3 权限模型管理员和普通用户Neko 的用户权限分为两类通过两个独立的密码来控制NEKO_PASSWORD普通用户密码默认只能观看不能操作。NEKO_PASSWORD_ADMIN管理员密码管理员可以操作浏览器还能管理其他用户踢人、锁定屏幕、强制刷新等。如果你希望所有人都能操作可以给普通用户也开放控制权限如果只是分享屏幕就保持默认。这套模型简单粗暴但实际部署时有个细节容易踩坑管理员和普通用户的密码不能设置成一样的否则登录时无法区分角色权限判断会出问题。我第一次部署时就图省事结果所有人的操作权限都没生效排查了半天才发现是这个原因。2. 自托管 Neko 之前的准备功课2.1 硬件和带宽怎么选Neko 是典型的“吃上行带宽”的应用。画面编码发生在服务器端服务器把流推给每一个访客访客越多上行带宽占用线性增长。以我自己常用的配置来估算分辨率设为 1280x720、帧率 30fps 时WebRTC 编码后的码率大约在 2~4Mbps具体取决于画面变化程度纯静态网页可能不到 1Mbps滚动带视频的页面能飙到 6Mbps 以上。如果设成 1920x108030fps那码率基本要 5~10Mbps。所以当你想让几个人同时看 1080p 视频时服务器的上行带宽至少要预留 20Mbps 才稳妥。CPU 方面容器里跑 Chromium 本身就费资源再加上视频编码压力不小。我的经验是2 核 CPU 2GB 内存勉强能跑但只建议 720p、2~3 个访客CPU 占用会长时间在 80% 以上。4 核 CPU 4GB 内存比较舒服的配置1080p30 也可以应付 3~5 个访客。如果同时打开十几个标签页内存 8GB 也别嫌多Chromium 吃内存的能力谁用谁知道。2.2 Docker 部署命令与关键参数Neko 官方推荐用 Docker Compose 部署单容器项目配置不算复杂。我直接贴一份可以跑起来的最小配置docker run -d \ --name neko \ --restart unless-stopped \ -p 8080:8080 \ -p 52000-52100:52000-52100/udp \ -e NEKO_SCREEN1280x72030 \ -e NEKO_PASSWORDneko \ -e NEKO_PASSWORD_ADMINadmin \ -e NEKO_EPR52000-52100 \ -e NEKO_ICELITE1 \ -e NEKO_NAT1TO1your-domain.com \ m1k1o/neko:latest每个参数含义如下-p 8080:8080Neko 的 Web 管理界面端口浏览器访问用。-p 52000-52100:52000-52100/udpWebRTC 的音视频传输端口范围。注意一定是 UDPTCP 在这个场景下不适用。端口范围可以改小但太小会影响多用户并发下的端口分配。NEKO_SCREEN容器内虚拟显示器的分辨率格式是“宽x高帧率”。数值越高越清晰但 CPU 编码压力和带宽占用也越大。NEKO_EPRWebRTC 的端口范围必须和-p映射的 UDP 范围保持一致。NEKO_ICELITE启用 ICE Lite 模式典型部署建议开启。NEKO_NAT1TO1如果你的服务器有公网 IP 或者绑定了域名填上 IP 或域名这样 WebRTC 协商时能更准确地找到服务器。没有公网 IP 的情况下留空也行但连接成功率可能会下降。2.3 HTTPS 和反向代理的现状一个小提醒现在主流浏览器对 WebRTC 的要求越来越严格尤其是 getUserMedia 相关能力在非 HTTPS 环境下经常受限。Neko 自身只提供 HTTP 服务如果只是内网访问问题不大但如果要外网访问强烈建议在前面挂一层 HTTPS。我用的方案是 Caddy 反代配置简洁到令人感动neko.example.com { reverse_proxy 127.0.0.1:8080 }Caddy 会自动申请和续期证书省去了 Nginx 配证书的繁琐步骤。如果你习惯 Nginx思路也一样就是开 WebSocket 支持和反向代理到 8080 端口证书用 Lets Encrypt 签发即可。注意Neko 的前端界面和后端 WebSocket 通信在反向代理时必须保留 Upgrade 头否则页面能打开但一直转圈加载不出来。Caddy 默认处理了这点Nginx 则需要手动配置proxy_set_header Upgrade $http_upgrade;等三行。3. 实操体验多人协同到底怎么玩3.1 登录、界面、首次连接部署完成后浏览器访问服务器的 8080 端口会先看到一个密码输入框。这里输入的是一开始设置的两个密码之一系统根据密码区分你是管理员还是普通用户。登录后进入的是一个全屏的浏览器画面几乎看不到传统意义上的“客户端界面”。中央是容器里的桌面底部有一排很克制的工具条包含输入法切换、粘贴文本、切换布局等按钮。整个界面非常干净给人感觉就像直接在一台远程电脑上打开了浏览器。首次连接时浏览器会请求摄像头和麦克风权限。这个是 WebRTC 的正常流程即便你不想开摄像头麦克风也建议取消勾选后依然允许连接否则部分浏览器版本会直接阻断 WebRTC 数据通道。我第一次用 Chrome 时点了“拒绝”结果画面一直黑屏一度以为是服务器问题。这个权限请求其实只是 WebRTC 建立连接的前置步骤不授予摄像头也不会影响看画面但拒绝会让协商流程异常建议直接允许。3.2 控制权机制到底谁能动鼠标Neko 默认的控制权规则是这样的管理员始终能操作普通用户是否能操作取决于环境变量NEKO_CONTROL的配置。默认情况下普通用户只有观看权限鼠标移上去会显示一个“眼睛”图标表示当前是只读模式。如果你部署的是小团队内部工具希望所有人能轮流操作可以把NEKO_CONTROLall打开。这样每个登录用户都能操作浏览器适合教学、协作测试的场景。但要注意一个问题当多个用户同时操作时鼠标是共享的你移动鼠标别人也在移动画面会“打架”。Neko 对这个问题没有做精细的处理实际体验中后发的事件会覆盖先发的所以协同操作时最好约定好谁在用。管理员在工具条里有一个“锁定”按钮点击后可以暂时禁止所有普通用户操作这时只有管理员能动鼠标键盘。这个功能在演示场景下非常刚需避免有人手滑操作乱页面。3.3 输入法、剪贴板和键盘布局既然是浏览器的云端镜像输入体验就是最大痛点。Neko 有一个输入法控制按钮点击后会弹出一个本地输入框你在这里输入文字然后自动传送到远端浏览器。这个设计很巧妙绕开了 WebRTC 对 IME 合成事件的限制——直接在远端模拟文本输入比逐个传递按键事件靠谱得多。剪贴板共享也是通过 WebRTC DataChannel 实现的。在本地复制文字然后在 Neko 界面里选择“粘贴到远程”远端浏览器的剪贴板就会收到内容反过来也可以从远程复制到本地。需要注意Neko 只能同步纯文本图片、文件、富文本这些都不支持。如果你需要在访客和容器之间传文件得另想办法比如用容器里挂一个临时的 Web 服务来中转。键盘布局的问题我也踩过一次坑。服务器容器的 locale 默认是英文环境如果你连接的是中文键盘输入特殊字符比如 、#、括号时会发现对不上。Neko 的容器环境变量里可以设置LANG和LC_ALL建议在部署时就规划好自己的常用语言不然协作过程中突然发现键盘错位非常影响效率。3.4 画质与延迟的实际感受说实话我之前对 WebRTC 传输浏览器画面的延迟预期挺低的毕竟不是在局域网内测试。但实际用下来在服务器和客户端都有稳定网络的情况下画面延迟大概是 100~200ms 级别操作反馈虽然不像本地那么跟手但绝对在“可用”的范畴内滚动网页、点击按钮、输入文字都没有明显的迟滞感。画质方面720p 下文字边缘会有一点发虚但可以接受1080p 下基本锐利。如果你追求更高画质可以把分辨率调到 1920x1080但帧率建议还是维持在 30fps 以内再往上编码压力大帧率不稳定反而更难受。Neko 的 WebRTC 是自适应码率的网络波动时会自动降低分辨率来保流畅实测在弱网环境下不会直接断开而是画质下降这个体验很稳。我建议的配参方案是场景分辨率帧率内存配置建议备注纯展示静态页面1280x720242GB 起码率低带宽压力小在线视频同步观看1920x1080304GB 起画面变化快码率高远程操作后台系统1600x900304GB 起兼顾清晰度和流畅度3.5 多人同时加入的真实场景测试我拉了两个朋友一起测试三个人同时加入 Neko 观看同一个视频页面。管理员播放视频后两个普通用户能看到几乎同步的画面音画延迟和单独观看时没有明显差异。这是因为 Neko 的 WebRTC 传输是服务器到各个客户端的星型结构每个客户端单独一条流互不影响。代价是服务器的上行带宽按人数叠加三个人看 1080p 视频上行流量占了大概 20~25Mbps这点在部署前必须有心理准备。如果访客太多带宽吃紧最简单的降载手段是降低分辨率和帧率比如从 1080p30 降到 720p30码率能砍一半还多。还有一个技巧是让管理员在不需要操作时关掉标签页里的视频因为 WebRTC 编码是对整个屏幕画面的编码页面上任何视频在播放都会推高码率。4. 常见问题与排查技巧实录4.1 画面黑屏或一直转圈这是遇到最多的问题。排查思路按顺序来确认是否允许了浏览器权限请求。这个前面说过必须允许 WebRTC 建立连接。确认 UDP 端口是否放通。Neko 的 WebRTC 使用 UDP很多云服务器安全组默认只放行 TCP 端口忘了放行 UDP 就全黑。确认 NAT 映射配置。如果服务器没有公网 IP或者部署在公司内网WebRTC 的打洞成功率会下降。这时靠NEKO_NAT1TO1和NEKO_ICELITE的配置来辅助协商。一个快速判断方法打开浏览器开发者工具切到 Console 和 Network 标签页如果看到大量iceConnectionState相关的错误或超时日志基本就是网络协商层出了问题去查 UDP 端口和 NAT 配置最有效。4.2 有画面但没声音Neko 的音视频流是同步传输的有画面没声音先检查容器内 Chromium 的音量是否静音。登录 Neko 后在容器浏览器标签页上右键检查找到音量图标看看是否是静音状态。这类问题在容器重启后尤其容易出现容器内的浏览器状态不会持久化音量设置可能恢复默认。另一个可能性是宿主机上没有音频设备。Neko 使用了虚拟声卡方案但如果宿主机内核缺少相关模块会导致容器内音频设备无法初始化。在 Docker 部署时加入--device /dev/snd可以解决部分问题。遇到没声音时先看容器日志里有没有audio相关的报错。4.3 多人操作时鼠标权限混乱前面提到过Neko 的共享鼠标设计决定了多人同时操作会冲突。如果团队协作时频繁出现鼠标跳动、点击错位的情况我建议的管理方式是把NEKO_CONTROL保持默认仅管理员可操作需要协作时让管理员临时点一下工具条上的解锁按钮。另外Neko 有一个“静默控制”扩展模式可以通过 API 来切换控制权限但需要二次开发对大多数人来说不值得。4.4 容器重启后配置失效Neko 默认是无状态的容器内所有数据在重启后都会清空包括浏览器的 cookies、历史记录、已安装的插件。对于大多数共享浏览器场景这反而是个安全特性——每次重启都是干净环境。如果你想让浏览器保持登录状态比如内部系统的会话需要挂载数据卷volumes: - neko-chromium-data:/home/neko/.config但要注意Neko 的镜像里定义了固定的用户 ID挂载的宿主机目录权限不对会导致 Chromium 无法写入配置。我踩过这个坑解决办法是把宿主机目录的 owner 改成容器内的 UID通常可以通过chown实现。4.5 公网访问需要注意什么把 Neko 暴露到公网前一定要想清楚权限问题。Neko 默认没有登录页之外的二次验证只要你把端口暴露到公网任何人拿到密码都能加入。所以至少做好这几件事不要把 NEKO_PASSWORD 和 NEKO_PASSWORD_ADMIN 设置成弱密码。挂上 HTTPS避免密码明文传输。用反向代理加一层简单的 IP 白名单或基本认证能挡掉大多数扫描流量。我自己的做法是放在 Tailscale 网络里只允许内网成员访问需要外网演示时才临时通过反向代理暴露。自托管服务的安全性永远不要指望默认配置能替你兜底。5. 实际部署中的几个经验之谈5.1 Docker Compose 配置模板怕 docker run 命令太长不好维护我更推荐直接用 Compose 管理。贴一份我自己在用的配置可以直接拿去改services: neko: image: m1k1o/neko:latest container_name: neko restart: unless-stopped shm_size: 1gb ports: - 8080:8080 - 52000-52100:52000-52100/udp environment: - NEKO_SCREEN1280x72030 - NEKO_PASSWORDneko - NEKO_PASSWORD_ADMINadmin - NEKO_EPR52000-52100 - NEKO_ICELITE1 - NEKO_NAT1TO1neko.example.com - NEKO_KEYBOARDus volumes: - neko-chromium-data:/home/neko/.config这里有个细节很多人会忽略shm_size一定要给足。Chromium 在容器内使用 /dev/shm 作为共享内存默认 Docker 只分配 64MB一旦多开标签页或加载复杂页面Chromium 会直接崩溃或白屏。给到 1GB 是安全值内存在 4GB 以上的服务器这么配置没有压力。5.2 用扩展支持更多浏览器Neko 官方主要推 Chromium但也提供了 Firefox、Brave、Vivaldi 等浏览器的镜像版本。多浏览器部署的价值在于测试网页兼容性——你可以在 Neko 里跑多个容器分别对应不同浏览器这样团队成员能快速测试“这个网站在 Firefox 下表现如何”这类问题。我用过m1k1o/neko-firefox这个镜像部署方式几乎一致只是换一下镜像名即可。如果你主要做前端开发同时跑 Chromium 和 Firefox 两个 Neko 容器非常实用省掉了本地装各种版本浏览器的麻烦。5.3 资源占用和容器生命周期管理Neko 容器的资源占用肉眼可见地受“打开的标签页数量”影响。如果你只是在首页停留内存占用大概 300~500MB一旦打开 YouTube 这类重页面内存能冲到 1GB 以上。所以建议给容器加上内存限制deploy: resources: limits: memory: 2g配合--restart unless-stopped或者 Compose 的restart: unless-stopped可以防止异常退出后服务起不来。另外长期运行的容器建议定期重启因为 Chromium 在长时间运行后会有内存泄漏的倾向。我一般在每周日凌晨用定时任务重启一次容器成本极低但能让运行一直保持流畅。5.4 安全加固的小细节有一点容易被忽略Neko 的NEKO_PASSWORD和NEKO_PASSWORD_ADMIN是明文存在环境变量里的宿主机上能读到环境变量的人也就等于拿到了权限。所以不要在服务器上对所有人开放 Docker 环境变量查看权限日志输出也可能不小心带上环境变量要注意保护。另外Neko 自带一个简单的行为审计能力——管理员可以在界面上看到当前有哪些用户在线、他们的 IP 信息。如果对安全要求高可以基于这个信息做访问控制但说实话把它当作纯内网工具使用才是最放心的场景。写在最后的个人体会折腾自托管这件事最迷人的地方就是总能遇到“原来还可以这么玩”的项目。Neko 给我的感受就是这样以前想共享一个网页给一群人看不是开视频会议共享屏幕就是导出录屏再发过去流程冗长且体验割裂。Neko 把浏览器本身变成了一个可多人共用的云端工具操作逻辑反而比会议软件更直观。不过它也确实不是适合所有场景的工具配置门槛、带宽占用、权限管理都需要提前规划。我个人最推荐的用法是小团队内部的教学、演示、协同测试或者自建一个三五人的在线放映室。如果你有类似的协作需求又恰好有一台闲置的服务器Neko 值得花一个小时部署起来试试。它的门槛不算高但玩明白之后真的能改变你对“共享浏览器”这件事的想象。