Automated
To automate Kairos installation, you can configure a specific portion of the installation configuration file. The configuration file can then be supplied in a few different ways, such as creating an additional ISO to mount, specifying a URL, or even creating an ISO from a container image with an embedded configuration file.
Here's an example of how you might customize the install block:
install:
# Device for automated installs
device: "/dev/sda"
# Reboot after installation
reboot: true
# Power off after installation
poweroff: true
# Set to true to enable automated installations
auto: true
# A list of bundles
bundles:
- quay.io/kairos/packages:k9s-utils-0.26.7
This block allows you to specify the device on which to install Kairos, whether to reboot or power off after installation, and which bundles to include.
Data source​
To supply your Kairos configuration file, you can create an ISO that contains both a user-data file (which contains your configuration) and a meta-data file.
Here's an example user-data configuration that is set up to automatically install Kairos onto /dev/sda and reboot after installation:
#cloud-config
install:
device: "/dev/sda"
reboot: true
poweroff: false
auto: true # Required, for automated installations
p2p:
network_token: ....
# extra configuration
The token p2p.network_token is a base64 encoded string which
contains an edgevpn token. For more information, check out the architecture section.
Save this file as cloud_init.yaml, then create an ISO with the following steps:
- Create a new directory and navigate to it:
$ mkdir -p build
$ cd build
- Create empty
meta-dataand copy your config asuser-data:
$ touch meta-data
$ cp -rfv cloud_init.yaml user-data
- Use
mkisofsto create the ISO file:
$ mkisofs -output ci.iso -volid cidata -joliet -rock user-data meta-data
Once the ISO is created, you can attach it to your machine and boot up as usual, along with the Kairos ISO.
For security reasons, when Kairos is installed in trusted boot mode, datasources are not parsed after installation. This prevents someone from plugging a usb stick on an edge device, applying arbitrary configuration to the system post-installation. To force parsing of the datasources after installation, you can set add the kairos.pull_datasources option to the cmdline. This requires extending the cmdline when building the installation medium with AuroraBoot (read more).
This security feature is only enabled when the system boots in trusted boot mode and only after installation (they are parsed in "live" mode). On "plain" boot mode, datasources are always parsed.
Via config URL​
Another way to supply your Kairos configuration file is to specify a URL as a boot argument during startup. To do this, add config_url=<URL> as a boot argument. This will allow the machine to download your configuration from the specified URL and perform the installation using the provided settings.
After installation, the configuration will be available on the system at /oem/90_custom.yaml.
If you're not sure where to host your configuration file, a common option is to upload it as a GitHub gist.
Templated URLs​
The config_url value is rendered as a Go template before the fetch, so per-machine identifiers can be embedded in the URL itself. This is convenient for discovery services that return a different cloud-config per host.
Example: register the machine with a discovery service using its SMBIOS UUID and primary MAC address.
#cloud-config
config_url: "http://discover.example.com/register?uuid={{ .Values.product.uuid }}&mac={{ (index .Values.network 0).macaddress }}"
Values come from the same sysinfo-based context that yip already exposes to cloud-config stages under {{ .Values.* }}. The fields most commonly useful for URL templating are:
| Variable | Description |
|---|---|
{{ .Values.product.uuid }} | SMBIOS product UUID |
{{ .Values.product.serial }} | SMBIOS product serial number |
{{ (index .Values.network 0).macaddress }} | MAC of the first sysinfo-enumerated network interface (virtual ones skipped) |
{{ .Values.node.hostname }} | Machine hostname |
{{ .Values.os.architecture }} | CPU architecture |
{{ .Values.Random }} | 32-character random string, freshly generated on each render. Useful as a cache-buster or one-shot nonce. |
{{ .Values.ProtectedID }} | HMAC-SHA256 of the host's machine-id (from /etc/machine-id), keyed with an app-specific string. Stable across reboots, unique per machine, and not reversible to the raw machine-id. Useful as an anonymized per-machine identifier for discovery-service registration when you do not want to expose SMBIOS UUID, MAC, or the raw machine-id. |
The full sysinfo.SysInfo tree from zcalusic/sysinfo is available; consult the upstream sample output for the complete field list. Sprig functions can also be applied, for example {{ .Values.product.uuid | lower }}.
Rendering semantics:
- Substituted scalar values are URL-encoded, so characters like
+, spaces, or&in a field value cannot corrupt query strings. - Undefined fields fail loudly: referencing a name that does not exist in the context aborts the boot rather than fetching a mangled URL.
- Fields that resolve to an empty string are not rejected automatically. The user may have intended empty (through a pipe, conditional, or
default). To require a non-empty value, wrap the field with the Helm-stylerequiredhelper:
#cloud-config
config_url: "http://discover.example.com/register?uuid={{ required \"uuid is required for discovery\" .Values.product.uuid }}"
- Templating runs on every cmdline-driven or config-file-driven fetch: the initramfs stage handled by immucore,
kairos-agent start/install/upgrade/reset, and everycos-setup-*stage.
The same variable set is available in the rest of the cloud-config; see Using templates for details.
ISO remastering​
It is possible to create custom ISOs with an embedded cloud configuration. This allows the machine to automatically boot with a pre-specified configuration file, which will be installed on the system after provisioning is complete. See also AuroraBoot for documentation.
Locally​
To create a custom ISO, you will need Docker installed on your machine.
Here's an example of how you might do this:
The image passed to the auroraboot image, needs to have one of the accepted schemes: docker, oci, file, dir or channel.
If you don't pass one, we will make an attempt to read it as a web URL but depending on your URL this might throw an error.
- AuroraBoot
- Manually
We can use AuroraBoot to handle the the ISO build process, for example:
$ IMAGE=<scheme://host[:port]/path[:tag]>
$ docker pull $IMAGE
# Build the ISO
$ docker run -v $PWD/cloud_init.yaml:/cloud_init.yaml \
-v $PWD/build:/tmp/auroraboot \
-v /var/run/docker.sock:/var/run/docker.sock \
--rm -ti quay.io/kairos/auroraboot \
--set container_image=oci:$IMAGE \
--set "disable_http_server=true" \
--set "disable_netboot=true" \
--cloud-config /cloud_init.yaml \
--set "state_dir=/tmp/auroraboot"
# Artifacts are under build/
$ sudo ls -liah build/iso
total 778M
34648528 drwx------ 2 root root 4.0K Feb 8 16:39 .
34648526 drwxr-xr-x 5 root root 4.0K Feb 8 16:38 ..
34648529 -rw-r--r-- 1 root root 253 Feb 8 16:38 config.yaml
34649370 -rw-r--r-- 1 root root 389M Feb 8 16:38 kairos.iso
34649371 -rw-r--r-- 1 root root 76 Feb 8 16:39 kairos.iso.sha256
$ IMAGE=<scheme://host[:port]/path[:tag]>
$ mkdir -p files-iso/boot/grub2
# You can replace this step with your own grub config. This GRUB configuration is the boot menu of the ISO
$ wget https://raw.githubusercontent.com/kairos-io/packages/main/packages/livecd/grub2/config/grub_live_bios.cfg -O files-iso/boot/grub2/grub.cfg
# Copy the config file
$ cp -rfv cloud_init.yaml files-iso/cloud_config.yaml
# Pull the image locally
$ docker pull $IMAGE
# Optionally, modify the image here!
# docker run --entrypoint /bin/bash --name changes -ti $IMAGE
# docker commit changes $IMAGE
# Build an ISO with $IMAGE
$ docker run -v $PWD:/cOS -v /var/run/docker.sock:/var/run/docker.sock -i --rm quay.io/kairos/auroraboot:v0.24.0 --debug build-iso --name "custom-iso" --date=false --overlay-iso /cOS/files-iso --output /cOS/ $IMAGE
In the case of Auroraboot, make sure that the cloud config that you are mounting in the container (-v $PWD/cloud_init.yaml:/cloud_init.yaml) exists. Otherwise docker will create an empty directory to mount it on the container without any warnings and you will end up with an empty cloud config.
This will create a new ISO with your specified cloud configuration embedded in it. You can then use this ISO to boot your machine and automatically install Kairos with your desired settings.
You can as well modify the image in this step and add additional packages before deployment. See customizing the system image.
Check out the AuroraBoot documentation and the examples for learn more on how to generate customized images for installation.
Kubernetes​
It is possible to create custom ISOs and derivatives using extended Kubernetes API resources with an embedded configuration file. This allows you to drive automated installations and customize the container image without breaking the concept of immutability.
You can read more about it here.