Skip to content

Overview

What is configuration management?

Configuration management involves the process of maintaining and controlling the settings, software, parameters, and overall setup of hardware devices such as computers, servers, routers, switches, and any IoT device. It ensures that these devices are configured according to predefined standards and policies, allowing for consistency, reliability, and efficient operation no matter how large or distributed a fleet is. Configuration management typically involves tasks such as initial setup, OTA software updates, ongoing monitoring, updating configurations, and enforcing security policies.

How is configuration management implemented in this solution?

In this solution the agent is implemented as a pull-based configuration management tool, ensuring your devices always converge to the defined state or display an error message. The local qbee agent regularly queries the centralized server for new configuration information. If there is none available, it checks if the device complies with the current state and goes back to sleep. However, if new configuration information is available, the agent downloads it and converges towards the new configuration. This approach offers several benefits, such as allowing the agent to operate and maintain configuration even if the network is down. Additionally, any devices added later to a group or tag, such as spare parts or replacements, will always receive the latest configuration, including the latest SSH keys, software and user definitions.

Quick facts about the configuration management

  • configuration changes are distributed to devices only after they are explicitly committed

  • our configuration management works pull and state based

  • it will take at least until the next connect interval to receive a new configuration for the agent

  • the agent will report success when changes are made on a device, or an error if it cannot reach desired state

  • the agent maintains its defined state. If a managed password or firewall setting is changed manually on the device the local agent will revert it in the next run (and send a log message about this). This is also true for files that are played out.

  • when the agent cannot converge to its desired state (for example due to conflicting setup), an error message is writted to the device log (for example a file is played out that does not have correct access rights, or a process should be started that does not exist)

  • this mechanism allows updates to a large number of devices in a very short time. It takes 5 minutes (or one agent interval) to update one device. It also takes just 5 minutes to update thousands of devices.

Concepts

In this document, we will operate on the following concepts:

  1. Node represents a group or a device.
  2. Entity represents a node or tag.
  3. Bundle is a configuration representing a specific aspect of system configuration (e.g. files, users, firewall, packages, etc.). There can be only one bundle of each type defined per entity.
  4. Configuration Change defines a new state for a bundle (e.g. add a user, change a file, etc.) for a specific Entity.
  5. Configuration Commit is a set of configuration changes that are approved to be applied to the system.
  6. Active Configuration is the currently committed configuration applied to the system for a specific Entity.

Configuration structure

Configuration changes are made on a bundle level for a specific entity. For example, to define a file distribution for a group of devices, one can either create a file distribution bundle change for a group node or for a tag. Once all changes are made, the configuration needs to be committed to become active. This mechanism allows to group several configuration changes into an atomic unit, which activates them all at once.

Overriding existing bundles

If an entity already has a bundle defined, creating a new change for the same entity and bundle combination, will override the previous configuration once the committ is performed. Since committs cannot be undone (they are immutable), in order to restore previous state of the configuration one needs to apply the old changes on top of the active configuration manually.

Configuration UI

Configuration UI

In general, all the different configuration bundles are in the menu structure on the left. Bundles work with color codes:

  • dark green: active on this level
  • light green: disabled on this level
  • grey: current bundle, if not saved
  • yellow dot: changes but not yet committed

In this example the group "Hardware" is configured. This can be seen in the breadcrumb trail on the top-left corner.

  • Enabled: this switch enables the configuration.
  • Extend: if "extend" is selected the configuration gets extended.

There are additional buttons which are defined here:

  • Commit Changes: this button is red now, because current changes are not committed. It is used to make the changes active and will then turn gray again.
  • Revert: revert will undo the last changes.
  • Save settings: saves current settings.
  • Delete configuration: will delete configuration.
  • +: add additional file distributions.

It is possible to switch between graphical representation and JSON.

  • Form: show the UI to configure the bundle
  • JSON: show the JSON representation. Use this for import/export and to manually change configuration.
  • Preview: This shows all config applied to entity. Highly useful for debugging.

Inheritance

Devices' configuration doesn't have to be set for each device separately, as the platform allows to apply configuration to groups and tags which then will be inherited by devices. The inheritance rules are simple: "top-to-bottom, left-to-right", which means that we look at the nodes from the root (top) to the device (bottom) and order of tags applied to each node from left to right. Let's consider the following device fleet structure to aid with further explanations:

[ All devices ]
    |
    +-> [ Group: Group_1 (Tag_1) ]
    |     |
    |     +-> [ Device: Device_1 (Tag_2) (Tag_3) ]
    |     +-> [ Device: Device_2 ]
    |
    +-> [ Group: Group_2 ]
          |
          +-> [ Device: Device_3 (Tag_2) ]

Inheritance paths for our devices would then be:

Device_1: All devices > Tag_1 > Group_1 > Tag_2 > Tag_3 > Device_1
Device_2: All devices > Tag_1 > Group_1 > Device_2
Device_3: All devices > Group_2 > Tag_2 > Device_3

This mean that Device_1 would receive configuration from All devices, Tag_1, Group_1, Tag_2, Tag_3 and Device_1 in that order. If Tag_1 had defined a file distribution bundle with FileSet1 and Tag_2 would have defined a file distribution bundle with FileSet2, Device_1 would receive both FileSet1 and FileSet2 (applied in the order of inheritance).

Bundle are independent of each other

Definining two different bundle types can be done on different levels independently. We follow inheritance rules on per-bundle basis, so defining configuration for file distribution and users on group G1, and users configuration on tag T2, would result in the device D1 receiving the file distribution defined on group G1, but the users defined on tag T2.

Verifying current configuration

At any time you can check your current device configuration by pressing the "Preview" button in any of the configuration items.

Configuration preview

This will give a full overview of the current configuration as a json file for the specific device. If you debug configuration it makes sense to check here to see what configuration is sent to the device.

Extending parent configuration

Certain bundle configurations can extend parent configuration. For example, we can define file distribution on a group level and supplement those files with device specific files. In order to do that, we need to set the "Extend" flag for the bundle on the lower level (device in this case).

For example, if we have the following configuration bundles committed:

node: G1
bundle: file_distribution
config:
  - enabled: true
  - file set 1

and

node: D1
bundle: file_distribution
config:
  - enabled: true
    - extend: true
  - file set 2

Device D1 will then receive the following active config:

bundles: [file_distribution]
config:
  file_distribution:
    - file set 1
    - file set 2

Disabling parent configuration

If we want to exclude certain configuration bundles from a device, we can do that be creating a configuration with "Enabled" flag disabled on the device (or any entity). That will result in the device not receiving this bundle at all, even if ancestor groups or tags have it configured.

Importing and exporting configuration

It is possible to import and export configurations. Either to keep track of those or to migrate settings between different branches of the tree. Please click in "JSON" in the configuration form. This shows the current configuration as a JSON file and here it is possible to import and export settings. You can also edit the JSON directly, but only correct JSON content is considered. If you want to overwrite then you can "clear area" and copy in the new JSON (for example the file that you have previously exported). Pressing the "Import settings" button will then turn it active.

Deleting a configuration

Once configuration is no longer needed, it can be deleted by clicking on the "Delete configuration" button on the bottom of the form. Deleted configuration won't be inherited and none of the devices will receive it.