summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorDavid P <megver83@parabola.nu>2021-06-30 16:22:12 -0400
committerDavid P <megver83@parabola.nu>2021-07-05 16:57:40 -0400
commit47dd6e46e5bb03f6968d5f34e12434d0007c702e (patch)
tree2a60c531abd6af414796cbc899a54290862269b0
parent79b988553b2707aed9fba21dd53033a7a011af6f (diff)
sync with archiso v54v54
Imported changes: 28ab118 (tag: v54) Add changelog for v54 9827cb1 ci: Use environment variables to override build settings cde7296 ci: Consolidate build-host script 8e44a8b ci: consolidate build script d0d4fa5 configs/releng/airootfs/etc/systemd/system/pacman-init.service: don't hardcode the keyrings 3678bba configs/releng/packages.x86_64: explicitly add wanted packages instead of relying on pulling them in as dependencies bd2b861 configs/*: add VM guest packages and enable their services f86cb0f ci: Expand parallel matrix with build modes 5630a23 ci: build based on buildmodes 6b11d7b mkarchiso: Also create package list for netboot ace88aa Update project documentation related to netboot 4d1e898 docs: Add netboot to buildmodes documentation d54bf63 mkarchiso: Add buildmode to export netboot artifacts 1fed84c Extend project overview with info on bootstrap images 1630d76 docs: Add documentation for buildmodes and bootstrap build mode 2cac539 mkarchiso: Implement buildmodes that allow building bootstrap images 535bc3c baseline: Add bootstrap packages file b7fd696 baseline: Add buildmodes to profiledef.sh 6afa695 releng: Add buildmodes to profiledef.sh 9c84b7c releng: Add packages file for bootstrap image 2a07aa2 Increase timeout for initial prompt in build VM 4b14350 Use QEMU 6.x options c58b44f Use QEMU 6.x options Parabola changes: * add dual architecture support for bootstrap buildmode by creating two separated tarballs * sync openrc profiles with releng updates * disable haveged initscript since we removed it from the packages list * add speakup_soft kernel module in openrc profiles to make espeakup work TODO: * add braille support for GUI lxde-openrc (w/orca?) NOTE: We don't have/use CI (Arch uses GitLab), so we don't import those changes Signed-off-by: David P <megver83@parabola.nu>
-rw-r--r--CHANGELOG.rst23
-rw-r--r--README.rst8
l---------configs/baseline/airootfs/etc/systemd/system/multi-user.target.wants/qemu-guest-agent.service1
l---------configs/baseline/airootfs/etc/systemd/system/multi-user.target.wants/vboxservice.service1
-rw-r--r--configs/baseline/bootstrap_packages.x86_642
-rw-r--r--configs/baseline/packages.x86_641
-rw-r--r--configs/baseline/profiledef.sh1
-rwxr-xr-xconfigs/lxde-openrc/airootfs/etc/local.d/pacman-init.start2
-rw-r--r--configs/lxde-openrc/airootfs/etc/mkinitcpio.conf2
l---------configs/lxde-openrc/airootfs/etc/runlevels/default/haveged1
-rw-r--r--configs/lxde-openrc/packages.both8
-rw-r--r--configs/lxde-openrc/profiledef.sh1
-rwxr-xr-xconfigs/releng-openrc/airootfs/etc/local.d/pacman-init.start2
-rw-r--r--configs/releng-openrc/airootfs/etc/mkinitcpio.conf2
l---------configs/releng-openrc/airootfs/etc/runlevels/default/haveged1
-rw-r--r--configs/releng-openrc/bootstrap_packages.both2
-rw-r--r--configs/releng-openrc/packages.both8
-rw-r--r--configs/releng-openrc/profiledef.sh1
l---------configs/releng/airootfs/etc/systemd/system/multi-user.target.wants/qemu-guest-agent.service1
-rw-r--r--configs/releng/airootfs/etc/systemd/system/pacman-init.service2
-rw-r--r--configs/releng/bootstrap_packages.both2
-rw-r--r--configs/releng/packages.both8
-rw-r--r--configs/releng/profiledef.sh1
-rw-r--r--docs/README.profile.rst154
-rwxr-xr-xparabolaiso/mkparabolaiso594
-rwxr-xr-xscripts/run_parabolaiso.sh8
26 files changed, 610 insertions, 227 deletions
diff --git a/CHANGELOG.rst b/CHANGELOG.rst
index 6d55065..c6c3498 100644
--- a/CHANGELOG.rst
+++ b/CHANGELOG.rst
@@ -2,6 +2,29 @@
Changelog
#########
+[54] - 2021-05-13
+=================
+
+Added
+-----
+
+- Add the concept of buildmodes to mkparabolaiso, which allows for building more than the default .iso artifact
+ (sequentially)
+- Add support to mkparabolaiso and both baseline and releng profiles for building a bootstrap image (a compressed
+ bootstrapped Parabola GNU/Linux-libre environment), by using the new buildmode `bootstrap`
+- Add support to mkparabolaiso and both baseline and releng profiles for building artifacts required for netboot with iPXE
+ (optionally allowing codesigning on the artifacts), by using the new buildmode `netboot`
+- Add qemu-guest-agent to the releng profile and enable their services by default to allow interaction between hypervisor
+ and virtual machine if the installation medium is booted in a virtualized environment
+
+Changed
+-------
+
+- Always use the .sig file extension when signing the rootfs image, as that is how mkinitcpio-parabolaiso expects it
+- Fix for run_parabolaiso scripts to be compatible with QEMU >= 6.0
+- Install all implicitly installed packages explicitly for the releng profile
+- Install keyrings more generically when using pacman-init.service
+
[53] - 2021-05-01
=================
diff --git a/README.rst b/README.rst
index 25f16a0..2500387 100644
--- a/README.rst
+++ b/README.rst
@@ -13,10 +13,18 @@ Requirements
The following packages need to be installed to be able to create an image with the included scripts:
* arch-install-scripts
+* awk
* dosfstools
* e2fsprogs
+* erofs-utils (optional)
+* findutils
+* gzip
+* libarchive
* libisoburn
* mtools
+* openssl
+* pacman
+* sed
* squashfs-tools
For running the images in a virtualized test environment the following packages are required:
diff --git a/configs/baseline/airootfs/etc/systemd/system/multi-user.target.wants/qemu-guest-agent.service b/configs/baseline/airootfs/etc/systemd/system/multi-user.target.wants/qemu-guest-agent.service
new file mode 120000
index 0000000..8e3ff80
--- /dev/null
+++ b/configs/baseline/airootfs/etc/systemd/system/multi-user.target.wants/qemu-guest-agent.service
@@ -0,0 +1 @@
+/usr/lib/systemd/system/qemu-guest-agent.service \ No newline at end of file
diff --git a/configs/baseline/airootfs/etc/systemd/system/multi-user.target.wants/vboxservice.service b/configs/baseline/airootfs/etc/systemd/system/multi-user.target.wants/vboxservice.service
new file mode 120000
index 0000000..cb2d560
--- /dev/null
+++ b/configs/baseline/airootfs/etc/systemd/system/multi-user.target.wants/vboxservice.service
@@ -0,0 +1 @@
+/usr/lib/systemd/system/vboxservice.service \ No newline at end of file
diff --git a/configs/baseline/bootstrap_packages.x86_64 b/configs/baseline/bootstrap_packages.x86_64
new file mode 100644
index 0000000..64966d0
--- /dev/null
+++ b/configs/baseline/bootstrap_packages.x86_64
@@ -0,0 +1,2 @@
+arch-install-scripts
+base
diff --git a/configs/baseline/packages.x86_64 b/configs/baseline/packages.x86_64
index 560143f..e9ab88d 100644
--- a/configs/baseline/packages.x86_64
+++ b/configs/baseline/packages.x86_64
@@ -6,4 +6,5 @@ linux-libre
mkinitcpio
mkinitcpio-parabolaiso
openssh
+qemu-guest-agent
syslinux
diff --git a/configs/baseline/profiledef.sh b/configs/baseline/profiledef.sh
index b715404..f5b3ae5 100644
--- a/configs/baseline/profiledef.sh
+++ b/configs/baseline/profiledef.sh
@@ -7,6 +7,7 @@ iso_publisher="Parabola GNU/Linux-libre <https://parabola.nu>"
iso_application="Parabola GNU/Linux-libre baseline"
iso_version="$(date +%Y.%m.%d)"
install_dir="parabola"
+buildmodes=('iso')
bootmodes=('bios.syslinux.mbr' 'bios.syslinux.eltorito' 'uefi-x64.systemd-boot.esp' 'uefi-x64.systemd-boot.eltorito')
arch="x86_64"
pacman_conf="pacman.conf"
diff --git a/configs/lxde-openrc/airootfs/etc/local.d/pacman-init.start b/configs/lxde-openrc/airootfs/etc/local.d/pacman-init.start
index 41c6166..60fdd4d 100755
--- a/configs/lxde-openrc/airootfs/etc/local.d/pacman-init.start
+++ b/configs/lxde-openrc/airootfs/etc/local.d/pacman-init.start
@@ -5,5 +5,5 @@
# Initializes Pacman keyring
if ! find /etc/pacman.d/gnupg -mindepth 1 2>/dev/null | read -r; then
pacman-key --init
- pacman-key --populate archlinux archlinux32 parabola
+ pacman-key --populate
fi
diff --git a/configs/lxde-openrc/airootfs/etc/mkinitcpio.conf b/configs/lxde-openrc/airootfs/etc/mkinitcpio.conf
index 02795f8..efbff15 100644
--- a/configs/lxde-openrc/airootfs/etc/mkinitcpio.conf
+++ b/configs/lxde-openrc/airootfs/etc/mkinitcpio.conf
@@ -7,7 +7,7 @@
# run. Advanced users may wish to specify all system modules
# in this array. For instance:
# MODULES=(piix ide_disk reiserfs)
-MODULES=(loop)
+MODULES=(loop speakup_soft)
# BINARIES
# This setting includes any additional binaries a given user may
diff --git a/configs/lxde-openrc/airootfs/etc/runlevels/default/haveged b/configs/lxde-openrc/airootfs/etc/runlevels/default/haveged
deleted file mode 120000
index 0ec5343..0000000
--- a/configs/lxde-openrc/airootfs/etc/runlevels/default/haveged
+++ /dev/null
@@ -1 +0,0 @@
-/etc/init.d/haveged \ No newline at end of file
diff --git a/configs/lxde-openrc/packages.both b/configs/lxde-openrc/packages.both
index 3e697ab..3b6ecfd 100644
--- a/configs/lxde-openrc/packages.both
+++ b/configs/lxde-openrc/packages.both
@@ -2,14 +2,15 @@
# SPDX-License-Identifier: GPL-3.0-or-later
#Base
alsa-utils-openrc
-archinstall
arch-install-scripts
+archinstall
base
bind-tools
brltty-openrc
btrfs-progs
cloud-init
crda
+cryptsetup
darkhttpd
ddrescue
dhclient
@@ -18,6 +19,7 @@ diffutils
dmraid
dnsmasq
dosfstools
+e2fsprogs
efibootmgr
espeakup-openrc
elogind
@@ -33,9 +35,11 @@ gptfdisk
grml-zsh-config
hdparm-openrc
irssi
+iw
iwd
jfsutils
kitty-terminfo
+less
lftp
libfido2
libusb-compat
@@ -75,11 +79,13 @@ partimage
pcsclite
ppp
pptpclient
+qemu-guest-agent
reflector
reiserfsprogs
rp-pppoe
rsync-openrc
rxvt-unicode-terminfo
+screen
sdparm
sg3_utils
smartmontools
diff --git a/configs/lxde-openrc/profiledef.sh b/configs/lxde-openrc/profiledef.sh
index 31a505c..632a00c 100644
--- a/configs/lxde-openrc/profiledef.sh
+++ b/configs/lxde-openrc/profiledef.sh
@@ -11,6 +11,7 @@ iso_publisher="Parabola GNU/Linux-libre <https://parabola.nu>"
iso_application="Parabola GNU/Linux-libre Live/Rescue CD"
iso_version="$(date +%Y.%m.%d)"
install_dir="parabola"
+buildmodes=('iso')
bootmodes=('bios.syslinux.mbr' 'bios.syslinux.eltorito' 'uefi-x64.refind.esp' 'uefi-x64.refind.eltorito')
arch="dual"
pacman_conf="pacman.conf"
diff --git a/configs/releng-openrc/airootfs/etc/local.d/pacman-init.start b/configs/releng-openrc/airootfs/etc/local.d/pacman-init.start
index 41c6166..60fdd4d 100755
--- a/configs/releng-openrc/airootfs/etc/local.d/pacman-init.start
+++ b/configs/releng-openrc/airootfs/etc/local.d/pacman-init.start
@@ -5,5 +5,5 @@
# Initializes Pacman keyring
if ! find /etc/pacman.d/gnupg -mindepth 1 2>/dev/null | read -r; then
pacman-key --init
- pacman-key --populate archlinux archlinux32 parabola
+ pacman-key --populate
fi
diff --git a/configs/releng-openrc/airootfs/etc/mkinitcpio.conf b/configs/releng-openrc/airootfs/etc/mkinitcpio.conf
index 02795f8..efbff15 100644
--- a/configs/releng-openrc/airootfs/etc/mkinitcpio.conf
+++ b/configs/releng-openrc/airootfs/etc/mkinitcpio.conf
@@ -7,7 +7,7 @@
# run. Advanced users may wish to specify all system modules
# in this array. For instance:
# MODULES=(piix ide_disk reiserfs)
-MODULES=(loop)
+MODULES=(loop speakup_soft)
# BINARIES
# This setting includes any additional binaries a given user may
diff --git a/configs/releng-openrc/airootfs/etc/runlevels/default/haveged b/configs/releng-openrc/airootfs/etc/runlevels/default/haveged
deleted file mode 120000
index 0ec5343..0000000
--- a/configs/releng-openrc/airootfs/etc/runlevels/default/haveged
+++ /dev/null
@@ -1 +0,0 @@
-/etc/init.d/haveged \ No newline at end of file
diff --git a/configs/releng-openrc/bootstrap_packages.both b/configs/releng-openrc/bootstrap_packages.both
new file mode 100644
index 0000000..64966d0
--- /dev/null
+++ b/configs/releng-openrc/bootstrap_packages.both
@@ -0,0 +1,2 @@
+arch-install-scripts
+base
diff --git a/configs/releng-openrc/packages.both b/configs/releng-openrc/packages.both
index 4742487..392e1ef 100644
--- a/configs/releng-openrc/packages.both
+++ b/configs/releng-openrc/packages.both
@@ -1,14 +1,15 @@
#
# SPDX-License-Identifier: GPL-3.0-or-later
alsa-utils-openrc
-archinstall
arch-install-scripts
+archinstall
base
bind-tools
brltty-openrc
btrfs-progs
cloud-init
crda
+cryptsetup
darkhttpd
ddrescue
dhclient
@@ -17,6 +18,7 @@ diffutils
dmraid
dnsmasq
dosfstools
+e2fsprogs
efibootmgr
espeakup-openrc
elogind
@@ -32,9 +34,11 @@ gptfdisk
grml-zsh-config
hdparm-openrc
irssi
+iw
iwd
jfsutils
kitty-terminfo
+less
lftp
libfido2
libusb-compat
@@ -74,11 +78,13 @@ partimage
pcsclite
ppp
pptpclient
+qemu-guest-agent
reflector
reiserfsprogs
rp-pppoe
rsync-openrc
rxvt-unicode-terminfo
+screen
sdparm
sg3_utils
smartmontools
diff --git a/configs/releng-openrc/profiledef.sh b/configs/releng-openrc/profiledef.sh
index 1d01d56..fe657de 100644
--- a/configs/releng-openrc/profiledef.sh
+++ b/configs/releng-openrc/profiledef.sh
@@ -7,6 +7,7 @@ iso_publisher="Parabola GNU/Linux-libre <https://parabola.nu>"
iso_application="Parabola GNU/Linux-libre Live/Rescue CD"
iso_version="$(date +%Y.%m.%d)"
install_dir="parabola"
+buildmodes=('iso')
bootmodes=('bios.syslinux.mbr' 'bios.syslinux.eltorito' 'uefi-x64.refind.esp' 'uefi-x64.refind.eltorito')
arch="dual"
pacman_conf="pacman.conf"
diff --git a/configs/releng/airootfs/etc/systemd/system/multi-user.target.wants/qemu-guest-agent.service b/configs/releng/airootfs/etc/systemd/system/multi-user.target.wants/qemu-guest-agent.service
new file mode 120000
index 0000000..8e3ff80
--- /dev/null
+++ b/configs/releng/airootfs/etc/systemd/system/multi-user.target.wants/qemu-guest-agent.service
@@ -0,0 +1 @@
+/usr/lib/systemd/system/qemu-guest-agent.service \ No newline at end of file
diff --git a/configs/releng/airootfs/etc/systemd/system/pacman-init.service b/configs/releng/airootfs/etc/systemd/system/pacman-init.service
index 28d4398..f446a80 100644
--- a/configs/releng/airootfs/etc/systemd/system/pacman-init.service
+++ b/configs/releng/airootfs/etc/systemd/system/pacman-init.service
@@ -10,7 +10,7 @@ After=etc-pacman.d-gnupg.mount
Type=oneshot
RemainAfterExit=yes
ExecStart=/usr/bin/pacman-key --init
-ExecStart=/usr/bin/pacman-key --populate parabola archlinux archlinux32
+ExecStart=/usr/bin/pacman-key --populate
[Install]
WantedBy=multi-user.target
diff --git a/configs/releng/bootstrap_packages.both b/configs/releng/bootstrap_packages.both
new file mode 100644
index 0000000..64966d0
--- /dev/null
+++ b/configs/releng/bootstrap_packages.both
@@ -0,0 +1,2 @@
+arch-install-scripts
+base
diff --git a/configs/releng/packages.both b/configs/releng/packages.both
index d1c59ca..48c48e6 100644
--- a/configs/releng/packages.both
+++ b/configs/releng/packages.both
@@ -1,14 +1,15 @@
#
# SPDX-License-Identifier: GPL-3.0-or-later
alsa-utils
-archinstall
arch-install-scripts
+archinstall
base
bind-tools
brltty
btrfs-progs
cloud-init
crda
+cryptsetup
darkhttpd
ddrescue
dhclient
@@ -17,6 +18,7 @@ diffutils
dmraid
dnsmasq
dosfstools
+e2fsprogs
efibootmgr
espeakup
ethtool
@@ -31,9 +33,11 @@ gptfdisk
grml-zsh-config
hdparm
irssi
+iw
iwd
jfsutils
kitty-terminfo
+less
lftp
libfido2
libusb-compat
@@ -71,11 +75,13 @@ partimage
pcsclite
ppp
pptpclient
+qemu-guest-agent
reflector
reiserfsprogs
rp-pppoe
rsync
rxvt-unicode-terminfo
+screen
sdparm
sg3_utils
smartmontools
diff --git a/configs/releng/profiledef.sh b/configs/releng/profiledef.sh
index 5ad616e..8ca837f 100644
--- a/configs/releng/profiledef.sh
+++ b/configs/releng/profiledef.sh
@@ -7,6 +7,7 @@ iso_publisher="Parabola GNU/Linux-libre <https://parabola.nu>"
iso_application="Parabola GNU/Linux-libre Live/Rescue CD"
iso_version="$(date +%Y.%m.%d)"
install_dir="parabola"
+buildmodes=('iso')
bootmodes=('bios.syslinux.mbr' 'bios.syslinux.eltorito' 'uefi-x64.systemd-boot.esp' 'uefi-x64.systemd-boot.eltorito')
arch="dual"
pacman_conf="pacman.conf"
diff --git a/docs/README.profile.rst b/docs/README.profile.rst
index f6cce5d..a3dc954 100644
--- a/docs/README.profile.rst
+++ b/docs/README.profile.rst
@@ -4,15 +4,16 @@ profile
A parabolaiso profile consists of several configuration files and a directory for files to be added to the resulting image.
- .. code:: bash
+.. code:: plaintext
- profile
- |- airootfs/
- |- efiboot/
- |- syslinux/
- |- packages.arch
- |- pacman.conf
- \- profiledef.sh
+ profile/
+ ├── airootfs/
+ ├── efiboot/
+ ├── syslinux/
+ ├── bootstrap_packages.arch
+ ├── packages.arch
+ ├── pacman.conf
+ └── profiledef.sh
The required files and directories are explained in the following sections.
@@ -22,55 +23,72 @@ profiledef.sh
This file describes several attributes of the resulting image and is a place for customization to the general behavior
of the image.
-The image file is constructed from some of the variables in **profiledef.sh**: `<iso_name>-<iso_version>-<arch>.iso`
-(e.g. `parabola-202010-x86_64.iso`).
-
-* `iso_name`: The first part of the name of the resulting image (defaults to `mkparabolaiso`)
-* `iso_label`: The ISO's volume label (defaults to `MKPARABOLAISO`)
-* `iso_publisher`: A free-form string that states the publisher of the resulting image (defaults to `mkparabolaiso`)
-* `iso_application`: A free-form string that states the application (i.e. its use-case) of the resulting image (defaults
- to `mkparabolaiso iso`)
-* `iso_version`: A string that states the version of the resulting image (defaults to `""`)
-* `install_dir`: A string (maximum eight characters long, which **must** consist of `[a-z0-9]`) that states the
- directory on the resulting image into which all files will be installed (defaults to `mkparabolaiso`)
-* `bootmodes`: A list of strings, that state the supported boot modes of the resulting image. Only the following are
+The image file is constructed from some of the variables in ``profiledef.sh``: ``<iso_name>-<iso_version>-<arch>.iso``
+(e.g. ``parabola-202010-x86_64.iso``).
+
+* ``iso_name``: The first part of the name of the resulting image (defaults to ``mkparabolaiso``)
+* ``iso_label``: The ISO's volume label (defaults to ``MKPARABOLAISO``)
+* ``iso_publisher``: A free-form string that states the publisher of the resulting image (defaults to ``mkparabolaiso``)
+* ``iso_application``: A free-form string that states the application (i.e. its use-case) of the resulting image (defaults
+ to ``mkparabolaiso iso``)
+* ``iso_version``: A string that states the version of the resulting image (defaults to ``""``)
+* ``install_dir``: A string (maximum eight characters long, which **must** consist of ``[a-z0-9]``) that states the
+ directory on the resulting image into which all files will be installed (defaults to ``mkparabolaiso``)
+* ``buildmodes``: An optional list of strings, that state the build modes that the profile uses. Only the following are
understood:
- - `bios.syslinux.mbr`: Syslinux for x86 BIOS booting from a disk
- - `bios.syslinux.eltorito`: Syslinux for x86 BIOS booting from an optical disc
- - `uefi-x64.systemd-boot.esp`: Systemd-boot for x86_64 UEFI booting from a disk
- - `uefi-x64.systemd-boot.eltorito`: Systemd-boot for x86_64 UEFI booting from an optical disc
- - `uefi-x64.refind.esp`: rEFInd for x86_64 UEFI booting from a disk
- - `uefi-x64.refind.eltorito`: rEFInd for x86_64 UEFI booting from an optical disc
- Note that BIOS El Torito boot mode must always be listed before UEFI El Torito boot mode.
-* `arch`: The architecture (e.g. `x86_64`) to build the image for. This is also used to resolve the name of the packages
- file (e.g. `packages.x86_64`)
-* `pacman_conf`: The `pacman.conf` to use to install packages to the work directory when creating the image (defaults to
- the host's `/etc/pacman.conf`)
-* `airootfs_image_type`: The image type to create. The following options are understood (defaults to `squashfs`):
-
- - `squashfs`: Create a squashfs image directly from the airootfs work directory
- - `ext4+squashfs`: Create an ext4 partition, copy the airootfs work directory to it and create a squashfs image from it
- - `erofs`: Create an EROFS image for the airootfs work directory
-* `airootfs_image_tool_options`: An array of options to pass to the tool to create the airootfs image. `mksquashfs` and
- `mkfs.erofs` are supported. See `mksquashfs --help` or `mkfs.erofs --help` for all possible options.
-* `file_permissions`: An associative array that lists files and/or directories who need specific ownership or
+ - ``bootstrap``: Build a compressed file containing a minimal system to bootstrap from
+ - ``iso``: Build a bootable ISO image (implicit default, if no ``buildmodes`` are set)
+ - ``netboot``: Build artifacts required for netboot using iPXE
+* ``bootmodes``: A list of strings, that state the supported boot modes of the resulting image. Only the following are
+ understood:
+
+ - ``bios.syslinux.mbr``: Syslinux for x86 BIOS booting from a disk
+ - ``bios.syslinux.eltorito``: Syslinux for x86 BIOS booting from an optical disc
+ - ``uefi-x64.systemd-boot.esp``: systemd-boot for x86_64 UEFI booting from a disk
+ - ``uefi-x64.systemd-boot.eltorito``: systemd-boot for x86_64 UEFI booting from an optical disc
+ - ``uefi-x64.refind.esp``: rEFInd for x86_64 UEFI booting from a disk
+ - ``uefi-x64.refind.eltorito``: rEFInd for x86_64 UEFI booting from an optical disc
+ Note that BIOS El Torito boot mode must always be listed before UEFI El Torito boot mode.
+* ``arch``: The architecture (e.g. ``x86_64``) to build the image for. This is also used to resolve the name of the packages
+ file (e.g. ``packages.x86_64``)
+* ``pacman_conf``: The ``pacman.conf`` to use to install packages to the work directory when creating the image (defaults to
+ the host's ``/etc/pacman.conf``)
+* ``airootfs_image_type``: The image type to create. The following options are understood (defaults to ``squashfs``):
+
+ - ``squashfs``: Create a squashfs image directly from the airootfs work directory
+ - ``ext4+squashfs``: Create an ext4 partition, copy the airootfs work directory to it and create a squashfs image from it
+ - ``erofs``: Create an EROFS image for the airootfs work directory
+* ``airootfs_image_tool_options``: An array of options to pass to the tool to create the airootfs image. ``mksquashfs`` and
+ ``mkfs.erofs`` are supported. See ``mksquashfs --help`` or ``mkfs.erofs --help`` for all possible options
+* ``file_permissions``: An associative array that lists files and/or directories who need specific ownership or
permissions. The array's keys contain the path and the value is a colon separated list of owner UID, owner GID and
- access mode. E.g. `file_permissions=(["/etc/shadow"]="0:0:400")`. When directories are listed with a trailing backslash ("/") **all** files and directories contained within the listed directory will have the same owner UID, owner GID, and access mode applied recursively.
+ access mode. E.g. ``file_permissions=(["/etc/shadow"]="0:0:400")``. When directories are listed with a trailing backslash (``/``) **all** files and directories contained within the listed directory will have the same owner UID, owner GID, and access mode applied recursively.
+
+bootstrap_packages.arch
+=======================
+
+All packages to be installed into the environment of a bootstrap image have to be listed in an architecture specific
+file (e.g. ``bootstrap_packages.x86_64``), which resides top-level in the profile.
+
+Packages have to be listed one per line. Lines starting with a ``#`` and blank lines are ignored.
+
+This file is required when generating bootstrap images using the ``bootstrap`` build mode.
packages.arch
=============
-All packages to be installed into the environment of the image have to be listed in an architecture specific file (e.g.
-`packages.x86_64`), which resides top-level in the profile.
+All packages to be installed into the environment of an ISO image have to be listed in an architecture specific file
+(e.g. ``packages.x86_64``), which resides top-level in the profile.
-Packages have to be listed one per line. Lines starting with a `#` and blank lines are ignored.
+Packages have to be listed one per line. Lines starting with a ``#`` and blank lines are ignored.
.. note::
The **mkinitcpio** and **mkinitcpio-parabolaiso** packages are mandatory (see `#30
<https://gitlab.archlinux.org/archlinux/archiso/-/issues/30>`_).
+This file is required when generating ISO images using the ``iso`` or ``netboot`` build modes.
pacman.conf
===========
@@ -79,32 +97,31 @@ A configuration for pacman is required per profile.
Some configuration options will not be used or will be modified:
-* `CacheDir`: the profile's option is **only** used if it is not the default (i.e. `/var/cache/pacman/pkg`) and if it is
+* ``CacheDir``: the profile's option is **only** used if it is not the default (i.e. ``/var/cache/pacman/pkg``) and if it is
not the same as the system's option. In all other cases the system's pacman cache is used.
-* `HookDir`: it is **always** set to the `/etc/pacman.d/hooks` directory in the work directory's airootfs to allow
+* ``HookDir``: it is **always** set to the ``/etc/pacman.d/hooks`` directory in the work directory's airootfs to allow
modification via the profile and ensure interoparability with hosts using dracut (see `#73
<https://gitlab.archlinux.org/archlinux/archiso/-/issues/73>`_)
-* `RootDir`: it is **always** removed, as setting it explicitely otherwise refers to the host's root filesystem (see
- `man 8 pacman` for further information on the `-r` option used by `pacstrap`)
-* `LogFile`: it is **always** removed, as setting it explicitely otherwise refers to the host's pacman log file (see
- `man 8 pacman` for further information on the `-r` option used by `pacstrap`)
-* `DBPath`: it is **always** removed, as setting it explicitely otherwise refers to the host's pacman database (see
- `man 8 pacman` for further information on the `-r` option used by `pacstrap`)
+* ``RootDir``: it is **always** removed, as setting it explicitely otherwise refers to the host's root filesystem (see
+ ``man 8 pacman`` for further information on the ``-r`` option used by ``pacstrap``)
+* ``LogFile``: it is **always** removed, as setting it explicitely otherwise refers to the host's pacman log file (see
+ ``man 8 pacman`` for further information on the ``-r`` option used by ``pacstrap``)
+* ``DBPath``: it is **always** removed, as setting it explicitely otherwise refers to the host's pacman database (see
+ ``man 8 pacman`` for further information on the ``-r`` option used by ``pacstrap``)
airootfs
========
-This - optional - directory may contain files and directories that will be copied to the work directory of the resulting
+This optional directory may contain files and directories that will be copied to the work directory of the resulting
image's root filesystem.
The files are copied before packages are being installed to work directory location.
-Ownership and permissions of files and directories from the profile's `airootfs` directory are not preserved. The mode
-will be `644` for files and `755` for directories, all of them will be owned by root. To set custom ownership and/or
-permissions, use `file_permissions` in **profiledef.sh**.
+Ownership and permissions of files and directories from the profile's ``airootfs`` directory are not preserved. The mode
+will be ``644`` for files and ``755`` for directories, all of them will be owned by root. To set custom ownership and/or
+permissions, use ``file_permissions`` in ``profiledef.sh``.
With this overlay structure it is possible to e.g. create users and set passwords for them, by providing
-`airootfs/etc/passwd`, `airootfs/etc/shadow`, `airootfs/etc/gshadow` (see `man 5 passwd`, `man 5 shadow` and `man 5
-gshadow` respectively).
-If user home directories exist in the profile's `airootfs`, their ownership and (and top-level) permissions will be
+``airootfs/etc/passwd``, ``airootfs/etc/shadow``, ``airootfs/etc/gshadow`` (see ``man 5 passwd``, ``man 5 shadow`` and ``man 5 gshadow`` respectively).
+If user home directories exist in the profile's ``airootfs``, their ownership and (and top-level) permissions will be
altered according to the provided information in the password file.
Boot loader configuration
@@ -114,18 +131,18 @@ A profile may contain configuration for several boot loaders. These reside in sp
explained in the following subsections.
The following *custom template identifiers* are understood and will be replaced according to the assignments of the
-respective variables in **profiledef.sh**:
+respective variables in ``profiledef.sh``:
-* `%PARABOLAISO_LABEL%`: Set this using the `iso_label` variable in **profiledef.sh**
-* `%INSTALL_DIR%`: Set this using the `iso_label` variable in **profiledef.sh**
-* `%ARCH%`: Set this using the `arch` variable in **profiledef.sh**
+* ``%PARABOLAISO_LABEL%``: Set this using the ``iso_label`` variable in ``profiledef.sh``.
+* ``%INSTALL_DIR%``: Set this using the ``iso_label`` variable in ``profiledef.sh``.
+* ``%ARCH%``: Set this using the ``arch`` variable in ``profiledef.sh``.
efiboot
-------
-This directory is mandatory when the `uefi-x64.systemd-boot.esp` or `uefi-x64.systemd-boot.eltorito` bootmodes are
-selected in **profiledef.sh**. It contains configuration for `systemd-boot
+This directory is mandatory when the ``uefi-x64.systemd-boot.esp`` or ``uefi-x64.systemd-boot.eltorito`` bootmodes are
+selected in ``profiledef.sh``. It contains configuration for `systemd-boot
<https://www.freedesktop.org/wiki/Software/systemd/systemd-boot/>`_.
.. note::
@@ -134,15 +151,16 @@ selected in **profiledef.sh**. It contains configuration for `systemd-boot
root of an EFI system partition.
The *custom template identifiers* are **only** understood in the boot loader entry `.conf` files (i.e. **not** in
-`loader.conf`).
+``loader.conf``).
-The same happens when the `uefi-x64.refind.esp` or `uefi-x64.refind.eltorito` bootmodes are selected.
+The same applies for the ``uefi-x64.refind.esp`` and ``uefi-x64.refind.eltorito`` bootmodes. In the case of OpenRC profiles,
+this directory contains configuration for `rEFInd <https://www.rodsbooks.com/refind/>`_.
syslinux
--------
-This directory is mandatory when the `bios.syslinux.mbr` or the `bios.syslinux.eltorito` bootmodes are selected in
-**profiledef.sh**.
+This directory is mandatory when the ``bios.syslinux.mbr`` or the ``bios.syslinux.eltorito`` bootmodes are selected in
+``profiledef.sh``.
It contains configuration files for `syslinux <https://wiki.syslinux.org/wiki/index.php?title=SYSLINUX>`_ or `isolinux
<https://wiki.syslinux.org/wiki/index.php?title=ISOLINUX>`_ , or `pxelinux
<https://wiki.syslinux.org/wiki/index.php?title=PXELINUX>`_ used in the resuling image.
diff --git a/parabolaiso/mkparabolaiso b/parabolaiso/mkparabolaiso
index 6f04947..db49ba7 100755
--- a/parabolaiso/mkparabolaiso
+++ b/parabolaiso/mkparabolaiso
@@ -14,10 +14,10 @@ app_name="${0##*/}"
# Define global variables. All of them will be overwritten later
pkg_list=()
+bootstrap_pkg_list=()
quiet=""
work_dir=""
out_dir=""
-img_name=""
gpg_key=""
iso_name=""
iso_label=""
@@ -29,9 +29,15 @@ arch=""
pacman_conf=""
packages=""
packages_dual=""
+bootstrap_packages=""
+bootstrap_packages_dual=""
+pacstrap_dir=""
+buildmodes=()
bootmodes=()
airootfs_image_type=""
airootfs_image_tool_options=()
+cert_list=()
+sign_netboot_artifacts=""
declare -A file_permissions=()
@@ -64,8 +70,8 @@ _msg_error() {
_mount_airootfs() {
trap "_umount_airootfs" EXIT HUP INT TERM
install -d -m 0755 -- "${work_dir}/mnt/airootfs"
- _msg_info "Mounting '${airootfs_dir}.img' on '${work_dir}/mnt/airootfs'..."
- mount -- "${airootfs_dir}.img" "${work_dir}/mnt/airootfs"
+ _msg_info "Mounting '${pacstrap_dir}.img' on '${work_dir}/mnt/airootfs'..."
+ mount -- "${pacstrap_dir}.img" "${work_dir}/mnt/airootfs"
_msg_info "Done!"
}
@@ -94,11 +100,17 @@ usage: ${app_name} [options] <profile_dir>
Default: '${iso_label}'
-P <publisher> Set the ISO publisher
Default: '${iso_publisher}'
+ -c [cert ..] Provide certificates for codesigning of netboot artifacts
+ Multiple files are provided as quoted, space delimited list.
+ The first file is considered as the signing certificate,
+ the second as the key.
-g <gpg_key> Set the PGP key ID to be used for signing the rootfs image
-h This message
+ -m [mode ..] Build mode(s) to use (valid modes are: 'bootstrap', 'iso' and 'netboot').
+ Multiple build modes are provided as quoted, space delimited list.
-o <out_dir> Set the output directory
Default: '${out_dir}'
- -p PACKAGE(S) Package(s) to install.
+ -p [package ..] Package(s) to install.
Multiple packages are provided as quoted, space delimited list.
-v Enable verbose output
-w <work_dir> Set the working directory
@@ -120,42 +132,46 @@ _show_config() {
_msg_info " Installation directory: ${install_dir}"
_msg_info " Build date: ${build_date}"
_msg_info " Output directory: ${out_dir}"
+ _msg_info " Current build mode: ${buildmode}"
+ _msg_info " Build modes: ${buildmodes[*]}"
_msg_info " GPG key: ${gpg_key:-None}"
+ _msg_info "Code signing certificates: ${cert_list[*]}"
_msg_info " Profile: ${profile}"
_msg_info "Pacman configuration file: ${pacman_conf}"
- _msg_info " Image file name: ${img_name}"
+ _msg_info " Image file name: ${image_name:-None}"
_msg_info " ISO volume label: ${iso_label}"
_msg_info " ISO publisher: ${iso_publisher}"
_msg_info " ISO application: ${iso_application}"
_msg_info " Boot modes: ${bootmodes[*]}"
- _msg_info " Packages: ${pkg_list[*]}"
+ _msg_info " Packages File: ${buildmode_packages}"
+ _msg_info " Packages: ${buildmode_pkg_list[*]}"
if [[ "${arch}" == "dual" ]]; then
- _msg_info " Packages (x86_64): ${pkg_list_x86_64[*]:-None}"
- _msg_info " Packages (i686): ${pkg_list_i686[*]:-None}"
+ _msg_info " Packages (i686): ${buildmode_pkg_list_i686[*]:-None}"
+ _msg_info " Packages (x86_64): ${buildmode_pkg_list_x86_64[*]:-None}"
fi
}
# Cleanup airootfs
-_cleanup_airootfs() {
- _msg_info "Cleaning up what we can on ${arch} airootfs..."
+_cleanup_pacstrap_dir() {
+ _msg_info "Cleaning up in ${arch} pacstrap location..."
# Delete all files in /boot
- [[ -d "${airootfs_dir}/boot" ]] && find "${airootfs_dir}/boot" -mindepth 1 -delete
+ [[ -d "${pacstrap_dir}/boot" ]] && find "${pacstrap_dir}/boot" -mindepth 1 -delete
# Delete pacman database sync cache files (*.tar.gz)
- [[ -d "${airootfs_dir}/var/lib/pacman" ]] && find "${airootfs_dir}/var/lib/pacman" -maxdepth 1 -type f -delete
+ [[ -d "${pacstrap_dir}/var/lib/pacman" ]] && find "${pacstrap_dir}/var/lib/pacman" -maxdepth 1 -type f -delete
# Delete pacman database sync cache
- [[ -d "${airootfs_dir}/var/lib/pacman/sync" ]] && find "${airootfs_dir}/var/lib/pacman/sync" -delete
+ [[ -d "${pacstrap_dir}/var/lib/pacman/sync" ]] && find "${pacstrap_dir}/var/lib/pacman/sync" -delete
# Delete pacman package cache
- [[ -d "${airootfs_dir}/var/cache/pacman/pkg" ]] && find "${airootfs_dir}/var/cache/pacman/pkg" -type f -delete
+ [[ -d "${pacstrap_dir}/var/cache/pacman/pkg" ]] && find "${pacstrap_dir}/var/cache/pacman/pkg" -type f -delete
# Delete all log files, keeps empty dirs.
- [[ -d "${airootfs_dir}/var/log" ]] && find "${airootfs_dir}/var/log" -type f -delete
+ [[ -d "${pacstrap_dir}/var/log" ]] && find "${pacstrap_dir}/var/log" -type f -delete
# Delete all temporary files and dirs
- [[ -d "${airootfs_dir}/var/tmp" ]] && find "${airootfs_dir}/var/tmp" -mindepth 1 -delete
+ [[ -d "${pacstrap_dir}/var/tmp" ]] && find "${pacstrap_dir}/var/tmp" -mindepth 1 -delete
# Delete package pacman related files.
find "${work_dir}" \( -name '*.pacnew' -o -name '*.pacsave' -o -name '*.pacorig' \) -delete
# Create an empty /etc/machine-id
- rm -f -- "${airootfs_dir}/etc/machine-id"
- printf '' > "${airootfs_dir}/etc/machine-id"
+ rm -f -- "${pacstrap_dir}/etc/machine-id"
+ printf '' > "${pacstrap_dir}/etc/machine-id"
_msg_info "Done!"
}
@@ -171,36 +187,36 @@ _run_mksquashfs() {
# Makes a ext4 filesystem inside a SquashFS from a source directory.
_mkairootfs_ext4+squashfs() {
- [[ -e "${airootfs_dir}" ]] || _msg_error "The path '${airootfs_dir}' does not exist" 1
+ [[ -e "${pacstrap_dir}" ]] || _msg_error "The path '${pacstrap_dir}' does not exist" 1
_msg_info "Creating ext4 image of 32 GiB..."
if [[ "${quiet}" == "y" ]]; then
- mkfs.ext4 -q -O '^has_journal,^resize_inode' -E 'lazy_itable_init=0' -m 0 -F -- "${airootfs_dir}.img" 32G
+ mkfs.ext4 -q -O '^has_journal,^resize_inode' -E 'lazy_itable_init=0' -m 0 -F -- "${pacstrap_dir}.img" 32G
else
- mkfs.ext4 -O '^has_journal,^resize_inode' -E 'lazy_itable_init=0' -m 0 -F -- "${airootfs_dir}.img" 32G
+ mkfs.ext4 -O '^has_journal,^resize_inode' -E 'lazy_itable_init=0' -m 0 -F -- "${pacstrap_dir}.img" 32G
fi
- tune2fs -c 0 -i 0 -- "${airootfs_dir}.img" > /dev/null
+ tune2fs -c 0 -i 0 -- "${pacstrap_dir}.img" > /dev/null
_msg_info "Done!"
_mount_airootfs
- _msg_info "Copying '${airootfs_dir}/' to '${work_dir}/mnt/airootfs/'..."
- cp -aT -- "${airootfs_dir}/" "${work_dir}/mnt/airootfs/"
+ _msg_info "Copying '${pacstrap_dir}/' to '${work_dir}/mnt/airootfs/'..."
+ cp -aT -- "${pacstrap_dir}/" "${work_dir}/mnt/airootfs/"
chown -- 0:0 "${work_dir}/mnt/airootfs/"
_msg_info "Done!"
_umount_airootfs
install -d -m 0755 -- "${isofs_dir}/${install_dir}/${arch}"
_msg_info "Creating SquashFS image, this may take some time..."
- _run_mksquashfs "${airootfs_dir}.img"
+ _run_mksquashfs "${pacstrap_dir}.img"
_msg_info "Done!"
- rm -- "${airootfs_dir}.img"
+ rm -- "${pacstrap_dir}.img"
}
# Makes a SquashFS filesystem from a source directory.
_mkairootfs_squashfs() {
- [[ -e "${airootfs_dir}" ]] || _msg_error "The path '${airootfs_dir}' does not exist" 1
+ [[ -e "${pacstrap_dir}" ]] || _msg_error "The path '${pacstrap_dir}' does not exist" 1
install -d -m 0755 -- "${isofs_dir}/${install_dir}/${arch}"
_msg_info "Creating ${arch} SquashFS image, this may take some time..."
- _run_mksquashfs "${airootfs_dir}"
+ _run_mksquashfs "${pacstrap_dir}"
_msg_info "Done!"
}
@@ -219,14 +235,14 @@ _mkchecksum() {
# Makes an EROFS file system from a source directory.
_mkairootfs_erofs() {
local fsuuid
- [[ -e "${airootfs_dir}" ]] || _msg_error "The path '${airootfs_dir}' does not exist" 1
+ [[ -e "${pacstrap_dir}" ]] || _msg_error "The path '${pacstrap_dir}' does not exist" 1
install -d -m 0755 -- "${isofs_dir}/${install_dir}/${arch}"
local image_path="${isofs_dir}/${install_dir}/${arch}/airootfs.erofs"
# Generate reproducible file system UUID from SOURCE_DATE_EPOCH
fsuuid="$(uuidgen --sha1 --namespace 93a870ff-8565-4cf3-a67b-f47299271a96 --name "${SOURCE_DATE_EPOCH}")"
_msg_info "Creating EROFS image, this may take some time..."
- mkfs.erofs -U "${fsuuid}" "${airootfs_image_tool_options[@]}" -- "${image_path}" "${airootfs_dir}"
+ mkfs.erofs -U "${fsuuid}" "${airootfs_image_tool_options[@]}" -- "${image_path}" "${pacstrap_dir}"
_msg_info "Done!"
}
@@ -245,9 +261,9 @@ _mksignature() {
# Helper function to run functions only one time.
_run_once() {
- if [[ ! -e "${work_dir}/build.${1}_${arch}" ]]; then
+ if [[ ! -e "${work_dir}/${run_once_mode}.${1}" ]]; then
"$1"
- touch "${work_dir}/build.${1}_${arch}"
+ touch "${work_dir}/${run_once_mode}.${1}_${arch}"
fi
}
@@ -257,7 +273,11 @@ _run_dual() {
if [[ "${arch}" == "dual" ]]; then
local arch
for arch in i686 x86_64; do
- airootfs_dir="${work_dir}/${arch}/airootfs"
+ if [[ "${buildmode}" == "bootstrap" ]]; then
+ pacstrap_dir="${work_dir}/${arch}/bootstrap/root.${arch}"
+ else
+ pacstrap_dir="${work_dir}/${arch}/airootfs"
+ fi
for cmd in "$@"; do
${cmd}
done
@@ -283,7 +303,7 @@ _make_pacman_conf() {
_cache_dirs="${_system_cache_dirs}"
fi
- _msg_info "Copying custom pacman.conf to work directory..."
+ _msg_info "Copying custom pacman.conf to ${arch} work directory..."
_msg_info "Using pacman CacheDir: ${_cache_dirs}"
# take the profile pacman.conf and strip all settings that would break in chroot when using pacman -r
# append CacheDir and HookDir to [options] section
@@ -291,7 +311,7 @@ _make_pacman_conf() {
# see `man 8 pacman` for further info
setarch "${arch}" pacman-conf --config "${pacman_conf}" | \
sed "/CacheDir/d;/DBPath/d;/HookDir/d;/LogFile/d;/RootDir/d;/\[options\]/a CacheDir = ${_cache_dirs}
- /\[options\]/a HookDir = ${airootfs_dir}/etc/pacman.d/hooks/" > "${work_dir}/pacman_${arch}.conf"
+ /\[options\]/a HookDir = ${pacstrap_dir}/etc/pacman.d/hooks/" > "${work_dir}/${buildmode}.pacman.conf.${arch}"
}
# Prepare working directory and copy custom airootfs files (airootfs)
@@ -299,27 +319,27 @@ _make_custom_airootfs() {
local passwd=()
local filename permissions
- install -d -m 0755 -o 0 -g 0 -- "${airootfs_dir}"
+ install -d -m 0755 -o 0 -g 0 -- "${pacstrap_dir}"
if [[ -d "${profile}/airootfs" ]]; then
_msg_info "Copying custom airootfs files..."
- cp -af --no-preserve=ownership,mode -- "${profile}/airootfs/." "${airootfs_dir}"
+ cp -af --no-preserve=ownership,mode -- "${profile}/airootfs/." "${pacstrap_dir}"
# Set ownership and mode for files and directories
for filename in "${!file_permissions[@]}"; do
IFS=':' read -ra permissions <<< "${file_permissions["${filename}"]}"
- # Prevent file path traversal outside of $airootfs_dir
- if [[ "$(realpath -q -- "${airootfs_dir}${filename}")" != "${airootfs_dir}"* ]]; then
- _msg_error "Failed to set permissions on '${airootfs_dir}${filename}'. Outside of valid path." 1
+ # Prevent file path traversal outside of $pacstrap_dir
+ if [[ "$(realpath -q -- "${pacstrap_dir}${filename}")" != "${pacstrap_dir}"* ]]; then
+ _msg_error "Failed to set permissions on '${pacstrap_dir}${filename}'. Outside of valid path." 1
# Warn if the file does not exist
- elif [[ ! -e "${airootfs_dir}${filename}" ]]; then
- _msg_warning "Cannot change permissions of '${airootfs_dir}${filename}'. The file or directory does not exist."
+ elif [[ ! -e "${pacstrap_dir}${filename}" ]]; then
+ _msg_warning "Cannot change permissions of '${pacstrap_dir}${filename}'. The file or directory does not exist."
else
if [[ "${filename: -1}" == "/" ]]; then
- chown -fhR -- "${permissions[0]}:${permissions[1]}" "${airootfs_dir}${filename}"
- chmod -fR -- "${permissions[2]}" "${airootfs_dir}${filename}"
+ chown -fhR -- "${permissions[0]}:${permissions[1]}" "${pacstrap_dir}${filename}"
+ chmod -fR -- "${permissions[2]}" "${pacstrap_dir}${filename}"
else
- chown -fh -- "${permissions[0]}:${permissions[1]}" "${airootfs_dir}${filename}"
- chmod -f -- "${permissions[2]}" "${airootfs_dir}${filename}"
+ chown -fh -- "${permissions[0]}:${permissions[1]}" "${pacstrap_dir}${filename}"
+ chmod -f -- "${permissions[2]}" "${pacstrap_dir}${filename}"
fi
fi
done
@@ -329,10 +349,10 @@ _make_custom_airootfs() {
# Install desired packages to airootfs
_make_packages() {
- _msg_info "Installing packages to '${airootfs_dir}/'..."
+ _msg_info "Installing packages to '${pacstrap_dir}/'..."
- local pkg_list_arch
- eval "pkg_list_arch=(\${pkg_list_${arch}[@]})"
+ local buildmode_pkg_list_arch
+ eval "buildmode_pkg_list_arch=(\${buildmode_pkg_list_${arch}[@]})"
if [[ -n "${gpg_key}" ]]; then
exec {PARABOLAISO_GNUPG_FD}<>"${work_dir}/pubkey.gpg"
@@ -340,9 +360,9 @@ _make_packages() {
fi
if [[ "${quiet}" = "y" ]]; then
- pacstrap -C "${work_dir}/pacman_${arch}.conf" -c -G -M -- "${airootfs_dir}" "${pkg_list[@]}" "${pkg_list_arch[@]}" &> /dev/null
+ pacstrap -C "${work_dir}/${buildmode}.pacman.conf.${arch}" -c -G -M -- "${pacstrap_dir}" "${buildmode_pkg_list[@]}" "${buildmode_pkg_list_arch[@]}" &> /dev/null
else
- pacstrap -C "${work_dir}/pacman_${arch}.conf" -c -G -M -- "${airootfs_dir}" "${pkg_list[@]}" "${pkg_list_arch[@]}"
+ pacstrap -C "${work_dir}/${buildmode}.pacman.conf.${arch}" -c -G -M -- "${pacstrap_dir}" "${buildmode_pkg_list[@]}" "${buildmode_pkg_list_arch[@]}"
fi
if [[ -n "${gpg_key}" ]]; then
@@ -365,27 +385,27 @@ _make_customize_airootfs() {
# Skip invalid home directories
[[ "${passwd[5]}" == '/' ]] && continue
[[ -z "${passwd[5]}" ]] && continue
- # Prevent path traversal outside of $airootfs_dir
- if [[ "$(realpath -q -- "${airootfs_dir}${passwd[5]}")" == "${airootfs_dir}"* ]]; then
- if [[ ! -d "${airootfs_dir}${passwd[5]}" ]]; then
- install -d -m 0750 -o "${passwd[2]}" -g "${passwd[3]}" -- "${airootfs_dir}${passwd[5]}"
+ # Prevent path traversal outside of $pacstrap_dir
+ if [[ "$(realpath -q -- "${pacstrap_dir}${passwd[5]}")" == "${pacstrap_dir}"* ]]; then
+ if [[ ! -d "${pacstrap_dir}${passwd[5]}" ]]; then
+ install -d -m 0750 -o "${passwd[2]}" -g "${passwd[3]}" -- "${pacstrap_dir}${passwd[5]}"
fi
- cp -dnRT --preserve=mode,timestamps,links -- "${airootfs_dir}/etc/skel/." "${airootfs_dir}${passwd[5]}"
- chmod -f 0750 -- "${airootfs_dir}${passwd[5]}"
- chown -hR -- "${passwd[2]}:${passwd[3]}" "${airootfs_dir}${passwd[5]}"
+ cp -dnRT --preserve=mode,timestamps,links -- "${pacstrap_dir}/etc/skel/." "${pacstrap_dir}${passwd[5]}"
+ chmod -f 0750 -- "${pacstrap_dir}${passwd[5]}"
+ chown -hR -- "${passwd[2]}:${passwd[3]}" "${pacstrap_dir}${passwd[5]}"
else
- _msg_error "Failed to set permissions on '${airootfs_dir}${passwd[5]}'. Outside of valid path." 1
+ _msg_error "Failed to set permissions on '${pacstrap_dir}${passwd[5]}'. Outside of valid path." 1
fi
done < "${profile}/airootfs/etc/passwd"
_msg_info "Done!"
fi
- if [[ -e "${airootfs_dir}/root/customize_airootfs.sh" ]]; then
- _msg_info "Running customize_airootfs.sh in '${airootfs_dir}' chroot..."
+ if [[ -e "${pacstrap_dir}/root/customize_airootfs.sh" ]]; then
+ _msg_info "Running customize_airootfs.sh in '${pacstrap_dir}' chroot..."
_msg_warning "customize_airootfs.sh is deprecated! Support for it will be removed in a future parabolaiso version."
- chmod -f -- +x "${airootfs_dir}/root/customize_airootfs.sh"
- eval -- arch-chroot "${airootfs_dir}" "/root/customize_airootfs.sh"
- rm -- "${airootfs_dir}/root/customize_airootfs.sh"
+ chmod -f -- +x "${pacstrap_dir}/root/customize_airootfs.sh"
+ eval -- arch-chroot "${pacstrap_dir}" "/root/customize_airootfs.sh"
+ rm -- "${pacstrap_dir}/root/customize_airootfs.sh"
_msg_info "Done! customize_airootfs.sh run successfully."
fi
}
@@ -402,8 +422,8 @@ _make_bootmodes() {
_make_boot_on_iso9660() {
_msg_info "Preparing ${arch} kernel and initramfs for the ISO 9660 file system..."
install -d -m 0755 -- "${isofs_dir}/${install_dir}/boot/${arch}"
- install -m 0644 -- "${airootfs_dir}/boot/initramfs-"*".img" "${isofs_dir}/${install_dir}/boot/${arch}/"
- install -m 0644 -- "${airootfs_dir}/boot/vmlinuz-"* "${isofs_dir}/${install_dir}/boot/${arch}/"
+ install -m 0644 -- "${pacstrap_dir}/boot/initramfs-"*".img" "${isofs_dir}/${install_dir}/boot/${arch}/"
+ install -m 0644 -- "${pacstrap_dir}/boot/vmlinuz-"* "${isofs_dir}/${install_dir}/boot/${arch}/"
_msg_info "Done!"
}
@@ -420,28 +440,28 @@ _make_bootmode_bios.syslinux.mbr() {
if [[ -e "${profile}/syslinux/splash.png" ]]; then
install -m 0644 -- "${profile}/syslinux/splash.png" "${isofs_dir}/syslinux/"
fi
- install -m 0644 -- "${airootfs_dir}/usr/lib/syslinux/bios/"*.c32 "${isofs_dir}/syslinux/"
- install -m 0644 -- "${airootfs_dir}/usr/lib/syslinux/bios/lpxelinux.0" "${isofs_dir}/syslinux/"
- install -m 0644 -- "${airootfs_dir}/usr/lib/syslinux/bios/memdisk" "${isofs_dir}/syslinux/"
+ install -m 0644 -- "${pacstrap_dir}/usr/lib/syslinux/bios/"*.c32 "${isofs_dir}/syslinux/"
+ install -m 0644 -- "${pacstrap_dir}/usr/lib/syslinux/bios/lpxelinux.0" "${isofs_dir}/syslinux/"
+ install -m 0644 -- "${pacstrap_dir}/usr/lib/syslinux/bios/memdisk" "${isofs_dir}/syslinux/"
_run_dual '_run_once _make_boot_on_iso9660'
if [[ -e "${isofs_dir}/syslinux/hdt.c32" ]]; then
install -d -m 0755 -- "${isofs_dir}/syslinux/hdt"
- if [[ -e "${airootfs_dir}/usr/share/hwdata/pci.ids" ]]; then
- gzip -cn9 "${airootfs_dir}/usr/share/hwdata/pci.ids" > \
+ if [[ -e "${pacstrap_dir}/usr/share/hwdata/pci.ids" ]]; then
+ gzip -cn9 "${pacstrap_dir}/usr/share/hwdata/pci.ids" > \
"${isofs_dir}/syslinux/hdt/pciids.gz"
fi
- find "${airootfs_dir}/usr/lib/modules" -name 'modules.alias' -print -exec gzip -cn9 '{}' ';' -quit > \
+ find "${pacstrap_dir}/usr/lib/modules" -name 'modules.alias' -print -exec gzip -cn9 '{}' ';' -quit > \
"${isofs_dir}/syslinux/hdt/modalias.gz"
fi
# Add other aditional/extra files to ${install_dir}/boot/
- if [[ -e "${airootfs_dir}/boot/memtest86+/memtest.bin" ]]; then
+ if [[ -e "${pacstrap_dir}/boot/memtest86+/memtest.bin" ]]; then
# rename for PXE: https://wiki.parabola.nu/index.php/Syslinux#Using_memtest
- install -m 0644 -- "${airootfs_dir}/boot/memtest86+/memtest.bin" "${isofs_dir}/${install_dir}/boot/memtest"
+ install -m 0644 -- "${pacstrap_dir}/boot/memtest86+/memtest.bin" "${isofs_dir}/${install_dir}/boot/memtest"
install -d -m 0755 -- "${isofs_dir}/${install_dir}/boot/licenses/memtest86+/"
- install -m 0644 -- "${airootfs_dir}/usr/share/licenses/common/GPL2/license.txt" \
+ install -m 0644 -- "${pacstrap_dir}/usr/share/licenses/common/GPL2/license.txt" \
"${isofs_dir}/${install_dir}/boot/licenses/memtest86+/"
fi
_msg_info "Done! SYSLINUX set up for BIOS booting from a disk successfully."
@@ -451,8 +471,8 @@ _make_bootmode_bios.syslinux.mbr() {
_make_bootmode_bios.syslinux.eltorito() {
_msg_info "Setting up SYSLINUX for BIOS booting from an optical disc..."
install -d -m 0755 -- "${isofs_dir}/syslinux"
- install -m 0644 -- "${airootfs_dir}/usr/lib/syslinux/bios/isolinux.bin" "${isofs_dir}/syslinux/"
- install -m 0644 -- "${airootfs_dir}/usr/lib/syslinux/bios/isohdpfx.bin" "${isofs_dir}/syslinux/"
+ install -m 0644 -- "${pacstrap_dir}/usr/lib/syslinux/bios/isolinux.bin" "${isofs_dir}/syslinux/"
+ install -m 0644 -- "${pacstrap_dir}/usr/lib/syslinux/bios/isohdpfx.bin" "${isofs_dir}/syslinux/"
# ISOLINUX and SYSLINUX installation is shared
_run_once _make_bootmode_bios.syslinux.mbr
@@ -464,7 +484,7 @@ _make_bootmode_bios.syslinux.eltorito() {
_make_efi_dir_on_iso9660() {
_msg_info "Preparing an /EFI directory for the ISO 9660 file system..."
install -d -m 0755 -- "${isofs_dir}/EFI/BOOT"
- install -m 0644 -- "${airootfs_dir}/usr/lib/systemd/boot/efi/systemd-bootx64.efi" \
+ install -m 0644 -- "${pacstrap_dir}/usr/lib/systemd/boot/efi/systemd-bootx64.efi" \
"${isofs_dir}/EFI/BOOT/BOOTx64.EFI"
install -d -m 0755 -- "${isofs_dir}/loader/entries"
@@ -479,15 +499,15 @@ _make_efi_dir_on_iso9660() {
# edk2-shell based UEFI shell
# shellx64.efi is picked up automatically when on /
- if [[ -e "${airootfs_dir}/usr/share/edk2-shell/x64/Shell_Full.efi" ]]; then
- install -m 0644 -- "${airootfs_dir}/usr/share/edk2-shell/x64/Shell_Full.efi" "${isofs_dir}/shellx64.efi"
+ if [[ -e "${pacstrap_dir}/usr/share/edk2-shell/x64/Shell_Full.efi" ]]; then
+ install -m 0644 -- "${pacstrap_dir}/usr/share/edk2-shell/x64/Shell_Full.efi" "${isofs_dir}/shellx64.efi"
fi
}
_make_refind_efi_dir_on_iso9660() {
_msg_info "Preparing an /EFI directory for the ISO 9660 file system..."
install -d -m 0755 -- "${isofs_dir}/EFI/BOOT/entries"
- install -m 0644 -- "${airootfs_dir}/usr/share/refind/refind_x64.efi" \
+ install -m 0644 -- "${pacstrap_dir}/usr/share/refind/refind_x64.efi" \
"${isofs_dir}/EFI/BOOT/BOOTx64.EFI"
install -m 0644 -- "${profile}/efiboot/EFI/BOOT/refind.conf" "${isofs_dir}/EFI/BOOT/"
@@ -501,8 +521,8 @@ _make_refind_efi_dir_on_iso9660() {
# edk2-shell based UEFI shell
# shellx64.efi is picked up automatically when on /
- if [[ -e "${airootfs_dir}/usr/share/edk2-shell/x64/Shell_Full.efi" ]]; then
- install -m 0644 -- "${airootfs_dir}/usr/share/edk2-shell/x64/Shell_Full.efi" "${isofs_dir}/shellx64.efi"
+ if [[ -e "${pacstrap_dir}/usr/share/edk2-shell/x64/Shell_Full.efi" ]]; then
+ install -m 0644 -- "${pacstrap_dir}/usr/share/edk2-shell/x64/Shell_Full.efi" "${isofs_dir}/shellx64.efi"
fi
}
@@ -511,8 +531,8 @@ _make_boot_on_fat() {
_msg_info "Preparing kernel and initramfs for the FAT file system..."
mmd -i "${work_dir}/efiboot.img" \
"::/${install_dir}" "::/${install_dir}/boot" "::/${install_dir}/boot/x86_64"
- mcopy -i "${work_dir}/efiboot.img" "${airootfs_dir}/boot/vmlinuz-"* \
- "${airootfs_dir}/boot/initramfs-"*".img" "::/${install_dir}/boot/x86_64/"
+ mcopy -i "${work_dir}/efiboot.img" "${pacstrap_dir}/boot/vmlinuz-"* \
+ "${pacstrap_dir}/boot/initramfs-"*".img" "::/${install_dir}/boot/x86_64/"
_msg_info "Done!"
}
@@ -523,11 +543,11 @@ _make_bootmode_uefi-x64.systemd-boot.esp() {
# the required image size in KiB (rounded up to the next full MiB with an additional MiB for reserved sectors)
efiboot_imgsize="$(du -bc \
- "${airootfs_dir}/usr/lib/systemd/boot/efi/systemd-bootx64.efi" \
- "${airootfs_dir}/usr/share/edk2-shell/x64/Shell_Full.efi" \
+ "${pacstrap_dir}/usr/lib/systemd/boot/efi/systemd-bootx64.efi" \
+ "${pacstrap_dir}/usr/share/edk2-shell/x64/Shell_Full.efi" \
"${profile}/efiboot/" \
- "${airootfs_dir}/boot/vmlinuz-"* \
- "${airootfs_dir}/boot/initramfs-"*".img" \
+ "${pacstrap_dir}/boot/vmlinuz-"* \
+ "${pacstrap_dir}/boot/initramfs-"*".img" \
2>/dev/null | awk 'function ceil(x){return int(x)+(x>int(x))}
function byte_to_kib(x){return x/1024}
function mib_to_kib(x){return x*1024}
@@ -541,7 +561,7 @@ _make_bootmode_uefi-x64.systemd-boot.esp() {
mmd -i "${work_dir}/efiboot.img" ::/EFI ::/EFI/BOOT
mcopy -i "${work_dir}/efiboot.img" \
- "${airootfs_dir}/usr/lib/systemd/boot/efi/systemd-bootx64.efi" ::/EFI/BOOT/BOOTx64.EFI
+ "${pacstrap_dir}/usr/lib/systemd/boot/efi/systemd-bootx64.efi" ::/EFI/BOOT/BOOTx64.EFI
mmd -i "${work_dir}/efiboot.img" ::/loader ::/loader/entries
mcopy -i "${work_dir}/efiboot.img" "${profile}/efiboot/loader/loader.conf" ::/loader/
@@ -553,9 +573,9 @@ _make_bootmode_uefi-x64.systemd-boot.esp() {
done
# shellx64.efi is picked up automatically when on /
- if [[ -e "${airootfs_dir}/usr/share/edk2-shell/x64/Shell_Full.efi" ]]; then
+ if [[ -e "${pacstrap_dir}/usr/share/edk2-shell/x64/Shell_Full.efi" ]]; then
mcopy -i "${work_dir}/efiboot.img" \
- "${airootfs_dir}/usr/share/edk2-shell/x64/Shell_Full.efi" ::/shellx64.efi
+ "${pacstrap_dir}/usr/share/edk2-shell/x64/Shell_Full.efi" ::/shellx64.efi
fi
# Copy kernel and initramfs
@@ -570,11 +590,11 @@ _make_bootmode_uefi-x64.refind.esp() {
# the required image size in KiB (rounded up to the next full MiB with an additional MiB for reserved sectors)
efiboot_imgsize="$(du -bc \
- "${airootfs_dir}/usr/share/refind/refind_x64.efi" \
- "${airootfs_dir}/usr/share/edk2-shell/x64/Shell_Full.efi" \
+ "${pacstrap_dir}/usr/share/refind/refind_x64.efi" \
+ "${pacstrap_dir}/usr/share/edk2-shell/x64/Shell_Full.efi" \
"${profile}/efiboot/" \
- "${airootfs_dir}/boot/vmlinuz-"* \
- "${airootfs_dir}/boot/initramfs-"*".img" \
+ "${pacstrap_dir}/boot/vmlinuz-"* \
+ "${pacstrap_dir}/boot/initramfs-"*".img" \
2>/dev/null | awk 'function ceil(x){return int(x)+(x>int(x))}
function byte_to_kib(x){return x/1024}
function mib_to_kib(x){return x*1024}
@@ -588,7 +608,7 @@ _make_bootmode_uefi-x64.refind.esp() {
mmd -i "${work_dir}/efiboot.img" ::/EFI ::/EFI/BOOT
mcopy -i "${work_dir}/efiboot.img" \
- "${airootfs_dir}/usr/share/refind/refind_x64.efi" ::/EFI/BOOT/BOOTx64.EFI
+ "${pacstrap_dir}/usr/share/refind/refind_x64.efi" ::/EFI/BOOT/BOOTx64.EFI
mmd -i "${work_dir}/efiboot.img" ::/EFI/BOOT/entries
mcopy -i "${work_dir}/efiboot.img" "${profile}/efiboot/EFI/BOOT/refind.conf" ::/EFI/BOOT/
@@ -600,9 +620,9 @@ _make_bootmode_uefi-x64.refind.esp() {
done
# shellx64.efi is picked up automatically when on /
- if [[ -e "${airootfs_dir}/usr/share/edk2-shell/x64/Shell_Full.efi" ]]; then
+ if [[ -e "${pacstrap_dir}/usr/share/edk2-shell/x64/Shell_Full.efi" ]]; then
mcopy -i "${work_dir}/efiboot.img" \
- "${airootfs_dir}/usr/share/edk2-shell/x64/Shell_Full.efi" ::/shellx64.efi
+ "${pacstrap_dir}/usr/share/edk2-shell/x64/Shell_Full.efi" ::/shellx64.efi
fi
# Copy kernel and initramfs
@@ -699,8 +719,8 @@ _validate_requirements_bootmode_uefi-x64.systemd-boot.esp() {
fi
# Check for optional packages
- # shellcheck disable=SC2076
if [[ "${arch}" == "dual" ]]; then
+ # shellcheck disable=SC2154
if [[ ! " ${pkg_list_x86_64[*]} " =~ ' edk2-shell ' ]]; then
_msg_info "'edk2-shell' is not in the x86_64 package list. The ISO will not contain a bootable UEFI shell."
fi
@@ -744,7 +764,6 @@ _validate_requirements_bootmode_uefi-x64.refind.esp() {
fi
# Check for optional packages
- # shellcheck disable=SC2076
if [[ "${arch}" == "dual" ]]; then
if [[ ! " ${pkg_list_x86_64[*]} " =~ ' edk2-shell ' ]]; then
_msg_info "'edk2-shell' is not in the x86_64 package list. The ISO will not contain a bootable UEFI shell."
@@ -775,6 +794,34 @@ _prepare_airootfs_image() {
fi
}
+# export build artifacts for netboot
+_export_netboot_artifacts() {
+ _msg_info "Exporting netboot artifacts..."
+ install -d -m 0755 "${out_dir}"
+ cp -a -- "${isofs_dir}/${install_dir}/" "${out_dir}/"
+ _msg_info "Done!"
+ du -h -- "${out_dir}/${install_dir}"
+}
+
+# sign build artifacts for netboot
+_sign_netboot_artifacts() {
+ local _file _dir
+ _msg_info "Signing netboot artifacts..."
+ _dir="${isofs_dir}/${install_dir}/"
+ for _file in "${_dir}/boot/${arch}/vmlinuz-"* "${_dir}/boot/${arch}/initramfs-"*.img; do
+ openssl cms \
+ -sign \
+ -binary \
+ -noattr \
+ -in "${_file}" \
+ -signer "${cert_list[0]}" \
+ -inkey "${cert_list[1]}" \
+ -outform DER \
+ -out "${_file}".ipxe.sig
+ done
+ _msg_info "Done!"
+}
+
_validate_requirements_airootfs_image_type_squashfs() {
if ! command -v mksquashfs &> /dev/null; then
(( validation_error=validation_error+1 ))
@@ -797,6 +844,44 @@ _validate_requirements_airootfs_image_type_erofs() {
fi
}
+_validate_requirements_buildmode_all() {
+ if ! command -v pacman &> /dev/null; then
+ (( validation_error=validation_error+1 ))
+ _msg_error "Validating build mode '${_buildmode}': pacman is not available on this host. Install 'pacman'!" 0
+ fi
+ if ! command -v find &> /dev/null; then
+ (( validation_error=validation_error+1 ))
+ _msg_error "Validating build mode '${_buildmode}': find is not available on this host. Install 'findutils'!" 0
+ fi
+ if ! command -v gzip &> /dev/null; then
+ (( validation_error=validation_error+1 ))
+ _msg_error "Validating build mode '${_buildmode}': gzip is not available on this host. Install 'gzip'!" 0
+ fi
+}
+
+_validate_requirements_buildmode_bootstrap() {
+ _validate_requirements_buildmode_all
+ if ! command -v bsdtar &> /dev/null; then
+ (( validation_error=validation_error+1 ))
+ _msg_error "Validating build mode '${_buildmode}': bsdtar is not available on this host. Install 'libarchive'!" 0
+ fi
+}
+
+_validate_requirements_buildmode_iso() {
+ _validate_requirements_buildmode_all
+ if ! command -v awk &> /dev/null; then
+ (( validation_error=validation_error+1 ))
+ _msg_error "Validating build mode '${_buildmode}': awk is not available on this host. Install 'awk'!" 0
+ fi
+}
+_validate_requirements_buildmode_netboot() {
+ _validate_requirements_buildmode_all
+ if ! command -v openssl &> /dev/null; then
+ (( validation_error=validation_error+1 ))
+ _msg_error "Validating build mode '${_buildmode}': openssl is not available on this host. Install 'openssl'!" 0
+ fi
+}
+
# SYSLINUX El Torito
_add_xorrisofs_options_bios.syslinux.eltorito() {
xorrisofs_options+=(
@@ -944,8 +1029,28 @@ _add_xorrisofs_options_uefi-x64.refind.eltorito() {
[[ " ${bootmodes[*]} " =~ ' bios.' ]] || xorrisofs_options+=('-eltorito-catalog' 'EFI/boot.cat')
}
+# Build bootstrap image
+_build_bootstrap_image() {
+ local _bootstrap_parent
+ _bootstrap_parent="$(dirname -- "${pacstrap_dir}")"
+
+ local image_name_arch
+ eval "image_name_arch=\${image_name_${arch}}"
+ [[ -z "${image_name_arch}" ]] || image_name="${image_name_arch}"
+
+ [[ -d "${out_dir}" ]] || install -d -- "${out_dir}"
+
+ cd -- "${_bootstrap_parent}"
+
+ _msg_info "Creating ${arch} bootstrap image..."
+ bsdtar -cf - "root.${arch}" | gzip -cn9 > "${out_dir}/${image_name}"
+ _msg_info "Done!"
+ du -h -- "${out_dir}/${image_name}"
+ cd -- "${OLDPWD}"
+}
+
# Build ISO
-_build_iso() {
+_build_iso_image() {
local xorrisofs_options=()
local bootmode
@@ -970,10 +1075,10 @@ _build_iso() {
-publisher "${iso_publisher}" \
-preparer "prepared by ${app_name}" \
"${xorrisofs_options[@]}" \
- -output "${out_dir}/${img_name}" \
+ -output "${out_dir}/${image_name}" \
"${isofs_dir}/"
_msg_info "Done!"
- du -h -- "${out_dir}/${img_name}"
+ du -h -- "${out_dir}/${image_name}"
}
# Read profile's values from profiledef.sh
@@ -992,16 +1097,31 @@ _read_profile() {
# shellcheck source=configs/releng/profiledef.sh
. "${profile}/profiledef.sh"
- # Resolve paths of files that are expected to reside in the profile's directory
if [[ "${arch}" == "dual" ]]; then
- [[ -n "$packages_dual" ]] || packages_dual=("${profile}/packages."{both,i686,x86_64})
- # shellcheck disable=SC2178
- packages_dual="$(realpath -- "${packages_dual[@]}")"
+ # Resolve paths of files that are expected to reside in the profile's directory for each architecture
+ [[ -n "$packages_dual" ]] || packages_files_dual=("${profile}/packages."{both,i686,x86_64})
+ packages_dual="$(realpath -- "${packages_files_dual[@]}")"
+ pacman_conf="$(realpath -- "${pacman_conf}")"
+
+ # Resolve paths of files that may reside in the profile's directory for each architecture
+ if [[ -z "$bootstrap_packages_dual" ]] && [[ -e "${profile}/bootstrap_packages.both" ]]; then
+ bootstrap_packages_files_dual=("${profile}/bootstrap_packages."{both,i686,x86_64})
+ bootstrap_packages_dual="$(realpath -- "${bootstrap_packages_files_dual[@]}")"
+ pacman_conf="$(realpath -- "${pacman_conf}")"
+ fi
else
+ # Resolve paths of files that are expected to reside in the profile's directory
[[ -n "$packages" ]] || packages="${profile}/packages.${arch}"
packages="$(realpath -- "${packages}")"
+ pacman_conf="$(realpath -- "${pacman_conf}")"
+
+ # Resolve paths of files that may reside in the profile's directory
+ if [[ -z "$bootstrap_packages" ]] && [[ -e "${profile}/bootstrap_packages.${arch}" ]]; then
+ bootstrap_packages="${profile}/bootstrap_packages.${arch}"
+ bootstrap_packages="$(realpath -- "${bootstrap_packages}")"
+ pacman_conf="$(realpath -- "${pacman_conf}")"
+ fi
fi
- pacman_conf="$(realpath -- "${pacman_conf}")"
cd -- "${OLDPWD}"
fi
@@ -1009,50 +1129,132 @@ _read_profile() {
# Validate set options
_validate_options() {
- local validation_error=0 bootmode
+ local validation_error=0 bootmode _cert _buildmode
local pkg_list_from_file=()
+ # shellcheck disable=SC2034
+ local pkg_list_from_file_i686=()
+ # shellcheck disable=SC2034
+ local pkg_list_from_file_x86_64=()
+ local bootstrap_pkg_list_from_file=()
+ # shellcheck disable=SC2034
+ local bootstrap_pkg_list_from_file_i686=()
+ # shellcheck disable=SC2034
+ local bootstrap_pkg_list_from_file_x86_64=()
+ local _override_cert_list=()
+
_msg_info "Validating options..."
- # Check if the package list file exists and read packages from it
if [[ "${arch}" == "dual" ]]; then
+ # Check if the package list files exist and read packages from them for each architecture
# shellcheck disable=SC2128
for packages in ${packages_dual}; do
- if [[ "${packages##*/}" = "packages.both" ]]; then
+ if [[ "${packages##*/}" == "packages.both" ]]; then
if [[ -e "${packages}" ]]; then
mapfile -t pkg_list_from_file < <(sed '/^[[:blank:]]*#.*/d;s/#.*//;/^[[:blank:]]*$/d' "${packages}")
pkg_list+=("${pkg_list_from_file[@]}")
if (( ${#pkg_list_from_file} < 1 )); then
(( validation_error=validation_error+1 ))
- _msg_error "No package specified in '${packages}'." 0
+ _msg_error "Packages file '${packages}' does not exist." 0
fi
else
(( validation_error=validation_error+1 ))
- _msg_error "File '${packages}' does not exist." 0
+ _msg_error "Packages file '${packages}' does not exist." 0
fi
elif [[ -e "${packages}" ]]; then
mapfile -t "pkg_list_from_file_${packages##*.}" < <(sed '/^[[:blank:]]*#.*/d;s/#.*//;/^[[:blank:]]*$/d' "${packages}")
eval "pkg_list_${packages##*.}+=(\${pkg_list_from_file_${packages##*.}[@]})"
fi
done
+
+ # Check if packages for the bootstrap image are specified for each architecture
+ if [[ "${buildmodes[*]}" == *bootstrap* ]]; then
+ for bootstrap_packages in ${bootstrap_packages_dual}; do
+ if [[ "${bootstrap_packages##*/}" == "bootstrap_packages.both" ]]; then
+ if [[ -e "${bootstrap_packages}" ]]; then
+ mapfile -t bootstrap_pkg_list_from_file < \
+ <(sed '/^[[:blank:]]*#.*/d;s/#.*//;/^[[:blank:]]*$/d' "${bootstrap_packages}")
+ bootstrap_pkg_list+=("${bootstrap_pkg_list_from_file[@]}")
+ if (( ${#bootstrap_pkg_list_from_file} < 1 )); then
+ (( validation_error=validation_error+1 ))
+ _msg_error "No package specified in '${bootstrap_packages}'." 0
+ fi
+ else
+ (( validation_error=validation_error+1 ))
+ _msg_error "Bootstrap packages file '${bootstrap_packages}' does not exist." 0
+ fi
+ elif [[ -e "${bootstrap_packages}" ]]; then
+ mapfile -t "bootstrap_pkg_list_from_file_${bootstrap_packages##*.}" < \
+ <(sed '/^[[:blank:]]*#.*/d;s/#.*//;/^[[:blank:]]*$/d' "${bootstrap_packages}")
+ eval "bootstrap_pkg_list_${bootstrap_packages##*.}+=(\${bootstrap_pkg_list_from_file_${bootstrap_packages##*.}[@]})"
+ fi
+ done
+ fi
else
+ # Check if the package list file exists and read packages from it
if [[ -e "${packages}" ]]; then
mapfile -t pkg_list_from_file < <(sed '/^[[:blank:]]*#.*/d;s/#.*//;/^[[:blank:]]*$/d' "${packages}")
pkg_list+=("${pkg_list_from_file[@]}")
if (( ${#pkg_list_from_file} < 1 )); then
(( validation_error=validation_error+1 ))
- _msg_error "No package specified in '${packages}'." 0
+ _msg_error "Packages file '${packages}' does not exist." 0
fi
else
(( validation_error=validation_error+1 ))
- _msg_error "File '${packages}' does not exist." 0
+ _msg_error "Packages file '${packages}' does not exist." 0
+ fi
+ # Check if packages for the bootstrap image are specified
+ if [[ "${buildmodes[*]}" == *bootstrap* ]]; then
+ if [[ -e "${bootstrap_packages}" ]]; then
+ mapfile -t bootstrap_pkg_list_from_file < \
+ <(sed '/^[[:blank:]]*#.*/d;s/#.*//;/^[[:blank:]]*$/d' "${bootstrap_packages}")
+ bootstrap_pkg_list+=("${bootstrap_pkg_list_from_file[@]}")
+ if (( ${#bootstrap_pkg_list_from_file} < 1 )); then
+ (( validation_error=validation_error+1 ))
+ _msg_error "No package specified in '${bootstrap_packages}'." 0
+ fi
+ else
+ (( validation_error=validation_error+1 ))
+ _msg_error "Bootstrap packages file '${bootstrap_packages}' does not exist." 0
+ fi
+ fi
+ fi
+ if [[ "${sign_netboot_artifacts}" == "y" ]]; then
+ # Check if the certificate files exist
+ for _cert in "${cert_list[@]}"; do
+ if [[ -e "${_cert}" ]]; then
+ _override_cert_list+=("$(realpath -- "${_cert}")")
+ else
+ (( validation_error=validation_error+1 ))
+ _msg_error "File '${_cert}' does not exist." 0
+ fi
+ done
+ cert_list=("${_override_cert_list[@]}")
+ # Check if there are at least two certificate files
+ if (( "${#cert_list[@]}" < 2 )); then
+ (( validation_error=validation_error+1 ))
+ _msg_error "Two certificates are required for codesigning, but '${cert_list[*]}' is provided." 0
fi
fi
-
# Check if pacman configuration file exists
if [[ ! -e "${pacman_conf}" ]]; then
(( validation_error=validation_error+1 ))
_msg_error "File '${pacman_conf}' does not exist." 0
fi
+
+ # Check if the specified buildmodes are supported
+ for _buildmode in "${buildmodes[@]}"; do
+ if typeset -f "_build_buildmode_${_buildmode}" &> /dev/null; then
+ if typeset -f "_validate_requirements_buildmode_${_buildmode}" &> /dev/null; then
+ "_validate_requirements_buildmode_${_buildmode}"
+ else
+ _msg_warning "Function '_validate_requirements_buildmode_${_buildmode}' does not exist. Validating the requirements of '${_buildmode}' build mode will not be possible."
+ fi
+ else
+ (( validation_error=validation_error+1 ))
+ _msg_error "${_buildmode} is not a valid build mode!" 0
+ fi
+ done
+
# Check if the specified bootmodes are supported
for bootmode in "${bootmodes[@]}"; do
if typeset -f "_make_bootmode_${bootmode}" &> /dev/null; then
@@ -1066,6 +1268,7 @@ _validate_options() {
_msg_error "${bootmode} is not a valid boot mode!" 0
fi
done
+
# Check if the specified airootfs_image_type is supported
if typeset -f "_mkairootfs_${airootfs_image_type}" &> /dev/null; then
if typeset -f "_validate_requirements_airootfs_image_type_${airootfs_image_type}" &> /dev/null; then
@@ -1077,6 +1280,7 @@ _validate_options() {
(( validation_error=validation_error+1 ))
_msg_error "Unsupported image type: '${airootfs_image_type}'" 0
fi
+
if (( validation_error )); then
_msg_error "${validation_error} errors were encountered while validating the profile. Aborting." 1
fi
@@ -1086,6 +1290,10 @@ _validate_options() {
# Set defaults and, if present, overrides from mkparabolaiso command line option parameters
_set_overrides() {
# Set variables that have command line overrides
+ [[ ! -v override_buildmodes ]] || buildmodes=("${override_buildmodes[@]}")
+ if (( "${#buildmodes[@]}" < 1 )); then
+ buildmodes+=('iso')
+ fi
if [[ -v override_work_dir ]]; then
work_dir="$override_work_dir"
elif [[ -z "$work_dir" ]]; then
@@ -1105,6 +1313,7 @@ _set_overrides() {
fi
pacman_conf="$(realpath -- "$pacman_conf")"
[[ ! -v override_pkg_list ]] || pkg_list+=("${override_pkg_list[@]}")
+ # TODO: allow overriding bootstrap_pkg_list
if [[ -v override_iso_label ]]; then
iso_label="$override_iso_label"
elif [[ -z "$iso_label" ]]; then
@@ -1126,6 +1335,10 @@ _set_overrides() {
install_dir="${app_name}"
fi
[[ ! -v override_gpg_key ]] || gpg_key="$override_gpg_key"
+ if [[ -v override_cert_list ]]; then
+ sign_netboot_artifacts="y"
+ fi
+ [[ ! -v override_cert_list ]] || cert_list+=("${override_cert_list[@]}")
if [[ -v override_quiet ]]; then
quiet="$override_quiet"
elif [[ -z "$quiet" ]]; then
@@ -1136,7 +1349,6 @@ _set_overrides() {
[[ -n "$arch" ]] || arch="$(uname -m)"
[[ -n "$airootfs_image_type" ]] || airootfs_image_type="squashfs"
[[ -n "$iso_name" ]] || iso_name="${app_name}"
- [[ -n "$img_name" ]] || img_name="${iso_name}-${iso_version}-${arch}.iso"
}
_export_gpg_publickey() {
@@ -1144,42 +1356,65 @@ _export_gpg_publickey() {
}
_make_version() {
- local osrelease
- install -d -m 0755 -- "${isofs_dir}/${install_dir}"
- _msg_info "Creating files with iso version..."
- # Write version file to airootfs
- rm -f -- "${airootfs_dir}/version"
- printf '%s\n' "${iso_version}" > "${airootfs_dir}/version"
- # Write version file to ISO 9660
- printf '%s\n' "${iso_version}" > "${isofs_dir}/${install_dir}/version"
- # Write grubenv with version information to ISO 9660
- printf '%.1024s' "$(printf '# GRUB Environment Block\nNAME=%s\nVERSION=%s\n%s' \
- "${iso_name}" "${iso_version}" "$(printf '%0.1s' "#"{1..1024})")" \
- > "${isofs_dir}/${install_dir}/grubenv"
+ local _os_release
+
+ _msg_info "Creating ${arch} version files..."
+ # Write version file to system installation dir
+ rm -f -- "${pacstrap_dir}/version"
+ printf '%s\n' "${iso_version}" > "${pacstrap_dir}/version"
+
+ if [[ "${buildmode}" == "iso" ]]; then
+ install -d -m 0755 -- "${isofs_dir}/${install_dir}"
+ # Write version file to ISO 9660
+ printf '%s\n' "${iso_version}" > "${isofs_dir}/${install_dir}/version"
+ # Write grubenv with version information to ISO 9660
+ printf '%.1024s' "$(printf '# GRUB Environment Block\nNAME=%s\nVERSION=%s\n%s' \
+ "${iso_name}" "${iso_version}" "$(printf '%0.1s' "#"{1..1024})")" \
+ > "${isofs_dir}/${install_dir}/grubenv"
+ fi
+
# Append IMAGE_ID & IMAGE_VERSION to os-release
- osrelease="$(realpath -- "${airootfs_dir}/etc/os-release")"
- if [[ ! -e "${airootfs_dir}/etc/os-release" && -e "${airootfs_dir}/usr/lib/os-release" ]]; then
- osrelease="$(realpath -- "${airootfs_dir}/usr/lib/os-release")"
+ _os_release="$(realpath -- "${pacstrap_dir}/etc/os-release")"
+ if [[ ! -e "${pacstrap_dir}/etc/os-release" && -e "${pacstrap_dir}/usr/lib/os-release" ]]; then
+ _os_release="$(realpath -- "${pacstrap_dir}/usr/lib/os-release")"
fi
- if [[ "${osrelease}" != "${airootfs_dir}"* ]]; then
- _msg_warning "os-release file '${osrelease}' is outside of valid path."
+ if [[ "${_os_release}" != "${pacstrap_dir}"* ]]; then
+ _msg_warning "os-release file '${_os_release}' is outside of valid path."
else
- [[ ! -e "${osrelease}" ]] || sed -i '/^IMAGE_ID=/d;/^IMAGE_VERSION=/d' "${osrelease}"
- printf 'IMAGE_ID=%s\nIMAGE_VERSION=%s\n' "${iso_name}" "${iso_version}" >> "${osrelease}"
+ [[ ! -e "${_os_release}" ]] || sed -i '/^IMAGE_ID=/d;/^IMAGE_VERSION=/d' "${_os_release}"
+ printf 'IMAGE_ID=%s\nIMAGE_VERSION=%s\n' "${iso_name}" "${iso_version}" >> "${_os_release}"
fi
_msg_info "Done!"
}
_make_pkglist() {
- install -d -m 0755 -- "${isofs_dir}/${install_dir}"
_msg_info "Creating a list of installed packages on ${arch} live-enviroment..."
- pacman -Q --sysroot "${airootfs_dir}" > "${isofs_dir}/${install_dir}/pkglist.${arch}.txt"
+ case "${buildmode}" in
+ "bootstrap")
+ pacman -Q --sysroot "${pacstrap_dir}" > "${pacstrap_dir}/pkglist.${arch}.txt"
+ ;;
+ "iso"|"netboot")
+ install -d -m 0755 -- "${isofs_dir}/${install_dir}"
+ pacman -Q --sysroot "${pacstrap_dir}" > "${isofs_dir}/${install_dir}/pkglist.${arch}.txt"
+ ;;
+ esac
_msg_info "Done!"
}
-_build_profile() {
+# build the base for an ISO and/or a netboot target
+_build_iso_base() {
+ local run_once_mode="base"
+ local buildmode_packages="${packages}"
+ if [[ "${arch}" == "dual" ]]; then
+ local buildmode_packages="${packages_dual}"
+ # Set the package list to use for each architecture
+ local buildmode_pkg_list_i686=("${pkg_list_i686[@]}")
+ local buildmode_pkg_list_x86_64=("${pkg_list_x86_64[@]}")
+ fi
+ # Set the package list to use
+ local buildmode_pkg_list=("${pkg_list[@]}")
# Set up essential directory paths
- airootfs_dir="${work_dir}/${arch}/airootfs"
+ pacstrap_dir="${work_dir}/${arch}/airootfs"
isofs_dir="${work_dir}/iso"
# Create working directory
[[ -d "${work_dir}" ]] || install -d -- "${work_dir}"
@@ -1199,12 +1434,79 @@ _build_profile() {
_run_dual '_run_once _make_customize_airootfs'
_run_dual '_run_once _make_pkglist'
_make_bootmodes
- _run_dual '_run_once _cleanup_airootfs' \
+ _run_dual '_run_once _cleanup_pacstrap_dir' \
'_run_once _prepare_airootfs_image'
- _run_once _build_iso
}
-while getopts 'p:C:L:P:A:D:w:o:g:vh?' arg; do
+# Build the bootstrap buildmode
+_build_buildmode_bootstrap() {
+ local run_once_mode="${buildmode}"
+ if [[ "${arch}" == "dual" ]]; then
+ local image_name_i686="${iso_name}-bootstrap-${iso_version}-i686.tar.gz"
+ local image_name_x86_64="${iso_name}-bootstrap-${iso_version}-x86_64.tar.gz"
+ local image_name="${image_name_i686} ${image_name_x86_64}"
+ local buildmode_packages="${bootstrap_packages_dual}"
+ # Set the package lists to use
+ local buildmode_pkg_list_i686=("${bootstrap_pkg_list_i686[@]}")
+ local buildmode_pkg_list_x86_64=("${bootstrap_pkg_list_x86_64[@]}")
+ local buildmode_pkg_list=("${bootstrap_pkg_list[@]}")
+
+ # Set up essential directory paths
+ pacstrap_dir_i686="${work_dir}/i686/bootstrap/root.i686"
+ pacstrap_dir_x86_64="${work_dir}/x86_64/bootstrap/root.x86_64"
+ [[ -d "${work_dir}" ]] || install -d -- "${work_dir}"
+ install -d -m 0755 -o 0 -g 0 -- "${pacstrap_dir_i686}" "${pacstrap_dir_x86_64}"
+ else
+ local image_name="${iso_name}-bootstrap-${iso_version}-${arch}.tar.gz"
+ local buildmode_packages="${bootstrap_packages}"
+ # Set the package list to use
+ local buildmode_pkg_list=("${bootstrap_pkg_list[@]}")
+
+ # Set up essential directory paths
+ pacstrap_dir="${work_dir}/${arch}/bootstrap/root.${arch}"
+ [[ -d "${work_dir}" ]] || install -d -- "${work_dir}"
+ install -d -m 0755 -o 0 -g 0 -- "${pacstrap_dir}"
+ fi
+
+ [[ "${quiet}" == "y" ]] || _show_config
+ _run_dual '_run_once _make_pacman_conf'
+ _run_dual '_run_once _make_packages'
+ _run_dual '_run_once _make_version'
+ _run_dual '_run_once _make_pkglist'
+ _run_dual '_run_once _cleanup_pacstrap_dir'
+ _run_dual '_run_once _build_bootstrap_image'
+}
+
+# Build the netboot buildmode
+_build_buildmode_netboot() {
+ local run_once_mode="${buildmode}"
+
+ _run_once _build_iso_base
+ if [[ -v cert_list ]]; then
+ _run_once _sign_netboot_artifacts
+ fi
+ _run_once _export_netboot_artifacts
+}
+
+# Build the ISO buildmode
+_build_buildmode_iso() {
+ local image_name="${iso_name}-${iso_version}-${arch}.iso"
+ local run_once_mode="${buildmode}"
+ _run_once _build_iso_base
+ _run_once _build_iso_image
+}
+
+# build all buildmodes
+_build() {
+ local buildmode
+ local run_once_mode="build"
+
+ for buildmode in "${buildmodes[@]}"; do
+ _run_once "_build_buildmode_${buildmode}"
+ done
+}
+
+while getopts 'c:p:C:L:P:A:D:w:m:o:g:vh?' arg; do
case "${arg}" in
p) read -r -a override_pkg_list <<< "${OPTARG}" ;;
C) override_pacman_conf="${OPTARG}" ;;
@@ -1212,7 +1514,9 @@ while getopts 'p:C:L:P:A:D:w:o:g:vh?' arg; do
P) override_iso_publisher="${OPTARG}" ;;
A) override_iso_application="${OPTARG}" ;;
D) override_install_dir="${OPTARG}" ;;
+ c) read -r -a override_cert_list <<< "${OPTARG}" ;;
w) override_work_dir="${OPTARG}" ;;
+ m) read -r -a override_buildmodes <<< "${OPTARG}" ;;
o) override_out_dir="${OPTARG}" ;;
g) override_gpg_key="${OPTARG}" ;;
v) override_quiet="n" ;;
@@ -1241,6 +1545,6 @@ profile="$(realpath -- "${1}")"
_read_profile
_set_overrides
_validate_options
-_build_profile
+_build
# vim:ts=4:sw=4:et:
diff --git a/scripts/run_parabolaiso.sh b/scripts/run_parabolaiso.sh
index 63f6c86..ca8b4c0 100755
--- a/scripts/run_parabolaiso.sh
+++ b/scripts/run_parabolaiso.sh
@@ -4,7 +4,7 @@
#
# SPDX-License-Identifier: GPL-3.0-or-later
#
-# A simple script to run an parabolaiso image using qemu. The image can be booted
+# A simple script to run a parabolaiso image using qemu. The image can be booted
# using BIOS or UEFI.
#
# Requirements:
@@ -73,7 +73,7 @@ run_image() {
local ovmf_code='/usr/share/edk2-ovmf/x64/OVMF_CODE.fd'
fi
qemu_options+=(
- '-drive' "if=pflash,format=raw,unit=0,file=${ovmf_code},readonly"
+ '-drive' "if=pflash,format=raw,unit=0,file=${ovmf_code},read-only=on"
'-drive' "if=pflash,format=raw,unit=1,file=${working_dir}/OVMF_VARS.fd"
'-global' "driver=cfi.pflash01,property=secure,value=${secure_boot}"
)
@@ -89,7 +89,7 @@ run_image() {
if [[ -n "${oddimage}" ]]; then
qemu_options+=(
'-device' 'scsi-cd,bus=scsi0.0,drive=cdrom1'
- '-drive' "id=cdrom1,if=none,format=raw,media=cdrom,readonly=on,file=${oddimage}"
+ '-drive' "id=cdrom1,if=none,format=raw,media=cdrom,read-only=on,file=${oddimage}"
)
fi
@@ -100,7 +100,7 @@ run_image() {
-name parabolaiso,process=parabolaiso_0 \
-device virtio-scsi-pci,id=scsi0 \
-device "scsi-${mediatype%rom},bus=scsi0.0,drive=${mediatype}0" \
- -drive "id=${mediatype}0,if=none,format=raw,media=${mediatype/hd/disk},readonly=on,file=${image}" \
+ -drive "id=${mediatype}0,if=none,format=raw,media=${mediatype/hd/disk},read-only=on,file=${image}" \
-display "${display}" \
-vga virtio \
-audiodev pa,id=snd0 \