131 lines
4.5 KiB
Markdown
131 lines
4.5 KiB
Markdown
# Setting up `inventory.instances`
|
|
|
|
In Clan *distributed services* can be declaratively deployed using the `inventory.instances` attribute
|
|
|
|
First of all it might be needed to explain what we mean by the term *distributed service*
|
|
|
|
## What is considered a distributed service?
|
|
|
|
A **distributed service** is a system where multiple machines work together to provide a certain functionality, abstracting complexity and allowing for declarative configuration and management.
|
|
|
|
A VPN service in a closed mesh network is a good example of a distributed service — each machine needs to know the addresses and cryptographic keys of the other machines in advance to establish secure, direct connections, enabling private and encrypted communication without relying on a central server.
|
|
|
|
The term **Multi-host-service-abstractions** was introduced previously in the [nixus repository](https://github.com/infinisil/nixus) and represents a similar concept.
|
|
|
|
## How to use such a Service in Clan?
|
|
|
|
In clan everyone can provide services via modules. Those modules must be [`clan.service` modules](../authoring/clanServices/index.md).
|
|
|
|
To use a service you need to create an instance of it via the `clan.inventory.instances` attribute:
|
|
The source of the module must be specified as a simple string.
|
|
|
|
```nix
|
|
{
|
|
inventory = {
|
|
instances = {
|
|
"my-vpn" = {
|
|
# service source
|
|
module.name = "zerotier";
|
|
# ...
|
|
};
|
|
};
|
|
};
|
|
}
|
|
```
|
|
|
|
After specifying the *service source* for an instance, the next step is to configure the service.
|
|
Services operate on a strict *role-based membership model*, meaning machines are added by assigning them specific *roles*.
|
|
|
|
The following example shows a *zerotier service* which consists of a `controller` and some `peer` machines.
|
|
|
|
```nix
|
|
{
|
|
inventory = {
|
|
instances = {
|
|
"my-vpn" = {
|
|
# service source
|
|
module.name = "zerotier";
|
|
roles.peer.machines = {
|
|
# Right side needs to be an attribute set. Its purpose will become clear later
|
|
"my-machine-name" = {};
|
|
};
|
|
roles.controller.machines = {
|
|
"some-server-name" = {};
|
|
};
|
|
};
|
|
};
|
|
};
|
|
}
|
|
```
|
|
|
|
The next step is optional for some services. It might be desired to pass some service specific settings.
|
|
Either to affect all machines of a given role, or to affect a very specific machine.
|
|
For example:
|
|
|
|
In ZeroTier, the `roles.peer.settings` could specify the allowed IP ranges.
|
|
|
|
The `roles.controller.settings` could define a how to manage dynamic IP assignments for devices that are not statically configured.
|
|
|
|
```nix
|
|
{
|
|
inventory = {
|
|
instances = {
|
|
"my-vpn" = {
|
|
# service source
|
|
module.name = "zerotier";
|
|
roles.peer.machines = {
|
|
# Right side needs to be an attribute set. Its purpose will become clear later
|
|
"my-machine-name" = {};
|
|
};
|
|
roles.peer.settings = {
|
|
# Allow all ranges
|
|
ipRanges = [ "all" ];
|
|
};
|
|
roles.controller.machines = {
|
|
"some-server-name" = {
|
|
settings = {
|
|
# Enable the dynamic IP controller feature on this machine only
|
|
dynamicIp.enable = true;
|
|
};
|
|
};
|
|
};
|
|
};
|
|
};
|
|
};
|
|
}
|
|
```
|
|
|
|
Following all the steps described will result in consistent machine configurations that can be *installed* or *updated* via the [Clan CLI](../reference/cli/index.md)
|
|
|
|
### Using `clan.modules` from other people (optional)
|
|
|
|
The following example shows how to use remote modules and configure them for use in your clan.
|
|
|
|
!!! Note
|
|
Typically you would just use the `import` builtin. But we wanted to provide a json-compatible interface to allow for external API integrations.
|
|
|
|
```nix title="flake.nix"
|
|
{
|
|
inputs = {
|
|
# ...
|
|
libstd.url = "github:libfoo/libfoo";
|
|
# ...
|
|
};
|
|
|
|
outputs =
|
|
inputs: flake-parts.lib.mkFlake { inherit inputs; } (
|
|
{
|
|
clan = {
|
|
inventory.instances = {
|
|
"my-foo" = {
|
|
# Imports clan.module."mod-A" from inputs.libstd
|
|
module.input = "libstd";
|
|
module.name = "mod-A";
|
|
};
|
|
};
|
|
};
|
|
}
|
|
);
|
|
}
|
|
```
|