修改磁盘镜像以创建基于 Raspberry Pi 的家庭实验室

使用 Raspberry Pi 或其他单板计算机创建一个“家庭私有云”。
172 位读者喜欢这个。
Science lab with beakers

构建一个 家庭实验室 可以是一种有趣的娱乐方式,同时学习新概念和试验新技术。 感谢单板计算机 (SBC) 的普及,尤其是 Raspberry Pi 的带领,在家中舒适地构建多计算机实验室比以往任何时候都更容易。 创建一个“家庭私有云”也是一个很好的方式来接触云原生技术,而成本远低于使用大型云提供商复制相同的设置。

本文解释了如何修改 Raspberry Pi 或其他 SBC 的磁盘镜像,预先配置主机以进行 SSH (安全外壳) 连接,并禁用在首次启动时强制交互以进行配置的服务。 这是一种使您的设备像云实例一样“启动即用”的好方法。 之后,您可以使用 SSH 连接通过自动化流程进行更专业、更深入的配置。

此外,当您向您的实验室添加更多 Pi 时,修改磁盘镜像可以让您只需将镜像写入 SD 卡,将其放入 Pi 中即可!

Multiple Raspberry Pi computers, a switch, and a power bank

解压缩并挂载镜像

对于这个项目,您需要修改服务器磁盘镜像。 我在测试期间使用了 Fedora Server 31 ARM 镜像。 下载磁盘镜像并 验证其校验和 后,您需要将其解压缩并挂载到主机文件系统上的某个位置,以便您可以根据需要对其进行修改。

您可以使用 xz 命令通过使用 --decompress 参数来解压缩 Fedora Server 镜像

xz --decompress Fedora-Server-armhfp-X-y.z-sda.raw.xz

这将为您留下一个原始的、解压缩的磁盘镜像(它会自动替换 .xz 压缩文件)。 这个原始磁盘镜像就像它听起来的那样:一个包含格式化和安装磁盘上的所有数据的文件。 这包括分区信息、引导分区、根分区和任何其他分区。 您需要挂载您打算工作的分区,但为此,您需要了解该分区在磁盘镜像中的起始位置以及磁盘上扇区的大小,以便您可以将文件挂载在正确的扇区。

幸运的是,您可以在磁盘镜像上像在真实磁盘上一样轻松地使用 fdisk 命令,并使用 --list-l 参数来查看分区列表及其信息

# Use fdisk to list the partitions in the raw image:
$ fdisk -l Fedora-Server-armhfp-31-1.9-sda.raw
Disk Fedora-Server-armhfp-X-y.z-sda.raw: 3.2 GiB, 3242196992 bytes, 6332416 sectors
Units: sectors of 1 * 512 = 512 bytes
Sector size (logical/physical): 512 bytes / 512 bytes
I/O size (minimum/optimal): 512 bytes / 512 bytes
Disklabel type: dos
Disk identifier: 0xdaad9f57

Device                               Boot   Start     End Sectors  Size Id Type
Fedora-Server-armhfp-X-y.z-sda.raw1         8192  163839  155648   76M  c W95 F
Fedora-Server-armhfp-X-y.z-sda.raw2 *     163840 1163263  999424  488M 83 Linux
Fedora-Server-armhfp-X-y.z-sda.raw3      1163264 6047743 4884480  2.3G 83 Linux

您需要的所有信息都在此输出中可用。 第 3 行指示扇区大小,包括逻辑和物理大小:(512 字节 / 512 字节)。

设备列表显示了原始磁盘镜像中的分区。 第一个,Fedora-Server-armhfp-X-y.z-sda.raw1 无疑是引导加载程序分区,因为它是第一个,很小(只有 76MB),并且类型为 W95 FAT32 (LBA),由 Id "c" 标识,一个用于从 SD 卡启动的 FAT32 分区。

第二个分区也不是很大,只有 488MB。 此分区是 Linux 本机类型分区 (Id 83),它可能是包含内核和 initramfs 的 Linux 引导分区。

第三个分区可能是您想要的:它有 2.3GB,因此它应该包含大部分发行版,并且它是一个 Linux 本机分区类型,这是预期的。 这应该包含您想要修改的分区和数据。

第三个分区从扇区 1163264 开始(由 fdisk 的输出中的“Start”列指示),因此您的挂载偏移量为 595591168,计算方法是将扇区大小 (512) 乘以起始扇区 (1163264)(即 512 * 1163264)。 这意味着您需要以 595591168 的偏移量挂载文件才能位于挂载点的正确位置。

有了这些信息,您现在可以将第三个分区挂载到您 home 目录中的一个目录中

$ mkdir ~/mnt
$ sudo mount -o loop,offset=595591168 Fedora-Server-armhfp-X-y.z-sda.raw ~/mnt
$ ls ~/mnt

