PiKVM 是基于树莓派实现的IP KVM工具,它能够把开发板模拟成键盘、鼠标、移动硬盘等,通过USB接入到目标主机,并且读取主机的视频输出,让运维人员可以通过远程Web界面对目标服务器进行管理,让家用电脑也可以实现类似BMC的带外管理功能。

但PiKVM这个工具在树莓派上的实现是直接做了一个基于Arch Linux的镜像,用户拿到可以直接烧到树莓派里用。我为了支持国产因为贫穷,决定用立创的泰山派来装这个东西。

注意本文不是保姆级教程,也不提供一个完善的解决方案,只是记录了我在泰山派上装PiKVM的过程,仅供参考。

硬件准备

主要硬件是一块泰山派开发板,约200块钱,买2G+16G存储的版本即可。

然后是HDMI采集卡,用于捕获服务器的视频流,这个正好以前玩直播的时候搞过一个正在吃灰,拿出来废物利用一下。现在HDMI采集卡也不贵,已经卷到几十块钱就能买到了。

最后是一根自己DIY的Y型USB线(USBC Y-Splitter cable),用于给开发板供电(带外管理当然得有自己的独立电源)以及把自己模拟成外设连接到主机用。PiKVM官方给的图在下面,线的颜色和实际的颜色应该是一致的。

要点:

  • 接到服务器端的Type-A端VCC要断掉,不要接到电源,据说会烧
  • 接USB电源的一端只保留地线和供电线,仅作供电用
  • 三个接头的GND地线要相连,保证地的电位一致
  • D- 和 D+ 是正常用来传输USB数据的,用于在我们这里就是用于USB外设模拟

总之找两根吃灰的四芯USB线剪断再焊接一下就成,注意做好绝缘。

至于PiKVM还可以通过GPIO接继电器连电脑开关的这种操作我就懒得搞了,我选择用小米插座远程断电,用Wake on LAN远程唤醒。

整体的接线方式可以参考PiKVM的文档

在泰山派这边,由于板子比较小,只有两个USB接口,所以接线方式是Type-C口用DIY的线接主机模拟USB外设和接外置电源,Type-A口接HDMI采集卡采集视频输出。

系统准备

开发板自带的是个Android系统,我们装PiKVM其实是需要22.04装起来比较顺畅,因为PiKVM需要Python 3.10,然而泰山派官方最高只提供了20.04的固件,我又太懒没整明白如何直接构建一个22.04的固件出来,所以采取曲线救国的方式进行:先刷20.04,然后自己升级到22.04。

下载ubuntu镜像烧录 https://lceda001.feishu.cn/wiki/IJtRwVu5kiylHykl3RJcQ8ANncY

启动后先配好WiFi,村通网,记得先给开发板插好wifi天线。

默认有一堆包的版本都被hold了,需要全部unhold:

sudo apt-mark unhold $(apt-mark showhold)

把讨厌的自动更新关了,全改0:

sudo vim /etc/apt/apt.conf.d/20auto-upgrades

装一个ssh server用ssh连进来调试起来就比较方便了:

sudo apt update
sudo apt install -y openssh-server

然后我们会发现,这玩意的磁盘也很奇葩,/oem和/userdata的分区分走了一大部分空间,需要把他们的分区删掉,容量合并到/路径的分区中,这样才够我们完成22.04的升级。

sudo umount /oem
sudo umount /userdata

# 删掉上面两个挂载点
sudo vim /etc/fstab

# 删掉最后两个,然后resize root这个分区把剩余空间都加进来
sudo cfdisk /dev/mmcblk0

# 最后扩容文件系统
sudo resize2fs /dev/mmcblk0p6

之后就是正常的发行版升级流程了,升级到ubuntu22.04

sudo apt upgrade
sudo apt install ubuntu-release-upgrader-core
sudo do-release-upgrade

KVMD安装

我们需要通过jacobbar/fruity-pikvm这个仓库来安装kvmd,它是打了一个deb包来进行kvmd的安装,从而支持其他开发板。我这里只借助它来部署下systemd service启动脚本之类的。

sudo apt install -y git
git clone https://github.com/jacobbar/fruity-pikvm.git
cd fruity-pikvm
sudo su
./install.sh

kvmd日志可能会报kvmd module not found

我们也不惯他毛病,不用它deb包里给的kvmd了,直接装个新的,这里用了我参考fruity-pikvm里的patch脚本的fork,可以支持大容量存储

sudo apt install -y python3-pip
git clone https://github.com/Windfarer/kvmd.git --branch tspi
cd kvmd
sudo pip install .
# 顺便装下它的依赖
sudo pip install async_lru gpiod

# 因为我们更新了版本,所以还要更新kvmd的web页面静态资源
sudo mv /usr/share/kvmd/web/ /usr/share/kvmd/web-bak
sudo cp -r web /usr/share/kvmd/

然后重启后会看到kvmd-otg报错:

OSError: [Errno 12] Cannot allocate memory: '/sys/kernel/config/usb_gadget/kvmd'

因为usb_gadget下只能存在一个目录,观察下这个目录下已经有一个rockchip的目录了,当前默认在usb这边开了个adb,需要关掉它,给kvmd让位:

mv /etc/init.d/.usb_config /etc/init.d/.usb_config.bak

