7 Concept and Workflow #
Abstract
The following sections describe the concept and general workflow of building appliances with KIWI NG 10.2.2.
7.1 Host Requirements To Build Images #
Building OS images requires several tools and sub-systems to be present on the host KIWI NG host. For example, to build a virtual disk image, tools for partition table setup or tools to create filesystems must to be available on the host that builds the image.
The number of required components depends on the selected image type and the
features used with the image. It’s unreasonable to expect KIWI NG users to know
which exact components are needed to build the image. A mechanism called
kiwi-systemdeps
is designed to handle the host requirements.
kiwi-systemdeps
consists out of a collection of sub-packages provided with the
python-kiwi
main package. Each individual package requires a number of tools
and subsystem packages that belongs to the package category. There are the
following systemdeps packages:
kiwi-systemdeps-core
:Supports building the simple root archive
tbz
image type.Installs the package managers which are supported by the target distribution as well as the
tar
archiving tool.
kiwi-systemdeps-containers
:Supports building
OCI
image types used withdocker
,podman
.Installs the distribution specific tool chain to build OCI compliant container images.
kiwi-systemdeps-containers-wsl
:Supports building
appx
image types.Installs the distribution specific tool chain to build WSL compliant container images on Windows systems.
kiwi-systemdeps-iso-media
:Supports building
iso
image types andoem
install media.Installs all tools required to build ISO filesystems.
Depends on the
-core
,-filesystems
and-bootloaders
kiwi-systemdeps packages.
kiwi-systemdeps-bootloaders
:Supports building bootable
oem
andiso
image types.Installs all bootloader tools depending on the host architecture to allow setup and install of the bootloader. The pulled in components are required for any image that is able to boot through some BIOS or firmware.
Depends on the
-core
kiwi-systemdeps packages.
kiwi-systemdeps-filesystems
:Supports building
fs-type
,oem
,pxe
,kis
and liveiso
image types.Installs all tools to create filesystems supported by KIWI NG. The pulled in components are needed for any image type that needs to create a filesystem. This excludes the archive-based image types like
docker
,appx
ortbz
. The package also installs tools one level below the actual filesystem creation toolkit. These are components to manage loop devices as well as partition table setup and subsystem support like LVM and LUKS.Depends on the
-core
kiwi-systemdeps packages.
kiwi-systemdeps-disk-images
:Supports building the
oem
image type.Installs all tools to create virtual disks. Virtual disks in KIWI NG are created using the QEMU toolchain.
Depends on the
-filesystems
and-bootloaders
kiwi-systemdeps packages.
kiwi-systemdeps-image-validation
:Installs the
jing
tool to validate the image description. This is useful for detailed error reports from KIWI NG if an image description validation error occurs. In addition, theanymarkup
Python module is installed if the the option to install recommended packages is set. Withanymarkup
available, KIWI NG can also handle image descriptions in another format than the XML markup (for example,YAML).
Depending on the image type the kiwi-systemdeps`
packages can help
to quickly setup the host system for building images.
In case the host must support everything, there is also the
main kiwi-systemdeps
package that has all other
existing systemdeps packages as its dependency.
Pulling in all kiwi-systemdeps
packages can result in a large number
packages installed on the host., because the required packages themselves
have other dependencies (for example, java for jing).
7.2 Setting up Repositories #
The repository selection is a crucial part of an appliance. KIWI NG allows the
end user to customize the selection of repositories and packages via
the repository
element.
7.2.1 Adding repositories #
KIWI NG installs packages into an appliance from the repositories defined in the image description. This means that at least one repository must be defined. Otherwise, KIWI NG cannot fetch any packages.
A repository is added to the description via the repository
element
which is a child of the top-level image
element:
<image schemaversion="8.0" name="{exc_image_base_name}">
<!-- snip -->
<repository type="rpm-md" alias="kiwi" priority="1">
<source path="obs://Virtualization:Appliances:Builder/openSUSE_Leap_15.5"/>
</repository>
<repository type="rpm-md" alias="OS" imageinclude="true">
<source path="{exc_repo}"/>
</repository>
</image>
The above example specifies two repositories:
The repository belonging to the KIWI NG project: obs://Virtualization:Appliances:Builder/openSUSE_Leap_15.5 at the Open Build Service (OBS).
The RPM repository belonging to the OS project: {exc_repo}, at the Open Build Service (OBS). The translated http URL is also included in the final appliance.
The repository
element accepts one source
child element that
contains the URL of the repository in an correct format along with the
following optional attributes:
imageinclude
: Specifies whether the repository should be added to the resulting image. Default is false.imageonly
: A repository withimageonly="true"
is not available during image build, but is present in the resulting appliance. Default is false.priority
: An integer value for all packages in this repository. If the same package is available in more than one repository, then the one with the highest priority is used.alias
: Name to use for the repository. It appears as the repository’s name in the image visible viazypper repos
ordnf repolist
. Ifalias`
is not specified, KIWI NG generates an alias name using hex representation from uuid4.repository_gpgcheck
: Specifies whether the repository is configured to perform repository signature validation. If not set, the package manager’s default is used.package_gpgcheck
: Boolean value that specifies whether each package’s GPG signature is verified. If omitted, the package manager’s default is used.components
: Distribution components used fordeb
repositories. Default ismain
.distribution
: Distribution name information, used for deb repositories.profiles
: List of profiles to which this repository applies.customize
: Script to run custom modifications to the repo file or files. Repo files allow for several customization options, but not all of them are supported to be set by kiwi through the current repository schema. As the used options do not follow any standard, and they are not compatible between package managers and distributions, the only way to handle this is through a script hook which is invoked with the repo file as parameter for each file created by KIWI NG.An example for a script call to add the
module_hotfixes
option for adnf
compatible repository configuration could look as follows:repo_file=$1 echo 'module_hotfixes = 1' >> ${repo_file}
NoteIf the script is provided as a relative path, it is expected to be found in the image description directory:
7.2.1.1 Supported repository paths #
The actual location of a repository is specified in the source
child
element of repository
via its only attribute path
. KIWI NG supports the
following paths types:
http://URL
orhttps://URL
orftp://URL
: a URL to the repository available via HTTP(s) or FTP.obs://$PROJECT/$REPOSITORY
: checks whether the repository$REPOSITORY
of the project$PROJECT
available on the Open Build Service (OBS). By default, KIWI NG looks for projects on build.opensuse.org, but this can be overridden using the runtime configuration file (see Section 7.7, “The Runtime Configuration File”). Note that it is not possible to add repositories using theobs://
path from different OBS instances (use direct URLs to the.repo
file instead in this case).obsrepositories:/
: special path only available for builds using the Open Build Service. The repositories configured for the OBS project where the KIWI NG image resides are made available inside the appliance. This allows you to configure the repositories of your image from OBS itself, without modifying the image description.dir:///path/to/directory
orfile:///path/to/file
: an absolute path to a local directory or file available on the host building the appliance.iso:///path/to/image.iso
: the specified ISO image is mounted during the build of the KIWI NG image and a repository is created, pointing to the mounted ISO.
7.3 Adding and Removing Packages #
In addition to the Section 7.2, “Setting up Repositories” setup, the package setup is
required. KIWI NG allows the end user to completely customize the selection
of packages via the packages
element.
<image schemaversion="8.0" name="{exc_image_base_name}">
<packages type="bootstrap">
<package name="udev"/>
<package name="filesystem"/>
<package name="openSUSE-release"/>
<!-- additional packages installed before the chroot is created -->
</packages>
<packages type="image">
<package name="patterns-openSUSE-base"/>
<!-- additional packages to be installed into the chroot -->
</packages>
</image>
The packages
element provides a collection of different child elements
that instruct KIWI NG when and how to perform package installation or
removal. Each packages
element acts as a group, whose behavior can be
configured via the following attributes:
type
: eitherbootstrap
,image
,delete
,uninstall
or one of the following build types:docker
,iso
,oem
,kis
,oci
.Packages for
type="bootstrap"
are pre-installed to populate the images’ root file system before chrooting into it.Packages in
type="image"
are installed immediately after the initial chroot into the new root file system.Packages in
type="delete"
andtype="uninstall"
are removed from the image, for details see Uninstall System Packages.And packages which belong to a build type are only installed when that specific build type is currently processed by KIWI NG.
profiles
: a list of profiles to which this package selection applies (see Section 7.4, “Image Profiles”).patternType
: selection type for patterns, supported values are:onlyRequired
,plusRecommended
, see: The product and namedCollection element.
The following sections describes the different child elements of
a packages
group.
7.3.1 The package
element #
The package
element represents a single package to be installed (or
removed), whose name is specified via the mandatory name
attribute:
<image schemaversion="8.0" name="{exc_image_base_name}">
<!-- snip -->
<packages type="bootstrap">
<package name="udev"/>
</packages>
</image>
This adds the package udev
to the list of packages to be added to the
initial filesystem. Note, that the value that you pass via the name
attribute is passed directly to the used package manager. Thus, if the
package manager supports other means how packages can be specified, you may
pass them in this context too. For example, RPM based package managers
(like dnf
or zypper
) can install packages via their
Provides:
. This can be used to add a package that provides a certain
capability (for example, Provides: /usr/bin/my-binary
) via:
<image schemaversion="8.0" name="{exc_image_base_name}">
<!-- snip -->
<packages type="bootstrap">
<package name="/usr/bin/my-binary"/>
</packages>
</image>
Whether this works depends on the package manager and on the environment
that is being used. In the Open Build Service, certain Provides
either
are not visible or cannot be properly extracted from the KIWI NG
description. Therefore, relying on Provides
is not recommended.
Packages can also be included only on specific host architectures via the
arch
attribute. KIWI NG compares the arch
attributes value with the host
architecture that builds the image according to the output of uname -m
.
<image schemaversion="8.0" name="{exc_image_base_name}">
<!-- snip -->
<packages type="image">
<package name="grub2"/>
<package name="grub2-x86_64-efi" arch="x86_64"/>
<package name="shim" arch="x86_64"/>
</packages>
</image>
This results in grub2-x86_64-efi
and shim
being only installed if the
build host is a 64bit x86 machine, but grub2
will be installed independent
of the architecture.
7.3.2 The archive
element #
In certain situations, it is necessary to include additional packages into the
image that are not available in the package manager’s native format. KIWI NG
supports the inclusion of regular tar archives via the archive
element, whose
name
attribute specifies the filename of the archive (KIWI NG looks for the
archive in the image description folder).
<packages type="image">
<archive name="custom-program1.tgz"/>
<archive name="custom-program2.tar"/>
</packages>
KIWI NG extracts the archive into the root directory of the image using
GNU tar. This means that only archives
supported by it can be included. When multiple archive
elements are
specified then they are applied in a top to bottom order. If a file is
already present in the image, then the file from the archive overwrites
it (same as with the image overlay).
7.3.3 Uninstall System Packages #
KIWI NG supports two different methods for removing packages from the appliance:
Packages present as a child element of
<packages type="uninstall">
are gracefully uninstalled by the package manager together with dependent packages and orphaned dependencies.Packages present as a child element of
<packages type="delete">
are removed by RPM/DPKG without any dependency check, potentially breaking dependencies and compromising the underlying package database.
Both types of removals take place after config.sh
is run in the
Section 7.10.1, “The Prepare Step”
(see also Section 7.6, “User-Defined Scripts”).
An uninstall
packages request deletes:
the listed packages
the packages dependent on the listed ones
any orphaned dependency of the listed packages
Use this feature with caution as it can cause removal of required tools, leading to failures in later build stages.
Removing packages via type="uninstall"
can be used to completely remove a
build time tool (for example, a compiler), without having to specify all
dependencies of that tool (as opposed to when using
type="delete"
). Consider the following example, where we want to compile a
custom program in config.sh
. We ship its source code via an
archive
element and add the build tools (ninja
, meson
and clang
) to
<packages type="image">
and <packages type="uninstall">
:
<image schemaversion="8.0" name="{exc_image_base_name}">
<!-- snip -->
<packages type="image">
<package name="ca-certificates"/>
<package name="coreutils"/>
<package name="ninja"/>
<package name="clang"/>
<package name="meson"/>
<archive name="foo_app_sources.tar.gz"/>
</packages>
<!-- These packages will be uninstalled after running config.sh -->
<packages type="uninstall">
<package name="ninja"/>
<package name="meson"/>
<package name="clang"/>
</packages>
</image>
The tools meson
, clang
and ninja
are then available during the
Section 7.10.1, “The Prepare Step”, and they can be used in
config.sh
(for further details, see
Section 7.6, “User-Defined Scripts”), for example to build
foo_app
:
pushd /opt/src/foo_app
mkdir build
export CC=clang
meson build
cd build && ninja && ninja install
popd
The <packages type="uninstall">
element ensures that the final
appliance no longer contains the tools required to build foo_app
,
thus making the image smaller.
There are also other use cases for type="uninstall"
, especially for
specialized appliances. For containers, you can remove the package
shadow
(it is required to setup new user accounts) or any remaining
partitioning tools (parted
or fdisk
). All networking tools can be
safely uninstalled in images for embedded devices without a network
connection.
7.3.4 The product
and namedCollection
element #
KIWI NG supports the inclusion of openSUSE products or of namedCollections
(patterns in SUSE based distributions or groups for RedHat based
distributions). These can be added via the product
and namedCollection
child elements, which both take the mandatory name
attribute and the
optional arch
attribute.
product
and namedCollection
can be used to shorten the list of
packages that need to be added to the image description. A
named pattern, specified with the namedCollection element is a
representation of a predefined list of packages. Specifying a pattern
installs all packages listed in the named pattern. Support for patterns is
distribution-specific and available in SLES, openSUSE, CentOS, RHEL and
Fedora. The optional patternType
attribute on the packages element allows
you to control the installation of dependent packages. You may assign one
of the following values to the patternType
attribute:
onlyRequired
: Incorporates only patterns and packages that the specified patterns and packages require. This is a “hard dependency” only resolution.plusRecommended
: Incorporates patterns and packages that are required and recommended by the specified patterns and packages.
7.3.5 The ignore
element #
Packages can be explicitly marked to be ignored for installation inside a
packages
collection. This can be used to exclude certain packages from being
installed when using patterns with patternType="plusRecommended"
as shown
in the following example:
<image schemaversion="8.0" name="{exc_image_base_name}">
<packages type="image" patternType="plusRecommended">
<namedCollection name="network-server"/>
<package name="grub2"/>
<package name="kernel"/>
<ignore name="ejabberd"/>
<ignore name="puppet-server"/>
</packages>
</image>
Packages can be marked as ignored during the installation by adding a
ignore
child element with the mandatory name
attribute set to the
name of the package. Optionally, you can specify the architecture via
arch
, similarly to The package element.
Adding ignore
elements as children of a <packages type="delete">
or
a <packages type="uninstall">
element has no effect! The packages will
still be deleted.
7.4 Image Profiles #
A profile is a namespace for additional settings that can be applied by KIWI NG in addition to the default settings (or other profiles), making it possible to build multiple appliances with the same build type but with different configurations.
The use of profiles is advisable to distinguish image builds of the same
type but with different settings. In the following example, two virtual
machine images of the oem
type are configured: one for QEMU (using the
qcow2
format) and one for VMWare (using the vmdk
format).
<image schemaversion="8.0" name="{exc_image_base_name}">
<profiles>
<profile name="QEMU" description="virtual machine for QEMU"/>
<profile name="VMWare" description="virtual machine for VMWare"/>
</profiles>
<preferences>
<version>15.0</version>
<packagemanager>zypper</packagemanager>
</preferences>
<preferences profiles="QEMU">
<type image="oem" format="qcow2" filesystem="ext4">
</preferences>
<preferences profiles="VMWare">
<type image="oem" format="vmdk" filesystem="ext4">
</preferences>
</image>
Each profile is declared via the element profile
that must be a
child of profiles
, and it must contain the name
and description
attributes. The description
is only present for documentation purposes,
name
, on the other hand, is used to instruct KIWI NG which profile to build
via the command line. Additionally, you can provide the boolean attribute
import
, which defines whether this profile should be used by default when
KIWI NG is invoked via the command line.
A profile inherits the default settings that do not belong to any
profile. It applies only to elements that contain the profile in their
profiles
attribute. The attribute profiles
expects a comma-separated
list of profiles for which the settings of this element apply.
Profiles can furthermore inherit settings from another profile via the
requires
sub-element:
<profiles>
<profile name="VM" description="virtual machine"/>
<profile name="QEMU" description="virtual machine for QEMU">
<requires profile="VM"/>
</profile>
</profiles>
In the above example, the profile QEMU
inherit the settings from VM
.
For further details on the usage of profiles, see Section 11.19, “Building Images with Profiles”
7.5 Adding Users #
User accounts can be added or modified via the users
element that
supports a list of multiple user
child elements:
<image schemaversion="8.0" name="{exc_image_base_name}">
<users>
<user
password="this_is_soo_insecure"
home="/home/me" name="me"
groups="users" pwdformat="plain"
/>
<user
password="$1$wYJUgpM5$RXMMeASDc035eX.NbYWFl0"
home="/root" name="root" groups="root"
/>
</users>
</image>
Each user
element represents a specific added or modified user.
The following attributes are mandatory:
name
: the UNIX usernamepassword
: The password for the user account. It can be provided either in clear-text form (pwdformat="plain"
) or in encrypted form (pwdformat="encrypted"
). Using lain passwords is not advisable, as anyone with access to the image description can see the password. It is recommended to generate a hash of your password usingopenssl
as follows:$ openssl passwd -1 -salt 'xyz' YOUR_PASSWORD
Additionally, the following optional attributes can be specified:
home
: the path to the user’s home directorygroups
: A comma-separated list of UNIX groups. The first element of the list is used as the user’s primary group. The remaining elements are appended to the user’s supplementary groups. When no groups are assigned, the system’s default primary group is be used.id
: The numeric user ID of the account.pwdformat
: The format in whichpassword
is provided, eitherplain
orencrypted
(the latter is the default).
7.6 User-Defined Scripts #
Abstract
This chapter describes the purpose of the user-defined scripts
config.sh
, image.sh
, pre_disk_sync.sh
and
disk.sh
. These scripts can be used to further customize an image in
ways that are not possible via the image description alone.
KIWI NG supports the following optional scripts that it runs in a root environment (chroot) containing an appliance:
- post_bootstrap.sh
Runs at the end of the
bootstrap
phase as part of the Section 7.10.1, “The Prepare Step”. The script can be used to configure the package manager with additional settings that apply in the following chroot-based installation step which completes the installation. The script can also be used for other tasks.- config.sh
Runs at the end of the Section 7.10.1, “The Prepare Step” and after users have been set and the overlay tree directory has been applied. It is usually used to apply a permanent and final change of data in the root tree, such as modifying a package-specific config file.
- config-overlay.sh
Available only if
delta_root="true"
is set. In this case, the script runs at the end of the Section 7.10.1, “The Prepare Step” prior the umount of the overlay root tree. It runs afterconfig.sh
(if specified), and it is the last entry point to change the delta root tree.- config-host-overlay.sh
Available only if
delta_root="true"
is set. In this case, the script runs at the end of the Section 7.10.1, “The Prepare Step” prior the umount of the overlay root tree. The script is called NOT CHROOTED from the host with the image root directory as its working directory. It runs afterconfig.sh
andconfig-overlay.sh
(if any or both are specified), and it is the last entry point to change the delta root tree.- images.sh
Executed at the beginning of the Section 7.10.2, “The Create Step”. It runs in the same image root tree created by the prepare step, but it is invoked whenever an image needs to be created from that root tree. It is normally used to apply image type specific changes to the root tree, such as a modification to a config file that must be done when building a live iso, but not when building a virtual disk image.
- pre_disk_sync.sh
Executed for the disk image type
oem
only, and it runs right before the synchronization of the root tree into the disk image loop file. Thepre_disk_sync.sh
can be used to change content of the root tree as a last action before the sync to the disk image is performed. This is useful, for example, for deleting components from the system which were needed earlier or cannot be modified afterwards when syncing into a read-only filesystem.- disk.sh
Executed for the disk image type
oem
only, and it runs after the synchronization of the root tree to the disk image loop file. The chroot environment for this script call is the virtual disk itself and not the root tree. The scriptdisk.sh
is normally used to apply changes at parts of the system that are not an element of the file-based root tree, such as the partition table, the contents of the final initrd, the bootloader, filesystem attributes, etc.
KIWI NG executes scripts via the operating system if their executable bit is set (in that case, a shebang is mandatory); otherwise they are invoked via the Bash shell. If a script exits with a non-zero exit code, KIWI NG reports the failure and aborts the image creation.
7.6.1 Developing/Debugging Scripts #
Creating a custom script may require some experimenting and testing. To help
developers with this task, KIWI NG calls scripts associated with a screen
session. The connection to screen
is only done if KIWI NG is called with the
--debug
option.
In this mode, a script can be started using the following template:
# The magic bits are still not set
echo "break"
/bin/bash
Calling the script executes a screen
session executes, which gives you access
to the break in shell. You can then implement the desired script code in this
environment.. Once the shell is closed the KIWI NG process continues.
In addition to providing a fully featured terminal throughout the execution of the script code, you also have have control of the session during the process of the image creation. Listing the active sessions for script execution can be done as follows:
$ sudo screen -list
There is a screen on:
19699.pts-4.asterix (Attached)
1 Socket in /run/screens/S-root.
As shown above the screen session for executing the script code provides
extended control, which can be considered a security risk. Because of that,
KIWI NG only runs scripts through screen
when explicitly enabled via the
--debug
switch. In production, all scripts must run natively and
must not require a terminal to operate correctly.
7.6.1.1 Script Template for config.sh / images.sh #
KIWI NG provides a collection of methods and variables that offer custom actions. For details, see Functions and Variables Provided by KIWI NG. The following template shows how to import this information into a script:
#======================================
# Include functions & variables
#--------------------------------------
test -f /.kconfig && . /.kconfig
test -f /.profile && . /.profile
...
Modifications of the unpacked root tree
Keep in mind that there is only one unpacked root tree the script operates in. This means that all changes are permanent and are not automatically restored.
7.6.1.2 Functions and Variables Provided by KIWI NG #
KIWI NG creates the .kconfig
and .profile
files to be sourced
by the shell scripts config.sh
and images.sh
.
.kconfig
contains several helper functions that can be used to
simplify image configuration, while .profile
contains environment
variables populated from the settings provided in the image
description.
7.6.1.2.1 Functions #
The .kconfig
file provides a common set of functions. Functions
specific to SUSE Linux Enterprise and openSUSE start with suse
, functions
applicable to all Linux distributions start with base
.
The following list describes all functions provided by .kconfig
:
- baseSetRunlevel {value}
Set the default run level.
- baseStripAndKeep {list of info-files to keep}
Helper function for the
baseStrip*
functions that reads a list of files to check from stdin for removing params: files which should be kept.- baseStripLocales {list of locales}
Removes all locales, except for the ones given as the parameter.
- baseStripTranslations {list of translations}
Removes all translations, except those given as the parameter.
- baseStripUnusedLibs
Removes libraries that are not directly linked against applications in the bin directories.
- baseUpdateSysConfig {filename} {variable} {value}
Updates the contents of a sysconfig variable.
- baseSystemdServiceInstalled {service}
Prints the path of the first found systemd unit or mount with name passed as the first parameter.
- baseSysVServiceInstalled {service}
Prints the name
${service}
if a SysV init service with the same name is found; otherwise it prints nothing.- baseSystemdCall {service_name} {args}
Calls
systemctl ${args} ${service_name}
if a systemd unit, a systemd mount, or a SysV init service with the${service_name}
exists.- baseInsertService {servicename}
Activates the specified service via
systemctl
.- baseRemoveService {servicename}
Deactivates the specified service via
systemctl
.- baseService {servicename} {on|off}
Activates or deactivates a service via
systemctl
. The function requires the service name and the valueon
oroff
as parameters.The following example enables the sshd service on boot:
baseService sshd on
- suseInsertService {servicename}
Calls baseInsertService. It exists only for compatibility reasons.
- suseRemoveService {servicename}
Calls baseRemoveService. It exists only for compatibility reasons.
- suseService {servicename} {on|off}
Calls baseService. It exists only for compatibility reasons.
- suseSetupProduct
Creates the
/etc/products.d/baseproduct
link pointing to the product referenced either by/etc/SuSE-brand
or/etc/os-release
or the latestprod
file available in/etc/products.d
- baseVagrantSetup
Configures the image to work as a vagrant box by performing the following changes:
add the
vagrant
user to/etc/sudoers
or/etc/sudoers.d/vagrant
insert the insecure vagrant ssh key, apply recommended ssh settings and start the ssh daemon
create the default shared folder
/vagrant
- Debug {message}
Helper function to print the supplied message if the variable DEBUG is set to 1 (disabled by default).
- Echo {echo commandline}
Helper function to print a message to the controlling terminal.
- Rm {list of files}
Helper function to delete files and log the deletion.
7.6.1.2.2 Profile Environment Variables #
The .profile
environment file is created by KIWI NG and contains a
specific set of variables listed below.
- $kiwi_compressed
A value of the
compressed
attribute set in thetype
element inconfig.xml
.- $kiwi_delete
A list of all packages which are children of the
packages
element withtype="delete"
inconfig.xml
.- $kiwi_drivers
A comma-separated list of driver entries as listed in the
drivers
section ofconfig.xml
.- $kiwi_iname
The name of the image as listed in
config.xml
.- $kiwi_iversion
The image version as a string.
- $kiwi_keytable
The contents of the keytable setup as specified in
config.xml
.- $kiwi_language
The contents of the locale setup as specified in
config.xml
.- $kiwi_profiles
A comma-separated list of profiles used to build this image.
- $kiwi_timezone
The contents of the timezone setup as specified in
config.xml
.- $kiwi_type
The image type as extracted from the
type
element inconfig.xml
.
.profile.extra
If there is the file /.profile.extra
available in the initrd, KIWI NG
imports the file importing /.profile
.
7.6.1.3 Configuration Tips #
Locale configuration:
To set locale, KIWI NG relies on
systemd-firstboot
that writes the locale configuration file/etc/locale.conf
. The values for the locale settings are taken from the description XML file in the<locale>
element under<preferences>
.Keep im mind that if the build distribution does not use
/etc/locale.conf
, thesystemd-firstboot
does not have any effect on the locale settings. For example, in the SLE12 distribution,systemd-firstboot
is only effective when locales in/etc/sysconfig/language
are not set, or when the file does not exist at all. For compatibility reasons, the file/etc/sysconfig/language
in SLE12 has precedence over/etc/locale.conf
, and management tools can still usesysconfig
files for locale settings.In any case, it is possible to configure the locale setting inside the
config.sh
script in KIWI NG using in distribution-specific way, or by adding any additional configuration file as part of the overlay root-tree.Stateless systemd UUIDs:
Machine ID files (
/etc/machine-id
,/var/lib/dbus/machine-id
) may be created and set during the image package installation depending on the distribution. Those UUIDs must be unique and must be set only once in each deployment.If
/etc/machine-id
does not exist or contains the stringuninitialized
(systemd v249 and later), this triggers firstboot action in systemd, and the services are run withConditionFirstBoot=yes
. Unless the file already contains a valid machine ID, systemd generates a machine ID and write it into the file, creating it if necessary. See the machine-id man page for more details.Depending on whether firstboot action should be triggered or not,
/etc/machine-id
can be created, removed, or set touninitialized
byconfig.sh
.To prevent images from including a generated machine ID, KIWI NG clears
/etc/machine-id
if it exists and does not contain the stringuninitialized
. This only applies to images based on a dracut initrd.Noterw
is necessary if/etc/machine-id
does not exist.For systemd to be able to write
/etc/machine-id
on boot, either the file must exist (so that a bind mount can be created) or/etc
must be writable.By default, the root filesystem is mounted read-only by dracut/systemd, so a missing
/etc/machine-id
will lead to an error on boot. To force the initial mount to be read-write, add therw
option to the kernel commandline.NoteAvoid inconsistent
/var/lib/dbus/machine-id
/etc/machine-id
and/var/lib/dbus/machine-id
must contain the same unique ID. On modern systems/var/lib/dbus/machine-id
, there is already a symlink to/etc/machine-id
. However, on older systems there might be two different files. This is the case for SLE-12 based images. If you are targeting older operating systems, it is recommended to add the symlink creation intoconfig.sh
:#====================================== # Make machine-id consistent with dbus #-------------------------------------- if [ -e /var/lib/dbus/machine-id ]; then rm /var/lib/dbus/machine-id fi ln -s /etc/machine-id /var/lib/dbus/machine-id
7.7 The Runtime Configuration File #
KIWI NG supports an additional configuration file for runtime specific settings which do not belong in the image description but which are persistent and are unsuitable for command-line parameters.
The runtime configuration file must adhere to the YAML
syntax, and the file can be pointed to via the global --config
option at call
time of KIWI NG. If no config file is provided, KIWI NG searches for the runtime
configuration file in the following locations:
~/.config/kiwi/config.yml
/etc/kiwi.yml
A default runtime config file in /etc/kiwi.yml
is provided with
the python3-kiwi package. The file contains all settings as comments
including a short description of each setting.
7.8 Customizing the Boot Process #
Most Linux systems use a special boot image to control the system boot process
after BIOS or UEFI hands over control of the hardware to the operating system.
This boot image is a compressed cpio initial RAM disk, and it’s called the
initrd
. The Linux kernel loads the initrd
into the RAM and
executes init
or, if present, linuxrc
.
Depending on the image type, KIWI NG creates the boot image automatically during
the create
step. To create the initrd
, KIWI NG uses a tool called
dracut
. dracut-generated initrd archives can be extended with custom modules to
add functionality which is not natively provided by dracut itself. In the scope
of KIWI NG, the following dracut modules are used:
-
kiwi-dump
Serves as an image installer. It provides the required implementation to install a KIWI NG image on a selectable target. This module is required if one of the attributes in the image type definition
installiso
,installstick
orinstallpxe
is set totrue
.-
kiwi-dump-reboot
Serves to boot the system into the installed image after installation is completed.
-
kiwi-live
Boots up a KIWI NG live image. This module is required if the
iso
image type is selected.-
kiwi-overlay
Allows to boot disk images with the attribute
overlayroot
set totrue
. A disk like that has its root partition compressed and readonly. The disk boots up using overlayfs for the root filesystem with a separate partition on the same disk for persistent data.-
kiwi-repart
Resizes an OEM disk image after installation on the target disk to meet the size limits configured in the
oemconfig
section of the image description. The module takes over the tasks of repartitioning the disk, resizing RAID, LVM, LUKS and other layers as well as resizing the system filesystems.-
kiwi-lib
Provides common functions used by dracut modules.
Using Custom Boot Image Support
In addition to the standard dracut-based creation of the boot image, KIWI NG
supports the use of custom boot images for the image types oem
and pxe
. The use of a custom boot image is enabled by setting the
following attribute in the image description:
<type ... initrd_system="kiwi"/>
Along with this setting, you must provide a reference to
a boot image description in the boot
attribute as follows:
<type ... boot="netboot/suse-tumbleweed"/> While KIWI NG supports this approach, it is recommended using dracut instead. Keep also in mind that although KIWI NG supports creation of custom boot images, KIWI NG does not include any official boot image descriptions. You can find an OEM boot description example at https://build.opensuse.org/package/show/Virtualization:Appliances:Images:Testing_x86:tumbleweed/custom-oem-boot-description and an PXE boot description example at https://build.opensuse.org/package/show/Virtualization:Appliances:Images:Testing_x86:tumbleweed/custom-pxe-boot-description
The custom boot image descriptions makes it possible to completely customize the behavior of the initrd. This concept is mostly used in PXE environments that are usually heavily customized and require a specific boot and deployment workflow.
7.8.1 Boot Image Hook-Scripts #
The dracut initrd system uses systemd
to implement a predefined workflow
of services documented in the bootup man page:
http://man7.org/linux/man-pages/man7/dracut.bootup.7.html
To hook in a custom boot script to this workflow, it is necessary to provide a dracut module that dracut picks when KIWI NG calls it. The module files can be provided either as a package or as part of the overlay directory in the image description.
The following example shows how to include a custom hook script before the system rootfs is mounted.
Create a subdirectory for the dracut module:
$ mkdir -p root/usr/lib/dracut/modules.d/90my-module
Register the dracut module in the configuration file:
$ vi root/etc/dracut.conf.d/90-my-module.conf add_dracutmodules+=" my-module "
Create the hook script:
$ touch root/usr/lib/dracut/modules.d/90my-module/my-script.sh
Create a module setup file in
root/usr/lib/dracut/modules.d/90my-module/module-setup.sh
containing the following:#!/bin/bash # called by dracut check() { # check module integrity } # called by dracut depends() { # return list of modules depending on this one } # called by dracut installkernel() { # load required kernel modules when needed instmods _kernel_module_list_ } # called by dracut install() { declare moddir=${moddir} inst_multiple _tools_my_module_script_needs_ inst_hook pre-mount 30 "${moddir}/my-script.sh" }
Declaring Extra Tools for Hook Scripts
The install()
function called by dracut can define extra tools required by
the specified hook script. The inst_multiple
command and its parameters
instruct dracut to include these extra tools and items into the initrd.
The specified tools and items can be files. Normally, they are executables and libraries required by the hook script.
Each file must be included in the KIWI NG description either in a package, archive, or in the root tree of the image description directory.
The parameters of the
inst_multiple
command are space separated.Each parameter can be a single executable name if it exists in
/bin
,/sbin
,/usr/bin
, or/usr/sbin`
directories.Otherwise, a full path to the file is required. This normally applies for libraries and other special files.
When KIWI NG calls dracut, the 90my-module
is installed into the
generated initrd. At boot time, systemd calls the scripts as part of the
dracut-pre-mount.service
.
The dracut system offers many other possibilities to customize the initrd than shown in the example above. For more information, visit the dracut project page.
7.8.2 Boot Image Parameters #
A dracut generated initrd in a KIWI NG image build process includes one or more of the KIWI NG provided dracut modules. The following list documents the available kernel boot parameters for these modules:
-
rd.kiwi.term
Exports the TERM variable into the initrd environment. If the default value for the terminal emulation is not correct,
rd.kiwi.term
can be used to overwrite the default. The environment is also passed to the systemd unit that calls dialog based programs in KIWI NG dracut code, which means that the TERM setting applies there too.-
rd.kiwi.debug
Activates the debug log file for the KIWI NG part of the boot process in
/run/initramfs/log/boot.kiwi
.-
rd.kiwi.install.pxe
Instructs an OEM installation image to lookup the system image on a remote location specified in
rd.kiwi.install.image
.-
rd.kiwi.install.image=URI
Specifies the remote location of the system image in a PXE based OEM installation.
-
rd.kiwi.install.pass.bootparam
Instructs an OEM installation image to pass an additional boot parameters to the kernel used to boot the installed image. This can be used, for example, to pass on first boot configuration for a PXE image. Note that options starting with
rd.kiwi
are not passed to avoid side effects.-
rd.kiwi.oem.maxdisk=size[KMGT]
Specifies the maximum disk size an unattended OEM installation uses for image deployment. Unattended OEM deployments default to deploying on
/dev/sda
(or more precisely, the first device that is not filtered out byoem-device-filter
). With RAID controllers, you may have big JBOD disks along with a 480G RAID1 configured for OS deployment. Withrd.kiwi.oem.maxdisk=500G
, the deployment is performed on the RAID disk.-
rd.kiwi.oem.force_resize
Forces the disk resize process on an OEM disk image. If set, no sanity check for unpartitioned/free space is performed and also an eventually configured
<oem-resize-once>
configuration from the image description will not be taken into account. The disk resize will be started which includes re-partition as well as all steps to resize the block layers up to the filesystem holding the data. Asrd.kiwi.oem.force_resize
bypasses all sanity checks to detect if such a resize process is needed or not, it can happen that all program calls of the resize process ends without any effect if the disk is already properly resized. It’s also important to understand that the partition UUIDs will change on every resize which might be an unwanted side effect of a forced resize.-
rd.kiwi.oem.installdevice
Configures the disk device to use in an OEM installation. This overwrites or resets any other OEM device-specific settings, such as
oem-device-filter
,oem-unattended-id
orrd.kiwi.oem.maxdisk
, and continues the installation on the given device. The device must exist and must be a block special.
Non interactive mode activated by rd.kiwi.oem.installdevice
When setting rd.kiwi.oem.installdevice
explicitly through the kernel command line,
KIWI NG uses the device without prompting for confirmation.
-
rd.live.overlay.size
Specifies the size for the
tmpfs
filesystem of a live ISO image that is used for theoverlayfs
mount process. If the write area of the overlayfs mount uses this tmpfs, any new data written during the runtime of the system is written in this space. The default value is50%
, meaning half of the available RAM space can be used for writing new data.-
rd.live.overlay.persistent
Instructs a live ISO image to prepare a persistent write partition.
-
rd.live.overlay.cowfs
Specifies which filesystem of a live ISO image to use for storing data on the persistent write partition.
-
rd.live.cowfile.mbsize
Specifies the size of the COW file in MB. When using tools like
live-grub-stick
, the live ISO image is copied as a file on the target device, and a GRUB loopback setup is created there to boot the live system from the file. In this case, the persistent write setup that normally creates an extra write partition on the target will fail in most situations, because the target has no free and unpartitioned space available. To prevent this from happening, a COW file (live_system.cow) of a partition is created alongside the live ISO image file. The default size of the COW file is 500MB.-
rd.live.cowfile.path
Effectively used in isoscan loop mounted live systems. For details on this type of live system refer to Section 11.2, “Deploy ISO Image as File on a FAT32 Formated USB Stick”. Specifies the path of the COW file below the
/run/initramfs/isoscan
loop mount point. If not specified the cowfile is placed at/run/initramfs/isoscan/live_system.cow
.-
rd.live.dir
Specifies a directory that contains the live OS root directory. Default is
LiveOS
.-
rd.live.squashimg
Specifies the name of the squashfs image file which contains the OS root. Default is
squashfs.img
.-
rd.kiwi.allow_plymouth
By default kiwi stops plymouth if present and active in the initrd. Setting rd.kiwi.allow_plymouth will keep plymouth active in the initrd including all effects that might have to the available consoles.
7.8.2.1 Boot Debugging #
If the boot process encounters a fatal error, the default behavior is to stop the boot process without any possibility to interact with the system. To prevent this, activate dracut’s builtin debug mode in combination with the KIWI NG debug mode as follows:
rd.debug rd.kiwi.debug
This must be set at the kernel command line. With these parameters activated, the system enters a limited shell environment when a fatal error occurs during boot. The shell provides a basic set of tools, and it can be used for inspection using the following command:
less /run/initramfs/log/boot.kiwi
7.9 Overview #
KIWI NG builds so-called system images (a fully installed and optionally configured system in a single file) of a Linux distribution in two steps (for further details, see Image Building Process):
Prepare operation: generate an unpacked image tree of your image. The unpacked tree is a directory containing the future file system of your image, generated from your image description.
Create operation: the unpacked tree generated in step 1 is packaged into the format required for the final usage (e.g. a
qcow2
disk image to launch the image with QEMU).
KIWI NG executes these steps using the following components, which it expects to find in the description directory:
- Chapter 8, Image Description:
The
config.xml
file contains the image description, which is a collection of general settings of the final image, like the image layout installed packages, present users, etc.NoteThe filename
config.xml
is not mandatory, the image description file can also have an arbitrary name plus the*.kiwi
extension. KIWI NG first looks for aconfig.xml
file. If it cannot be found, it picks the first*.kiwi
file.- Section 7.6, “User-Defined Scripts”:
If present, custom configuration shell scripts run at different stages of the build process. They can be used to fine tune the image in ways that are not possible via the settings provided in
config.xml
.- Overlay tree directory:
The overlay tree is a folder (called
root
) or a tarball (calledroot.tar.gz
) that contains files and directories that will be copied into the unpacked image tree during the Prepare operation. The copying is executed after all the packages included inconfig.xml
have been installed. Any already present files are overwritten.- CD root user data:
For live ISO images and install ISO images an optional archive is supported. This is a tar archive matching the name
config-cdroot.tar[.compression_postfix]
.If present, the archive will be unpacked as user data on the ISO image. For example, this is used to add license files or user documentation. The documentation can then be read directly from the CD/DVD without booting from the media.
7.10 Image Building Process #
KIWI NG creates images in a two step process: The first step, the prepare
operation, generates a so-called unpacked image tree (directory) using
the information provided in the config.xml
configuration file
(see Chapter 8, Image Description)
The second step, the create operation, creates the packed image or
image in the specified format based on the unpacked image tree and the
information provided in the config.xml
configuration file.
7.10.1 The Prepare Step #
As the first step, KIWI NG creates an unpackaged image tree, also called “root tree”. This directory will be the installation target for software packages to be installed during the image creation process.
For the package installation, KIWI NG relies on the package manager specified
in the packagemanager
element in config.xml
. KIWI NG supports the
following package managers: dnf
, zypper
(default) and apt
.
The prepare step consists of the following substeps:
Create Target Root Directory
By default KIWI NG aborts with an error if the target root tree already exists to avoid accidental deletion of an existing unpacked image. The option
--allow-existing-root
can be used to work based on an existing root treeBootstrap Target Root Directory
First, KIWI NG configures the package manager to use the repositories specified in the configuration file, via the command line, or both. After the repository setup, the packages specified in the
bootstrap
section of the image description are installed in a temporary directory external to the target root tree. This establishes the initial environment to support the completion of the process in a chroot setting. At the end of thebootstrap
phase the scriptpost_bootstrap.sh
is executed, if present.NoteThe essential bootstrap packages are usually
filesystem
andglibc-locale
to specify as part of the bootstrap. The dependency chain of these two packages is usually sufficient to populate the bootstrap environment with all required software to support the installation of packages into the new root tree.Install Packages
After the
bootstrap
phase all other<packages>
sections are used to complete the installation as chroot operation. KIWI NG uses the package manager as installed in thebootstrap
phase and installs all other packages as configured.NoteThe installation of software packages through the selected package manager may install unwanted packages. Removing these packages can be accomplished by marking them for deletion in the image description, see Section 7.3.3, “Uninstall System Packages”.
Apply the Overlay Tree
Next, KIWI NG applies all files and directories present in the overlay directory named
root
or in the compressed overlayroot.tar.gz
to the target root tree. Files already present in the target root directory are overwritten. This allows you to overwrite any file that was installed by one of the packages during the installation phase.Apply Archives
All archives specified in the
archive
element of theconfig.xml
file are applied in the specified order (top to bottom) after the overlay tree copy operation is complete (see Section 7.3.2, “Thearchive
element”). Files and directories are extracted relative to the top level of the new root tree. As with the overlay tree, it is possible to overwrite files already existing in the target root tree.Execute the user-defined script
config.sh
At the end of the preparation stage the script
config.sh
is executed (if present). It is run in the top level directory of the target root tree. The script’s primary function is to complete the system configuration. For more details about custom scripts see Section 7.6, “User-Defined Scripts”Modify the Root Tree
The unpacked image tree is now finished to be converted into the final image in the create step. It is possible to make manual modifications to the unpacked tree before it is converted into the final image.
Since the unpacked image tree is just a directory, it can be modified using the standard tools. Optionally, it is also possible to “change root (
chroot
)” into it, for instance to invoke the package manager. Beside the standard file system layout, the unpacked image tree contains an additional directory named/image
that is not present in a regular system. It contains information KIWI NG requires during the create step, including a copy of theconfig.xml
file.By default, KIWI NG will not stop after the prepare step and will directly proceed with the create step. Therfore to perform manual modifications, proceed as follows:
$ kiwi-ng system prepare $ARGS $ # make your changes $ kiwi-ng system create $ARGS
WarningModifications of the unpacked root tree
Do not make any changes to the system, since they are lost when re-running the
prepare
step again. Additionally, you may introduce errors that occur during thecreate
step which are difficult to track. The recommended way to apply changes to the unpacked image directory is to change the configuration and re-run theprepare
step.
7.10.2 The Create Step #
KIWI NG creates the final image during the create step: it converts the unpacked root tree into one or multiple output files appropriate for the respective build type.
It is possible to create multiple images from the same unpacked
root tree, for example, a self installing OEM
image and a virtual machine image from the same image description. The only
prerequisite is that both image types are specified in config.xml
.
During the create step the following operations are performed by KIWI NG:
Execute the User-defined Script
images.sh
At the beginning of the image creation process the script named
images.sh
is executed (if present). For more details about custom scripts see Section 7.6, “User-Defined Scripts”Create the Requested Image Type
KIWI NG converts the unpacked root into an output format appropriate for the requested build type.