LOADING...

加载过慢请开启缓存(浏览器默认开启)

loading

Systemd-nspawn 桌面化

System-nspawn 简单的配置和使用可以参考 Systemd-nspawn 配置与使用。本文以名为 debian-11 的 debian 系容器,在名为 gentoo 的 gentoo 系主机下操作。

基础配置

主机配置

/var/lib/machines 中的容器,可以由 systemd 直接管理到,每个容器可以有自己的配置:

cp /lib/systemd/system/[email protected] /etc/systemd/system/[email protected]

因为 nspawn 的对网络的支持比较有限,所以直接使用主机网络,将 --network-veth 选项去掉。

因为 nspawn 对 subuid/subgid 的支持相对有限,所以直接使用主机的 uid/gid,讲 -U 选项去掉。

重载 systemd 的配置,启动容器并开机随主机启动容器:

systemctl daemon-reload
systemctl enable --now systemd-nspawn@debian-11

用户配置

容器的 uid 要和主机的 uid 保持一致,才不会出现各种 video 组的相关权限问题,当然,容器里的 video gid 和主机的也要保持一致。

machinectl shell debian-11
useradd -m -u $user_uid $user_name
sed -ri 's/^(video|audio)/# \1/' /etc/group
echo "video:x:$video_gid:" >> /etc/group
echo "audio:x:$audio_gid:" >> /etc/group
gpasswd -a $user_name video
gpasswd -a $user_name audio
exit

记得要检查容器的 /etc/group,有没有 id 冲突,debian 的 sudo gid 和 gentoo 的 video gid 是冲突的。

系统配置

容器里的系统配置,可以参考 Linux 基础配置

主题样式(可选)

主题样式如果要和主机保持一致,需要在容器也安装一致的主题和设置,如 debian 容器的 qt 主题设置为 breeze theme:

machinectl shell debian-11
apt install -y breeze breeze-gtk-theme
su - $user_name
echo 'export QT_STYLE_OVERRIDE=Breeze' >> ~/.profile
exit

中文(可选)

容器需要配置 zh_CN 的 locale.gen 和 dbus,并安装中文字体:

machinectl shell debian-11
apt install -y locales \
               fonts-noto-cjk
exit

输入法是使用主机的,像主机使用 fcitx,程序是需要有 fctix 的 gtk 和 qt 的 so 库支持,所以需要在容器安装并设置环境变量:

machinectl shell debian-11
apt install -y fcitx-frontend-qt5 fcitx-frontend-gtk2 fcitx-frontend-gtk3 \
               fcitx5-frontend-qt5 fcitx5-frontend-gtk2 fcitx5-frontend-gtk3
su - $user_name
cat << EOF >> ~/.profile
export LC_CTYPE=zh_CN.utf8  
export XMODIFIERS="@im=fcitx"  
export XIM=fcitx  
export XIM_PROGRAM=fcitx  
export GTK_IM_MODULE=fcitx  
export QT_IM_MODULE=fcitx
EOF
exit

能随主机启动配置

容器跟随主机开机时自动启动(systemctl enable systemd-nspawn@xxx)可以预先配置的选项,如果出现了“不能随机启动的配置选项”,就会报错,无法启动容器。

GPU

需要的通用 GPU 配置,需要在 /etc/systemd/system/[email protected] 中的 ExecStart 追加:

--bind=/dev/dri \
--bind=/dev/shm \

Nvidia

Nvidia 的显卡需要驱动和一些辅助工具才能工作,可以在容器安装和主机版本一致的驱动,也可以将主机机的显卡驱动和辅助工具都给容器,但是需要每次主机更新驱动后,配置文件都需要重新修改下 --bind

首先是辅助工具的文件:

--bind=/usr/bin/nvidia-bug-report.sh:/usr/bin/nvidia-bug-report.sh \
--bind=/opt/bin/nvidia-cuda-mps-control:/usr/bin/nvidia-cuda-mps-control \
--bind=/opt/bin/nvidia-cuda-mps-server:/usr/bin/nvidia-cuda-mps-server \
--bind=/opt/bin/nvidia-debugdump:/usr/bin/nvidia-debugdump \
--bind=/usr/bin/nvidia-modprobe:/usr/bin/nvidia-modprobe \
--bind=/opt/bin/nvidia-ngx-updater:/usr/bin/nvidia-ngx-updater \
--bind=/opt/bin/nvidia-powerd:/usr/bin/nvidia-powerd \
--bind=/usr/bin/nvidia-sleep.sh:/usr/bin/nvidia-sleep.sh \
--bind=/opt/bin/nvidia-smi:/usr/bin/nvidia-smi \
--bind=/usr/bin/nvidia-xconfig:/usr/bin/nvidia-xconfig \

