Mixing refers to composing an operating system for specific use cases. While the default Clear Linux* OS for Intel® Architecture provides options to install bundles for various server capabilities, some developers may wish to 1) augment the operating system itself with functionality from their own packages or 2) modify the structure of current bundles to cater to their particular needs.


To start working with the Mixer tools, you’ll need a recent image of Clear Linux OS for Intel Architecture with the following bundle installed. If you don’t have it already, you can add it with the swupd bundle-add command like so:

# swupd bundle-add mixer

Current Workflow


  1. Create a workspace. Create an empty directory in your Clear image to use as a “workspace” for mixing. For these steps, we assume your workspace location is /home/clr/mix.

  2. Configure builder.conf. Copy the template conf file

    # cp /usr/share/defaults/bundle-chroot-builder/builder.conf /home/clr/mix/

    The file builder.conf will be read automatically from the current workspace directory, but the -config option exists to specify where the file is if you want to store it elsewhere. To use one in your current workspace, copy the template to /home/clr/mix. The .yum-mix.conf file will be auto-generated for you, as will the Swupd_Root.pem. A yum configuration is needed for the chroot-builder to know where the RPMs are hosted, and the certificate file is needed to sign the root Manifest to provide security for content verification.

    Note there are different sections to the builder.conf. The [Builder] section provides the mixer tools with required configuration options, defining where generated bundles and update metadata should get published. The [swupd] section is used by swupd-server to create an update with specific update parameters.

    Edit the template configuration file according to your needs. For this example, your builder.conf should look like this, with both URL variables set to the domain or IP of the update server:

    # vim /etc/bundle-chroot-builder/builder.conf:
    CONTENTURL=<URL where the content will be hosted>
    VERSIONURL=<URL where the version of the mix will be hosted>

    The SERVER_STATE_DIR is where the mix content will be outputted to, and it is automatically created for you by the mixer. This can be set to any location, but for this example let’s use the workspace directory. The same applies for BUNDLE_DIR; it will be generated for you in the location specified in the builder.conf, in this case /home/clr/mix/mix-bundles. This is where the bundle definitions are stored for your mix, and it’s where the chroot-builder looks to know what bundles must be installed.

    You may change the CERT=/path/to/cert line, which tells the chroot builder to insert the certificate specified for the mix in /os-core- update/usr/share/clear/update-ca/. This is the certificate used by the software update client to verify the Manifest.MoM signature. For now, it is HIGHLY recommended that you do not modify this line, as the certificate swupd expects needs a very specific configuration to sign and verify properly. The certificate will be automatically generated for you, and the Manifest.MoM will be signed automatically as well, providing security for the update content you create.

    The CONTENTURL and VERSIONURL may be an IP address, or a domain name, which hosts the /home/clr/mix/update/www (SERVER_STATE_DIR) directory. Creating a symlink to the directory in your server webdir is an easy way to host the content. A client running the mix will look to that URL to figure out if there is a new version available and the location from which to download the update content.

    To learn more about the FORMAT option, please refer to the bottom of this document “Format Version” and https://github.com/clearlinux/swupd-server/wiki/Format-Bumps. For now leave the FORMAT value alone and do not increment it.

    The mix version and Clear version will come from two state files: .mixversion and .clearversion, both of which will be created for you when you set-up the workspace and added to the VERSIONS_PATH defined.

  3. Generate the starting point for your Mix. In your workspace, run:

    # sudo mixer init-mix -clearver 13180 -mixver 10

    If you wish to just build a mix that includes all Clear bundles with no modifications, run:

    # sudo mixer init-mix -all -clearver 13180 -mixver 10
  4. Create/locate RPMs for mix.. (Steps 4-6 are necessary only if you want to add your own RPMs to the Mix. If you are working only with Clear bundles, then skip to Step 7.)

    If you are creating RPMs from scratch, you may use autospec, mock, rpmbuild, etc. to build them. If they are not built on Clear, make sure your configuration and toolchain builds them correctly for Clear, or there is no guarantee they will be compatible.

  5. Import RPMs into workspace. The way to do this is to create an rpms directory in your workspace (for example /home/clr/mix/rpms), and to copy the RPMs you want into that directory. The mixer script will look here for RPMs in order to build a local RPM repo for yum to use.

  6. Create a local RPM repo. Create an empty directory in your workspace named local and add the paths in your builder.conf:

    These variables are automatically read; you simply need to run::
      # sudo mixer add-rpms

    After the script exits, you should see your RPMs and a repodata directory in /home/clr/mix/local. If the RPMs are not all in the local directory, check to make sure that they are indeed valid RPM files and not corrupt.

  7. Update/Add bundle definitions. The mixer uses a local clone of the clr-bundles repo to define bundles for the mix.

    To define your bundles:

    1. Navigate to the mix-bundles/ directory.

    2. Make any needed modifications to the bundle set.

    3. Commit the result:

      $ git add .
      $ git commit -s -m 'Update bundles for mix #<VER>'

    You can easily copy bundles over from the clr-bundles/clr-bundles-VER/bundles/ directory in the case that you want to simply use existing bundle sets. Note that mix-bundles should not have any folders inside of it, only bundle definitions.

    Do not modify things in the clr-bundles dir, this is simply a mirror for you to use or refer to the Clear Linux OS bundle definitions.

    Why do this? With Git history, mixes are easy to revert to or refer to in the future if something were to go wrong with a new mix. If you’re just testing this out, or if you really do not want to mess with Git, you can ignore committing for now.

    To add your own bundle, create a bundle definition file in mix-bundles/ and refer to mix-bundles/os-core-update for formatting, but be sure that the name does not conflict with another bundle. Add your package name(s) in that bundle definition file to tell it what package(s) must be installed as part of that bundle.

  8. Build the bundle chroots To build all of the chroots that are based on the bundles you defined, in your workspace run:

    # sudo mixer build-chroots

    If you have many bundles defined for your mix, this step may take some time.

  9. Create update. In the workspace, run:

    # sudo mixer build-update

    When the build completes, you’ll find your mix update content under /home/clr/mix/update/www/VER. In this example, it will be located in /home/clr/mix/update/www/<MIXVERSION>, where <MIXVERSION> is the mix version you defined, or 10 by default.

    All content to make a fully usable mix will be created by this step, but note that only zero packs are automatically generated. To create optional delta packs, run the pack-maker as follows:

    # sudo mixer-pack-maker.sh --to <MIX_VERSION> --from <PAST_VERSION> -S /home/clr/mix/update

    The pack-maker will generate all delta packs for changed bundles from PAST_VERSION to MIX_VERSION. If your STATE_DIR is in a different location be sure to specify where with the -S option. For the first build, no delta packs can be created because the “update” is from version 0, which impicitly has no content, thus no deltas can be generated. For subsequent builds, mixer-pack-maker.sh can be run to generate delta content between them (i.e 10 to 20).

  10. Creating an image To create a bootable image from your update content, you will need the configuration file for ister to create images:

    # curl -O https://raw.githubusercontent.com/bryteise/ister/master/release-image-config.json

    Edit this to include all the bundles you want pre-installed into your image. For a minimal, base image this would be:

    "Bundles": ["os-core", "os-core-update", "kernel-native"]

    And lastly, set the “Version:” to say which mix version content the image should be built from, i.e. 10 for your first build. To build the image, run:

    # sudo mixer build-image -format 1

    The output from this should be an image that is bootable as a VM or installable to baremetal.


    You need to pass in -format <FORMAT_NUMBER> if the format you are building is different than the format of Clear Linux OS you are currently building on. Format version can be found via

    # cat /usr/share/defaults/swupd/format