直接在磁盘镜像中工作

一旦磁盘镜像被解压缩并挂载到主机上的某个位置,就该开始修改镜像以满足您的需求了。 在我看来,对镜像进行更改的最简单方法是使用 chroot 将会话的工作根目录更改为已挂载镜像的根目录。 但这里有个棘手的问题。

当您更改根目录时,您的会话将使用新根目录中的二进制文件。 除非您是从 ARM 系统进行所有这些操作,否则解压缩的磁盘镜像的体系结构将与您使用的主机系统不同。 即使在 chroot 中,主机系统也将无法使用具有不同体系结构的二进制文件。 至少不是本机。

幸运的是,有一个解决方案:qemu-user-static。 来自 Debian Wiki

"[qemu-user-static] 提供了用户模式仿真二进制文件,以静态方式构建。 在此模式下,QEMU 可以在另一个 CPU 上启动为一台 CPU 编译的 Linux 进程... 如果安装了 binfmt-support 包,qemu-user-static 包将注册提供的仿真器可以处理的二进制格式,因此可以直接运行外部二进制文件。"

这正是您需要在 chroot 中以非本机体系结构工作所需的东西。 如果主机系统是 Fedora,请使用 DNF 安装 qemu-user-static 包,然后重新启动 systemd-binfmt.service

# Enable non-native arch chroot with DNF, adding new binary format information
# Output suppressed for brevity
$ dnf install qemu-user-static
$ systemctl restart systemd-binfmt.service

这样,您应该可以将根目录更改为已挂载的磁盘镜像,并运行 uname 命令以验证一切是否正常工作

sudo chroot ~/mnt/ /usr/bin/uname -a -r
Linux marvin 5.5.16-200.fc31.x86_64 #1 SMP Wed Apr 8 16:43:33 UTC 2020 armv7l armv7l armv7l GNU/Linux

从更改后的根目录运行 uname 会在输出中显示 armv7l,这是原始磁盘镜像的体系结构,而不是主机。 一切都按预期工作,您可以继续修改镜像。

修改磁盘镜像

现在您可以直接更改到基于 ARM 的磁盘镜像并在该环境中工作,您可以开始对镜像本身进行更改。 您希望设置镜像,使其可以在启动后立即访问,而无需直接在 Raspberry Pi 上进行任何其他设置。 为此,您需要安装并启用 sshd(OpenSSH 守护程序)并添加 SSH 访问的授权密钥。

为了使其更像云环境并实现家庭私有云的梦想,请添加一个本地用户,授予该用户 sudo 权限,并且(就像云巨头一样)允许该用户在没有密码的情况下使用 sudo

因此,您的待办事项清单是

  • 安装并启用 SSHD(Fedora ARM 镜像中已安装并启用了 SSHD,但您可能需要为您的发行版手动执行此操作)
  • 设置一个本地用户
  • 允许本地用户使用 sudo(没有密码,可选)
  • 添加授权密钥
  • 允许 root 使用授权密钥通过 SSH 连接(可选)

我使用 GitHub 的一项功能,该功能允许您上传您的公共 SSH 密钥,并在 https://github.com/<your_github_username>.keys 上提供这些密钥。 我发现这是一种方便的分发公共密钥的方式,尽管我很偏执,总是检查下载的密钥是否与我期望的匹配。 如果您不想使用此方法,您可以直接从您的主机计算机将您的公共密钥复制到 chroot 中,或者您可以将您的密钥托管在您控制的 Web 服务器上,以便使用相同的工作流程。

要开始修改磁盘镜像,请再次 chroot 进入已挂载的磁盘镜像,这次启动一个 shell,以便可以运行多个命令

# Output of these commands (if any) are omitted for brevity
$ sudo chroot ~/mnt /bin/bash

# Install openssh-server and enable it (already done on Fedora)
$ dnf install -y openssh-server
$ systemctl enable sshd.service

# Allow root to SSH with your authorized keys
$ mkdir /root/.ssh

# Download, or otherwise add to the authorized_keys file, your public keys
# Replace the URL with the path to your own public keys
$ curl https://github.com/clcollins.keys -o /root/.ssh/authorized_keys
$ chmod 700 /root/.ssh
$ chmod 600 /root/.ssh/authorized_keys

# Add a local user, and put them in the wheel group
# Change the group and user to whatever you desire
groupadd chris
useradd -g chris -G wheel -m -u 1000 chris

# Download or add your authorized keys
# Change the homedir and URL as you've done above
mkdir /home/chris/.ssh
curl https://github.com/clcollins.keys -o /home/chris/.ssh/authorized_keys
chmod 700 /home/chris/.ssh
chmod 600 /home/chris/.ssh/authorized_keys
chown -R chris.chris /home/chris/.ssh/

