Merge pull request 'Add default bootstrapNodes for data-mesher service' (#4555) from fix-4424 into main

Reviewed-on: https://git.clan.lol/clan/clan-core/pulls/4555
Reviewed-by: lassulus <clanlol@lassul.us>
This commit is contained in:
lassulus
2025-08-08 12:24:51 +00:00
4 changed files with 161 additions and 122 deletions

View File

@@ -1,29 +0,0 @@
{
lib,
config,
settings,
...
}:
{
services.data-mesher.initNetwork =
let
# for a given machine, read it's public key and remove any new lines
readHostKey =
machine:
let
path = "${config.clan.core.settings.directory}/vars/per-machine/${machine}/data-mesher-host-key/public_key/value";
in
builtins.elemAt (lib.splitString "\n" (builtins.readFile path)) 1;
in
{
enable = true;
keyPath = config.clan.core.vars.generators.data-mesher-network-key.files.private_key.path;
tld = settings.network.tld;
hostTTL = settings.network.hostTTL;
# admin and signer host public keys
signingKeys = builtins.map readHostKey (builtins.attrNames settings.bootstrapNodes);
};
}

View File

@@ -5,31 +5,15 @@ let
{ {
options = { options = {
bootstrapNodes = lib.mkOption { bootstrapNodes = lib.mkOption {
type = lib.types.nullOr (lib.types.attrsOf lib.types.str); type = lib.types.nullOr (lib.types.listOf lib.types.str);
# the default bootstrap nodes are any machines with the admin or signers role
# we iterate through those machines, determining an IP address for them based on their VPN
# currently only supports zerotier
# default = builtins.foldl' (
# urls: name:
# let
# ipPath = "${config.clan.core.settings.directory}/vars/per-machine/${name}/zerotier/zerotier-ip/value";
# in
# if builtins.pathExists ipPath then
# let
# ip = builtins.readFile ipPath;
# in
# urls ++ [ "[${ip}]:${builtins.toString settings.network.port}" ]
# else
# urls
# ) [ ] (dmLib.machines config).bootstrap;
description = '' description = ''
A list of bootstrap nodes that act as an initial gateway when joining A list of bootstrap nodes that act as an initial gateway when joining
the cluster. the cluster.
''; '';
example = { example = [
"node1" = "192.168.1.1:7946"; "192.168.1.1:7946"
"node2" = "192.168.1.2:7946"; "192.168.1.2:7946"
}; ];
}; };
network = { network = {
@@ -55,6 +39,59 @@ let
}; };
}; };
}; };
mkBootstrapNodes =
{
config,
lib,
roles,
settings,
}:
lib.mkDefault (
builtins.foldl' (
urls: name:
let
ipPath = "${config.clan.core.settings.directory}/vars/per-machine/${name}/zerotier/zerotier-ip/value";
in
if builtins.pathExists ipPath then
let
ip = builtins.readFile ipPath;
in
urls ++ [ "[${ip}]:${builtins.toString settings.network.port}" ]
else
urls
) [ ] (builtins.attrNames ((roles.admin.machines or { }) // (roles.signer.machines or { })))
);
mkDmService = dmSettings: config: {
enable = true;
openFirewall = true;
settings = {
log_level = "warn";
state_dir = "/var/lib/data-mesher";
# read network id from vars
network.id = config.clan.core.vars.generators.data-mesher-network-key.files.public_key.value;
host = {
names = [ config.networking.hostName ];
key_path = config.clan.core.vars.generators.data-mesher-host-key.files.private_key.path;
};
cluster = {
port = dmSettings.network.port;
join_interval = "30s";
push_pull_interval = "30s";
interface = dmSettings.network.interface;
bootstrap_nodes = dmSettings.bootstrapNodes;
};
http.port = 7331;
http.interface = "lo";
};
};
in in
{ {
_class = "clan.service"; _class = "clan.service";
@@ -67,11 +104,9 @@ in
interface = interface =
{ lib, ... }: { lib, ... }:
{ {
imports = [ sharedInterface ]; imports = [ sharedInterface ];
options = { options = {
network = { network = {
tld = lib.mkOption { tld = lib.mkOption {
type = lib.types.str; type = lib.types.str;
@@ -89,54 +124,117 @@ in
}; };
}; };
perInstance = perInstance =
{ settings, roles, ... }:
{ {
nixosModule = { extendSettings,
imports = [ roles,
./admin.nix lib,
./shared.nix ...
]; }:
_module.args = { inherit settings roles; }; {
}; nixosModule =
{ config, ... }:
let
settings = extendSettings {
bootstrapNodes = mkBootstrapNodes {
inherit
config
lib
roles
settings
;
};
};
in
{
imports = [ ./shared.nix ];
services.data-mesher = (mkDmService settings config) // {
initNetwork =
let
# for a given machine, read it's public key and remove any new lines
readHostKey =
machine:
let
path = "${config.clan.core.settings.directory}/vars/per-machine/${machine}/data-mesher-host-key/public_key/value";
in
builtins.elemAt (lib.splitString "\n" (builtins.readFile path)) 1;
in
{
enable = true;
keyPath = config.clan.core.vars.generators.data-mesher-network-key.files.private_key.path;
tld = settings.network.tld;
hostTTL = settings.network.hostTTL;
# admin and signer host public keys
signingKeys = builtins.map readHostKey (
builtins.attrNames ((roles.admin.machines or { }) // (roles.signer.machines or { }))
);
};
};
};
}; };
}; };
roles.signer = { roles.signer = {
interface = interface = sharedInterface;
{ ... }:
{
imports = [ sharedInterface ];
};
perInstance = perInstance =
{ settings, roles, ... }:
{ {
nixosModule = { extendSettings,
imports = [ lib,
./signer.nix roles,
./shared.nix ...
]; }:
_module.args = { inherit settings roles; }; {
}; nixosModule =
{ config, ... }:
let
settings = extendSettings {
bootstrapNodes = mkBootstrapNodes {
inherit
config
lib
roles
settings
;
};
};
in
{
imports = [ ./shared.nix ];
services.data-mesher = (mkDmService settings config);
};
}; };
}; };
roles.peer = { roles.peer = {
interface = interface = sharedInterface;
{ ... }:
{
imports = [ sharedInterface ];
};
perInstance = perInstance =
{ settings, roles, ... }:
{ {
nixosModule = { extendSettings,
imports = [ lib,
./peer.nix roles,
./shared.nix ...
]; }:
_module.args = { inherit settings roles; }; {
}; nixosModule =
{ config, ... }:
let
settings = extendSettings {
bootstrapNodes = mkBootstrapNodes {
inherit
config
lib
roles
settings
;
};
};
in
{
imports = [ ./shared.nix ];
services.data-mesher = (mkDmService settings config);
};
}; };
}; };
} }

View File

@@ -1,39 +1,9 @@
{ {
config, config,
settings,
... ...
}: }:
{ {
services.data-mesher = {
enable = true;
openFirewall = true;
settings = {
log_level = "warn";
state_dir = "/var/lib/data-mesher";
# read network id from vars
network.id = config.clan.core.vars.generators.data-mesher-network-key.files.public_key.value;
host = {
names = [ config.networking.hostName ];
key_path = config.clan.core.vars.generators.data-mesher-host-key.files.private_key.path;
};
cluster = {
port = settings.network.port;
join_interval = "30s";
push_pull_interval = "30s";
interface = settings.network.interface;
bootstrap_nodes = (builtins.attrValues settings.bootstrapNodes);
};
http.port = 7331;
http.interface = "lo";
};
};
# Generate host key. # Generate host key.
clan.core.vars.generators.data-mesher-host-key = { clan.core.vars.generators.data-mesher-host-key = {
files = files =

View File

@@ -16,11 +16,11 @@
instances = { instances = {
data-mesher = data-mesher =
let let
bootstrapNodes = { bootstrapNodes = [
admin = "[2001:db8:1::1]:7946"; "[2001:db8:1::1]:7946" # admin
peer = "[2001:db8:1::2]:7946"; "[2001:db8:1::2]:7946" # peer
# signer = "2001:db8:1::3:7946"; # "2001:db8:1::3:7946" #signer
}; ];
in in
{ {
roles.peer.machines.peer.settings = { roles.peer.machines.peer.settings = {