infrastructure/meta/options.nix

426 lines
12 KiB
Nix
Raw Permalink Normal View History

# SPDX-FileCopyrightText: 2024 Tom Hubrecht <tom.hubrecht@dgnum.eu>
# SPDX-FileContributor: Maurice Debray <maurice.debray@dgnum.eu>
# SPDX-FileContributor: Ryan Lahfa <ryan.lahfa@dgnum.eu>
#
# SPDX-License-Identifier: EUPL-1.2
2024-05-14 23:31:49 +02:00
{ config, lib, ... }@args:
2024-02-23 10:50:50 +01:00
let
inherit (lib)
mkEnableOption
mkDefault
mkIf
mkOption
2024-12-08 16:44:49 +01:00
optionalAttrs
2024-02-23 10:50:50 +01:00
;
inherit (lib.types)
attrs
attrsOf
enum
2024-02-23 10:50:50 +01:00
ints
listOf
nullOr
str
submodule
2024-05-14 23:31:49 +02:00
unspecified
2024-02-23 10:50:50 +01: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-05-14 23:31:49 +02:00
org = config.organization;
nixpkgs = import ./nixpkgs.nix;
2024-02-23 10:50:50 +01:00
in
{
options = {
organization = {
members = mkOption {
type = attrsOf (
submodule (
{ name, ... }:
{
options = {
name = mkOption {
type = str;
description = ''
Name of the member.
'';
};
2024-02-23 10:50:50 +01:00
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!
'';
};
};
}
)
);
2024-02-23 10:50:50 +01:00
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 {
type = attrsOf (submodule {
options = {
admins = mkOption {
type = listOf str;
default = [ ];
description = ''
List of administrators of the service.
'';
};
adminGroups = mkOption {
type = listOf str;
default = [ ];
description = ''
List of administrator groups of the service.
'';
};
};
});
description = ''
Administrator access of the different DGNum services,
it is mainly indicative as most services cannot configure this statically.
'';
};
2024-02-23 10:50:50 +01:00
};
nodes = mkOption {
type = attrsOf (
submodule (
{ config, name, ... }:
{
options = {
deployment = mkOption {
type = attrs;
default = { };
};
stateVersion = mkOption {
2024-12-08 15:51:31 +01:00
type = nullOr str;
2024-02-23 10:50:50 +01:00
description = ''
State version of the node.
'';
};
nixpkgs = {
version = mkOption {
type = enum nixpkgs.versions;
description = ''
Version of nixpkgs to use.
'';
example = "unstable";
};
2024-12-08 10:48:53 +01:00
system = mkOption {
type = enum nixpkgs.systems;
description = ''
Type of system for this node, will impact how it is evaluated and deployed.
'';
example = "zyxel-nwa50ax";
};
2024-02-23 10:50:50 +01:00
};
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.
'';
};
2024-02-23 10:50:50 +01:00
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.
'';
};
2024-03-23 20:22:58 +01:00
vm-cluster = mkOption {
type = nullOr str;
default = null;
description = "VM cluster where the VM is located";
};
2024-02-23 10:50:50 +01:00
};
config = {
2024-12-08 16:44:49 +01:00
deployment =
{
tags = [
"infra-${config.site}"
config.nixpkgs.system
];
2024-12-08 16:44:49 +01:00
}
// (optionalAttrs (builtins.hasAttr name args.config.network) {
targetHost =
let
ip = with args.config.network.${name}.addresses; ipv4 ++ ipv6;
in
mkIf (ip != [ ]) (mkDefault (builtins.head ip));
});
2024-02-23 10:50:50 +01:00
};
}
)
);
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.
'';
};
2024-04-23 13:46:33 +02:00
netbirdIp = mkOption {
type = nullOr str;
description = ''
IP address of the node in the netbird network.
'';
};
2024-02-23 10:50:50 +01: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)
);
2024-02-23 13:10:31 +01:00
ipv6 = builtins.filter (_: true) ((getAddresses "ipv6") (builtins.attrValues config.interfaces));
2024-02-23 10:50:50 +01:00
};
};
}
)
);
description = ''
Network configuration for the different machines.
'';
};
2024-05-14 23:31:49 +02:00
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.
'';
};
2024-02-23 10:50:50 +01:00
};
2024-05-14 23:31:49 +02:00
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;
2024-05-14 23:47:20 +02:00
extract = name: builtins.mapAttrs (_: builtins.getAttr name);
2024-05-14 23:31:49 +02:00
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
2024-05-14 23:47:20 +02:00
(membersExists (name: "A member of the node ${name} admins was not found in the members list.") (
extract "admins" config.nodes
2024-05-14 23:31:49 +02:00
))
# Check that all node adminGroups exist
2024-05-14 23:47:20 +02:00
(groupsExists (name: "A member of the node ${name} adminGroups was not found in the groups list.") (
extract "adminGroups" config.nodes
))
# 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
2024-05-14 23:31:49 +02:00
))
2024-05-14 23:47:20 +02:00
# 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)
# Check that all members have ssh keys
2024-05-14 23:47:20 +02:00
(builtins.map (name: {
assertion = ((import ../keys)._keys.${name} or [ ]) != [ ];
message = "No ssh keys found for ${name}.";
2024-05-14 23:47:20 +02:00
}) members)
2024-05-14 23:31:49 +02:00
];
};
2024-02-23 10:50:50 +01:00
}