Show HN: Proxmox -> 通过网络将宿主机的蓝牙共享给虚拟机
摘要
一款通过网络将宿主机的蓝牙适配器共享给Proxmox虚拟机的工具,绕过了Intel芯片和游戏发行版的硬件直通限制。
查看缓存全文
缓存时间: 2026/07/25 20:11
lucid-fabrics/proxmox-bluetooth 项目
来源:https://github.com/lucid-fabrics/proxmox-bluetooth
让蓝牙终于能在你的 Proxmox Linux 虚拟机里工作了。
Ko-fi (https://ko-fi.com/lucidfabrics) Buy Me a Coffee (https://buymeacoffee.com/lucidfabrics) GitHub Sponsors (https://github.com/sponsors/lucid-fabrics)
太长不看版: 将蓝牙直通到 Proxmox 虚拟机在 Intel 板载芯片(BE200、AX210、AX211——硬件设计如此,没有任何设置能解决)上会失败,并且在游戏系统(如 ChimeraOS 和 Bazzite)上也不可靠。本工具通过网络将主机的蓝牙共享给虚拟机——只需两条命令,任何 Linux 支持的芯片都能工作,重启后依然有效。手柄、耳机和 Home Assistant 传感器均可使用。
在你的游戏虚拟机(ChimeraOS、Bazzite、普通 Linux)内部配对 Xbox / PlayStation 手柄、耳机或传感器——即使是那些“无法直通”的蓝牙芯片。
听起来很熟悉?
- 你在 Proxmox 上搭建了游戏虚拟机。一切正常……除了蓝牙。
- 你的手柄一直闪烁、闪烁、闪烁,然后放弃。
- 你听了论坛建议买了 Intel BE200 / AX210 网卡,仍然不行。
- 你尝试了
qm set ... -usb,在虚拟机里看到了设备,但它就是不肯工作。 - 每个帖子的最终回复都是“用 USB 线吧”。
这不是你的错,你的硬件也没坏。 Intel 的蓝牙芯片设计成这样:只有启动它的机器才能驱动它。当 Proxmox 把芯片交给虚拟机时,芯片自身会被清空。没有任何设置能解决这个问题。这是芯片的物理特性决定的。
第一步:先试简单的方法
普通的 USB 直通在很多场景下都能工作——一个普通 USB 蓝牙适配器插在普通 Linux 发行版(Debian、Ubuntu)上通常就能用:
qm set <VM_ID> -usb0 host=<USB设备ID>
如果这样就能在你的虚拟机里获得蓝牙功能,那就别往下看了——你不需要本项目。本项目是为以下情况准备的:Intel 板载芯片(BE200/AX2xx——永远无法工作,设计如此)、游戏发行版(ChimeraOS/Bazzite 的内核加上古怪的芯片固件)、精简版云内核,以及那些在虚拟机重启几次后就会卡死的 USB 适配器。
解决方案:别把芯片交给虚拟机,共享它。
芯片留在 Proxmox 主机上,因为那里它能正常工作。一个小巧的桥接程序通过本地网络将它流式传输到虚拟机中。你的虚拟机看到的完全是一个普通的蓝牙适配器。延迟比手柄自身的无线电延迟还要低——你根本感觉不到。
只需两条命令,仅此而已。
在 Proxmox 主机上运行:
curl -fsSL https://raw.githubusercontent.com/lucid-fabrics/proxmox-bluetooth/main/install.sh | sudo bash
你会看到类似这样的输出:
==> 本机上的蓝牙适配器:
[0] hci0 - 70:08:10:A4:F1:45 (USB)
==> 所有适配器状态正常。可以继续。
==> 蓝牙 (hci0) 已在 192.168.1.3:9700 上共享。
现在在你的虚拟机内部运行以下命令:
curl -fsSL https://raw.githubusercontent.com/lucid-fabrics/proxmox-bluetooth/main/install.sh | sudo bash -s -- 192.168.1.3
怎么做: 将最后一行命令(你机器的 IP 会不同)复制下来,然后在虚拟机内部运行。
在虚拟机内部,你会看到:
==> 完成。本虚拟机已拥有可正常工作的蓝牙。现在去配对新手柄吧。
怎么做: 打开虚拟机里的蓝牙设置,像平常一样配对。搞定。
以上步骤在两边都会开机自启并自动重连。设置一次,忘记它的存在。
我的芯片能用吗?
只要 Proxmox 主机能看到它,你的虚拟机就能用。在主机上运行以下命令检查:
curl -fsSL https://raw.githubusercontent.com/lucid-fabrics/proxmox-bluetooth/main/install.sh | sudo bash -s -- --check
如果一切正常,你会看到:
==> 本机上的蓝牙适配器:
[0] hci0 - 70:08:10:A4:F1:45 (USB)
==> 所有适配器状态正常。可以继续。
怎么做: 无需额外操作——直接运行上面的安装命令即可。
如果你的芯片属于“卡死”的 Intel 芯片情况,你会看到:
!! hci0 无响应(卡在引导加载器中)。
解决方法:关机,将电源开关关闭 15 秒,再开机。
仅重启或按前面板电源按钮是不够的。请参阅 README。
怎么做: 严格按照提示操作。这看起来有点极端,但这是唯一有效的方法——原因见下面的 FAQ。已有真人测试确认(欢迎通过 PR 添加你的):
| 硬件 | 状态 |
|---|---|
| Intel BE200 | ✅ 已测试——本项目就是因它而生 |
| Intel AX200 / AX210 / AX211 | ✅ 同系列,行为相同 |
| MediaTek MT7921 / MT7922 | ✅ 标准 Linux 支持 |
| 通用 CSR / Realtek USB 适配器 | ✅ 你的主机 Linux 能驱动的任何设备 |
| UGREEN “BT 6.0” 适配器(Barrot 芯片) | ❌ 在 Linux 上固件有问题,无论是否使用桥接。请避免购买。 |
常见问题(FAQ),用人话解释
我的手柄会延迟吗?
不会。在同一台机器上,桥接带来的延迟远低于 1 毫秒。蓝牙本身比这慢得多。
能用于耳机、键盘、Home Assistant 传感器吗?
可以——桥接是协议透明的(它只转发原始蓝牙流量,不解析也不过滤)。任何能在普通 Linux 蓝牙适配器上工作的设备都可以:手柄、音频、HID、Home Assistant 的 BLE 传感器。
能同时配对多个设备吗?
可以。它在虚拟机中的表现完全像一个普通适配器——同时连接两个手柄加一个耳机都没问题。所谓的“一次一个”限制是指虚拟机(一个虚拟机独占一个芯片),而不是设备数量。
我需要购买什么吗?
不需要。你已有的网卡就能用。甚至你换下来的旧网卡多半也能用。
我的整个虚拟机“挂了”——黑屏、无网络(ChimeraOS / Bazzite)。
它没挂——只是进入睡眠了。游戏发行版会在空闲后自动挂起(像 Steam Deck 一样),而带有 GPU 直通的虚拟机永远无法从这种挂起中唤醒。在虚拟机内部彻底禁用挂起:
sudo systemctl mask sleep.target suspend.target hibernate.target hybrid-sleep.target
我的手柄配对了,但在 Steam(ChimeraOS / Bazzite)里没有任何反应。
这是它们的输入层已知的小问题,不是蓝牙的问题:运行 sudo systemctl restart inputplumber,然后关闭再打开手柄即可解决。
我的 Intel 网卡看起来完全死了——没有适配器,日志吓人。
它卡死在了空白引导状态。请关闭机器,将电源开关关闭 15 秒,然后开机。仅重启或按前面板电源按钮是不够的。这个技巧花了我们整整一天才摸索出来——不用谢。
主机上有多个蓝牙芯片。
--check 会列出找到的所有适配器(hci0、hci1……),并显示它们的 MAC 地址以便区分。如果发现多个,它不会猜测——会要求你选择。用 ./install.sh --adapter 1 共享特定的一个。同时将两个芯片桥接到两个不同的虚拟机目前还不支持(当前一个主机只能安装一次)——如果你需要这个功能,请提 issue,改动很小。
我的虚拟机挂了 / 我重建了虚拟机 / 我想让另一个虚拟机用蓝牙。
只需在新的虚拟机中运行客户机端的一行命令即可——主机为任何连接的虚拟机提供服务(一次一个)。旧虚拟机挂了无需清理。如果旧虚拟机仍在运行,先在其上停止客户端(运行 --uninstall)。唯一要注意的是:配对信息保存在客户机内,因此需要在新虚拟机中重新配对设备。
它能在 ChimeraOS / Bazzite 系统更新后幸存吗?
能。这些发行版在更新时会替换系统镜像,但保留 /etc 和 /var——而本项目恰恰安装在这些目录中。你的桥接和配对信息会在更新后自动恢复。
主机自己会失去蓝牙功能吗?
是的,在共享期间。通常放在机柜里的服务器很少需要蓝牙。如果临时需要,可以用 --pause 将芯片归还给主机,--resume 再交回给虚拟机(虚拟机将自动重新连接)。--uninstall 则永久移除所有内容。
这安全吗?
桥接使用一个 LAN 端口(9700,绑定到主机 IP),无身份验证——第一个连接上来的机器获得芯片。在家庭局域网内,通常没问题。如果担心安全问题,可以设置防火墙规则限制只有虚拟机的 IP 能访问 9700 端口。
距离很近?设备只能靠近配对?
那是天线的问题,不是桥接的问题。M.2 网卡需要连接两根小小的天线;裸卡装在金属机箱里几乎没有信号。USB 适配器:使用前置端口或短延长线比插在布满线缆的后置面板上效果好得多。
那么 Windows 虚拟机呢?
桥接只针对 Linux 客户机(它依赖 Linux 的蓝牙协议栈)。Windows 虚拟机通常没有这个问题:直接用 qm set <VM_ID> -usb0 host=<USB设备ID> 直通一个 USB 适配器就能工作。本工具之所以存在,是因为 Linux 客户机会在 Windows 轻松解决的地方卡住。
那么 LXC 容器呢?
容器与主机共享内核,因此不需要桥接——你可以直接将主机的蓝牙分配给 LXC(绑定设备 / cgroup allow)。本工具面向的是真正运行自己内核的虚拟机。
这只适用于 Proxmox 吗?
不——任何运行 KVM 虚拟机的 Linux 主机都可以(甚至两台物理上独立的机器也可以)。Proxmox 只是问题最突出的地方。
好奇者:到底发生了什么?
Intel CNVi 蓝牙(BE200/AX2xx)需要主机的 btusb/btintel 驱动程序在启动时加载其固件。任何直通交接(USB 重定向、vfio、驱动解绑)都会将芯片重置为 ROM 引导加载器,而客户机永远无法完成固件握手。
桥接程序是来自官方 BlueZ 源码树的 btproxy(从未在任何发行版包中发布)。在主机上,它以 HCI 用户通道模式打开适配器,并通过 TCP 提供原始 HCI 数据。在客户机中,它通过 hci_vhci 创建一个虚拟控制器,并将数据流导入其中。客户机中的 BlueZ 既不知道也不关心。
Systemd 单元:btproxy-server.service(主机,替代 bluetooth.service)和 btproxy-client.service(客户机,通过 drop-in 文件在 bluetooth.service 之前启动)。附带的二进制文件是从 BlueZ 5.66 的 tools/btproxy 使用普通 -O2 编译的(默认构建会注入 ASAN/UBSAN 调试依赖)。它只需要 glibc。详见 build.sh。
支持本项目
这个解决方案花了一整天的时间挠头、三次“死机”重启,以及一次真实地走到电源开关前的经历——这样其他人就不必再浪费那一天了。像这样的工具能够保持免费和持续维护,只有一个原因:曾经被帮助过的人选择帮助下一个遇到同样问题的人。如果此刻你正是这样的人,谢谢你。这真正地让这个项目保持活力。
卸载
使用同一个脚本,加上 --uninstall 参数,在你想要恢复的机器上运行即可。
许可协议
MIT
相似文章
在Proxmox VE中运行microVM的简便方法
介绍了pve-microvm,这是一个Debian软件包,它将QEMU的microvm机器类型集成到Proxmox VE中,实现了低于300毫秒的启动时间和硬件隔离,开销极小,支持多种客户操作系统。
Show HN:BornToBeRoot 的 NETworkManager 的免费 Linux 适配版
NMLinux 是 NETworkManager 的免费、开源 Linux 适配版,为常用网络工具提供统一的图形界面。它基于 Python 和 PySide6 构建,包含 SSH、RDP、VNC、Wi-Fi、路由追踪、网速测试等模块,面向系统管理员和高级用户。
@rammcodes: 天哪... 你现在可以仅用 VS Code 将 localhost 分享给任何人!VS Code 内置了端口功能,…
VS Code 内置了端口功能,允许用户无需第三方工具即可将 localhost 暴露到互联网,方便进行演示和测试的分享。
Show HN: machine0 – 可通过 CLI 控制的持久化 NixOS 虚拟机
machine0 是一个 CLI 工具,用于配置持久化的 NixOS 和 Ubuntu 虚拟机,提供专用资源、静态 IP、按分钟计费,以及挂起/恢复和黄金镜像等功能。
Show HN: Boo – 基于libghostty的screen风格终端多路复用器
Boo是一个基于libghostty构建的GNU screen风格终端多路复用器,使用Zig编写。它提供精确的屏幕重绘以及用于脚本和AI代理的自动化原语。