新买了一台主机,准备搭个 PVE 服务器,在这记录一下过程。
安装 PVE
PVE 本身基于 Debian 系统,安装起来并不会十分复杂。下载最新版的 PVE 镜像,还有最新版引导盘制作软件 Rufus,将镜像写入 U 盘后再从 U 盘启动即可。遇到一个比较坑的问题,引导进入 PVE 安装界面后却提示 no device with valid ISO found, please check your installation medium
。因为我这 U 盘拿来做各种启动盘也挺久了所以一开始没怀疑到它,总觉得是自己引导盘做的有问题,还换了 Etcher,用 AI 搜来的过时信息对 bios 一通修改。结果最后换了个 U 盘就好了,并不用做任何多余的操作。
安装 PVE 时注意考虑好主机名和分配给服务器的 ip 再设置,之后虽然也可以修改,不过一开始能固定下来后面就省点心。
PVE 服务器改名
hostnamectl set-hostname <新名字>
修改 /etc/hosts 替换老名字
mkdir /root/tmp cp -r /etc/pve/nodes/<老名字>/* /root/tmp/ # 复制现有配置 rm -rf /etc/pve/nodes/<老名字> mkdir /etc/pve/nodes/<新名字> cp -r /root/tmp/* /etc/pve/nodes/<新名字> # 复制现有配置 reboot
修改镜像源
安装完后要更新软件,首先就是改镜像源了。按清华大学镜像站的指引更换 Debian 和 Proxmox 软件源。
企业版源列表文件内的内容 /etc/apt/sources.list.d/pve-enterprise.list 可以全部注释掉。
ceph 源,将 ceph.source 复制备份后新建 /etc/apt/sources.list.d/ceph.list,内容为
deb https://mirrors.ustc.edu.cn/proxmox/debian/ceph-squid bookworm no-subscription
最后执行 apt update && apt dist-upgrade -y 更新并重启即可。
删除 local-lvm
local-lvm 和 local 本意是一个放 iso 方便安装虚拟机,一个放虚拟机磁盘,相当于默认分了个区,没法有效利用磁盘空间,所以直接删了合并成一个。local-lvm 删除后,空间合并给 local 存储空间。
lvremove /dev/pve/data lvextend -l +100%FREE -r /dev/pve/root
命令操作完后在 Web 界面删除 local-lvm 存储:点击左侧列表的数据中心节点 – 存储 – 选中 local-lvm 删除。
最后还要配置下 local 存储,在上一步的存储界面选中 local,点击 编辑 – 内容,确保选中了 所有选项(包括磁盘映像、容器等),这样 local 分区就可以存放各类文件了。
使用 LXC 容器作为文件虚拟器
我一开始的做法是起一堆虚拟机,每个 vm 运行一个服务,但这样开销太大了,应该有效利用 lxc。其实如果不是考虑到以后起 vm 折腾(假想需求中……)的需要,其实直接 linux 单机运行服务就行,不用搞什么 pve。总之,现在的一些 smb、jellyfin、syncthing 之类的服务都可以转成 lxc 完成。原来单独一个 vm 起 samba 后各个 vm 还要挂载,用 lxc 的话宿主直接挂载就能访问。稍微麻烦点的就是权限控制了。建议用无特权 lxc。
硬盘的全盘加密仍然可以考虑做,这个不影响。现在把直通给 vm 的硬盘从 vm 配置里移除,这样 pve 就能看到这块加密磁盘了,解密后挂载好,数据是可以正常访问的。
下载 lxc 模板
安装 lxc 需要用到模板,下载一个现成的比较方便。点击下载便会在控制台输出直接下载链接。国内因为网络问题下载速度慢,可以参照其他教程配置国内镜像源下载,或者自行去镜像网站下载后上传到 pve 也行。
模板下载后就可以在服务器页面右上角创建 CT 了,“无特权容器”和“嵌套”默认都是勾上的,不用改。设置 root 密码,选择 CT 模板,一路配置硬件参数就行。我一开始用 turnkey 的 fileserver 模板创建时 lxc 磁盘给小了只有 1G,在创建时会报空间不足,多给点就行了。
启动后从 pve 面板进入 lxc 的控制台,登录 root 用户后开始安装,turnkey 里自带一些服务需要设置密码,比如 fileserver 需要配置 samba 的密码,之后做个在线更新,很快就会安装完。
配置 samba
安装完用浏览器访问 lxc 的 ip,进入 webmin 界面,到 System – Users and Groups – 右边的 local group – create a new group,创建 smb group,这里给它指定 group id 为 1000,名字随意。
再回到 local user tab – create a new user,填入以下信息后创建,用户名密码随意,主要是 uid 和 group 要选好。如有多个用户 uid 可以从 1000 递增。
这里先切换到 pve 的 root 控制台,打开 /etc/pve/lxc/[容器ID].conf,在里面添加一行目录映射规则 mp0: /mnt/bindmounts/shared,mp=/shared,意思是把 pve 主机的 /mnt/bindmounts/shared 映射到 lxc 的 /shared。有多个映射时 mp0 数字递增,不重复即可。重启 lxc。
再回到 lxc 的 webmin,到左侧 Servers – Samba Windows File Sharing – 右边 create a new file share,创建目录的 samba 共享目录。
完成后点开共享目录,下方有个 Security and Access Control。里面有个 Writable? 设为 Yes 就是可写了,里面也有一些 Read only users、Read/write users 等更精细的控制。
如果硬盘里已经有数据了,那还有一步关键的是在 pve 主机里设置共享目录的权限。现在 lxc 里我们 smb 用户的 uid 是 1000,gid 也是 1000。在 pve 的 /etc/subuid 已经自动生成了映射 root:100000:65536,这个配置的意思是 pve 的 root 用户可以将 100000 开始的 65536 个 uid 映射给 lxc 容器(lxc 容器是以 pve 中的 root 用户身份启动的)。而默认情况下 lxc 内的 uid 是从 0 开始一一对应,即 pve 的 uid 1000000 对应 lxc 内的 root 用户(0)。那么依次类推,lxc 内的 smb 用户(uid=1000)对应 pve 的 uid 101000。所以我们在 pve 上要给共享目录设置 chown -R 101000:101000(lxc 的 samba group id 也是 1000,映射规则也是一致的)。
配置 jellyfin
jellyfin 需要安装 turnkey 的 mediaserver 模板。前面的步骤都和 fileserver 类似。安装完成后 lxc 的 root 控制台会显示 jellyfin、webmin、smb、ssh 等服务的地址,直接用浏览器访问即可。
随后进入 jellyfin web 后台做初始设置,lxc 同样挂载 pve 的目录后就能访问了。
硬件转码
其实可以不用设置独占,直接共享就行了。来到 pve 后台,选中 jellyfin 所在的 lxc,右边选资源 – 添加 – 设备直通,会让你填设备路径。路径在 pve 主机里用 ls /dev/dri查看,像我的只有核显,就是 card0 和 renderD128。这俩一起表示了一张显卡。
card0 代表的是 DRM(Direct Render Manager,直接渲染管理器)。它负责直接与 GPU 硬件交互。用来处理多路图形渲染请求、内存管理、显示模式设置等底层任务。所以它表示的是整个物理或虚拟的图形卡。对这个设备的操作通常与显示输出和整体 GPU 管理相关。
renderD128 代表 DRI(Direct Render Infrastructure,直接渲染基础设施)。这是一套允许用户空间的应用程序(如 X11/Wayland 合成器、游戏、3D 软件)直接与 GPU 通信的框架,而无需通过 X Server 进行不必要的上下文切换。/dev/dri 目录就是 DRI 框架暴露给用户空间的设备接口。它提供了一个仅用于计算和渲染的接口,并不关心画面最终要显示在哪里,唯一目的就是高效地处理 3D 渲染、视频编解码、计算着色器等任务。所以很明白了,我们需要的正是 renderD128 的编解码能力。
在 lxc 里,jellyfin 的 uid 是 107,render 的 group id 是 104,所以上面就这样填。重启 lxc。然后去 jellyfin 控制台 – 播放 – 转码,硬件加速的下拉框里选 Video Acceleration API (VAAPI),VA-API 设备的输入框里应该已经自动填上了 /dev/dri/renderD128。往下的“启用硬件解码”部分所有都可以勾上,“硬件编码选项”和“编码格式选项”(这两个我勾上就会失败)不要改,其实剩下的全保持默认就可以了,保存。
为了测试转码,可以到 jellyfin 右上角用户设置 – 播放里,把“允许的最高视频转码分辨率”设一个较低的值如 720P,强制视频进行转码。然后播放一个视频,看看播放信息即可确认是否转码。然后再 ssh 登录 lxc,用 top 看下 cpu 的占用即可。我的机器上开启前后 cpu 占用从 330+ 降到了 60+,这样可以确认 gpu 在工作了。
PS:不确定 AMD 是否和 intel 一样。
开启前>
开启后>
以下配置目前用不上了,但照着配置也是没问题可以正常使用的,暂且留着吧 |
安装文件虚拟机
新建一个虚拟机用来管理所有数据磁盘,并通过 smb 分享给其他服务,省得虚拟机各搞各的了。随便装个 Fedora 或者 Debian,配一下 smb.conf。
/usr/sbin/groupadd smbgroup # 设置 smb 用户组 /usr/sbin/useradd smb_user1 # 新建 smb 用户 /usr/sbin/usermod -aG smbgroup smb_user1 # 添加到组 smbpasswd -a smb_user1 # 设置密码 ufw allow samba # 防火墙放行,如果有的话 sudo chgrp -R smbgroup /srv/samba/shared # 每个共享目录都要操作 sudo chmod 2770 /srv/samba/shared # 设置 SGID,保证新建文件继承组身份
配置 smb.conf
[global] security = user smb passwd file = /etc/samba/smbpasswd access based share enum = Yes server min protocol = SMB3 # 避免用不安全的过时协议 ntlm auth = ntlmv2-only # 禁用不安全的 NTLMv1 认证 server smb encrypt = required # 明确要求客户端使用加密 [tmp-space] # 设置共享目录 comment = 临时目录 create mask = 0664 directory mask = 0775 inherit permissions = Yes path = /srv/samba/tmp-folder read only = No # 目录默认可写 valid users = smb_user1 smb_user2 # 允许哪些用户访问 read list = smb_user1 # 重载读写配置,user1 设为只读 write list = smb_user2 @wgroup # 仅 user2 和 wgroup 里的用户可写,再配合全局的 read only 设置就比较完善了
最后重启 smb:systemctl restart smbd nmbd
连接 smb
Windows 系统只需要在我的电脑 – 工具栏中的“计算机” – 映射网络驱动器即可。
Linux 系统可以添加到 systemd 中以便开启自动挂载,/etc/systemd/system/mnt-smb.mount创建配置文件,请注意,这里 mnt-smb.mount 文件名跟你的实际挂载路径相关,比如挂载到 /mnt/ABC 你就取名为 mnt-ABC.mount。
[Unit] Description=Mount My SMB Share Requires=network-online.target # 需要网络就绪 After=network-online.target # 在网络就绪后才执行 Wants=network-online.target # 期望网络就绪 [Mount] What=//192.168.A.B/smb-dir Where=/mnt/smb Type=cifs Options=credentials=/etc/samba/credentials,iocharset=utf8,nofail [Install] WantedBy=multi-user.target
其中 /etc/samba/credentials 保存了 smb 的用户名和密码用于连接。内容为
username=smb_user password=123456
另外,如果你的 linux 用户跟 smb 用户不是同一个,那么在 .mount 文件的 Options 里再加上 uid=1000,gid=1000,1000 换成 linux 用户的实际 id,这样 linux 用户才有权限写入 smb 目录。
设置完毕后 reload 下配置
systemctl daemon-reload systemctl enable mnt-sync.mount systemctl start mnt-sync.mount
PS: 使用 mount 命令时经常遇到奇奇怪怪的问题,比如设置了 credentials 密码文件,但是死活 mount 不上。各种报错,什么 w/return code = -13 啊,STATUS_ACCESS_DENIED 啊,改用密码就一切正常。这时可以用 apt upgrade cifs-utils 升级一下软件就解决了……真想骂人,什么智障东西,浪费了我几个小时折腾环境。
直通硬盘给文件服务器
上面设置文件服务器的目的就是将所有数据硬盘都交由一个虚拟机管理,然后通过 smb 共享给其他机器使用,这样方便集中化管理与隔离,而且相比直接部署在 pve 上,用单独的虚拟机也不会污染主机。
识别硬盘
使用 ls -l /dev/disk/by-id/ 找到新硬盘的持久化 ID。因为还会有其他包括系统盘的输出,不好辨认的话可以 apt install lshw 安装 lshw 查看硬盘的具体信息。安装后执行 lshw -class disk -class storage 即可,输出类似
*-disk description: ATA Disk product: ST3000DM001-1CH1 vendor: Seagate physical id: 0.0.0 bus info: scsi@3:0.0.0 logical name: /dev/sda version: CC27 serial: Z1F41BLC size: 2794GiB (3TB) configuration: ansiversion=5 sectorsize=4096
找到这里 serial: Z1F41BLC,然后再执行对比 ls -l /dev/disk/by-id | grep Z1F41BLC 的输出,找到磁盘的 id,不要直接用 /dev/sda,因为它每次重启后是可能发生变化的。
直通硬盘
使用 qm set <VMID> -scsiX /dev/disk/by-id/<硬盘ID>,backup=0,discard=on 命令(推荐VirtIO-SCSI)。
- backup=0:防止 PVE 备份工具尝试备份这个直通磁盘,因为这些磁盘通常很大且可能包含不支持快照的文件系统。
- discard=on:如果直通的是 SSD,启用此选项以支持 TRIM/Discard 指令,有助于 SSD 维护性能和寿命。
- -scsiX:控制器类型选择,推荐 VirtIO SCSI 控制器,性能最好,支持更多高级特性(如 TRIM),不过需要虚拟机安装驱动(现代 Linux 系统通常自带,Windows 需额外安装)。参数中的 X 可以是 0~5 数字,查看虚拟机的硬件,像图中并没有 scsi0,所以可以填 0~5 均可
。
重启虚拟机,配置硬盘
- Linux:系统内分区、格式化、挂载。
- Windows:如用 VirtIO-SCSI,需要安装 VirtIO 驱动;如果用 SATA,则可直接在磁盘管理中初始化使用。
全盘加密
apt install cryptsetup ... # 先用 lsblk 找到对应的磁盘 cryptsetup -y -v luksFormat /dev/sdX # 把 X 替换成目标磁盘,会清空硬盘所有数据 ... # 根据提示输入一个密码用于加解密磁盘 cryptsetup luksOpen /dev/sdX encrypted-disk # 打开加密磁盘,会要求输入刚才的密码 mkfs.ext4 /dev/mapper/encrypted-disk # 创建 ext4 文件系统 mkdir /mnt/enc-disk # 挂载加密磁盘 mount /dev/mapper/encrypted-disk /mnt/enc-disk # 之后可以正常使用了 # 卸载和关闭 umount /mnt/enc-disk cryptsetup luksClose encrypted-disk # 添加恢复密钥 cryptsetup luksAddKey /dev/<你的设备> openssl rand -hex -out /root/encryption-key.bin 2048 # 生成密钥文件 cryptsetup luksAddKey /dev/sdX /path/to/keyfile
每次开机执行 luksOpen + mount 后即可使用。关机时系统会自动卸载磁盘,一般不用手动处理。但是手动卸载可以确保没有正在使用的连接,以免被强制卸载导致数据损坏。文件服务器一般是常开的,所以挂载卸载都是手动操作一下。
Syncthing
Syncthing 用来做设备间数据同步。下面设置以当前用户的身份启动 syncthing。
mkdir -p ~/.config/systemd/user/ vi ~/.config/systemd/user/syncthing.service # 文件内容在下方 systemctl --user daemon-reload systemctl --user enable syncthing.service systemctl --user start syncthing.service loginctl enable-linger <用户名> # 用户不登陆也自动运行 systemd 服务
[Unit] Description=Syncthing - Open Source Continuous File Synchronization for %i Documentation=man:syncthing(1) After=network.target [Service] ExecStart=/usr/bin/syncthing serve --no-browser --no-restart --logflags=0 Restart=on-failure SuccessExitStatus=3 4 RestartForceExitStatus=3 4 # Hardening ProtectSystem=full PrivateTmp=true SystemCallArchitectures=native MemoryDenyWriteExecute=true NoNewPrivileges=true [Install] WantedBy=default.target
PS:因为是在 smb 目录里做同步,同步时就会看到本机会自动修改同步数据中各个目录的权限,搞得很麻烦,到所有目录设置里勾选上“忽略权限”就可以了。
电源管理
echo “powersave” | tee /sys/devices/system/cpu/cpu*/cpufreq/scaling_governor 设置节能模式,不过我接了功率插座看修改前后并没有什么变化,空闲时功耗仍然保持在 30w,勉强还能接受。目前的配置是 i5-12400 + 单 hdd + ssd。如果 hdd 空闲时能停转可能会好一些。
参考
https://kcore.org/2022/02/05/lxc-subuid-subgid/
https://linuxcontainers.cn/lxc/getting-started/
https://wayjam.me/posts/allinone-install-file-media-server/
https://zhuanlan.zhihu.com/p/29306228339
最后贴一下官方文档,有各种问题都可以去里面找找