This feature is still experimental and will change in the future.
Exports are a mechanism for services to share structured data.
They provide a way for different machines and service instances to discover and access information they need from each other,
Exports are useful when you need to:
Examples:
Exports use a scope-based system to publish data. Each export is tagged with a scope that identifies its source:
Scope levels:
Exports are stored internally using scope keys, therefore you should always use the clanLib helper functions to work with them.
The internal format is subject to change.
To export data from your service, use the mkExports helper function available in the perInstance or perMachine context:
{ clanLib, ... }: {
roles.peer = {
perInstance = { instanceName, mkExports, roles, ... }: {
exports = mkExports {
# Your exported data here
peer.host.plain = "192.192.192.12";
};
nixosModule = { ... }: {
};
};
};
} The mkExports function automatically creates the appropriate scope for your exports based on the current service, instance, role, and machine context.
Within your service module, you can access exports using the clanLib.exports helper functions.
selectExports - Query Multiple ExportsGet all exports matching specific criteria
{ exports, clanLib, ... }: {
perInstance = { ... }: {
nixosModule = { ... }: {
# Get all exports from the "vpn" service
vpnConfigs = clanLib.selectExports
{ service = "vpn"; }
exports;
};
};
} Query parameters (all optional, default to wildcard "*"):
service - Filter by service nameinstance - Filter by instance namerole - Filter by role namemachine - Filter by machine nameReturns an attribute set where keys are scope identifiers and values are the exported data.
clanLib provides several helper functions for working with exports:
buildScopeKeyBuild a scope key string from components:
clanLib.buildScopeKey {
serviceName = "myservice";
instanceName = "prod";
roleName = "server";
machineName = "backend01";
}
# => "myservice:prod:server:backend01" (internal information) parseScopeParse a scope string into its components:
clanLib.parseScope "myservice:prod:server:backend01"
# => {
# serviceName = "myservice";
# instanceName = "prod";
# roleName = "server";
# machineName = "backend01";
# } getExportRetrieve a single export by scope:
clanLib.getExport
{ serviceName = "myservice"; machineName = "backend01"; }
exports
# => <some data> selectExportsFilter exports matching specific criteria:
# Get all exports for a specific service
clanLib.selectExports
{ serviceName = "myservice"; }
exports
# => {
# <scopes> :: <some data>
# }
# Get all exports for a specific machine
clanLib.selectExports
{ machineName = "backend01"; }
exports
# => {
# <scopes> :: <some data>
# } When defining exports, certain restrictions apply based on context:
perInstance: Can only export to the matching scope.perMachine: Can only export to the machine scope.service = "myservice")These restrictions prevent accidental conflicts and maintain clear data ownership.
Use the helper functions: Always use clanLib.* functions instead of accessing the internal format directly
Use appropriate scopes: Export at the most specific scope that makes sense
perInstanceFor real-world use cases, see the clan-services