From 4ebdf021a3d5b1913e21dd4c32c5009c8091270b Mon Sep 17 00:00:00 2001 From: Johannes Kirschbauer Date: Fri, 16 May 2025 16:15:51 +0200 Subject: [PATCH] Docs: init migration guide for clanServices --- docs/mkdocs.yml | 1 - docs/site/guides/clanServices.md | 53 +++++++ .../site/guides/migrate-inventory-services.md | 148 +++++++++++++++++- docs/site/manual/distributed-services.md | 130 --------------- 4 files changed, 197 insertions(+), 135 deletions(-) delete mode 100644 docs/site/manual/distributed-services.md diff --git a/docs/mkdocs.yml b/docs/mkdocs.yml index bc5a99ce8..aee5d675c 100644 --- a/docs/mkdocs.yml +++ b/docs/mkdocs.yml @@ -64,7 +64,6 @@ nav: - Autoincludes: manual/adding-machines.md - Inventory: - Inventory: manual/inventory.md - - Services: manual/distributed-services.md - Secure Boot: manual/secure-boot.md - Flake-parts: manual/flake-parts.md - Authoring: diff --git a/docs/site/guides/clanServices.md b/docs/site/guides/clanServices.md index fb1cd2f88..21526d084 100644 --- a/docs/site/guides/clanServices.md +++ b/docs/site/guides/clanServices.md @@ -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. +The term **Multi-host-modules** was introduced previously in the [nixus repository](https://github.com/infinisil/nixus) and represents a similar concept. + --- ## Overview @@ -17,6 +19,8 @@ inventory.instances. 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. +These operate on a strict *role-based membership model*, meaning machines are added by assigning them specific *roles*. + --- ## Basic Example @@ -32,6 +36,7 @@ inventory.instances = { input = "clan-core"; # <-- The flake input where the service is defined }; # 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.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" ``` +## 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 You can use services exposed by Clan’s core module library, `clan-core`. diff --git a/docs/site/guides/migrate-inventory-services.md b/docs/site/guides/migrate-inventory-services.md index f97214edc..5a8b315dc 100644 --- a/docs/site/guides/migrate-inventory-services.md +++ b/docs/site/guides/migrate-inventory-services.md @@ -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..machines..settings` for machine-specific config. +* Use `roles..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 -- [Authoring a 'clan.service' module](../authoring/clanServices/index.md) -- [Setting up `inventory.instances`](../manual/distributed-services.md) -- [Inventory Reference](../reference/nix-api/inventory.md) \ No newline at end of file +* [Authoring a 'clan.service' module](../authoring/clanServices/index.md) +* [ClanServices](../guides/clanServices.md) +* [Inventory Reference](../reference/nix-api/inventory.md) \ No newline at end of file diff --git a/docs/site/manual/distributed-services.md b/docs/site/manual/distributed-services.md deleted file mode 100644 index 314490c9f..000000000 --- a/docs/site/manual/distributed-services.md +++ /dev/null @@ -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"; - }; - }; - }; - } - ); -} -```