Using the Inventory
Clan's inventory system is a composable way to define and deploy services across machines.
This guide shows how to instantiate a clanService
, explains how service
definitions are structured in your inventory, and how to pick or create services
from modules exposed by flakes.
The term Multi-host-modules was introduced previously in the nixus repository and represents a similar concept.
Overview
Services are used in inventory.instances
, and assigned to roles and
machines -- meaning you decide which machines run which part of the service.
For example:
inventory.instances = {
borgbackup = {
roles.client.machines."laptop" = {};
roles.client.machines."workstation" = {};
roles.server.machines."backup-box" = {};
};
}
This says: "Run borgbackup as a client on my laptop and workstation, and
as a server on backup-box". client
and server
are roles defined by the
borgbackup
service.
Module source specification
Each instance includes a reference to a module specification -- this is how Clan knows which service module to use and where it came from.
It is not required to specify the module.input
parameter, in which case it
defaults to the pre-provided services of clan-core. In a similar fashion, the
module.name
parameter can also be omitted, it will default to the name of the
instance.
Example of instantiating a borgbackup
service using clan-core
:
inventory.instances = {
borgbackup = { # <- Instance name
# This can be partially/fully specified,
# - If the instance name is not the name of the module
# - If the input is not clan-core
# module = {
# name = "borgbackup"; # Name of the module (optional)
# input = "clan-core"; # The flake input where the service is defined (optional)
# };
# Participation of the machines is defined via roles
roles.client.machines."machine-a" = {};
roles.server.machines."backup-host" = {};
};
}
Module Settings
Each role might expose configurable options. See clan's clanServices reference for all available options.
Settings can be set in per-machine or per-role. The latter is applied to all machines that are assigned to that role.
inventory.instances = {
borgbackup = {
# Settings for 'machine-a'
roles.client.machines."machine-a" = {
settings = {
backupFolders = [
/home
/var
];
};
};
# Settings for all machines of the role "server"
roles.server.settings = {
directory = "/var/lib/borgbackup";
};
};
}
Tags
Tags can be used to assign multiple machines to a role at once. It can be thought of as a grouping mechanism.
For example using the all
tag for services that you want to be configured on all
your machines is a common pattern.
The following example could be used to backup all your machines to a common backup server
inventory.instances = {
borgbackup = {
# "All" machines are assigned to the borgbackup 'client' role
roles.client.tags = [ "all" ];
# But only one specific machine (backup-host) is assigned to the 'server' role
roles.server.machines."backup-host" = {};
};
}
Sharing additional Nix configuration
Sometimes you need to add custom NixOS configuration alongside your clan
services. The extraModules
option allows you to include additional NixOS
configuration that is applied for every machine assigned to that role.
There are multiple valid syntaxes for specifying modules:
inventory.instances = {
borgbackup = {
roles.client = {
# Direct module reference
extraModules = [ ../nixosModules/borgbackup.nix ];
# Or using self (needs to be json serializable)
# See next example, for a workaround.
extraModules = [ self.nixosModules.borgbackup ];
# Or inline module definition, (needs to be json compatible)
extraModules = [
{
# Your module configuration here
# ...
#
# If the module needs to contain non-serializable expressions:
imports = [ ./path/to/non-serializable.nix ];
}
];
};
};
}
Picking a clanService
You can use services exposed by Clan's core module library, clan-core
.
🔗 See: List of Available Services in clan-core
Defining Your Own Service
You can also author your own clanService
modules.
🔗 Learn how to write your own service: Authoring a service
You might expose your service module from your flake — this makes it easy for other people to also use your module in their clan.
💡 Tips for Working with clanServices
- You can add multiple inputs to your flake (
clan-core
,your-org-modules
, etc.) to mix and match services. - Each service instance is isolated by its key in
inventory.instances
, allowing to deploy multiple versions or roles of the same service type. - Roles can target different machines or be scoped dynamically.