2024-10-12 00:20:58 +02:00
|
|
|
{ config, lib, ... }@args:
|
|
|
|
|
|
|
|
let
|
|
|
|
inherit (lib)
|
|
|
|
mkEnableOption
|
|
|
|
mkDefault
|
|
|
|
mkIf
|
|
|
|
mkOption
|
|
|
|
;
|
|
|
|
|
|
|
|
inherit (lib.types)
|
|
|
|
attrs
|
|
|
|
attrsOf
|
|
|
|
ints
|
|
|
|
listOf
|
|
|
|
nullOr
|
2024-12-05 09:59:59 +01:00
|
|
|
singleLineStr
|
2024-10-12 00:20:58 +02:00
|
|
|
str
|
|
|
|
submodule
|
|
|
|
unspecified
|
|
|
|
;
|
|
|
|
|
2024-12-05 09:59:59 +01:00
|
|
|
inherit (ints) positive;
|
|
|
|
|
2024-10-12 00:20:58 +02:00
|
|
|
addressType =
|
|
|
|
max:
|
|
|
|
submodule {
|
|
|
|
options = {
|
|
|
|
address = mkOption {
|
|
|
|
type = str;
|
|
|
|
description = "IP address.";
|
|
|
|
};
|
|
|
|
prefixLength = mkOption {
|
|
|
|
type = ints.between 8 max;
|
|
|
|
description = "Length of the prefix used in the local network.";
|
|
|
|
};
|
|
|
|
};
|
|
|
|
};
|
|
|
|
|
2024-12-05 09:59:59 +01:00
|
|
|
vpnKeyType = submodule {
|
|
|
|
options = {
|
|
|
|
id = mkOption {
|
|
|
|
type = positive;
|
|
|
|
description = ''
|
|
|
|
Unique ID that will be used to guess IP address
|
|
|
|
'';
|
|
|
|
};
|
|
|
|
key = mkOption {
|
|
|
|
type = str;
|
|
|
|
description = ''
|
|
|
|
Public key of the user for this VPN
|
|
|
|
'';
|
|
|
|
};
|
|
|
|
};
|
|
|
|
};
|
2024-10-12 00:20:58 +02:00
|
|
|
org = config.organization;
|
|
|
|
in
|
|
|
|
|
|
|
|
{
|
|
|
|
options = {
|
|
|
|
organization = {
|
|
|
|
members = mkOption {
|
2024-12-05 09:59:59 +01:00
|
|
|
type = attrsOf (
|
|
|
|
submodule (
|
|
|
|
{ name, ... }:
|
|
|
|
{
|
|
|
|
options = {
|
|
|
|
name = mkOption {
|
|
|
|
type = str;
|
|
|
|
description = ''
|
|
|
|
Name of the member.
|
|
|
|
'';
|
|
|
|
};
|
|
|
|
|
|
|
|
email = mkOption {
|
|
|
|
type = str;
|
|
|
|
description = ''
|
|
|
|
Main e-mail address of the member.
|
|
|
|
'';
|
|
|
|
};
|
|
|
|
|
|
|
|
username = mkOption {
|
|
|
|
type = str;
|
|
|
|
default = name;
|
|
|
|
description = ''
|
|
|
|
The username used for authentication.
|
|
|
|
WARNING: Must be the same as the ens login!
|
|
|
|
'';
|
|
|
|
};
|
|
|
|
|
|
|
|
sshKeys = lib.mkOption {
|
|
|
|
type = listOf singleLineStr;
|
|
|
|
description = ''
|
|
|
|
A list of verbatim OpenSSH public keys that should be added to the
|
|
|
|
user's authorized keys.
|
|
|
|
'';
|
|
|
|
example = [
|
|
|
|
"ssh-rsa AAAAB3NzaC1yc2etc/etc/etcjwrsh8e596z6J0l7 example@host"
|
|
|
|
"ssh-ed25519 AAAAC3NzaCetcetera/etceteraJZMfk3QPfQ foo@bar"
|
|
|
|
];
|
|
|
|
};
|
|
|
|
|
|
|
|
vpnKeys = mkOption {
|
|
|
|
type = attrsOf vpnKeyType;
|
|
|
|
default = { };
|
|
|
|
description = "Attribute sets to define vpn keys of the user";
|
|
|
|
};
|
|
|
|
};
|
|
|
|
}
|
|
|
|
)
|
|
|
|
);
|
|
|
|
|
|
|
|
description = ''
|
|
|
|
Members of the DGNum organization.
|
|
|
|
'';
|
|
|
|
};
|
|
|
|
|
|
|
|
groups = mkOption {
|
|
|
|
type = attrsOf (listOf str);
|
|
|
|
description = ''
|
|
|
|
Groups of the DGNum organization.
|
|
|
|
'';
|
|
|
|
};
|
|
|
|
|
|
|
|
external = mkOption {
|
|
|
|
type = attrsOf (listOf str);
|
|
|
|
description = ''
|
|
|
|
External services used by the DGNum organization.
|
|
|
|
'';
|
|
|
|
};
|
|
|
|
|
|
|
|
services = mkOption {
|
2024-10-12 00:20:58 +02:00
|
|
|
type = attrsOf (submodule {
|
|
|
|
options = {
|
2024-12-05 09:59:59 +01:00
|
|
|
admins = mkOption {
|
|
|
|
type = listOf str;
|
|
|
|
default = [ ];
|
2024-10-12 00:20:58 +02:00
|
|
|
description = ''
|
2024-12-05 09:59:59 +01:00
|
|
|
List of administrators of the service.
|
2024-10-12 00:20:58 +02:00
|
|
|
'';
|
|
|
|
};
|
|
|
|
|
2024-12-05 09:59:59 +01:00
|
|
|
adminGroups = mkOption {
|
|
|
|
type = listOf str;
|
|
|
|
default = [ ];
|
2024-10-12 00:20:58 +02:00
|
|
|
description = ''
|
2024-12-05 09:59:59 +01:00
|
|
|
List of administrator groups of the service.
|
2024-10-12 00:20:58 +02:00
|
|
|
'';
|
|
|
|
};
|
|
|
|
};
|
|
|
|
});
|
|
|
|
description = ''
|
2024-12-05 09:59:59 +01:00
|
|
|
Administrator access of the different DGNum services,
|
|
|
|
it is mainly indicative as most services cannot configure this statically.
|
2024-10-12 00:20:58 +02:00
|
|
|
'';
|
|
|
|
};
|
|
|
|
};
|
|
|
|
|
|
|
|
nodes = mkOption {
|
|
|
|
type = attrsOf (
|
|
|
|
submodule (
|
|
|
|
{ config, name, ... }:
|
|
|
|
{
|
|
|
|
options = {
|
|
|
|
deployment = mkOption {
|
|
|
|
type = attrs;
|
|
|
|
default = { };
|
|
|
|
};
|
|
|
|
|
|
|
|
stateVersion = mkOption {
|
|
|
|
type = str;
|
|
|
|
description = ''
|
|
|
|
State version of the node.
|
|
|
|
'';
|
|
|
|
};
|
|
|
|
|
|
|
|
nixpkgs = mkOption {
|
|
|
|
type = str;
|
|
|
|
inherit (import ./nixpkgs.nix) default;
|
|
|
|
description = ''
|
|
|
|
Version of nixpkgs to use.
|
|
|
|
'';
|
|
|
|
};
|
|
|
|
|
|
|
|
nix-modules = mkOption {
|
|
|
|
type = listOf str;
|
|
|
|
default = [ ];
|
|
|
|
description = ''
|
|
|
|
List of modules to import from [nix-modules](https://git.hubrecht.ovh/hubrecht/nix-modules).
|
|
|
|
'';
|
|
|
|
};
|
|
|
|
|
|
|
|
hashedPassword = mkOption {
|
|
|
|
type = str;
|
|
|
|
description = ''
|
|
|
|
The hashed password for the root account.
|
|
|
|
'';
|
|
|
|
};
|
|
|
|
|
|
|
|
admins = mkOption {
|
|
|
|
type = listOf str;
|
|
|
|
default = [ ];
|
|
|
|
description = ''
|
|
|
|
List of members to be given root access to this node.
|
|
|
|
'';
|
|
|
|
};
|
|
|
|
|
|
|
|
adminGroups = mkOption {
|
|
|
|
type = listOf str;
|
|
|
|
default = [ ];
|
|
|
|
description = ''
|
|
|
|
List of groups to be given root access to this node.
|
|
|
|
'';
|
|
|
|
};
|
|
|
|
|
|
|
|
site = mkOption {
|
|
|
|
type = str;
|
|
|
|
description = ''
|
|
|
|
Geographical site where the node is located.
|
|
|
|
'';
|
|
|
|
};
|
|
|
|
|
|
|
|
vm-cluster = mkOption {
|
|
|
|
type = nullOr str;
|
|
|
|
default = null;
|
|
|
|
description = "VM cluster where the VM is located";
|
|
|
|
};
|
|
|
|
};
|
|
|
|
|
|
|
|
config = {
|
|
|
|
deployment = {
|
|
|
|
tags = [ "infra-${config.site}" ];
|
|
|
|
targetHost =
|
|
|
|
let
|
|
|
|
ip = with args.config.network.${name}.addresses; ipv4 ++ ipv6;
|
|
|
|
in
|
|
|
|
mkIf (ip != [ ]) (mkDefault (builtins.head ip));
|
|
|
|
};
|
|
|
|
};
|
|
|
|
}
|
|
|
|
)
|
|
|
|
);
|
|
|
|
description = ''
|
|
|
|
Nodes of the infrastructure.
|
|
|
|
'';
|
|
|
|
};
|
|
|
|
|
|
|
|
network = mkOption {
|
|
|
|
type = attrsOf (
|
|
|
|
submodule (
|
|
|
|
{ config, ... }:
|
|
|
|
{
|
|
|
|
options = {
|
|
|
|
interfaces = mkOption {
|
|
|
|
type = attrsOf (
|
|
|
|
submodule (
|
|
|
|
{ config, ... }:
|
|
|
|
{
|
|
|
|
options = {
|
|
|
|
ipv4 = mkOption {
|
|
|
|
type = listOf (addressType 32);
|
|
|
|
default = [ ];
|
|
|
|
description = ''
|
|
|
|
List of ipv4 addresses assigned to the interface.
|
|
|
|
'';
|
|
|
|
};
|
|
|
|
|
|
|
|
ipv6 = mkOption {
|
|
|
|
type = listOf (addressType 64);
|
|
|
|
default = [ ];
|
|
|
|
description = ''
|
|
|
|
List of ipv6 addresses assigned to the interface.
|
|
|
|
'';
|
|
|
|
};
|
|
|
|
|
|
|
|
gateways = mkOption {
|
|
|
|
type = listOf str;
|
|
|
|
description = ''
|
|
|
|
List of gateways used by the interface.
|
|
|
|
'';
|
|
|
|
};
|
|
|
|
|
|
|
|
DHCP = mkOption {
|
|
|
|
type = nullOr str;
|
|
|
|
default = null;
|
|
|
|
description = "Whether to enable DHCP on the interface.";
|
|
|
|
};
|
|
|
|
|
|
|
|
dns = mkOption {
|
|
|
|
type = listOf str;
|
|
|
|
default = [ ];
|
|
|
|
};
|
|
|
|
|
|
|
|
enableDefaultDNS = mkEnableOption "default DNS servers.";
|
|
|
|
};
|
|
|
|
|
|
|
|
config.dns = mkIf config.enableDefaultDNS [
|
|
|
|
"1.1.1.1#cloudflare-dns.com"
|
|
|
|
"8.8.8.8#dns.google"
|
|
|
|
"1.0.0.1#cloudflare-dns.com"
|
|
|
|
"8.8.4.4#dns.google"
|
|
|
|
"2606:4700:4700::1111#cloudflare-dns.com"
|
|
|
|
"2001:4860:4860::8888#dns.google"
|
|
|
|
"2606:4700:4700::1001#cloudflare-dns.com"
|
|
|
|
"2001:4860:4860::8844#dns.google"
|
|
|
|
];
|
|
|
|
}
|
|
|
|
)
|
|
|
|
);
|
|
|
|
};
|
|
|
|
|
|
|
|
addresses = {
|
|
|
|
ipv4 = mkOption {
|
|
|
|
type = listOf str;
|
|
|
|
default = [ ];
|
|
|
|
description = ''
|
|
|
|
List of public ipv4 addresses of the node.
|
|
|
|
'';
|
|
|
|
};
|
|
|
|
|
|
|
|
ipv6 = mkOption {
|
|
|
|
type = listOf str;
|
|
|
|
default = [ ];
|
|
|
|
description = ''
|
|
|
|
List of public ipv6 addresses of the node.
|
|
|
|
'';
|
|
|
|
};
|
|
|
|
};
|
|
|
|
|
|
|
|
hostId = mkOption {
|
|
|
|
type = str;
|
|
|
|
description = ''
|
|
|
|
Network Id of the node.
|
|
|
|
'';
|
|
|
|
};
|
|
|
|
|
|
|
|
netbirdIp = mkOption {
|
|
|
|
type = nullOr str;
|
|
|
|
description = ''
|
|
|
|
IP address of the node in the netbird network.
|
|
|
|
'';
|
|
|
|
};
|
2024-12-05 09:59:59 +01:00
|
|
|
|
|
|
|
vpnKeys = mkOption {
|
|
|
|
type = attrsOf vpnKeyType;
|
|
|
|
default = { };
|
|
|
|
description = "Attribute sets to define vpn keys of the machine";
|
|
|
|
|
|
|
|
};
|
2024-10-12 00:20:58 +02:00
|
|
|
};
|
|
|
|
|
|
|
|
config =
|
|
|
|
let
|
|
|
|
getAddresses =
|
|
|
|
version: builtins.concatMap (int: builtins.map (builtins.getAttr "address") int.${version});
|
|
|
|
in
|
|
|
|
{
|
|
|
|
addresses = {
|
|
|
|
ipv4 = builtins.filter (ip: builtins.substring 0 7 ip != "192.168") (
|
|
|
|
getAddresses "ipv4" (builtins.attrValues config.interfaces)
|
|
|
|
);
|
|
|
|
ipv6 = builtins.filter (_: true) ((getAddresses "ipv6") (builtins.attrValues config.interfaces));
|
|
|
|
};
|
|
|
|
};
|
|
|
|
}
|
|
|
|
)
|
|
|
|
);
|
|
|
|
description = ''
|
|
|
|
Network configuration for the different machines.
|
|
|
|
'';
|
|
|
|
};
|
|
|
|
|
|
|
|
assertions = mkOption {
|
|
|
|
type = listOf unspecified;
|
|
|
|
internal = true;
|
|
|
|
default = [ ];
|
|
|
|
description = ''
|
|
|
|
This option allows modules to express conditions that must
|
|
|
|
hold for the evaluation of the system configuration to
|
|
|
|
succeed, along with associated error messages for the user.
|
|
|
|
'';
|
|
|
|
};
|
|
|
|
};
|
|
|
|
|
|
|
|
config =
|
|
|
|
let
|
|
|
|
members = builtins.attrNames org.members;
|
|
|
|
groups = builtins.attrNames org.groups;
|
|
|
|
|
|
|
|
nameExists =
|
|
|
|
list: f: groups:
|
|
|
|
builtins.attrValues (
|
|
|
|
builtins.mapAttrs (name: members: {
|
|
|
|
assertion = builtins.all (x: builtins.elem x list) members;
|
|
|
|
message = f name;
|
|
|
|
}) groups
|
|
|
|
);
|
|
|
|
|
|
|
|
membersExists = nameExists members;
|
|
|
|
groupsExists = nameExists groups;
|
|
|
|
|
|
|
|
extract = name: builtins.mapAttrs (_: builtins.getAttr name);
|
|
|
|
in
|
|
|
|
{
|
|
|
|
assertions = builtins.concatLists [
|
|
|
|
# Check that all group members exist
|
|
|
|
(membersExists (
|
|
|
|
name: "A member of the ${name} group was not found in the members list."
|
|
|
|
) org.groups)
|
|
|
|
|
|
|
|
# Check that all node admins exist
|
|
|
|
(membersExists (name: "A member of the node ${name} admins was not found in the members list.") (
|
|
|
|
extract "admins" config.nodes
|
|
|
|
))
|
|
|
|
|
|
|
|
# Check that all node adminGroups exist
|
|
|
|
(groupsExists (name: "A member of the node ${name} adminGroups was not found in the groups list.") (
|
|
|
|
extract "adminGroups" config.nodes
|
|
|
|
))
|
|
|
|
|
2024-12-05 09:59:59 +01:00
|
|
|
# Check that all services admins exist
|
|
|
|
(membersExists (name: "A member of the service ${name} admins was not found in the members list.") (
|
|
|
|
extract "admins" org.services
|
|
|
|
))
|
|
|
|
|
|
|
|
# Check that all services adminGroups exist
|
|
|
|
(groupsExists (
|
|
|
|
name: "A member of the service ${name} adminGroups was not found in the groups list."
|
|
|
|
) (extract "adminGroups" org.services))
|
|
|
|
|
|
|
|
# Check that all external services admins exist
|
|
|
|
(membersExists (
|
|
|
|
name: "A member of the external service ${name} admins was not found in the members list."
|
|
|
|
) org.external)
|
2024-10-12 00:20:58 +02:00
|
|
|
];
|
|
|
|
};
|
|
|
|
}
|