在 PVE 8.x 下,Intel N100 凭借其极低的功耗和出色的 QSV 解码能力,成为了家用 NAS/All-in-One 路由器的明星 CPU。传统的核显直通(Passthrough)只能将核显分给单一虚拟机,而通过 SR-IOV(Single Root I/O Virtualization) 技术,我们可以将 N100 的核显(UHD Graphics)虚拟出最多 7 个独立通道(VF),同时分给多个虚拟机(VM)或 LXC 容器。
本文将演示如何在 PVE 8.x 宿主机下开启 SR-IOV,并将其分配给 LXC 容器(Jellyfin/Plex 常用载体)或 Docker 虚拟机,最终完美开启 Intel Quick Sync Video(QSV)硬件解码。
准备工作
- PVE 版本:Proxmox VE 8.x (内核版本 6.2/6.5/6.8 均适用)
- 硬件:Intel N100 (Alder Lake-N) 宿主机
- 网络:宿主机能够正常连接互联网(需要拉取 GitHub 仓库和编译依赖)
第一步:PVE 宿主机编译与安装 i915-sriov-dkms 驱动
由于 Intel 官方尚未将 Alder Lake-N 的 SR-IOV 驱动完全合入 Linux 主线内核,我们需要使用社区维护的 i915-sriov-dkms 驱动。
1. 安装 PVE 内核头文件和编译依赖
在 PVE 网页端打开 Shell,或者通过 SSH 连接,执行以下命令:
apt update
# 安装当前内核对应的头文件和编译工具
apt install -y pve-headers-$(uname -r) dkms git build-essential sysfsutils
2. 克隆并安装 DKMS 驱动
目前较稳定的项目是 strongtz/i915-sriov-dkms。我们将其克隆到本地并进行编译安装:
cd /usr/src
git clone https://github.com/strongtz/i915-sriov-dkms.git i915-sriov-2.14
# 进入目录,如果是更高版本的内核(如 6.5/6.8),建议拉取项目最新的分支,或手动确认代码兼容性
cd i915-sriov-2.14
# 注册并编译 DKMS 模块
dkms add .
dkms install -m i915-sriov -v 2.14
注:如果执行 dkms install 成功,说明驱动已成功注入当前内核。若报错,请检查 pve-headers 是否与当前运行的内核版本严格一致。
3. 配置内核参数(Grub / Systemd-boot)
我们需要开启 IOMMU 并允许驱动加载 GuC/HuC 固件(N100 硬解关键)。
编辑 Grub 配置文件(若系统使用 grub 引导):
nano /etc/default/grub
找到 GRUB_CMDLINE_LINUX_DEFAULT 这一行,修改为:
GRUB_CMDLINE_LINUX_DEFAULT="quiet intel_iommu=on iommu=pt i915.enable_guc=3 i915.max_vfs=7"
注:i915.max_vfs=7 表示启用最大 7 个虚拟核显。
更新 Grub:
update-grub
(如果 PVE 使用的是 systemd-boot,需要编辑 /etc/kernel/cmdline,在末尾添加上述参数,然后执行 proxmox-boot-tool refresh)
4. 强制启用虚拟功能 (VFs)
创建 udev 规则或使用 sysfsutils 在系统启动时自动创建虚拟显卡。这里推荐使用 sysfs:
编辑 /etc/sysfs.conf:
nano /etc/sysfs.conf
在文件末尾追加以下内容(假设主核显在 PCI 域 0000:00:02.0,可用 lspci | grep VGA 确认):
devices/pci0000:00/0000:00:02.0/sriov_numvfs = 7
配置完成后,重启 PVE 宿主机:
reboot
5. 验证 SR-IOV 是否开启成功
重启后,登录 PVE 运行:
lspci | grep VGA
如果输出中除了 00:02.0 VGA compatible controller 主卡外,还多了 7 个 00:02.1 到 00:02.7 的 VGA compatible controller(或 Mobile Instrument),说明 SR-IOV 虚拟成功。
通过 ls /dev/dri 查看设备节点:
ls -la /dev/dri
应该能看到 card0 至 card7 以及 renderD128 至 renderD135。其中 renderD128 通常是主显卡,renderD129 ~ renderD135 是虚拟出来的 VF 显卡。
第二步:将核显 VF 分配给容器或虚拟机
这里推荐两种最主流的方案:LXC 容器(轻量、高效) 和 KVM 虚拟机(如运行 OpenMediaVault/Unraid/Ubuntu Docker)。
方案 A:分配给 LXC 容器(推荐 Jellyfin 用户)
LXC 容器直接共享宿主机内核,不需要在容器内安装复杂的显卡驱动,只需做设备挂载。
假设我们要分配 renderD129(即第一个虚拟 VF)给 ID 为 101 的 LXC 容器。
在 PVE 宿主机上,查看
renderD129和对应card1的组 ID(GID):ls -l /dev/dri输出可能类似于:
crw-rw---- 1 root video 226, 1 Oct 24 10:00 card1 crw-rw---- 1 root render 226, 129 Oct 24 10:00 renderD129请记录主设备号和次设备号:
card1是226, 1;renderD129是226, 129。编辑 LXC 容器配置文件(
/etc/pve/lxc/101.conf):nano /etc/pve/lxc/101.conf在文件末尾添加以下配置,允许容器访问该显卡节点:
# 允许容器挂载对应的字符设备 lxc.cgroup2.devices.allow: c 226:1 rwm lxc.cgroup2.devices.allow: c 226:129 rwm # 将设备节点 bind mount 进容器内 lxc.mount.entry: /dev/dri/card1 dev/dri/card1 none bind,optional,create=file lxc.mount.entry: /dev/dri/renderD129 dev/dri/renderD129 none bind,optional,create=file保存并关闭。
方案 B:分配给 KVM 虚拟机(虚拟机内跑 Docker)
如果你在 PVE 内开了一台 Linux VM(如 Debian/Ubuntu),并想在 VM 里的 Docker 容器运行 Jellyfin/Plex:
- 进入 PVE 网页控制台,选择你的虚拟机 -> 硬件(Hardware) -> 添加(Add) -> PCI 设备(PCI Device)。
- 在设备列表里,选择其中一个虚拟出来的核显(例如
0000:00:02.1)。 - 勾选 All Functions,并将 Primary GPU 保持不勾选(避免抢占虚拟终端显示)。
- 保存,并启动虚拟机。虚拟机将把这个 VF 当作一个物理 PCIe 显卡直接读取。
第三步:容器/系统内权限与依赖环境配置
分配完显卡后,我们需要确保容器内的 Jellyfin 或 Plex 能够拥有读写显卡节点的权限。
1. 解决 LXC 容器内的权限问题
进入 LXC 容器(例如通过 PVE 网页端的 101 容器控制台):
检查 /dev/dri 目录:
ls -la /dev/dri
你应该能看到 card1 和 renderD129。但是,容器内运行 Jellyfin 的用户(通常是 jellyfin,UID/GID 一般是 109 或 110)必须有权访问 render 组。
在容器内将 jellyfin 用户加入到 render 和 video 组:
usermod -aG video,render jellyfin
如果不确定,可以直接在容器内给显卡赋予 666 权限(临时排查或家用方便方案):
chmod 666 /dev/dri/card1 /dev/dri/renderD129
(注意:每次容器重启后权限可能会重置,可以通过在容器的 /etc/rc.local 中加入上述 chmod 命令来固化)
2. 安装 Intel 驱动依赖(LXC 与 虚拟机均需要)
无论是 LXC 容器还是 VM,系统都需要 intel-media-va-driver-non-free 驱动来支持 QSV 解码。
以 Debian/Ubuntu 系统为例(容器内或 VM 内):
apt update
apt install -y va-driver-all vainfo intel-media-va-driver-non-free
安装完成后,运行 vainfo 检查是否成功识别核显:
# 如果在 LXC 容器内,可能需要指定设备路径
vainfo --device /dev/dri/renderD129
若输出类似以下内容,则说明硬件解码驱动完全就绪:
libva info: VA-API version 1.17.0
libva info: Trying to open /usr/lib/x86_64-linux-gnu/dri/iHD_drv_video.so
libva info: Found init function __vaDriverInit_1_17
libva info: va_openDriver() returns 0
vainfo: VA-API version: 1.17 (libva 2.17.0)
...
vainfo: Supported profile and entrypoints
VAProfileH264Main : VAEntrypointVLD
VAProfileH264Main : VAEntrypointEncSliceLP
VAProfileHEVCMain : VAEntrypointVLD
VAProfileHEVCMain : VAEntrypointEncSliceLP
VAProfileAV1Profile0 : VAEntrypointVLD
(注:出现 EncSliceLP 代表支持 Low-Power 模式编码,这对于 N100 QSV 极为重要)
第四步:Jellyfin / Plex 开启 QSV 硬解
1. Jellyfin 配置
- 登录 Jellyfin 网页后台,进入 控制台 -> 播放 -> 转码。
- 硬件加速:选择 Intel QuickSync (QSV)。
- Intel QuickSync 选项:
- 勾选
H.264、HEVC、MPEG2、VC1、VP9、AV1的解码支持(N100 完整支持 AV1 解码)。
- 勾选
- 启用硬件编码:勾选。
- 启用低功率 H.264 硬件编码 / 启用低功率 HEVC 硬件编码(Enable Low-Power H.264/HEVC hardware encoding):
- 必须勾选。N100(Alder Lake-N)的核显架构依赖 Low-Power 模式进行硬塑,不勾选此项可能导致转码失败。
- 保存设置。
2. Plex Pass 配置 (需要会员)
如果你使用的是 Plex,并且拥有 Plex Pass:
- 打开 Plex 网页端,进入 设置 -> 转码器。
- 勾选 Use hardware acceleration when available(启用硬件加速)。
- 勾选 Use hardware-accelerated video encoding(启用硬件加速视频编码)。
- Hardware transcoding device:在下拉列表中选择带有
Alder Lake-N或Intel UHD Graphics标志的虚拟显卡。 - 保存。
避坑与调优指南
Q1: 运行 vainfo 报错 VA-API error: unknown libva error
- 原因:通常是 GuC/HuC 固件未在宿主机正确加载。
- 解决方法:在 PVE 宿主机上运行
dmesg | grep i915。检查是否有GuC/HuC firmware load failed相关的错误。如果提示固件丢失,需要前往 Linux Firmware 官网下载对应 Alder Lake 的glk_huc.bin或tgl_guc_*.bin固件并放入/lib/firmware/i915/目录下,然后重新制作 initramfs:update-initramfs -u -k all。
Q2: 宿主机升级 PVE 内核后,SR-IOV 失效了
- 原因:PVE 升级内核(例如从 6.5 升级到 6.8)后,原先编译的 DKMS 驱动没有自动应用到新内核。
- 解决方法:
在新内核下重新执行编译与安装:
并检查apt install -y pve-headers-$(uname -r) dkms autoinstall/etc/sysfs.conf里的显卡 PCI 地址是否因硬件变动而发生改变。
Q3: Jellyfin 播放视频出现绿屏、花屏或提示“客户端不支持此媒体”
- 原因:Jellyfin 的官方 Docker 镜像或系统的
va-driver冲突。或者是由于未勾选“低功率(Low-Power)”转码。 - 解决方法:
- 进入 Jellyfin 容器内,确认
intel-media-va-driver-non-free是激活状态,而非开源的mesa驱动。 - 如果是 Docker 部署,确保将
/dev/dri映射进容器,并且 Docker 运行用户有读写/dev/dri的权限(可以通过设置user: 0:0或分配正确的group_add解决)。
- 进入 Jellyfin 容器内,确认