修改设备树,编译并烧录Kernel

如果不改设备树,可能会在kvmd-otg的日志中看到这样的报错:

FileNotFoundError: [Errno 2] No such file or directory: '/sys/kernel/config/usb_gadget/kvmd/functions/hid.usb0'

为了能正常模拟成键鼠,我们不可避免地要改内核参数编译kernel了,所以还是要准备下编译环境。

当然要装啥编译工具请自己参考【立创·泰山派RK3566】开发板下面的各种文档进行安装,毕竟我们Arch Linux用户家里啥没有啊。

第05章.【立创·泰山派RK3566】系统SDK 下载 tspi_linux_sdk_repo_20240131.tar.gz 并解压。

解压完你会发现毛都没有,原来都解压到.repo目录下了,还需要额外的命令把他的仓库都同步回来。

.repo/repo/repo sync -l -j16

然后不一会就出现了一大堆目录。

修改设备树,重新编译内核(第一次编译有一些电压的东西要选,参考【Linux】系统SDK编译

在sdk的kernel/arch/arm64/boot/dts/rockchip/tspi-rk3566-core-v10.dtsi路径里找到这个usbdrd_dwc3,将它的dr_mode改为peripheral,即外围设备。

&usbdrd_dwc3 {
	dr_mode = "peripheral";
	extcon = <&usb2phy0>;
	status = "okay";
};

配置defconfig,在kernel/arch/arm64/configs/rockchip_linux_defconfig这个文件中追加如下参数

CONFIG_USB_CONFIGFS_F_HID=y
CONFIG_TUN=y

# 下面这个里面应该有,确认一下是否为y
CONFIG_USB_CONFIGFS_MASS_STORAGE=y 

其中第一行是用来启用键鼠模拟的,第二行是为了开启tun设备,这个是为了tailscale的虚拟局域网准备的,这里一次都改完,避免重复折腾。

编译内核

./build.sh kernel

编译完的产物应该在rockdev/boot.img

然后把它刷进去,需要先把开发板切换到loader升级模式,参考【下载】镜像烧入

注意使用di命令只刷boot

sudo ./upgrade_tool di -b boot.img

刷完就可以把各种线连上试试了,访问 https://开发板ip地址 应该就能看到PiKVM的管理页面,默认帐号密码都是admin

TailScale

这年头谁还有公网IP啊,全靠tailscale苟着,虚拟局域网凑合用用也可以了。

由于kernel版本有点低,想用tailscale需要切换一下iptables

update-alternatives --set iptables /usr/sbin/iptables-legacy
update-alternatives --set ip6tables /usr/sbin/ip6tables-legacy
update-alternatives --set arptables /usr/sbin/arptables-legacy
update-alternatives --set ebtables /usr/sbin/ebtables-legacy

然后安装tailscale

sudo apt install -y curl
curl -fsSL https://tailscale.com/install.sh | sh
tailscale up

大容量存储

这个功能用于将开发板模拟成USB存储设备,用于服务器的开机引导装系统等操作

插一张存储卡之后进行下面的操作

# 确认存储卡的分区
sudo fdisk -l

# 格成ext4
sudo mkfs -t ext4 /dev/mmcblk1p1

# 修改挂载
sudo vim /etc/fstab

## 加入下面的内容
/dev/mmcblk1p1 /var/lib/kvmd/msd  ext4  nodev,nofail,nosuid,noexec,ro,errors=remount-ro,data=journal,X-kvmd.otgmsd-root=/var/lib/kvmd/msd,X-kvmd.otgmsd-user=kvmd  0 0

# 确认fstab是否能用,有报错千万别重启,修起来很麻烦
sudo mount -a

sudo vim /etc/kvmd/override.yaml
# 加入下面内容并保存
kvmd:
    msd:
        type: otg

重启开发板,再登录PiKVM的页面,应该就能看到Drive功能了。

网络唤醒(Wake on LAN)

需要先在目标服务器的BIOS进行相应设置,在目标服务器的系统内看一下网卡的mac地址,然后给它开启wake on lan功能。

创建/etc/systemd/system/wol.service 文件,加入下面内容,需要把其中的网卡名称改成服务器上的实际设备名称

[Unit]
Description=Enable Wake On Lan

[Service]
Type=oneshot
ExecStart = /usr/sbin/ethtool --change enp3s0 wol g

[Install]
WantedBy=basic.target

然后设置自动启动

sudo systemctl daemon-reload
sudo systemctl enable wol.service

在系统中通过如下命令可以看到是否开启了wol,如果Wake-on: g则是已经开启:

sudo ethtool <网卡名称>

在开发板这边,修改/etc/kvmd/override.yaml 增加wol配置项,里面配上目标服务器的mac地址:

kvmd:
    # other configurations
    wol:
        mac: ff:ff:ff:ff:ff:ff

配完重启开发板,之后在Web界面右上角system菜单中看到WoL。

错误排查

上面的过程中可以通过查看kvmd的服务状态和日志检查具体的错误信息

sudo systemctl status kvmd
# 这个kvmd-otg是启动时一次性运行的,所以它如果无报错停止了是正常的
sudo systemctl status kvmd-otg

sudo journalctl -u kvmd
sudo journalctl -u kvmd-otg