Fleet organization patterns
When most device configuration is shared across device types, regions, or deployment stages, you can compose layered configuration within a single fleet definition instead of duplicating fleets for each variation.
Layered gitRef composition Copy linkLink copied!
A fleet’s template spec contains a spec.config list that can hold multiple gitRef entries, each pointing to a different directory in a Git repository.
Entries are applied in list order.
When two entries write the same file path, the entry that appears later in the list takes precedence.
This composition model lets you structure configuration as layers:
- A base layer with configuration shared by all devices in the fleet.
- One or more override layers that vary by device label, such as region, device type, or deployment stage.
The following fleet template shows a base layer and a region-specific override layer:
spec:
config:
- name: base-config
gitRef:
repository: site-settings
targetRevision: main
path: /config/base
- name: region-config
gitRef:
repository: site-settings
targetRevision: main
path: /config/regions/{{ .metadata.labels.region }}
The base-config entry delivers files shared by every device.
The region-config entry uses a template placeholder to resolve a region-specific directory per device.
A device labeled region: eu-west receives files from /config/regions/eu-west, while a device labeled region: us-east receives files from /config/regions/us-east.
Config entry ordering Copy linkLink copied!
Entries in spec.config are applied in the order they appear in the list.
If two entries write a file to the same path on the device, the last entry in the list takes precedence.
Place override layers after the base layer so that their files replace the base versions.
This ordering rule applies regardless of the provider type.
A gitRef entry at position three overrides a conflicting file from an httpRef entry at position two.
Combining multiple provider types Copy linkLink copied!
A fleet template is not limited to gitRef entries.
You can combine different provider types in a single spec.config list:
-
gitRef - Version-controlled configuration files stored in a Git repository.
-
httpRef - Dynamically generated configuration retrieved from HTTP endpoints.
-
secretRef - Kubernetes secrets containing credentials or certificates.
-
inline - Small configuration snippets defined directly in the fleet specification.
Template placeholders work in all provider types.
For example, you can use {{ .metadata.labels.site }} in a secretRef name to deliver site-specific credentials to each device based on its site label.
Using getOrDefault for optional overrides Copy linkLink copied!
When a template placeholder references a device label that a device does not have, the placeholder silently produces an empty string.
A bare placeholder such as {{ .metadata.labels.nonexistent }} resolves to an empty string without raising an error.
This can cause devices to receive empty paths or configuration values without any warning.
Always use getOrDefault for labels that might not be present on every device.
Use the getOrDefault function to provide a meaningful fallback value instead of an empty string:
path: /config/overrides/{{ getOrDefault .metadata.labels "variant" "default" }}
Devices with a variant label receive the configuration directory that matches their label value.
Devices without the variant label receive the default directory instead.
Git repository structure Copy linkLink copied!
Organizing your Git repository with a clear directory hierarchy makes the layered composition pattern easier to maintain. The following layout separates base configuration from region-specific and device-type-specific overrides:
site-settings/
config/
base/
motd.conf
ntp.conf
regions/
eu-west/
ntp.conf
us-east/
ntp.conf
types/
pos-terminal/
app.conf
kiosk/
app.conf
Each fleet template entry points to a directory at the appropriate level.
The base layer points to config/base/, a region override points to config/regions/{{ .metadata.labels.region }}, and a device-type override points to config/types/{{ .metadata.labels.type }}.
Files in an override directory replace files from the base layer only when both layers write to the same file path; all other base files remain unchanged.
Template placeholder functions and expressions Copy linkLink copied!
Template placeholders support variable substitution and the upper, lower, replace, and getOrDefault functions.
You can chain these functions in pipelines, for example {{ getOrDefault .metadata.labels "key" "default" | upper }}.
Template placeholders also support conditional expressions using if, else, else if, and with blocks, along with the comparison functions eq, ne, lt, gt, le, ge, and, or, and not.
Loops (range) are not supported in template placeholders.
Inside a with block, dot (.) is rebound to the value of the with expression.
Use $ to access root-level fields such as {{ $.metadata.name }} or {{ $.metadata.labels.key }}.
Without the $ prefix, field references resolve against the rebound context and fail server-side validation.