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
- Create USB Installer (optional): guides/getting-started/installer.md
- Add Machines: guides/getting-started/add-machines.md
- Add Services: guides/getting-started/add-services.md
- Secrets & Facts: guides/getting-started/secrets.md
- Deploy Machine: guides/getting-started/deploy.md
- Continuous Integration: guides/getting-started/check.md

View File

@@ -1,6 +1,6 @@
# 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.
@@ -10,30 +10,40 @@ The term **Multi-host-modules** was introduced previously in the [nixus reposito
## 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
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.
You can reference services from any flake input, allowing you to compose services from multiple flake sources.
This says: “Run borgbackup as a *client* on my *laptop* and *server1*, and as a *server* on *backup-box*.”
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`:
```nix
inventory.instances = {
# Instance Name: Arbitrary unique name for this 'borgbackup' instance
# Instance Name: Different name for this 'borgbackup' instance
borgbackup-example = {
module = {
name = "borgbackup"; # <-- Name of the module
input = "clan-core"; # <-- The flake input where the service is defined
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
# 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
=== "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)"
```{.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
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"
clan {
The option: `machines.<name>` is used to add extra *nixosConfiguration* to a machine
```{.nix .annotate title="flake.nix" hl_lines="3-13 18-22"}
clan = {
inventory.machines = {
jon = {
# Define targetHost here
# Required before deployment
deploy.targetHost = "root@ip";
deploy.targetHost = "root@jon"; # (1)
# Define tags here
tags = [ "desktop" "backup" ];
tags = [ ];
};
sara = {
deploy.targetHost = "root@sara";
tags = [ ];
};
};
}
```
```nix title="flake.nix"
clan {
# Define additional nixosConfiguration here
# Or in /machines/jon/configuration.nix (autoloaded)
machines = {
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
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)"
```nix
```{.nix hl_lines="22"}
{
inputs.clan-core.url = "https://git.clan.lol/clan/clan-core/archive/main.tar.gz";
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)"
```nix
```{.nix hl_lines="14"}
{
inputs.clan-core.url = "https://git.clan.lol/clan/clan-core/archive/main.tar.gz";
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`
<!-- 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
];
<!-- Note: Use "jon" instead of "<machine>" as "<" is not supported in title tag -->
# Put your username here for login
users.users.user.name = "__YOUR_USERNAME__";
```nix title="./machines/jon/configuration.nix" hl_lines="12 15 19"
{
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
disko.devices.disk.main.device = "/dev/disk/by-id/__CHANGE_ME__";
# Put your username here for login
users.users.user.name = "__YOUR_USERNAME__";
# IMPORTANT! Add your SSH key here
# e.g. > cat ~/.ssh/id_ed25519.pub
users.users.root.openssh.authorizedKeys.keys = [ "__YOUR_SSH_KEY__" ];
# Replace this __CHANGE_ME__ with the copied result of the lsblk command
disko.devices.disk.main.device = "/dev/disk/by-id/__CHANGE_ME__";
# ...
}
```
# 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 `__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.
By default, Clan uses the [sops](https://github.com/getsops/sops) format