Install Void Linux on Raspberry Pi

on 2025-06-20

简介

Void Linux 是一款相对小众的 Linux 发行版

其主要的特点如下

  • 独立构建, Void Linux 不基于已有的发行版修改, 有自己的一套包管理系统: xbps
  • 滚动发行, 更新内容会持续推送到系统中, 没有需要重新安装的大版本更新
  • 不使用 Systemd, 使用 runit 作为系统初始化与服务管理程序
  • 支持多种 C 标准库:Void Linux 同时支持 glibc 和 musl 两种实现,可根据需要选择

选择的理由

在上一次的文章中, 我在 Rpi Zero 2W 中使用 Garage 替代 Minio, 同时用 Podman 替代了 Docker, 将系统的内存使用量从 300+ MiB, 缩减到了 100+ MiB

此时系统的另一大内存消耗的地方便落到了 Systemd 上, 我期望找到一个不使用 Systemd 的精简发行版, 同时希望它对于 Rpi 有良好的支持

比较后我发现,只有 Alpine Linux 和 Void Linux 满足需求,而 Void Linux 的安装过程对我而言更加简单

安装过程

设置分区

Void Linux 的 Arm Platform 下载页面提供了树莓派 aarch64 的两种下载包

  • platform image 也就是系统镜像, 包含了磁盘分区内容
  • rootfs tarball 只包含了系统文件, 可以自定义分区与文件系统

我选择的是 rootfs tarball, 采用与 Arch Linux Arm 相同的分区方案

分区大小文件系统说明
/dev/mmcblk0p1512MiBvfat挂载 boot 分区
/dev/mmcblk0p2剩余磁盘空间ext4挂载 / 分区

而后使用 bsdtar 将下载的压缩包解压到 sd 卡中

修改启动内容

而后修改启动内容, 共有两处

/boot/config.txt 底部增加配置

...

[all]
dtoverlay=dwc2
gpu_mem=16

修改 /boot/cmdline.txt 的启动命令

root=/dev/mmcblk0p2 rw rootwait modules-load=dwc2,g_ether,ip_tables,iptable_nat g_ether.host_addr=ca:9d:fb:09:5a:62 g_ether.dev_addr=d6:b1:ca:33:f0:2d cgroup_enable=cpuset cgroup_enable=memory cgroup_memory=1 console=serial0,115200 console=tty1 fsck.repair=yes dwc_otg.lpm_enable=0 elevator=noop

之后就可以插入树莓派并启动, 使用 root 用户名和 voidlinux 作为密码登陆

系统基本配置

增加普通用户

在 Void Linux 中, 默认只有 root 用户, 我们要添加一个普通用户作为我们日常使用的账户

# 添加名为 xxl 的组,GID 为 1000
groupadd -g 1000 xxl

# 添加名为 xxl 的用户,UID 为 1000,主组为 xxl,创建主目录,shell 为 /bin/bash
useradd -u 1000 -g 1000 -m -s /bin/bash xxl

# 设置密码
passwd xxl

# 将 xxl 增加至 wheel 组, 而后修改 /etc/sudoers, 让 wheel 组可以执行 sudo 指令
usermod -aG wheel xxl

设置时区

sudo ln -sf /usr/share/zoneinfo/Asia/Shanghai /etc/localtime

更换镜像源与系统更新

根据清华源的帮助文档

执行以下步骤

mkdir -p /etc/xbps.d
cp /usr/share/xbps.d/*-repository-*.conf /etc/xbps.d/
sed -i 's|https://repo-default.voidlinux.org|https://mirrors.tuna.tsinghua.edu.cn/voidlinux|g' /etc/xbps.d/*-repository-*.conf

使用 xbps-install -Syu 更新系统

安装系统日志

Void Linux 默认安装后不会带有 syslog 组件, 需要自行安装

# 安装 socklog-void 作为 syslog 的实现
xbps-install socklog-void

# 设置为开机启动
ln -s /etc/sv/socklog-unix /var/service/
ln -s /etc/sv/nanoklogd /var/service/

安装 Podman

使用 xbps-install podman podman-compose 安装软件包

并修改 /etc/subuid/etc/subgid 的内容, 两个文件内容相同

xxl:100000:65536

启动 Podman 后可能遇到以下问题

WARN[0000] "/" is not a shared mount, this could cause issues or missing mounts with rootless containers

这表明根文件系统 / 不是一个 "shared mount",非 root 用户使用容器时可能会出现 volume 不可见、bind mount 不生效等奇怪的问题。

需要修改 /etc/rc.local, 将以下内容添加到文件末尾

mount --make-rshared /

可以通过 findmnt -o TARGET,PROPAGATION / 检查是否生效

runit 设置

添加用户级别运行服务

完成上述配置后, Podman 就已经可以使用了, 但还需要让 Podman 在系统重启时, 自动启动相关的 rootless 容器

在有 Systemd 的系统中, 可以使用以下的命令, 启动一个用户级的 Podman 重启服务

systemctl --user enable podman-restart.service

在 runit 中, 我们也需要实现类似的逻辑

按照官方文档中的示例, 我们可以创建 /etc/sv/runsvdir-xxl 目录

在其中添加 run 文件, 并写入以下内容

#!/bin/sh
export USER="xxl"
export HOME="/home/xxl"

groups="$(id -Gn "$USER" | tr ' ' ':')"
svdir="$HOME/.service"

# 此条命令用于检测 chronyc 是否同步
# 为防止出现时间显示错误, 仅在同步完成后才执行后续逻辑
# 也可酌情去掉, 不影响服务启动
chronyc tracking | grep -q "Leap status *: Normal" || exit 1

exec chpst -u "$USER:$groups" runsvdir "$svdir"

我们声明了一个系统级服务, 用于启动用户级别的服务

runit 原生没有启动顺序的配置, 如果需要一个服务在另一个服务后运行, 只能在服务启动时自行判断, 如果依赖服务未启动, 则 exit 1 退出, 这样 runit 会自动重试

随后我们创建 ~/.service~/.sv 两个文件夹

其中, ~/.service 是软链接运行目录, 而 ~/.sv 是服务仓库

添加 podman-restart

~/.sv 添加 podman-restart 文件夹, 并添加 run 脚本

#!/bin/sh
exec 2>&1

[ -r ./conf ] && . ./conf
podman ${LOGGING} start --all --filter restart-policy=always || exit 1
exec chpst -b podman-restart pause

其中 exec 命令是待执行的 Daemon 进程, 由于重启为一次性任务, 实际执行 pause 命令,该命令会使进程无限阻塞,从而保持服务状态不退出, 并将其名字改为 podman-restart, 否则进程退出后, runit 还会反复重试, 造成不必要的资源浪费

conf 文件内容

LOGGING="--log-level=info"

随后增加 log 文件夹, 并加入 run 脚本, 用于记录该进程的日志

#!/bin/sh
exec svlogd -tt ./main

完整的服务文件夹结构

.sv/podman-restart/
├── conf
├── log
│   └── run
└── run

最后启动 podman-restart 服务和 runsvdir-xxl 服务

# 为 run 脚本增加执行权限
sudo chmod +x /etc/sv/runsvdir-xxl/run
chmod +x ~/.sv/podman-restart/{run,log/run}

cd ~/.service
ln -s ../.sv/podman-restart .

sudo ln -s /etc/sv/runsvdir-xxl /var/service/

最终效果

在安装 Void Linux 系统后, 系统启动后无而外服务情况下, 内存消耗仅 60+ MiB, 增加 Garage 服务后, 也仅消耗 90+ MiB 内存