MKOSI笔记
MKOSI-INITRD
mkosi-initrd
是使用MKOSI进行initramfs构建的工具。
1 | mkosi-initrd [选项] |
可用选项有:
--kernel-version=
:使用的内核版本,默认使用$(uname -r)
。--format=|-t
:输出格式,可选值有cpio
或uki
,默认使用cpio
。-o|--output=
:输出文件名前缀,默认为initrd
。-O|--output-dir=
:输出的目录,默认为工作目录。--debug
:Debug输出。
它本质上是一个使用了特殊的默认配置的MKOSI Wrapper脚本(见mkosi.conf),在执行时,它会获取当前主机的内核版本(或用户指定的内核版本),并将当前内核的/usr/lib/modules/版本号
目录映射到镜像中进行构建。
该命令行工具由MKOSI的Pypi包提供,对于发行版来说,它们也可以使用Kernel-install脚本进行集成(参考setup-mkosi)。
MKOSI-SANDBOX
mkosi-sandbox
用于在沙箱中执行命令:
1 | mkosi-sandbox [选项] [命令] [参数] |
命令默认为bash
。
接受的选项有:
--tmpfs 目录
:沙箱中挂载的Tmpfs。--dev 目录
:沙箱中创建的Devfs。--proc 目录
:沙箱中创建的Procfs。--dir 目录
:沙箱中递归创建的目录。--bind|--bind-try|--ro-bind|--ro-bind-try 主机目录 沙箱目录
:(只读)绑定挂载到沙箱的目录。--symlink 路径 链接
:在沙箱中创建软链接。--write 数据 路径
:在沙箱中写入指定文件。--overlay-lowerdir 主机目录
:设置下一个Overlayfs的下层目录。--overlay-upperdir 主机目录|tmpfs
:设置下一个Overlayfs的上层目录。--overlay-workdir 主机目录
:设置下一个Overlayfs挂载的工作目录。--overlay 沙箱目录
:在沙箱中挂载Overlayfs。--unsetenv 变量名
:在沙箱中去掉环境变量。--setenv 变量名 值
:在沙箱中设置环境变量。--chdir 目录
:启动沙箱时的工作目录。--same-dir
:启动沙箱时的工作目录为当前宿主机所处的目录。--become-root
:成为沙箱内的Root用户并获取CAP_SYS_ADMIN
,默认为普通用户。--suppress-chown
:禁止使用chown()
系统调用。--unshare-net
:隔离网络命名空间。--unshare-ipc
:隔离IPC命名空间。
实例:
1 | mkosi-sandbox --bind / / --same-dir --become-root bash --login |
1 | mkosi-sandbox \ |
MKOSI
Linux发行版 = Base Files(Base Rootfs) + Essential Packages + Package Manager:
- Debian/Ubuntu =
debootstrap
(base-files
+base-passwd
) +"Essential: yes" Packages
+apt
- Fedora/CentOS/RHEL =
yum|dnf --installroot
(setup
+basesystem
+filesystem
) +@core Package Group
+yum|dnf
- Arch =
pacstrap
(base
) +base Meta Package
+pacman
- Gentoo =
stage 3 Image
+@system Set
+emerge
mkosi
是建立在dnf --installroot
、debootstrap
、pacstrap
等工具之上的,快速构建客制化的系统镜像并进行测试的工具。
“镜像”在这里是一个通用概念,这意味着MKOSI可以生成以下类型的“镜像”:
- 使用GPT分区表的磁盘镜像,可以克隆到磁盘中。
- CPIO归档,用于作为initramfs使用。
- USI(Unified System Image,即将完整的操作系统打包进UKI的镜像)
- Sysext、Confext、Portable Service Image镜像
- 用于容器的目录树镜像
安装
mkosi
在各大发行版的软件源中有提供:
1 | # Debian |
也可以使用pip
安装:
1 | pipx install git+https://https://github.com/systemd/mkosi.git |
语法
1 | mkosi [选项] 子命令 |
构建配置文件
mkosi
的任何命令都基于特定的规则读取配置文件,优先级顺序分别是:
- 最优先:命令行选项。
- 当前目录下的
mkosi.local.conf
配置文件或mkosi.local
目录下的配置文件。该文件仅用于本地配置,不应该共享。 -C|--directory=
指定目录(默认为当前目录)下的mkosi.conf
配置文件。--directory=
指定目录(默认为当前目录)下的mkosi.conf.d/
目录内的配置文件。- 用户指定的Profile对应的
mkosi.profiles/
里面的子目录配置。 mkosi.images/
里面的子镜像的配置。
子命令
mkosi
由多种子命令组成,这些命令其实都是一些外部工具的简易接口:
summary
:打印配置文件中定义的配置总结,这也反映了构建时会进行的操作。build
:从配置文件中读取配置并开始构建镜像。sysupdate
:执行systemd-sysupdate
,其中,--transfer-source=
设为输出目录(默认为mkosi.output/
),--definition=
设为SysupdateDirectory=
的值(默认为mkosi.sysupdate/
),任何子命令之后的参数都会被传递给systemd-sysupdate
。- 要求:MKOSI使用的Sysupdate配置中,必须设置
PathRelativeTo=explicit
和Path=/
才能正常使用sysupdate
子命令进行更新,这会使得配置中的Path=
使用mkosi.output/
(或OutputDirectory=
指定的目录)作为根。 - 如果使用了ToolsTree,且存在文件系统中存在
/usr/share/factory
,那么ToolsTree中必须也存在/usr/share/factory
,否则会发生文件系统只读错误,这是因为ToolsTree的/usr
在Sandbox中是被只读挂载的,无法在沙盒中创建/usr/share/factory
挂载点。 - 这同时也意味着,
SplitArtifacts=partitions
必须启用以对分区进行更新,而且更新内容(分区镜像文件、EFI程序、initramfs)文件名必须与Sysupdate配置中的MatchPattern=
匹配。
- 要求:MKOSI使用的Sysupdate配置中,必须设置
shell
:(如果还没有构建)先构建镜像,然后调用systemd-nspawn
Chroot到镜像内。- 仅适用于
QCow2=no
且未压缩的镜像。
- 仅适用于
boot
:(如果还没有构建)先构建镜像,然后调用systemd-nspawn
以容器形式启动镜像。- 仅适用于
QCow2=no
且未压缩的镜像。
- 仅适用于
qemu
:(如果还没有构建)先构建镜像,然后调用qemu
以虚拟机形式启动镜像。- 对于目录树,MKOSI使用
virtiofsd
引导。 ssh
:连接到镜像对应的虚拟机。genkey
:创建SSH密钥。
- 对于目录树,MKOSI使用
serve
:(如果还没有构建)先构建镜像,然后调用内置的HTTP服务器在8081
端口上暴露工作目录。- (仅用于
disk
镜像)burn 块设备
:(如果还没有构建)先构建镜像,然后将镜像扩展到目标块设备的大小,再烧录到指定的块设备上。 journalctl
:获取镜像内的日志。coredumpctl
:获取镜像内的内核转储文件。clean
:清理之前的构建产物。bump
:刷新mkosi.version
文件中的镜像版本。genkey
:生成安全启动密钥。
命令行选项
这里提到的命令行选项是和构建配置完全无关的:
-f|--force
:进行指定操作前,不加分辨地重新构建镜像。-B--auto-bump
:执行操作后自动刷新版本号。-C|--directory=
:指定工作目录,默认为当前工作目录。--debug
:启用Debug级输出。--debug-shell
:当在镜像中执行命令失败时,启动一个额外的Debug Shell用于排错。--debug-workspace=
:执行操作后,指定的临时文件目录内容不会删除。
构建配置
构建配置文件符合.ini
格式,每一行都是Key=Value
的形式,每一个配置项都有等价的命令行选项,转换方式是SomeSetting
到some-setting
。
配置中存在以下可用的占位符:
含义 | 占位符 |
---|---|
Distribution= |
%d |
Release= |
%r |
Architecture= |
%a |
Format= |
%t |
Output= |
%o |
OutputDirectory= |
%O |
ImageId= |
%i |
ImageVersion= |
%v |
Profiles= |
%p |
配置文件所在目录 | %C |
工作目录 | %P |
MKOSI的执行目录 | %D |
当前子镜像的镜像名 | %I |
具体的构建配置有:
[Match]
段与[TriggerMatch]
段
匹配构建时包含当前配置文件的特定条件。每个配置项除了使用=
连接键值对外,还可以使用=|
连接键值对,多个使用=
连接键值对的配置项之间是逻辑与关系,必须全部满足;多个使用=|
连接键值对的配置项之间是逻辑或关系,满足一个即可。
可用配置项有:
Profiles=
:使用的Profile。Distribution=
:构建的发行版。Release=
:构建的发行版版本。Architecture=
:构建的架构。可用的值有alpha
、arc
、arm
、arm64
、ia64
、loongarch64
、mips64-le
、mips-le
、parisc
、ppc
、ppc64
、ppc64-le
、riscv32
、riscv64
、s390
、s390x
、tilegx
、x86
、x86-64
。HostArchitecture=
:主机的架构。ImageId=
:构建的镜像名称。ImageVersion=
:构建的镜像版本。Bootable=
:构建的镜像是否可引导。Format=
:构建的镜像格式。ToolsTreeDistribution=
:使用的Tools Tree发行版。PathExists=
:主机上存在指定目录。SystemdVersion=
:主机上的systemd版本。
[Match]
段之间是纯粹的AND关系,也就是说,不同的[Match]
段必须全部满足。而[TriggerMatch]
段之间是OR关系,也就是说,不同的[TriggerMatch]
段中,只要有一个[TriggerMatch]
段满足即可。
(v20以上版本)[Include]
段
Include=
:导入指定的额外配置文件。如果值为mkosi-initrd
,那么会使用mkosi-initrd
的配置生成initramfs。- 特殊值
mkosi-initrd
表示mkosi-initrd
的配置。 - 特殊值
mkosi-tools
表示ToolsTree的配置。 - 特殊值
mkosi-vm
表示运行虚拟机时的默认配置。
- 特殊值
(v20以上版本)[Config]
段
额外配置。
Profiles=
:使用指定的Profile,Profile是mkosi.profiles/
目录下保存的一个子工作目录,它支持的内容和MKOSI的主工作目录完全一致(除了不能有mkosi.profiles/
目录),会覆盖主工作目录的对应部分。- Profile通常是让用户通过
--profile=
命令行选项进行自选的。它可以用于匹配,因此适合保存相同镜像的不同口味。 - Profile并不能修改
mkosi.images/
中的子镜像的配置。
- Profile通常是让用户通过
ConfigureScript=
:在读取配置文件后立刻执行的脚本。默认为mkosi.configure
。MinumumVersion=
:要求的最小MKOSI版本号。PassEnvironment=
:传递的环境变量,空格分隔。Dependencies=
:依赖的子镜像,子镜像是mkosi.images/
目录下保存的一个子工作目录,它支持的配置项和MKOSI的主工作目录相比会少一些,如果没有Dependencies=
,那么所有子镜像都会在主镜像构建之前自动构建,即Dependencies=*
,如果有Dependencies=
,那么只构建依赖的镜像。- 子镜像不接受的配置项有:
Architecture=
BuildDirectory=
BuildSources=
BuildSourcesEphemeral=
CacheDirectory=
CacheOnly=
Distribution=
ExtraSearchPaths=
Incremental=
LocalMirror=
Mirror=
OutputDirectory=
OutputMode=
PackageCacheDirectory=
PackageDirectories=
Profiles=
ProxyClientCertificate=
ProxyClientKey=
ProxyExclude=
ProxyPeerCertificate=
ProxyUrl=
Release=
RepartOffline=
Repositories=
RepositoryKeyCheck=
SandboxTrees=
SourceDateEpoch=
ToolsTree=
ToolsTreeCertificates=
UseSubvolumes=
VerityCertificate=
VerityKey=
VolatilePackageDirectories=
WithNetwork=
WithTests
WorkspaceDirectory=
[Distribution]
段
发行版配置。
Distribution=
:使用的发行版,目前支持fedora,debian,ubuntu,arch,opensuse,mageia,centos,centos_epel,openmandriva,rocky,rocky_epel,alma,alma_epel,gentoo,custom
。默认使用主机的发行版。- 当
Distribution=custom
时,无法自动构建Rootfs,需要自行提供。
- 当
Release=
:使用的版本。默认使用主机的版本。Architecture=
:使用的架构。默认使用主机的架构。Mirror=
:使用的镜像源。- 在使用EPEL时,如果要为EPEL使用其他镜像,使用
$EPEL_MIRROR
环境变量。 - Debian的Debug和Security源无法直接切换镜像,考虑使用
mkosi.pkgmngr
,或是构建无Debug和Security仓库的sid|unstable
版本。
- 在使用EPEL时,如果要为EPEL使用其他镜像,使用
LocalMirror=
:在构建时使用的镜像源,但并不写入最终镜像内。RepositoryKeyCheck=
:检查镜像源密钥。- (新版本)
RepositoryKeyFetch=
:在安装时自动尝试获取软件源密钥,默认启用,如果禁用,将从宿主机传递软件源密钥,这需要安装对应的*-keyring
软件包。 Repositories=
:启用的Yum源名(例如epel
),或是Apt源的分区(例如main
)。使用逗号分隔。
[Output]
段
输出方式。
Format=
:导出格式,mkosi
支持非常多种镜像,包括但不仅限于:disk
(旧版本为gpt_ext4|gpt_ext4|gpt_xfs
):GPT+UEFI磁盘镜像。使用systemd-repart
生成。directory
:纯目录形式的容器根文件系统。tar
:Tar包。cpio
:CPIO包。uki
:UKI镜像。esp
:类似于uki
,但是转换为一个包含单个ESP的GPT分区表的磁盘镜像。oci
:OCI容器镜像。sysext|confext|portable
:系统扩展镜像。none
:当前配置用于分组,不实际生成镜像。
ManifestFormat=
:生成镜像大纲(保存安装的所有软件包列表)的格式,可选json
或changelog
,默认不生成。Output=
:镜像文件/目录的前缀,默认为image
。OutputDirectory=
:构建产品的保存目录,默认为工作目录下的mkosi.output/
。CompressOutput=
:输出镜像的压缩方式,请注意,这会导致shell
、boot
、qemu
命令在该镜像上不可用。仅可用于tar
、cpio
、uki
、esp
和oci
镜像。可选值有布尔值和xz
、zstd
等压缩算法。默认使用zstd
。CompressLevel=
:(新版本)压缩等级。
SplitArtifacts=
:分开导出的产品列表,使用逗号分隔,可选值有uki
、kernel
、initrd
、partitions
。- 默认值
no
等价于uki,kernel,initrd
。 uki
会导出UKI。kernel
和initrd
会导出组成UKI的内核和initramfs。partitions
在使用磁盘镜像时,会告诉systemd-repart
针对每个分区分别进行导出。默认情况下,导出的分区文件会以镜像名.分区名
命名。OutputSplitRoot=
:(旧版本)导出根分区镜像的名称。OutputSplitVerify=
:(旧版本)导出的校验分区的名称。OutputSplitKernel=
:(旧版本)导出的ESP分区的名称。
- 默认值
ImageVersion=
:镜像的版本号。- 你也可以使用
mkosi.version
指定版本号,此文件还可以是一个可执行的Shell脚本,使其输出作为版本号。
- 你也可以使用
ImageID=
:镜像名称,会写入镜像的os-release
文件中。- (新版本)
RepartDirectories=
:systemd-repart
的分区定义配置文件目录,默认为工作目录下的mkosi.repart/
。- 注意,MKOSI的分区配置文件中的
CopyFiles=
的源路径会使用镜像中的根文件系统。
- 注意,MKOSI的分区配置文件中的
- (新版本)
SectorSize=
:systemd-repart
的块大小。 - (新版本)
Seed=
:systemd-repart
使用的UUID,也可以使用mkosi.seed
文件保存,默认值为random
。 - (新版本)
Overlay=
:和BaseTrees=
一起使用,是否仅仅保留相对于Base Tree发生改变的内容,用于构建系统扩展镜像。- 在构建系统扩展镜像时,可以使用该选项结合
BaseTree=
指定的目录以获取增量部分,即扩展镜像的部分。
- 在构建系统扩展镜像时,可以使用该选项结合
- (新版本)
CleanScripts=
:用于构建的最后阶段进行清理的脚本,默认为mkosi.clean
。
(v20以上版本)[Build]
段
ToolsTree=
:在指定目录下搜索构建工具组,也可以使用mkosi.tools/
目录保存,这有助于使用其他版本的构建工具组。- 如果值为
default
,那么会从指定的发行版的软件源中自动获取Tools Tree。在目标发行版的systemd版本低于构建所需的最低要求时,会自动启用。在当前发行版低于构建所需的最低systemd版本时,该选项必须启用。 ToolsTreeDistribution=
:用于自动获取ToolsTree=
的目标发行版。ToolsTreeRelease=
:用于自动获取ToolsTree=
的目标发行版版本。ToolsTreeMirror=
:用于自动获取ToolsTree=
的目标发行版镜像源。ToolsTreeRepositories=
:和Repositories=
一样,但是用于构建ToolsTree=
。ToolsTreeSandboxTrees=
:和SandboxTrees=
一样,但是用于构建ToolsTree=
。ToolsTreePackages=
:在ToolsTree=
中包含的额外软件包。ToolsTreeCertificates=
:是否使用Tools Tree中的证书,这包括/etc/pki
、/etc/ssl
、/etc/ca-certificates
和/var/lib/ca-certificates
,如果禁用,使用主机上的证书。
- 如果值为
Incremental=
:渐进构建,可选值为布尔值或strict
。在执行mkosi.build
脚本之前提供镜像缓存,这可以显著提高构建速度。如果为strict
,那么如果缓存镜像不存在则会报错退出。CacheOnly=
:纯缓存模式,可选值有auto
、metadata
、always
或never
,如果为always
,那么包管理器不会联网,只使用本地缓存;如果为metadata
,那么包管理器不会联网更新元数据;如果为auto
,那么仅在不存在缓存镜像时更新元数据。SandboxTrees=
:接受逗号分隔的,冒号绝对路径对。前者是主机上的路径,后者是MKOSI沙箱内的路径,表示在执行构建之前拷贝到沙箱的文件。也可以使用mkosi.sandbox/
目录进行保存。WorkspaceDirectory=
:临时文件的保存目录,默认为$XDG_CACHE_HOME
或$HOME/.cache
或/var/tmp
。CacheDirectory=
:构建时软件包管理器缓存的保存目录,默认使用工作目录下的mkosi.cache/
。PackageCacheDirectory=
:软件包管理器的缓存目录。BuildDirectory=
:用于执行Out-of-Tree构建的构建目录,这使得构建产品可以在多次构建时共享。默认为mkosi.builddir/
。UseSubvolumes=
:是否使用Btrfs子卷,可选值有布尔值或auto
。RepartOffline=
:是否在不使用回环设备的情况下构建磁盘镜像,仅在以XFS为根文件系统且启用SELinux的情况下需要启用。History=
:是否保存历史,历史会被保存在.mkosi-private
目录下。ExtraSearchPaths=
:用于搜索工具的额外目录,会在构建时被添加到$PATH
中。ProxyUrl=
:使用的代理地址。ProxyExclude=
:不使用代理的主机名。ProxyPeerCertificate=
:代理Peer的证书。ProxyClientCertificate=
:代理客户端的证书。ProxyCientKey=
:代理客户端的Key。
[Content]
段
镜像配置:
Packages=
:包含的包,使用逗号或是换行符分隔。会使用该发行版对应的包管理器进行安装。BuildPackages=
:在构建的Overlayfs中安装包。这样的包应当用于mkosi.build
脚本。PackageDirectories=
:读取指定目录下的额外软件包并在构建时在镜像中进行安装。- (新版本)
WithRecommends=
:是否安装弱依赖,仅适用于apt
、dnf
和zypper
。默认禁用。 WithDocs=
:是否在镜像内保留文档。默认启用。- (新版本)
MakeInitrd=
:是否在镜像内创建/init
和/etc/initrd-release
文件。该配置项通常在MKOSI-INITRD内部使用。 - (新版本)
BaseTrees=
:接受逗号分隔的,冒号绝对路径对。前者是主机上的路径,后者是镜像内的路径,表示在获取发行版基本根文件系统之前,将主机文件/目录拷贝到镜像内。这也是Overlay=yes
参考的基础文件系统。如果没有指定镜像内的路径,那么默认为/
。 SkeletonTrees=
:接受逗号分隔的,冒号绝对路径对。前者是主机上的路径,后者是镜像内的路径,表示在已经构建基本根文件系统,开始安装软件包之前,将主机文件/目录拷贝到镜像内。mkosi.skeleton/
目录下的文件总是会被拷贝到相同的目标位置下。
ExtraTrees=
:接受逗号分隔的,冒号绝对路径对。前者是主机上的路径,后者是镜像内的路径,表示在安装软件包之后,将主机文件/目录拷贝到镜像内。mkosi.extra/
目录下的文件总是会被拷贝到相同的目标位置下。
RemovePackages=
:在构建后删除指定的包。RemoveFiles=
:在构建后删除指定的文件,路径使用镜像内的根文件系统。CleanPackageMetadata=
:是否在构建后清理镜像内包管理器的缓存。默认为是。Bootable=
:镜像是否可引导(是否安装引导程序),可选值除了布尔值还有auto
。默认为auto
,即尽可能设置。如果设为yes
,那么在Bootloader=
设置的Bootloader软件包不存在时,构建会失败。- 镜像内必须安装对应架构的内核。
- (新版本)
Bootloader=
:使用的引导程序,可选none
、systemd-boot
或grub
。默认为systemd-boot
。- 如果
Bootable=no
,那么该配置项无意义。 - 如果使用
none
,那么和Bootable=no
效果一致。 - 如果使用
grub
,那么镜像中必须安装对应架构的grub
软件包,确保存在/usr/lib/grub
或/usr/share/grub2
目录。 - 如果使用
systemd-boot
,那么镜像中必须安装对应架构的grub
软件包,确保存在bootctl
程序。
- 如果
- (新版本)
BiosBootloader=
:是否安装BIOS引导,可选none
或grub
,如果启用,那么需要创建大小为1MB,类型为21686148-6449-6e6f-744e-656564454649
的biosboot
分区。默认为none
。- 如果
Bootable=no
,那么该配置项无意义。 - 如果使用
grub
,那么镜像中必须安装对应架构的grub
软件包。
- 如果
- (新版本)
ShimBootLoader=
:是否安装Shim,可选none
、unsigned
或signed
。在SecureBoot=true
的情况下,如果为unsigned
,那么MKOSI会安装未签名的Shim,并自行对其进行签名,如果为signed
,那么MKOSI会安装已签名的Shim。默认为none
。- 如果设为
unsigned
,那么镜像内必须安装shim-unsigned
软件包。 - 如果设为
signed
,那么镜像内必须安装shim-signed
软件包。 - 在没有启用
SecureBoot=true
的情况下,该选项没有意义。
- 如果设为
- (新版本)
KernelModulesInclude=
:在镜像中包含的内核模块,格式为相对于/usr/lib/modules/内核版本/kernel
目录的路径正则表达式,这对于initramfs特别有用。- 关键词
default
表示包含MKOSI-INITRD的mkosi.conf
中的所有默认配置,参见mkosi.conf。这也是未设置该配置项的默认值。 - 关键词
host
表示包含宿主机当前加载的所有模块。
- 关键词
- (新版本)
KernelModulesExclude=
:在镜像中排除的内核模块。- 因为MKOSI默认会加载
mkosi-initrd
的配置,因此如果希望重设模块,必须先设置KernelModulesExclude=.*
。
- 因为MKOSI默认会加载
initramfs配置:
- (新版本)
KernelModulesInitrd=
:是否在Bootable=true
的镜像中使用MKOSI构建一个独立的,额外的initramfs,默认启用。- 这是推荐的行为,因为MKOSI开发组期望构建出的镜像使用与本地环境无关的initramfs。构建过程中会使用镜像内的安装的内核和固件(在安装时均会被MKOSI移动到
/usr/lib/modules/
目录下)进行打包。
- 这是推荐的行为,因为MKOSI开发组期望构建出的镜像使用与本地环境无关的initramfs。构建过程中会使用镜像内的安装的内核和固件(在安装时均会被MKOSI移动到
- (新版本)
KernelModulesInitrdInclude=
:在initramfs中包含的模块。- 关键词
default
表示包含MKOSI-INITRD的mkosi.conf
中的所有默认配置,参见mkosi.conf。这也是未设置该配置项的默认值。 - 关键词
host
表示包含宿主机当前加载的所有模块。
- 关键词
- (新版本)
KernelModulesInitrdExclude=
:在initramfs中排除的模块。 UnifiedKernelImages=
:是否使用UKI而不是独立initramfs。默认为auto
,即尽可能使用。- 如果启用了UKI:如果
systemd-repart
发现了存在哈希值(即,启用了Verity)的根文件系统分区,那么会将其哈希值写入UKI的roothash=
内核命令行参数中。否则,如果systemd-repart
发现了存在哈希值(即,启用了Verity)的/usr/
文件系统分区,那么会将其哈希值写入UKI的usrhash=
内核命令行参数中。 - 如果未启用UKI,且使用
systemd-boot
:如果systemd-repart
发现了存在哈希值(即,启用了Verity)的根文件系统分区,那么会将其哈希值写入BLS引导条目的roothash=
内核命令行参数中。否则,如果systemd-repart
发现了存在哈希值(即,启用了Verity)的/usr/
文件系统分区,那么会将其哈希值写入BLS引导条目的usrhash=
内核命令行参数中。否则,如果找到了GPT PARTLABEL为root*
的分区,那么会将其PARTUUID写入BLS引导条目的root=PARTUUID=
内核命令行参数中。 - 如果未启用UKI,且使用GRUB:如果
systemd-repart
发现了存在哈希值(即,启用了Verity)的根文件系统分区,那么会将其哈希值写入grub.cfg
的roothash=
内核命令行参数中。否则,如果systemd-repart
发现了存在哈希值(即,启用了Verity)的/usr/
文件系统分区,那么会将其哈希值写入grub.cfg
的usrhash=
内核命令行参数中。否则,如果找到了GPT PARTLABEL为root*
的分区,那么会将其PARTUUID写入grub.cfg
的root=PARTUUID=
内核命令行参数中。否则,如果找到了GPT PARTLABEL为usr*
的分区,那么会将其PARTUUID写入grub.cfg
的mount.usr=PARTUUID=
内核命令行参数中。 UnifiedKernelImageFormat=
:UKI文件命名,默认为&e-&k
,支持的占位符有:&&
:&
本身。&e
:Token。&k
:内核版本。&h
:roothash=
或usrhash=
的值。&c
:引导尝试次数。
UnifiedKernelImageProfiles=
:构建额外的UKI配置,接受逗号分隔的UKI配置文件。也可以保存在mkosi.uki-profiles/
目录下。UKI配置以.conf
结尾,只有一个UKIProfile
段,可用内容有:Profile=
:配置信息,包括ID
(必须)和TITLE
。Cmdline=
:内核命令行参数。
PeAddons=
:(已被移除)构建额外的PE插件,接收逗号分隔的ukify
配置文件,额外的PE插件会以配置文件名.addon.efi
命名,也可以将ukify
配置文件保存在mkosi.pe-addons/
目录下。
- 如果启用了UKI:如果
- (新版本)
MicrocodeHost=
:是否在initramfs中仅仅包含主机的CPU微码。默认禁用。 - (新版本)
InitrdPackages=
:在initramfs中额外安装的软件包。 - (新版本)
Initrds=
:使用用户提供的指定initramfs,而不是自行构建。 KernelCommandLine=
:封装在UKI或initramfs内的内核命令行参数。- 如果检测到使用了Verity的
root
分区或usr
分区,那么会自动填充roothash=分区Hash值
或usrhash=分区Hash值
。 - 内核命令行参数
root=PARTUUID
和mount.usr=PARTUUID
会被自动填充类型为root
或/usr
的分区的UUID。
- 如果检测到使用了Verity的
镜像预设配置:
MachineID=
:设置镜像内的机器ID,默认为random
,也可以使用mkosi.machine-id
文件保存。Locale=
:镜像内的语言。Keymap=
:镜像内的Keymap。Hostname=
:设置镜像内的默认主机名。RootShell=
:Root用户的默认Shell。RootPassword=
(旧版本为Password=
):设置镜像内Root用户的默认密码。- 也可以在工作目录下编写
mkosi.rootpw
文件。
- 也可以在工作目录下编写
Autologin=
:是否设置Root用户在/dev/pts/0
、/dev/tty1
和/dev/hvc0
的自动登录。Ssh=
:是否在镜像内创建SSH套接字以允许通过mkosi ssh
连接,使用mkosi genkey
创建密钥。SELinuxRelabel=
:是否在镜像内进行Relabel。
为了实现更多功能,还可以在构建镜像的不同过程中执行脚本:
- (新版本)
SyncScripts=
:在同步软件包管理器元数据后执行的脚本,默认为mkosi.sync
。 PrepareScripts=
:在安装软件包后立刻执行的脚本。默认为mkosi.prepare
。BuildScripts=
:在创建好根文件系统后立刻执行的脚本。默认为mkosi.build
。BuildSources=
:接受逗号分隔的,冒号绝对路径对。前者是主机上的路径,后者是镜像内的路径,进行构建时拷贝的代码树目录,镜像内的代码树目录总是会自动添加/work/src
前缀。BuildSourcesEphemeral=
:是否不保留对源码树的更改,默认禁用。
PostInstallationScripts=
:在配置完Extra Tree后执行的脚本,默认为mkosi.postinst
。FinalizeScripts=
:在构建完全完成后的最后阶段执行的脚本,默认为mkosi.finalize
。PostOutputScripts=
:在输出产品后执行的脚本,默认为mkosi.postoutput
。Environment=
:给脚本传递的环境变量。EnvironmentFile=
:从文件给脚本传递环境变量。WithTests=
:设为假,则在执行mkosi.build
脚本时,$WITH_TESTS
变量为0。WithNetwork=
:在执行脚本时提供网络。
[Validation]
段
SecureBoot=
:是否启用安全启动,这会影响是否对UKI进行签名。SecureBootAutoEnroll=
:是否自动导入安全启动的Key。- 这仅对虚拟机生效,如果希望对物理机生效,在Extra Tree中包含
/efi/loader/loader.conf
文件,并写入secure-boot-enroll force
或secure-boot-enroll manual
。
- 这仅对虚拟机生效,如果希望对物理机生效,在Extra Tree中包含
SecureBootKey=
:使用的安全启动PEM密钥。默认使用mkosi.key
。SecureBootCertificate=
:使用的安全启动X509证书。默认使用mkosi.crt
。SecureBootSignTool=
:为PE文件进行安全启动签名的程序,可选systemd-sbsign
、sbsign
、pesign
或auto
。SignExpectedPcr=
:使用systemd-measure
在UKI中包含PCR(平台配置寄存器)的签名,可选布尔值或auto
。Passphrase=
:LUKS加密的密钥文件,必须是600权限位,它应当保存完整的LUKS密钥,以一个换行结尾(即/etc/crypttab
文件的格式)。- 也可以选择在工作目录下创建
mkosi.passphrase
文件。
- 也可以选择在工作目录下创建
VerityKey=
:用于为Verity设备签名的PEM密钥。默认使用mkosi.key
。VerityCertificate=
:用于为Verity设备签名的X509证书。默认使用mkosi.crt
。Checksum=
:指定镜像的校验码。Sign=
:是否用gpg
给校验码签名。默认为否。Key=
:给校验码签名的密钥。OpenPGPTool=
:使用的OpenPGP实现,默认为gpg
,可选值有sqop
、rsop
。
[Runtime]
段(旧版本为[Host]
段)
Credentials=
:启动时传递给镜像中的systemd的系统凭据。
容器配置:
NSpawnSettings=
:使用systemd-nspawn
启动时,读取的.nspawn
单元文件。- 默认使用
mkosi.nspawn
文件。
- 默认使用
所有虚拟机配置项都仅适用于使用qemu
启动的虚拟机,即只适用于磁盘类型的镜像:
VirtualMachineMonitor=
:使用的虚拟机超管,可选值有qemu
或vmspawn
。QemuGui=
:若启用,会以图形界面形式启动Qemu。默认以Headless形式启动。- 旧版本下为
QemuHeadless=
:若启用,会以Headless形式启动Qemu。默认以图形界面形式启动。
- 旧版本下为
QemuSmp=
:设置Qemu的SMP。默认为2。QemuMem=
:设置Qemu的内存。默认为2G。QemuKvm=
:是否启用KVM加速,默认为auto
。QemuVsock=
:是否启用VSock,默认为auto
。QemuVsockConnectionId=
:VSock的连接ID,可选值有hash
、auto
或手动输入。QemuSwtpm=
:是否启用TPM,默认为auto
。QemuCdrom=
:是否在Qemu中以CD形式读取镜像,默认禁用。QemuBoot=
:使用的Qemu固件,可选uefi
、linux
。- 新版本下改为
QemuFirmware=
:可选uefi
、bios
、linux
、auto
。 - 新版本下可以使用
QemuFirmwareVariables=
设置UEFI固件中的变量。 - 新版本下可用
QemuKernel=
,指定使用的Direct Boot Kernel。
- 新版本下改为
QemuDrives=
:添加的驱动器,格式为ID:大小[:目录:选项]
。RuntimeTrees=
接受逗号分隔的,冒号绝对路径对。前者是主机上的路径,后者是虚拟机内的路径,如果没有后面的部分,则自动挂载在/root/src
目录下。RuntimeSize=
:将镜像在启动时扩大到指定大小。RuntimeNetwork=
:使用的Qemu网络,可选值有user
、interface
或none
。RuntimeBuildSources=
:挂载指定的源代码目录到虚拟机内的/work
目录下。RuntimeHome=
:是否挂载主机的家目录到虚拟机的/root
。RuntimeScratch=
:是否在/var/tmp
下挂载额外的空间。可选值为布尔值或auto
。UnitProperties=
:传递给NSPawn的Scope属性。KernelCommandLineExtra=
:通过Qemu传递的额外内核命令行参数。- 在Qemu中硬编码的额外内核命令行参数为(mkosi/mkosi/qemu.py):
rw
systemd.wants=network.target
module_blacklist=vmw_vmci systemd.tty.term.hvc0=宿主机终端类型 systemd.tty.columns.hvc0=宿主机终端列数 systemd.tty.rows.hvc0=宿主机终端行数
- 除非明确地手动进行设置,否则存在以下内核命令行参数的默认值:
ip=enc0:any ip=enp0s1:any ip=enp0s2:any ip=host0:any ip=none
loglevel=4
SYSTEMD_SULOGIN_FORCE=1
- 在Qemu中硬编码的额外内核命令行参数为(mkosi/mkosi/qemu.py):
QemuArgs
:配置空格分隔的Qemu原生参数。Ephemeral=
:是否将镜像设为不可变,所有操作在关闭之后都会撤销。SshKey=
:使用的SSH私钥。SshCertificate=
:使用的SSH证书。Machine=
:机器名,用于SSH连接。ForwardJournal=
:是否将容器或虚拟机的日志发送到宿主机。SysupdateDirectory=
:mkosi sysupdate
使用的配置目录,默认使用mkosi.sysupdate/
。- MKOSI使用的Sysupdate配置必须设置
PathRelativeTo=explicit
和Path=/
才能正常使用sysupdate
子命令进行更新,这会使得配置中的Path=
使用mkosi.output/
(或OutputDirectory=
指定的目录)作为根。 - 这同时也意味着,
SplitArtifacts=
必须启用以对分区进行更新,而且更新内容(分区镜像文件、EFI程序、initramfs)文件名必须与Sysupdate配置中的MatchPattern=
匹配。
- MKOSI使用的Sysupdate配置必须设置
分区
(旧版本,现已删除)在[Partitions]
段内支持以下配置项:
RootSize=
:根分区大小,默认为3G。ESPSize=
:ESP大小,默认为256MB。仅在Bootable=yes
时有效。SwapSize=
:Swap分区大小,默认为0。HomeSize=
:/home
分区大小,默认为0。SrvSize=
:/srv
分区大小,默认为0。VarSize=
:/var
分区大小。默认为0。TmpSize=
:/var/tmp
分区大小。默认为0。BiosSize=
:biosboot
分区大小,默认为0。XbootldrSize=
:XBOOTLDR
分区大小。默认为0。UsrOnly=
:仅仅保留/usr
目录,很适合无状态的镜像。
MKOSI会从mkosi.repart/
或RepartDirectories=
指定的目录中读取systemd-repart
的配置文件,并据此对磁盘镜像进行分区。文件命名应当为优先级-分区名.conf
,格式为:
1 | [Partition] |
默认情况下,MKOSI使用以下内置配置:
00-esp.conf
:
1 | [Partition] |
- 需要注意的是,
CopyFiles=
的源路径的根是构建中的镜像的根。
05-bios.conf
:
1 | [Partition] |
10-root.conf
:
1 | [Partition] |
资源目录
有以下相关的资源目录:
mkosi.conf.d/
:额外的MKOSI配置,可以是文件,也可以是子工作目录,子工作目录支持的内容和MKOSI的主工作目录完全一致(必须包含mkosi.conf
文件)。- 如果使用文件的话,那么文件中的
[Match]
段仅对该文件生效。 - 如果使用子工作目录的话,那么子工作目录中的
mkosi.conf
中的[Match]
段对整个子工作目录生效。
- 如果使用文件的话,那么文件中的
mkosi.local/
:额外的本地MKOSI配置,可以是文件,也可以是子工作目录。mkosi.skeleton/
或mkosi.skeleton.tar
:在已经构建基本根文件系统,开始安装软件包之前,将文件/目录拷贝到镜像内。与SkeletonTrees=
配置项有关。mkosi.extra/
或mkosi.extra.tar
:在安装软件包之后,将额外的文件/目录拷贝到镜像内。与ExtraTrees=
配置项有关。mkosi.pkgmngr/
或mkosi.pkgmngr.tar
:在构建时配置包管理器,但是不将文件写入镜像。这可以作为在构建时手动配置软件包管理器的手段,如果需要包含到镜像中,应该使用mkosi.skeleton/
或mkosi.skeleton.tar
。mkosi.nspawn
:systemd-nspawn
读取的容器单元文件。与NspawnSettings=
配置项有关。mkosi.cache/
:构建时软件包管理器缓存的保存目录。与CacheDirectory=
配置项有关。mkosi.builddir/
:用于执行Out-of-Tree构建的构建目录。与BuildDirectory=
配置项有关。mkosi.rootpw
:镜像中Root用户的密码。文件必须具有0600或更低的权限位。与RootPasswordFile=
配置项有关。mkosi.passphrase
:LUKS加密使用的密码。文件必须具有0600或更低的权限位。与PassphraseFile=
配置项有关。mkosi.crt
和mkosi.key
:用于签名(UEFI SecureBoot、Verity等)的X.509证书和PEM私钥。与SecureBootCertificate=
、SecureBootKey=
、VerityCertificate=
和VerityKey=
配置项有关。mkosi.output/
:用于保存所有的构建产品。与OutputDirectory=
配置项有关。mkosi.credentials/
:额外的系统凭据。目录中的每个文件名将用作凭据名,文件内容成为凭据值。与Credentials=
配置项有关。mkosi.repart/
:用于systemd-repart
的分区定义文件,这些文件在构建磁盘镜像时传递给systemd-repart
。如果存在mkosi.repart/
或是使用了RepartDirectories=
,那么就不会使用任何默认的分区定义。与RepartDirectories=
配置项有关。mkosi.uki-profiles/
:额外的UKI配置文件。与UnifiedKernelImageProfiles=
配置项有关。mkosi.pe-addons/
:额外的PE插件的ukify
配置文件。与PeAddons=
配置项有关。
钩子脚本
钩子脚本如果在末尾添加了.chroot
后缀(例如,mkosi.postinst.chroot
),那么会Chroot到镜像内部执行,否则会在工作环境中执行,脚本中有以下可用变量:
Variable | 含义 | configure |
sync |
prepare |
build |
postinst |
finalize |
postoutput |
clean |
---|---|---|---|---|---|---|---|---|---|
$ARCHITECTURE |
镜像的架构 | ✓ | ✓ | ✓ | ✓ | ✓ | ✓ | ✓ | ✓ |
$QEMU_ARCHITECTURE |
Qemu格式的架构,用于通过qemu-system-$QEMU_ARCHITECTURE 获取Qemu程序 |
✓ | |||||||
$DISTRIBUTION |
镜像的发行版 | ✓ | ✓ | ✓ | ✓ | ✓ | ✓ | ✓ | ✓ |
$DISTRIBUTION_ARCHITECTURE |
发行版格式的架构 | ✓ | ✓ | ✓ | ✓ | ✓ | ✓ | ✓ | ✓ |
$RELEASE |
镜像的版本 | ✓ | ✓ | ✓ | ✓ | ✓ | ✓ | ✓ | ✓ |
$PROFILES |
Profiles= 中设置的配置文件,使用逗号分隔 |
✓ | ✓ | ✓ | ✓ | ✓ | ✓ | ✓ | |
$CACHED |
如果有可用的缓存,为1 |
✓ | |||||||
$CHROOT_SCRIPT |
Chroot的目标路径,用于结合mkosi-chroot 使用 |
✓ | ✓ | ✓ | ✓ | ||||
$SRCDIR |
执行Chroot前的路径 | ✓ | ✓ | ✓ | ✓ | ✓ | ✓ | ✓ | ✓ |
$CHROOT_SRCDIR |
执行Chroot以后,原来的目录所在的路径 | ✓ | ✓ | ✓ | ✓ | ||||
$BUILDROOT |
当前正在构建的镜像的根目录 | ✓ | ✓ | ✓ | ✓ | ||||
$BUILDDIR |
树外构建目录的路径 | ✓ | ✓ | ✓ | ✓ | ||||
$CHROOT_BUILDDIR |
Chroot以后,树外构建目录的路径 | ✓ | |||||||
$DESTDIR |
构建脚本生成产品的保存目录 | ✓ | |||||||
$CHROOT_DESTDIR |
Chroot以后,构建脚本生成产品的保存目录 | ✓ | |||||||
$OUTPUTDIR |
构建产品的暂存目录 | ✓ | ✓ | ✓ | ✓ | ✓ | |||
$CHROOT_OUTPUTDIR |
Chroot以后,构建产品的暂存目录 | ✓ | ✓ | ✓ | |||||
$PACKAGEDIR |
本地包存储的目录 | ✓ | ✓ | ✓ | ✓ | ||||
$ARTIFACTDIR |
构建产品的目录 | ✓ | ✓ | ✓ | ✓ | ||||
$WITH_DOCS |
是否有文档 | ✓ | ✓ | ||||||
$WITH_TESTS |
是否有测试 | ✓ | ✓ | ||||||
$WITH_NETWORK |
是否有网络 | ✓ | ✓ | ✓ | ✓ | ||||
$SOURCE_DATE_EPOCH |
如果设置了SourceDateEpoch=TIMESTAMP ,那么会保存时间戳 |
✓ | ✓ | ✓ | ✓ | ✓ | |||
$MKOSI_UID |
调用mkosi 的用户UID |
✓ | ✓ | ✓ | ✓ | ✓ | ✓ | ✓ | ✓ |
$MKOSI_GID |
调用mkosi 的用户GID |
✓ | ✓ | ✓ | ✓ | ✓ | ✓ | ✓ | ✓ |
$MKOSI_CONFIG |
当前镜像配置的JSON | ✓ | ✓ | ✓ | ✓ | ✓ | ✓ | ✓ | |
$IMAGE_ID |
ImageID= 的值 |
✓ | ✓ | ✓ | ✓ | ✓ | ✓ | ✓ | ✓ |
$IMAGE_VERSION |
ImageVersion= 的值 |
✓ | ✓ | ✓ | ✓ | ✓ | ✓ | ✓ | ✓ |
此外,以下命令可用:
mkosi-chroot
:一个封装的chroot
,会自动Chroot到镜像内执行命令。- 镜像的包管理器可用,你也可以使用
mkosi-install|remove|upgrade|reinstall
封装工具。 git
已经自动配置好safe.directory=*
。useradd
和groupadd
已经自动配置好--root=$BUILDROOT
。
执行流程
创建MKOSI沙箱:
- 解析命令行选项。
- 解析配置文件。
- 执行
mkosi.configure
脚本。 - 检查当前用户是不是Root,如果当前用户不是Root,则尝试根据当前用户的SubUID和SubGID隔离用户命名空间。
- 隔离挂载命名空间。
- 只读化重新挂载各种目录,包括:
/usr
/etc
/opt
/srv
/boot
/efi
/media
/mnt
开始构建镜像:
- (新版本)拷贝Sandbox Tree(
mkosi.sandbox/
)中的文件到镜像中。 - 更新软件包元数据。
- 执行Sync脚本(
mkosi.sync
), - 拷贝Base Tree(
mkosi.base/
)中的文件到镜像中。 - 检查并尝试复用缓存镜像。
- 拷贝一份包管理器元数据到镜像内。
- 拷贝Skeleton Tree(
mkosi.skeleton/
)中的文件到镜像中。 - 安装发行版及其软件包。
- 使用
final
参数执行mkosi.prepare
脚本。 - 如果存在
mkosi.build
脚本的话,在Overlayfs中安装构建所需的软件包。 - 使用
build
参数执行mkosi.prepare
脚本。 - 如果存在对应的配置的话,缓存该镜像。
- 执行
mkosi.build
脚本。 - 结束构建。
- 拷贝构建脚本的产物到镜像内。
- 拷贝Extra Tree(
mkosi.extra/
)中的文件到镜像中。 - 执行
mkosi.postinst
脚本。 - 写入配置项中配置的其他杂项文件。例如
Ssh=
、Autologin=
和MakeInitrd=
。 - 安装
systemd-boot
,并按需配置安全启动。 - 执行
systemd-sysusers
。 - 执行
systemd-tmpfiles
。 - 执行
systemctl preset-all
。 - 执行
depmod
。 - 执行
systemd-firstboot
。 - 执行
systemd-hwdb
。 - 移除指定的软件包和文件。
- 按需执行SELinux Relabel。
- 执行
mkosi.finalize
脚本。 - 如果存在对应的配置的话,生成UKI镜像。
- 导出产物。
- 执行
mkosi.postoutput
脚本。
最佳实践
- 创建工作目录,并使用
mkosi.conf
和mkosi.conf.d/*.conf
(或mkosi.conf.d/*/mkosi.conf
)配置文件以固化构建信息。 - 使用
mkosi.postinst.chroot
脚本在镜像中进行配置。 - 使用
mkosi.extra
向镜像中传递额外文件。 - 使用
mkosi.build.chroot
基本进行流水线构建。在脚本中使用$BUILDDIR
和$SRCDIR
获取目录。 - 缓存有两种方式:使用
mkosi.cache
目录进行包缓存,或是使用Incremental=
进行渐进构建。需要重建渐进缓存时,使用-ff
选项。 - 要测试不同的内核命令行参数的效果,使用
KernelCommandLineExtra=
而不是重建镜像,以提高效率。 - 可以在无特权的情况下构建磁盘镜像,但是容器文件系统仍然需要Root权限。
- 在启用
SecureBoot=yes
时,可以执行mkosi genkey
直接生成证书和密钥,也可以自己创建mkosi.key
和mkosi.crt
。你还可以使用ShimBootloader=yes
以安装Shim。 - 使用
BiosBootloader=grub
以为BIOS引导安装GRUB。 - 使用
useradd -m -g $USER --password "$(openssl passwd -stdin -6 <<< '密码明文')"
添加一个普通用户。 - 在Debian中
mkosi qemu
不可用,解决方案为执行cp /usr/lib/tmpfiles.d/static-nodes-permissions.conf /etc/tmpfiles.d/static-nodes-permissions.conf
,修改/dev/kvm
的权限位为0666
。 - 在非特权模式构建时,
chown()
调用是被禁用的(钩子脚本中没有禁用,要禁用,设置环境变量MKOSI_CHROOT_SUPPRESS_CHOWN=1
),要解决该问题,使用SubUID:unshare --map-auto --map-current-user --setuid 0 --setgid 0
。 - 在你正式构建时,使用
WithRecommends=no
以安装弱依赖。 - 在使用
dd
克隆产品镜像前,执行truncate -s|--size=文件大小 镜像文件.img
以调整磁盘镜像大小。 - MKOSI可以负责构建initramfs,因此一个没有initramfs构建工具的镜像是可能的。
- 不过需要注意的是,MKOSI构建的initramfs中会使用systemd作为
/init
,这与使用MKOSI-INITRD构建的initramfs是一致的。
- 不过需要注意的是,MKOSI构建的initramfs中会使用systemd作为
- 使用
mkosi.profiles/
保存不同的镜像口味,使用mkosi.conf.d/
保存不同情况下的镜像配置,对于多种子场景的情况,将情况相对少且固定的子场景放在父目录(例如,输出格式为容器或VM),将情况相对较多且不固定的子场景放在子目录(例如,版本)。 - 使用
Format=uki
和MakeInitrd=no
来创建一个USI(Unified System Image,单个UEFI PE形式的完整系统)。
发行版最小化构建
一些发行版的最小化构建软件包如下:
Arch
1 | [Content] |
Fedora
1 | [Content] |
CentOS/Rocky
1 | [Content] |
Debian
1 | [Content] |
Ubuntu
1 | [Distribution] |
OpenSUSE
1 | [Content] |
实例
构建一个Fedora容器镜像
使用命令行:
1 | mkosi -d fedora -p kernel,systemd,systemd-udev,systemd-boot --format directory build |
使用配置文件:
1 | # mkosi.conf |
然后执行:
1 | mkosi build |
构建一个Debian可引导磁盘镜像
使用配置文件:
1 | # mkosi.conf |
然后执行:
1 | mkosi build |
构建initramfs
mkosi.conf
:
1 | [Output] |
构建一个USI(UEFI PE程序形式的完整系统镜像)
具体的精简方式见Build USI。
mkosi.conf
:
1 | [Distribution] |
构建一个系统扩展镜像
mkosi.conf
:
1 | [Output] |
mkosi.images/base/mkosi.conf
(扩展镜像相对的基础镜像):
1 | [Output] |
- 在启用了
Incremental=yes
的情况下,子镜像不能是Bootable=yes
,否则会导致Cache冲突。
mkosi.images/btrfs/mkosi.conf
1 | [Config] |
构建一个不可变操作系统
首先创建一个如下分区的操作系统:
00-esp.conf
:
1 | [Partition] |
10-root-verity-sig.conf
:
1 | [Partition] |
11-root-verity.conf
:
1 | [Partition] |
12-root.conf
:
1 | [Partition] |
除此之外我们还需要构建一个initramfs,initramfs中的systemd-repart.service
的启动时间需要进行些许修改:
mkosi.images/initrd/mkosi.conf
1 | [Include] |
mkosi.images/initrd/mkosi.extra/usr/lib/systemd/system/systemd-repart.service.d/sysroot.conf
:
1 | [Unit] |
为了进行AB更新,我们还需要在镜像中包含一些预设的分区配置:
mkosi.extra/usr/lib/repart.d/00-esp.conf
:
1 | [Partition] |
mkosi.extra/usr/lib/repart.d/10-root-verity-sig.conf
:
1 | [Partition] |
mkosi.extra/usr/lib/repart.d/11-root-verity.conf
:
1 | [Partition] |
mkosi.extra/usr/lib/repart.d/12-root.conf
:
1 | [Partition] |
mkosi.extra/usr/lib/repart.d/20-root-verity-sig.conf
:
1 | [Partition] |
mkosi.extra/usr/lib/repart.d/21-root-verity.conf
:
1 | [Partition] |
mkosi.extra/usr/lib/repart.d/22-root.conf
:
1 | [Partition] |
mkosi.extra/usr/lib/repart.d/30-swap.conf
:
1 | [Partition] |
mkosi.extra/usr/lib/repart.d/40-var.conf
:
1 | [Partition] |
因为/etc
不可变,所以我们还需要在构建时提供Machine ID:
1 | systemd-id128 new > mkosi.machine-id |
最后为了未来镜像中的系统更新,我们还需要提供systemd-sysupdate
的配置(你需要自行补充[Source]
段):
mkosi.extra/usr/lib/sysupdate.d/10-root-verity-sig.transfer
:
1 | [Transfer] |
mkosi.extra/usr/lib/sysupdate.d/11-root-verity.transfer
:
1 | [Transfer] |
mkosi.extra/usr/lib/sysupdate.d/12-root.transfer
:
1 | [Transfer] |
mkosi.extra/usr/lib/sysupdate.d/20-uki.transfer
:
1 | [Transfer] |
构建一个不安全的/usr
不可变操作系统
由于上文提到的原因(UKI必须使用Verity Hash对/usr/
分区进行定位),我们无法让MKOSI在构建镜像时,自动向UKI中填充/usr/
分区所在的位置,因此,我们必须手动在mkosi.conf
中设置:
1 | [Content] |
systemd-repart
配置如下:
00-esp.conf
:
1 | [Partition] |
10-usr.conf
:
1 | [Partition] |
此外,还需要在镜像内提供一些分区配置:
mkosi.extra/usr/lib/repart.d/00-esp.conf
:
1 | [Partition] |
mkosi.extra/usr/lib/repart.d/10-usr-verA.conf
:
1 | [Partition] |
mkosi.extra/usr/lib/repart.d/20-usr-verB.conf
:
1 | [Partition] |
mkosi.extra/usr/lib/repart.d/30-swap.conf
:
1 | [Partition] |
mkosi.extra/usr/lib/repart.d/40-root.conf
:
1 | [Partition] |
mkosi.extra/usr/lib/repart.d/50-home.conf
:
1 | [Partition] |
我们还需要确保/etc/
目录在启动时动态生成,因此需要:
mkosi.extra/usr/lib/tmpfiles.d/etc.conf
:
1 | # 仅作参考 |
为了确保ldconfig.service
在/etc/
目录生成后再启动,我们还需要:
mkosi.extra/usr/lib/systemd/system/ldconfig.service.d/tmpfiles.conf
:
1 | [Unit] |
最后,我们需要MKOSI的更新配置:
mkosi.sysupdate/10-usr.transfer
:
1 | [Transfer] |
mkosi.sysupdate/20-uki.transfer
:
1 | [Transfer] |