elemental

Configuration Directory Guide

The configuration directory is the place where users define the desired state of the image they intend to build by using the elemental3 customize command.

Generally, the available configuration areas that this directory supports are the following:

This document provides an overview of each configuration area, the rationale behind it and its API.

Product Release Reference

NOTE: Before reviewing this file, make sure you familiarize yourself with the release manifest concept.

One of Elemental’s key features is enabling users to base their image on a set of components that are aligned with a specific product release.

Consumers can use the release.yaml file to configure the desired product that they wish to use as base. Furthermore, they can explicitly choose which components from this product to enable based on their specific use case.

release.yaml

name: suse-product
manifestURI: file:///path/to/manifest/suse-product-manifest.yaml
# manifestURI: oci://registry.suse.com/suse-product/release-manifest:0.0.1
components:
  helm:
    - chart: foo
      valuesFile: foo.yaml
  systemd:
    - extension: bar

Operating System

Users can provide configurations related to the operating system through the install.yaml and butane.yaml files.

install.yaml

The install.yaml file enables users to configure the OS installation process by introducing the following API:

bootloader: grub
kernelCmdLine: "console=ttyS0"
raw:
  diskSize: 8G
iso:
  device: "/dev/sda"

butane.yaml

The butane.yaml optional file enables users to configure the actual operating system by allowing them to provide their own Butane configuration. During the customization processes, this will be translated into an Ignition configuration which will be included in the image and executed at first boot. The example below shows how it can be used to set up users:

version: 1.6.0
variant: fcos
passwd:
  users:
  - name: root
    # Hash for 'linux' passwd created with "openssl passwd -6"
    password_hash: "$6$dkiCjuXvS8brdFUA$w1b4wSV.0wQ7BmZ7l/Be6fhqlk8CMEE8NQkhtaXIPjMTFw90JNYfI1lBhSoUILhmqupcmOp681FHIdvIZdbc90"

Elemental does not enforce or prefer any specific Butane variant.

Check Filesystem Modes for more information on the filesystem layout and which paths are writable.

Check Elemental and Ignition Integration for further details about Ignition being used in the scope of Elemental.

[!NOTE] The inclusion of an external Butane configuration file is not considered to be a stable part of the Elemental user interface. Butane configuration could be superseded by a native Elemental declaration in the future.

Kubernetes

Users can provide Kubernetes related configurations through the cluster.yaml file within the kubernetes/ directory.

cluster.yaml

The cluster.yaml file enables users to define the Kubernetes nodes that will be created, as well as to extend the cluster with Helm charts and/or remote Kubernetes manifests by introducing the following API:

manifests:
  - https://raw.githubusercontent.com/rancher/local-path-provisioner/v0.0.31/deploy/local-path-storage.yaml
helm:
  charts:
    - name: "rancher"
      version: "2.11.1"
      targetNamespace: "cattle-system"
      repositoryName: "rancher"
      valuesFile: rancher.yaml
  repositories:
    - name: "rancher"
      url: "https://releases.rancher.com/server-charts/stable"
nodes:
- hostname: node1.example
  type: server
  init: true
- hostname: node2.example
  type: server
- hostname: node3.example
  type: server
- hostname: node4.example
  type: agent
network:
    apiVIP: 192.168.122.100
    apiHost: api.cluster01.example.com
    apiVIP6: fd12:3456:789a::21

Kubernetes Directory

The kubernetes/ directory enables users to configure custom Helm chart values and/or further extend the Kubernetes cluster with locally defined manifests.

The directory’s structure is as follows:

.
└── kubernetes
    ├── helm
    │   └── values
    │       └── rancher.yaml
    ├── manifests
    │   └── local-manifest.yaml
    └── config
        ├── agent.yaml
        └── server.yaml

Network

Network configuration can be declaratively applied through the network/ directory in one of two ways:

  1. Via nmstate configuration files.
  2. Via a user-defined network script.

NOTE: If the network/ directory is missing, the system will implicitly fall back to DHCP.

IMPORTANT: Elemental does not support mixing nmstate configuration files and a user-defined script within the same network/ directory.

Configuring the network via nmstate files

You can define your desired network state by providing nmstate configuration files, in YAML format, within the network/ directory.

These files will be processed by the NetworkManager Configurator (nmc), a CLI tool that leverages the functionality provided by the nmstate library and enables users to easily define the desired state of their network.

You can define the configurations for multiple hosts by creating files named after the hostname that would be set. Thereby allowing multiple different nodes to be spawned from the same built image, with each node self-identifying during the first boot process based on MAC address matching of the network card(s).

Examples for this type of configurations can be viewed under the examples directory — single-node setup and multi-node setup.