Creating your next Mix version

  1. Initialize next Mix version info. To update the versions and prep for your next mix:

    Update the .mixversion file to the next version number you want to build. From this point you can iterate through, starting again at step 4 and doing modifications as needed. For example:

    • Add/Remove/Modify Bundles
    • sudo mixer build-chroots
    • sudo mixer build-update
    • (Optionally) sudo mixer-pack-maker.sh –to <NEWVERSION> –from <PREV_VERSION> -S /home/clr/mix/update
  2. Update Bundles (Optional). Update clr-bundles. In the workspace, run:

    # sudo mixer get-bundles

    This step is optional because it is only needed when you want to update the upstream clr-bundles in your workspace to a new version, which requires updating the .clearversion file.

Format Version

The “format” used in builder.conf might be more precisely referred to as an OS “compatibility epoch”. Versions of the OS within a given epoch are fully compatible with themselves and can update to any version in that epoch. Across the format boundary something has changed in the OS, such that updating from build M in format X, to build N in format Y will not work. Generally this occurs when the software updater or manifests changed in a way that is no longer compatible with the previous update scheme.

A format increment is the way we insure pre- and co-requisite changes flow out with proper ordering. The update client will only ever update to the latest release in its respective format version (unless overridden by command line flags), thus we can guarantee all clients will update to the final version in their given format, which must contain all the changes needed to understand the content built in the following format. Only after reaching the final release in the old format will a client be able to continue to update to releases in the new format.

For the creation of a custom mix, the format version should start at ‘1’, or some known number, and increment only when a compatibility breakage is introduced. Normal updates (updating a software package for example) do not require a format increment.