# Allow the wheel group (with your local user) to use suso without a password
echo "%wheel ALL=(ALL) NOPASSWD:ALL" >> /etc/sudoers.d/91-wheel-nopasswd

这通常是设置首次启动时通过 SSH 连接到 Raspberry Pi 或其他单板计算机所需完成的全部操作。 但是,每个发行版都有自己的怪癖。 例如,Rasbian 已经包含一个本地用户 pi,并且不使用 wheel 组。 因此,对于 Raspbian,最好使用现有用户,或者删除 pi 用户并将其替换为另一个用户。

对于 Fedora ARM,镜像会提示您在首次启动时完成设置。 这违背了您在上面所做的更改的目的,特别是由于它会阻止启动直到设置完成。 您的目标是使 Raspberry Pi 像私有云基础设施的一部分一样运行,并且该工作流程包括在启动后通过 SSH 远程设置主机。 禁用由服务 initial-setup.service 控制的初始设置

# Disable the initial-setup.service for both the multi-user and graphical targets
unlink /etc/systemd/system/multi-user.target.wants/initial-setup.service
unlink /etc/systemd/system/graphical.target.wants/initial-setup.service

当您处于更改根目录时,您可以对您的系统进行任何其他您可能想要的更改,或者只是将其保留在那里,并在首次启动后遵循通过 SSH 进行配置的云原生工作流程。

重新压缩并安装修改后的镜像

完成对系统的这些更改后,剩下的就是重新压缩磁盘镜像并将其安装到 Raspberry Pi 的 SD 卡上。

确保退出 chroot,然后卸载磁盘镜像

$ sudo umount ~/mnt/

正如您最初解压缩镜像一样,您可以再次使用 xz 命令来压缩镜像。 通过使用 --keep 参数,xz 将保留原始镜像,而不是清理它。 虽然这会占用更多的磁盘空间,但保留未压缩的镜像允许您对您正在处理的镜像进行增量更改,而无需每次都解压缩它们。 这对于在测试和调整您喜欢的镜像时节省时间非常有用

# Compress the raw disk image to a .xz file, but keep the raw disk image
xz --compress Fedora-Server-armhfp-31-1.9-sda.raw --keep

压缩需要一段时间,所以花点时间站起来,伸展一下,让你的血液再次流动起来。

压缩完成后,新的、修改后的磁盘镜像可以复制到 SD 卡,以便在 Raspberry Pi 上使用。标准的 dd 方法可以很好地将镜像复制到 SD 卡,但我更喜欢使用 Fedora 的 arm-image-installer,因为它在处理未经编辑的镜像时提供了更多选项。 它对于编辑过的镜像也同样有效,并且比 dd 命令更用户友好。

请务必检查 SD 卡所在的磁盘,并在 --media 参数中使用该磁盘。

# Use arm-image-installer to copy the modified disk image to the SD card
arm-image-installer --image=Fedora-Server-armhfp-X-y.z-sda.raw.xz --target=rpi3 --media=/dev/sdc --norootpass --resizefs -y

现在,你已经拥有了一个新的、修改过的 Fedora Server ARM 镜像,可用于 Raspberry Pi 或其他单板计算机,随时可以启动并立即通过 SSH 连接到你的修改。此方法还可以用于进行其他更改,如果你喜欢 Fedora 以外的其他发行版的原始磁盘镜像,也可以使用此方法。这是一个构建家庭私有云的好基础。在以后的文章中,我将指导你使用云技术和自动化设置家庭实验室。

延伸阅读

我花了很多精力研究如何完成本文中的工作。以下列出了我在学习如何自定义磁盘镜像和使用非本地架构时发现的两个最有用的资源。 它们在帮助我从“我不知道自己在做什么”到“好吧,我可以做到!”的转变过程中非常有帮助。

接下来阅读什么
标签
Chris Collins
Chris Collins 是 Red Hat 的 SRE,也是 OpenSource.com 的通讯员,他对自动化、容器编排及其周围的生态系统充满热情,并且喜欢在家中重新创建企业级技术以获得乐趣。

4 条评论

我非常感谢关于 Raspberry Pi 4 入门培训的任何建议。 我也很感谢您对从三年级到高中课程的投入或建议。 提前致谢。

你知道我所做的是,按照我想要的方式设置一个 pi,包括 ssh、所有补丁、固件、gpio 布线、软件包等等。 然后在另一台计算机上使用 dd 创建该 sd 卡的镜像。 在我部署它之前,我快速挂载它并修改它的 ip 地址和主机名,然后刻录该镜像,新的 pi 就可以使用了...

我发现能够修改简单的设备是一种罕见的乐趣,可以让我们的思想进一步发展,增加我们偶然发现改变生活的对我们自己和人类的理解的机会。

Creative Commons License此作品根据 Creative Commons Attribution-Share Alike 4.0 International License 许可。
© . All rights reserved.