Docs: getting started add services

This commit is contained in:
Johannes Kirschbauer
2025-06-30 15:14:47 +02:00
parent ff52f38f87
commit eab918324b
6 changed files with 196 additions and 54 deletions

View File

@@ -51,6 +51,7 @@ nav:
- Creating Your First Clan: guides/getting-started/index.md - Creating Your First Clan: guides/getting-started/index.md
- Create USB Installer (optional): guides/getting-started/installer.md - Create USB Installer (optional): guides/getting-started/installer.md
- Add Machines: guides/getting-started/add-machines.md - Add Machines: guides/getting-started/add-machines.md
- Add Services: guides/getting-started/add-services.md
- Secrets & Facts: guides/getting-started/secrets.md - Secrets & Facts: guides/getting-started/secrets.md
- Deploy Machine: guides/getting-started/deploy.md - Deploy Machine: guides/getting-started/deploy.md
- Continuous Integration: guides/getting-started/check.md - Continuous Integration: guides/getting-started/check.md

View File

@@ -1,6 +1,6 @@
# Using `clanServices` # Using `clanServices`
Clans `clanServices` system is a composable way to define and deploy services across machines. It replaces the legacy `clanModules` approach and introduces better structure, flexibility, and reuse. Clans `clanServices` 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. 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.
@@ -10,30 +10,40 @@ The term **Multi-host-modules** was introduced previously in the [nixus reposito
## Overview ## Overview
A `clanService` is used in: Services are used in `inventory.instances`, and then they attach to *roles* and *machines* — meaning you decide which machines run which part of the service.
For example:
```nix ```nix
inventory.instances.<instance_name> inventory.instances = {
borgbackup = {
roles.client.machines = [ "laptop" "server1" ];
roles.server.machines = [ "backup-box" ];
};
}
``` ```
Each instance includes a reference to a **module specification** — this is how Clan knows which service module to use and where it came from. This says: “Run borgbackup as a *client* on my *laptop* and *server1*, and as a *server* on *backup-box*.”
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*. ## 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.
Usually one would just use `imports` but we needd to make the `module source` configurable via Python API.
By default it is not required to specify the `module`, in which case it defaults to the preprovided services of clan-core.
--- ---
## Basic Example ## Override Example
Example of instantiating a `borgbackup` service using `clan-core`: Example of instantiating a `borgbackup` service using `clan-core`:
```nix ```nix
inventory.instances = { inventory.instances = {
# Instance Name: Arbitrary unique name for this 'borgbackup' instance # Instance Name: Different name for this 'borgbackup' instance
borgbackup-example = { borgbackup-example = {
module = { module = {
name = "borgbackup"; # <-- Name of the module name = "borgbackup"; # <-- Name of the module (optional)
input = "clan-core"; # <-- The flake input where the service is defined input = "clan-core"; # <-- The flake input where the service is defined (optional)
}; };
# 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 # Right side needs to be an attribute set. Its purpose will become clear later

View File

@@ -10,15 +10,6 @@ See the complete [list](../../guides/more-machines.md#automatic-registration) of
## Create a machine ## Create a machine
=== "CLI (imperative)"
```sh
clan machines create jon
```
The imperative command might create a machine folder in `machines/jon`
And might persist information in `inventory.json`
=== "flake.nix (flake-parts)" === "flake.nix (flake-parts)"
```{.nix hl_lines=12-15} ```{.nix hl_lines=12-15}
@@ -80,37 +71,54 @@ See the complete [list](../../guides/more-machines.md#automatic-registration) of
} }
``` ```
=== "CLI (imperative)"
```sh
clan machines create jon
```
The imperative command might create a machine folder in `machines/jon`
And might persist information in `inventory.json`
### Configuring a machine ### Configuring a machine
Inside of the `flake.nix` file: !!! Note
The option: `inventory.machines.<name>` is used to define metadata about the machine
That includes for example `deploy.targethost` `machineClass` or `tags`
```nix title="flake.nix" The option: `machines.<name>` is used to add extra *nixosConfiguration* to a machine
clan {
```{.nix .annotate title="flake.nix" hl_lines="3-13 18-22"}
clan = {
inventory.machines = { inventory.machines = {
jon = { jon = {
# Define targetHost here # Define targetHost here
# Required before deployment # Required before deployment
deploy.targetHost = "root@ip"; deploy.targetHost = "root@jon"; # (1)
# Define tags here # Define tags here
tags = [ "desktop" "backup" ]; tags = [ ];
};
sara = {
deploy.targetHost = "root@sara";
tags = [ ];
}; };
}; };
}
```
```nix title="flake.nix"
clan {
# Define additional nixosConfiguration here # Define additional nixosConfiguration here
# Or in /machines/jon/configuration.nix (autoloaded) # Or in /machines/jon/configuration.nix (autoloaded)
machines = { machines = {
jon = { config, pkgs, ... }: { jon = { config, pkgs, ... }: {
environment.systemPackages = with pkgs; [ firefox ]; users.users.root.openssh.authorizedKeys.keys = [
"ssh-ed25519 AAAAC3NzaC..." # elided (2)
];
}; };
}; };
} }
``` ```
1. It is required to define a *targetHost* for each machine before deploying. Best practice has been, to use the zerotier ip/hostname or the ip from the from overlay network you decided to use.
2. Add your *ssh key* here - That will ensure you can always login to your machine via *ssh* in case something goes wrong.
### (Optional): Renaming Machine ### (Optional): Renaming Machine
For renaming jon to your own machine name, you can use the following command: For renaming jon to your own machine name, you can use the following command:

View File

@@ -0,0 +1,118 @@
# How to add services
A service in clan is a self-contained, reusable unit of system configuration that provides a specific piece of functionality across one or more machines.
Think of it as a recipe for running a tool — like automatic backups, VPN networking, monitoring, etc.
In Clan Services are multi-Host & role-based:
- Roles map machines to logical service responsibilities, enabling structured, clean deployments.
- You can use tags instead of explicit machine names.
To learn more: [Guide about clanService](../clanServices.md)
!!! Important
It is recommended to add at least one networking service such as `zerotier` that allows to reach all your clan machines from your setup computer across the globe.
## Configure a Zerotier Network (recommended)
```{.nix title="flake.nix" hl_lines="20-28"}
{
inputs.clan-core.url = "https://git.clan.lol/clan/clan-core/archive/main.tar.gz";
inputs.nixpkgs.follows = "clan-core/nixpkgs";
inputs.flake-parts.follows = "clan-core/flake-parts";
inputs.flake-parts.inputs.nixpkgs-lib.follows = "clan-core/nixpkgs";
outputs =
inputs@{ flake-parts, ... }:
flake-parts.lib.mkFlake { inherit inputs; } {
imports = [ inputs.clan-core.flakeModules.default ];
clan = {
inventory.machines = {
jon = {
targetHost = "root@jon";
};
sara = {
targetHost = "root@jon";
};
};
inventory.instances = {
zerotier = { # (1)
# Defines 'jon' as the controller
roles.controller.machines.jon = {};
# Defines all machines as networking peer.
# The 'all' tag is a clan builtin.
roles.peer.tags.all = {};
};
}
};
systems = [
"x86_64-linux"
"aarch64-linux"
"x86_64-darwin"
"aarch64-darwin"
];
};
}
```
1. See [reference/clanServices](../../reference/clanServices/index.md) for all available services and how to configure them.
Or read [authoring/clanServices](../authoring/clanServices/index.md) if you want to bring your own
## Adding more recommended defaults
Adding the following services is recommended for most users:
```{.nix title="flake.nix" hl_lines="25-35"}
{
inputs.clan-core.url = "https://git.clan.lol/clan/clan-core/archive/main.tar.gz";
inputs.nixpkgs.follows = "clan-core/nixpkgs";
inputs.flake-parts.follows = "clan-core/flake-parts";
inputs.flake-parts.inputs.nixpkgs-lib.follows = "clan-core/nixpkgs";
outputs =
inputs@{ flake-parts, ... }:
flake-parts.lib.mkFlake { inherit inputs; } {
imports = [ inputs.clan-core.flakeModules.default ];
clan = {
inventory.machines = {
jon = {
targetHost = "root@jon";
};
sara = {
targetHost = "root@jon";
};
};
inventory.instances = {
zerotier = {
roles.controller.machines.jon = {};
roles.peer.tags.all = {};
};
admin = { # (1)
roles.default.tags.all = { };
roles.default.settings = {
allowedKeys = {
"my-user" = "ssh-ed25519 AAAAC3N..."; # elided
};
};
};
state-version = { # (2)
roles.default.tags.all = { };
};
};
};
systems = [
"x86_64-linux"
"aarch64-linux"
"x86_64-darwin"
"aarch64-darwin"
];
};
}
```
1. The `admin` service will generate a **root-password** and **add your ssh-key** that allows for convienient administration.
2. The `state-version` service will generate a [nixos state version](https://wiki.nixos.org/wiki/FAQ/When_do_I_update_stateVersion) for each system once it is deployed.

View File

@@ -31,7 +31,7 @@ Now that you have created a new machine, we will walk through how to install it.
=== "flake.nix (flake-parts)" === "flake.nix (flake-parts)"
```nix ```{.nix hl_lines="22"}
{ {
inputs.clan-core.url = "https://git.clan.lol/clan/clan-core/archive/main.tar.gz"; inputs.clan-core.url = "https://git.clan.lol/clan/clan-core/archive/main.tar.gz";
inputs.nixpkgs.follows = "clan-core/nixpkgs"; inputs.nixpkgs.follows = "clan-core/nixpkgs";
@@ -63,7 +63,7 @@ Now that you have created a new machine, we will walk through how to install it.
=== "flake.nix (classic)" === "flake.nix (classic)"
```nix ```{.nix hl_lines="14"}
{ {
inputs.clan-core.url = "https://git.clan.lol/clan/clan-core/archive/main.tar.gz"; inputs.clan-core.url = "https://git.clan.lol/clan/clan-core/archive/main.tar.gz";
inputs.nixpkgs.follows = "clan-core/nixpkgs"; inputs.nixpkgs.follows = "clan-core/nixpkgs";
@@ -133,31 +133,32 @@ In this example we would copy `nvme-eui.e8238fa6bf530001001b448b4aec2929`
Edit the following fields inside the `./machines/<machine_name>/configuration.nix` Edit the following fields inside the `./machines/<machine_name>/configuration.nix`
<!-- Note: Use "jon" instead of "<machine>" as "<" is not supported in title tag --> <!-- Note: Use "jon" instead of "<machine>" as "<" is not supported in title tag -->
```nix title="./machines/jon/configuration.nix" hl_lines="13 18 22 26"
{
imports = [
# contains your disk format and partitioning configuration.
../../modules/disko.nix
# this file is shared among all machines
../../modules/shared.nix
# enables GNOME desktop (optional)
../../modules/gnome.nix
];
# Put your username here for login ```nix title="./machines/jon/configuration.nix" hl_lines="12 15 19"
users.users.user.name = "__YOUR_USERNAME__"; {
imports = [
# contains your disk format and partitioning configuration.
../../modules/disko.nix
# this file is shared among all machines
../../modules/shared.nix
# enables GNOME desktop (optional)
../../modules/gnome.nix
];
# Replace this __CHANGE_ME__ with the copied result of the lsblk command # Put your username here for login
disko.devices.disk.main.device = "/dev/disk/by-id/__CHANGE_ME__"; users.users.user.name = "__YOUR_USERNAME__";
# IMPORTANT! Add your SSH key here # Replace this __CHANGE_ME__ with the copied result of the lsblk command
# e.g. > cat ~/.ssh/id_ed25519.pub disko.devices.disk.main.device = "/dev/disk/by-id/__CHANGE_ME__";
users.users.root.openssh.authorizedKeys.keys = [ "__YOUR_SSH_KEY__" ];
# ... # IMPORTANT! Add your SSH key here
} # e.g. > cat ~/.ssh/id_ed25519.pub
``` users.users.root.openssh.authorizedKeys.keys = [ "__YOUR_SSH_KEY__" ];
# ...
}
```
!!! Info "Replace `__YOUR_USERNAME__` with the ip of your machine, if you use avahi you can also use your hostname" !!! Info "Replace `__YOUR_USERNAME__` with the ip of your machine, if you use avahi you can also use your hostname"
!!! Info "Replace `__CHANGE_ME__` with the appropriate `ID-LINK` identifier, such as `nvme-eui.e8238fa6bf530001001b448b4aec2929`" !!! Info "Replace `__CHANGE_ME__` with the appropriate `ID-LINK` identifier, such as `nvme-eui.e8238fa6bf530001001b448b4aec2929`"

View File

@@ -1,4 +1,8 @@
Setting up secrets is **Required** for any *machine deployments* or *vm runs* - You need to complete the steps: [Create Admin Keypair](#create-your-admin-keypair) and [Add Your Public Key(s)](#add-your-public-keys)
---
Clan enables encryption of secrets (such as passwords & keys) ensuring security and ease-of-use among users. Clan enables encryption of secrets (such as passwords & keys) ensuring security and ease-of-use among users.
By default, Clan uses the [sops](https://github.com/getsops/sops) format By default, Clan uses the [sops](https://github.com/getsops/sops) format