然后是配置文件:

--bind=/etc/modprobe.d/nvidia.conf:/usr/lib/x86_64-linux-gnu/modprobe.d/nvidia-utils.conf \
--bind=/usr/share/X11/xorg.conf.d/nvidia-drm-outputclass.conf:/usr/share/X11/xorg.conf.d/10-nvidia-drm-outputclass.conf \
--bind=/usr/share/egl/egl_external_platform.d/15_nvidia_gbm.json:/usr/share/egl/egl_external_platform.d/15_nvidia_gbm.json \
--bind=/usr/share/glvnd/egl_vendor.d/10_nvidia.json:/usr/share/glvnd/egl_vendor.d/10_nvidia.json \
--bind=/usr/share/vulkan/icd.d/nvidia_icd.json:/usr/share/vulkan/icd.d/nvidia_icd.json \
--bind=/usr/share/vulkan/implicit_layer.d/nvidia_layers.json:/usr/share/vulkan/implicit_layer.d/nvidia_layers.json \

最后是 so 文件,但是这些跟随版本变动大,所以可以在主机执行命令生成,并将生成的文本加入到 ExecStart 中。

ldconfig -p | grep -Ei '(nvidia|libcuda)' | awk -F '=> ' '{print $2}' | sed -E 's|(/usr/lib64/(.*))|bind=\1:/usr/lib/x86_64-linux-gnu/\2 \\|g'

首次映射需要在容器执行 ldconfig

machinectl shell -q debian-11 /sbin/ldconfig

Xorg

要使用主机的 Xorg 服务,首先是需要将 Xorg 服务的 socket 给到容器:

--bind-ro=/tmp/.X11-unix \

然后设置环境变量:

machinect shell $user_name@debian-11
echo "export DISPLAY=$HOST_DISPLAY" >> ~/.profile
exit

最后如果 Xorg 服务是带又权限的,主机可以执行 xhost +local:

用户共享(可选)

临时的共享可以通过 machinectl bind 来,具体查找是否挂载可以在容器中执行 findmnt。永久的挂载共享建议追加:

--bind=/home/$user_name/Downloads/Work:/Work \

不能随主机启动配置

容器不能跟随主机开机时自动启动可以预先配置的选项。

Dbus(可选)

Systemd 默认 dbus 的 socket 是 /run/user/$user_uid/bus,是用户阶段生成的,并非系统阶段。需要用户的 dbus 生成后,才能去手动映射到容器,而且不能映射到容器 /run 下,因为容该目录是变动的,每次重启重启后都需要执行一次:

machinectl bind--mkdir debian-11 /run/user/$user_uid/bus /home/chongwish/.bus

之后需要告诉容器 dbus 的位置:

machinect shell $user_name@debian-11
echo 'export DBUS_SESSION_BUS_ADDRESS=unix:path=$HOME/.bus' >> ~/.profile
exit

如果容器的应用需要用到 dbus 的全局菜单,需要:

machinectl shell debian-11
apt install -y libdbusmenu-gtk4 libdbusmenu-gtk3-4 libdbusmenu-qt5-2 \
               vala-panel-appmenu
exit

PulseAudio(可选)

PulseAudio 默认的 socket 是在 /run/user/$user_uid/pulse/native,同 dbus 一样映射:

machinectl bind debian-11 /run/user/$user_uid/pulse/native /home/$user_name/.pulse-native

然后写入到环境变量:

machinectl shell $user_name@debian-11
echo "export PULSE_SERVER=\$HOME/.pulse-native" >> ~/.profile
exit

如果声音有独占问题,可以在执行:

machinectl shell debian-11
sed -i "s/; enable-shm = yes/enable-shm = no/g" /etc/pulse/client.conf
exit

GPU

Nvidia

Nvidia 的驱动设备在首次使用后生成,在此之后容器才能挂载使用:

machinectl bind debian-11 /dev/nvidia0
machinectl bind debian-11 /dev/nvidiactl
machinectl bind debian-11 /dev/nvidia-modeset