Docs: init migration guide for clanServices
This commit is contained in:
@@ -64,7 +64,6 @@ nav:
|
|||||||
- Autoincludes: manual/adding-machines.md
|
- Autoincludes: manual/adding-machines.md
|
||||||
- Inventory:
|
- Inventory:
|
||||||
- Inventory: manual/inventory.md
|
- Inventory: manual/inventory.md
|
||||||
- Services: manual/distributed-services.md
|
|
||||||
- Secure Boot: manual/secure-boot.md
|
- Secure Boot: manual/secure-boot.md
|
||||||
- Flake-parts: manual/flake-parts.md
|
- Flake-parts: manual/flake-parts.md
|
||||||
- Authoring:
|
- Authoring:
|
||||||
|
|||||||
@@ -4,6 +4,8 @@ Clan’s `clanServices` system is a composable way to define and deploy services
|
|||||||
|
|
||||||
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.
|
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](https://github.com/infinisil/nixus) and represents a similar concept.
|
||||||
|
|
||||||
---
|
---
|
||||||
|
|
||||||
## Overview
|
## Overview
|
||||||
@@ -17,6 +19,8 @@ inventory.instances.<instance_name>
|
|||||||
Each instance includes a reference to a **module specification** — this is how Clan knows which service module to use and where it came from.
|
Each instance includes a reference to a **module specification** — this is how Clan knows which service module to use and where it came from.
|
||||||
You can reference services from any flake input, allowing you to compose services from multiple flake sources.
|
You can reference services from any flake input, allowing you to compose services from multiple flake sources.
|
||||||
|
|
||||||
|
These operate on a strict *role-based membership model*, meaning machines are added by assigning them specific *roles*.
|
||||||
|
|
||||||
---
|
---
|
||||||
|
|
||||||
## Basic Example
|
## Basic Example
|
||||||
@@ -32,6 +36,7 @@ inventory.instances = {
|
|||||||
input = "clan-core"; # <-- The flake input where the service is defined
|
input = "clan-core"; # <-- The flake input where the service is defined
|
||||||
};
|
};
|
||||||
# Participation of the machines is defined via roles
|
# Participation of the machines is defined via roles
|
||||||
|
# Right side needs to be an attribute set. Its purpose will become clear later
|
||||||
roles.client.machines."machine-a" = {};
|
roles.client.machines."machine-a" = {};
|
||||||
roles.server.machines."backup-host" = {};
|
roles.server.machines."backup-host" = {};
|
||||||
};
|
};
|
||||||
@@ -45,6 +50,54 @@ If you used `clan-core` as an input attribute for your flake:
|
|||||||
inputs.clan-core.url = "git+https://git.clan.lol/clan/clan-core"
|
inputs.clan-core.url = "git+https://git.clan.lol/clan/clan-core"
|
||||||
```
|
```
|
||||||
|
|
||||||
|
## Configuration Example
|
||||||
|
|
||||||
|
Each role might expose configurable options
|
||||||
|
|
||||||
|
See clan's [clanServices reference](../reference/clanServices/index.md) for available options
|
||||||
|
|
||||||
|
```nix
|
||||||
|
inventory.instances = {
|
||||||
|
borgbackup-example = {
|
||||||
|
module = {
|
||||||
|
name = "borgbackup";
|
||||||
|
input = "clan-core";
|
||||||
|
};
|
||||||
|
roles.client.machines."machine-a" = {
|
||||||
|
# 'client' -Settings of 'machine-a'
|
||||||
|
settings = {
|
||||||
|
backupFolders = [
|
||||||
|
/home
|
||||||
|
/var
|
||||||
|
];
|
||||||
|
};
|
||||||
|
# ---------------------------
|
||||||
|
};
|
||||||
|
roles.server.machines."backup-host" = {};
|
||||||
|
};
|
||||||
|
}
|
||||||
|
```
|
||||||
|
|
||||||
|
## Tags
|
||||||
|
|
||||||
|
Multiple members can be defined using tags as follows
|
||||||
|
|
||||||
|
```nix
|
||||||
|
inventory.instances = {
|
||||||
|
borgbackup-example = {
|
||||||
|
module = {
|
||||||
|
name = "borgbackup";
|
||||||
|
input = "clan-core";
|
||||||
|
};
|
||||||
|
#
|
||||||
|
# The 'all' -tag targets all machines
|
||||||
|
roles.client.tags."all" = {};
|
||||||
|
# ---------------------------
|
||||||
|
roles.server.machines."backup-host" = {};
|
||||||
|
};
|
||||||
|
}
|
||||||
|
```
|
||||||
|
|
||||||
## Picking a clanService
|
## Picking a clanService
|
||||||
|
|
||||||
You can use services exposed by Clan’s core module library, `clan-core`.
|
You can use services exposed by Clan’s core module library, `clan-core`.
|
||||||
|
|||||||
@@ -1,7 +1,147 @@
|
|||||||
# How to migrate `Inventory.services`
|
# Migrating from using `clanModules` to `clanServices`
|
||||||
|
|
||||||
|
**Audience**: This is a guide for **people using `clanModules`**.
|
||||||
|
If you are a **module author** and need to migrate your modules please consult our **new** [clanServices authoring guide](../authoring/clanServices/index.md)
|
||||||
|
|
||||||
|
## What's Changing?
|
||||||
|
|
||||||
|
Clan is transitioning from the legacy `clanModules` system to the `clanServices` system. This guide will help you migrate your service definitions from the old format (`inventory.services`) to the new format (`inventory.instances`).
|
||||||
|
|
||||||
|
| Feature | `clanModules` (Old) | `clanServices` (New) |
|
||||||
|
| ---------------- | -------------------------- | ----------------------- |
|
||||||
|
| Module Class | `"nixos"` | `"clan.service"` |
|
||||||
|
| Inventory Key | `services` | `instances` |
|
||||||
|
| Module Source | Static | Composable via flakes |
|
||||||
|
| Custom Settings | Loosely structured | Strongly typed per-role |
|
||||||
|
| Migration Status | Deprecated (to be removed) | ✅ Preferred |
|
||||||
|
|
||||||
|
---
|
||||||
|
|
||||||
|
## Before: Old `services` Definition
|
||||||
|
|
||||||
|
```nix
|
||||||
|
services = {
|
||||||
|
admin = {
|
||||||
|
simple = {
|
||||||
|
roles.default.tags = [ "all" ];
|
||||||
|
|
||||||
|
roles.default.config = {
|
||||||
|
allowedKeys = {
|
||||||
|
"key-1" = "ssh-ed25519 AAAA...0J jon@jon-os";
|
||||||
|
};
|
||||||
|
};
|
||||||
|
};
|
||||||
|
};
|
||||||
|
};
|
||||||
|
```
|
||||||
|
|
||||||
|
---
|
||||||
|
|
||||||
|
## ✅ After: New `instances` Definition with `clanServices`
|
||||||
|
|
||||||
|
```nix
|
||||||
|
instances = {
|
||||||
|
# The instance_name is arbitrary but must be unique
|
||||||
|
# We recommend to incorporate the module name in some kind to keep it clear
|
||||||
|
admin-simple = {
|
||||||
|
module = {
|
||||||
|
name = "admin";
|
||||||
|
input = "clan-core";
|
||||||
|
};
|
||||||
|
|
||||||
|
roles.default.tags."all" = {};
|
||||||
|
|
||||||
|
# Move settings either into the desired role
|
||||||
|
# In that case they effect all 'client-machines'
|
||||||
|
roles.default.settings = {
|
||||||
|
allowedKeys = {
|
||||||
|
"key-1" = "ssh-ed25519 AAAA...0J jon@jon-os";
|
||||||
|
};
|
||||||
|
};
|
||||||
|
# ----------------------------
|
||||||
|
# OR move settings into the machine
|
||||||
|
# then they affect only that single 'machine'
|
||||||
|
roles.default.machines."jon".settings = {
|
||||||
|
allowedKeys = {
|
||||||
|
"key-1" = "ssh-ed25519 AAAA...0J jon@jon-os";
|
||||||
|
};
|
||||||
|
};
|
||||||
|
};
|
||||||
|
};
|
||||||
|
```
|
||||||
|
|
||||||
|
---
|
||||||
|
|
||||||
|
## Steps to Migrate
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
### 1. Move `services` entries to `instances`
|
||||||
|
|
||||||
|
Check if a service that you use has been migrated [In our reference](../reference/clanServices/index.md)
|
||||||
|
|
||||||
|
In your inventory, move it from:
|
||||||
|
|
||||||
|
```nix
|
||||||
|
services = { ... };
|
||||||
|
```
|
||||||
|
|
||||||
|
to:
|
||||||
|
|
||||||
|
```nix
|
||||||
|
instances = { ... };
|
||||||
|
```
|
||||||
|
|
||||||
|
Each nested service-instance-pair becomes a flat key, like `borgbackup.simple → borgbackup-simple`.
|
||||||
|
|
||||||
|
---
|
||||||
|
|
||||||
|
### 2. Add `module.name` and `module.input`
|
||||||
|
|
||||||
|
Each instance must declare the module name and flake input it comes from:
|
||||||
|
|
||||||
|
```nix
|
||||||
|
module = {
|
||||||
|
name = "borgbackup";
|
||||||
|
input = "clan-core"; # The name of your flake input
|
||||||
|
};
|
||||||
|
```
|
||||||
|
|
||||||
|
If you used `clan-core` as an input:
|
||||||
|
|
||||||
|
```nix
|
||||||
|
inputs.clan-core.url = "github:clan/clan-core";
|
||||||
|
```
|
||||||
|
|
||||||
|
Then refer to it as `input = "clan-core"`.
|
||||||
|
|
||||||
|
---
|
||||||
|
|
||||||
|
### 3. Move role and machine config under `roles`
|
||||||
|
|
||||||
|
In the new system:
|
||||||
|
|
||||||
|
* Use `roles.<role>.machines.<hostname>.settings` for machine-specific config.
|
||||||
|
* Use `roles.<role>.settings` for role-wide config.
|
||||||
|
* Remove: `.config` as a top-level attribute is removed.
|
||||||
|
|
||||||
|
Example:
|
||||||
|
|
||||||
|
```nix
|
||||||
|
roles.default.machines."test-inventory-machine".settings = {
|
||||||
|
packages = [ "hello" ];
|
||||||
|
};
|
||||||
|
```
|
||||||
|
|
||||||
|
---
|
||||||
|
|
||||||
|
!!! Warning
|
||||||
|
* Old `clanModules` (`class = "nixos"`) are deprecated and will be removed in the near future.
|
||||||
|
* `inventory.services` is no longer recommended; use `inventory.instances` instead.
|
||||||
|
* Module authors should begin exporting service modules under the `clan.modules` attribute of their flake.
|
||||||
|
|
||||||
## Further reference
|
## Further reference
|
||||||
|
|
||||||
- [Authoring a 'clan.service' module](../authoring/clanServices/index.md)
|
* [Authoring a 'clan.service' module](../authoring/clanServices/index.md)
|
||||||
- [Setting up `inventory.instances`](../manual/distributed-services.md)
|
* [ClanServices](../guides/clanServices.md)
|
||||||
- [Inventory Reference](../reference/nix-api/inventory.md)
|
* [Inventory Reference](../reference/nix-api/inventory.md)
|
||||||
@@ -1,130 +0,0 @@
|
|||||||
# 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";
|
|
||||||
};
|
|
||||||
};
|
|
||||||
};
|
|
||||||
}
|
|
||||||
);
|
|
||||||
}
|
|
||||||
```
|
|
||||||
Reference in New Issue
Block a user