For more information on the nmstate library, refer to the upstream documentation.

For more information on nmc, refer to the upstream repository.

Configuring the network via a user-defined script

For use cases where configuring the network through nmstate files is not sufficient, you can define a custom script for the actual network configuration.

A script named configure-network.sh will be executed on first boot during the initrd phase:

.
├── ..
├── kubernetes/
└── network/
    └── configure-network.sh

NOTE: If available, the default network is set up before the configure-network.sh runs. This ensures that the script is able to retrieve relevant configurations also from remote locations.

IMPORTANT: The configure-network.sh script will run in a restricted environment. To apply the desired network state, you must provide your configurations through a set of helper tools available to the configure-network.sh script during execution. For a complete list of the available tools, see the Helper tools section.

Helper tools

This section lists the tools that are available to the configure-network.sh script during its execution.

NetworkManager Configurator

The NetworkManager Configurator (nmc) is available for the configure-network.sh script. You can retrieve your nmstate configuration files in whatever way best suits your use case, and then use nmc to generate and apply the desired network state.

configure-network.sh example:

#!/bin/bash
...
mkdir desired-states
curl -L -o desired-states/my.host.yaml https://example.com/my.host.yaml

mkdir generated
nmc generate --config-dir desired-states --output-dir generated
nmc apply --config-dir generated
set_conf_d

You can call the set_conf_d shell function to apply configuration snippets into NetworkManager’s conf.d directory. It accepts either multiple files or a single directory as arguments.

configure-network.sh example:

#!/bin/bash
...
mkdir configs
curl -L -o configs/foo.conf https://example.com/foo.conf
curl -L -o configs/bar.conf https://example.com/bar.conf

# example: passing a directory
set_conf_d "configs/"

# example: passing multiple files
set_conf_d "configs/foo.conf" "configs/bar.conf"
set_dispatcher_d

You can call the set_dispatcher_d shell function to set dispatcher scripts in the NetworkManager’s dispatcher.d directory. It accepts either multiple files or a single directory as arguments.

configure-network.sh example:

#!/bin/bash
...
mkdir dispatchers
curl -L -o dispatchers/foo.sh https://example.com/foo.sh
curl -L -o dispatchers/bar.sh https://example.com/bar.sh

# example: passing a directory
set_dispatcher_d "dispatchers/"

# example: passing multiple files
set_dispatcher_d "dispatchers/foo.sh" "dispatchers/bar.sh"
set_sys_conn

You can call the set_sys_conn shell function to set network connection profiles in the NetworkManager’s system-connections directory. It accepts either multiple files or a single directory as arguments.

IMPORTANT: Using both set_sys_conn and nmc to configure the network connection profiles may result in unexpected behaviour. Consider using one or the other depending on your use case.

configure-network.sh example:

#!/bin/bash
...
mkdir sys-conns
curl -L -o sys-conns/foo.nmconnection https://example.com/foo.nmconnection
curl -L -o sys-conns/bar.nmconnection https://example.com/bar.nmconnection

# example: passing a directory
set_sys_conn "sys-conns/"

# example: passing multiple files
set_sys_conn "sys-conns/foo.nmconnection" "sys-conns/bar.nmconnection"
set_hostname

You can call the set_hostname shell function to set the node’s hostname. It accepts a single string literal as an argument.

configure-network.sh example:

#!/bin/bash
...
set_hostname "myhostname"
disable_wired_conn

You can call the disable_wired_conn shell function to remove any existing wired connections and configure no-auto-default=* in the NetworkManager’s conf.d directory.

configure-network.sh example:

#!/bin/bash
...
disable_wired_conn

Custom Scripts

Elemental can bundle in custom scripts that will be executed during the firstboot phase of provisioning a system. Additionally, these scripts may require the availability of particular local files which can be embedded into the configuration partition too.

These scripts are executed alphabetically. It is suggested to use a numbered prefix within the 50–99 range (e.g. 60-my-script.sh). Elemental may leverage the values in the 00–49 range in the future, so unless necessary, those should be avoided.

Finally, if any of the provided scripts or files is needed beyond the firstboot phase, a script should be included that explicitly copies them to the filesystem.

.
├── ...
└── custom
    ├── files
    │   ├── custom-binary
    │   ├── subdirectory
    │   │   └── some-file.txt
    │   └── custom-script.sh
    └── scripts
        └── 70-manual-configuration.sh

Note that attempting to write to read-only directories (e.g., /usr) from a custom script will fail. Check Filesystem Modes for more information on the filesystem layout and which paths are writable.

It is crucial to perform cleanup (unmounting) in every script that involves mounting a specific path.