Merge branch 'hosts-v2' into 'main'

Nouvelle structure du repo nix

See merge request nounous/nixos!74
merge-requests/74/merge
lzebulon 2026-09-27 10:28:30 +02:00
commit 3455cf25a7
44 changed files with 957 additions and 442 deletions

View File

@ -26,12 +26,21 @@
agenix,
...
}:
let
lib = nixpkgs.lib.extend (
final: prev:
import ./lib {
inherit inputs;
lib = final;
}
);
in
flake-parts.lib.mkFlake { inherit inputs; } {
imports = [ inputs.treefmt-nix.flakeModule ];
systems = [ "x86_64-linux" ];
flake = with nixpkgs.lib; {
flake = with lib.crans.info; {
nixosConfigurations =
let
baseModules = [
@ -39,72 +48,10 @@
agenix.nixosModules.default
];
in
{
apprentix = nixosSystem {
specialArgs = inputs;
modules = [ ./hosts/vm/apprentix ] ++ baseModules;
};
collabora = nixosSystem {
specialArgs = inputs;
modules = [ ./hosts/vm/collabora ] ++ baseModules;
};
jitsi = nixosSystem {
specialArgs = inputs;
modules = [ ./hosts/vm/jitsi ] ++ baseModules;
};
livre = nixosSystem {
specialArgs = inputs;
modules = [ ./hosts/vm/livre ] ++ baseModules;
};
mediakiwi = nixosSystem {
specialArgs = inputs;
modules = [ ./hosts/vm/mediakiwi ] ++ baseModules;
};
neo = nixosSystem {
specialArgs = inputs;
modules = [ ./hosts/vm/neo ] ++ baseModules;
};
nextcloud = nixosSystem {
specialArgs = inputs;
modules = [ ./hosts/vm/nextcloud ] ++ baseModules;
};
periodique = nixosSystem {
specialArgs = inputs;
modules = [ ./hosts/vm/periodique ] ++ baseModules;
};
redite = nixosSystem {
specialArgs = inputs;
modules = [ ./hosts/vm/redite ] ++ baseModules;
};
reverseproxy = nixosSystem {
specialArgs = inputs;
modules = [ ./hosts/vm/reverseproxy ] ++ baseModules;
};
thot = nixosSystem {
specialArgs = inputs;
modules = [ ./hosts/physiques/thot ] ++ baseModules;
};
two = nixosSystem {
specialArgs = inputs;
modules = [ ./hosts/vm/two ] ++ baseModules;
};
vaultwarden = nixosSystem {
specialArgs = inputs;
modules = [ ./hosts/vm/vaultwarden ] ++ baseModules;
};
cransIso = nixosSystem {
(attrsToNixosSystem ./hosts/vm attrs_all_info attrs_vm_info baseModules)
// (attrsToNixosSystem ./hosts/physiques attrs_all_info attrs_physique_info baseModules)
// {
cransIso = lib.nixosSystem {
system = "x86_64-linux";
specialArgs = inputs;
modules = [

View File

@ -0,0 +1,22 @@
{
name = "cameron";
description = "Serveur de stockage adh";
id = 2;
isDebian = true;
networking = {
adm.enable = true;
san.enable = true;
switch = {
# todo recheck port
salameche = -1;
};
};
ilo = {
id = 52;
switch.salameche = 16;
};
}

View File

@ -0,0 +1,23 @@
{
name = "cephiroth";
description = "Serveur de stockage ceph";
id = 3;
# Sous Nix mais dans une autre branche
isDebian = true;
networking = {
adm.enable = true;
san.enable = true;
switch = {
carapuce = 12;
arceus = 12;
};
};
ilo = {
id = 53;
switch.salameche = 20;
};
}

View File

@ -0,0 +1,23 @@
{
name = "daniel";
description = "PVE adm";
id = 12;
isDebian = true;
networking = {
adm.enable = true;
san.enable = true;
srv-nat.enable = true;
switch = {
carapuce = 3;
arceus = 3;
};
};
ilo = {
id = 22;
switch.salameche = 4;
};
}

View File

@ -0,0 +1,17 @@
{
name = "ft";
description = "Serveur de backup du Crans, en SQ39";
id = 15;
isDebian = true;
networking = {
adm.enable = true;
switch = {
carapuce = 13;
arceus = 13;
};
};
}

View File

@ -0,0 +1,22 @@
{
name = "gulp";
description = "PVE adh";
id = 18;
isDebian = true;
networking = {
adm.enable = true;
adh.enable = true;
switch = {
carapuce = 11;
arceus = 11;
};
};
ilo = {
id = 28;
switch.salameche = 12;
};
}

View File

@ -0,0 +1,24 @@
{
name = "jack";
description = "PVE adm";
id = 13;
isDebian = true;
networking = {
adm.enable = true;
san.enable = true;
srv-nat.enable = true;
switch = {
carapuce = 5;
arceus = 5;
};
};
ilo = {
id = 23;
switch.salameche = 6;
};
}

View File

@ -0,0 +1,21 @@
{
name = "odlyd";
description = "PVE adh";
id = 16;
isDebian = true;
networking = {
adm.enable = true;
adh.enable = true;
switch = {
# pas branche
};
};
ilo = {
id = 26;
switch.salameche = 8;
};
}

View File

@ -0,0 +1,23 @@
{
name = "sam";
description = "PVE adm";
id = 11;
isDebian = true;
networking = {
adm.enable = true;
san.enable = true;
srv-nat.enable = true;
switch = {
carapuce = 1;
arceus = 1;
};
};
ilo = {
id = 21;
switch.salameche = 2;
};
}

View File

@ -0,0 +1,22 @@
{
name = "stitch";
description = "PVE adh";
id = 17;
isDebian = true;
networking = {
adm.enable = true;
adh.enable = true;
switch = {
carapuce = 9;
arceus = 9;
};
};
ilo = {
id = 27;
switch.salameche = 10;
};
}

View File

@ -0,0 +1,22 @@
{
name = "tealc";
description = "Serveur de stockage adm";
id = 1;
isDebian = true;
networking = {
adm.enable = true;
san.enable = true;
switch = {
carapuce = 10;
arceus = 10;
};
};
ilo = {
id = 51;
switch.salameche = 18;
};
}

View File

@ -38,19 +38,5 @@
restic
];
crans = {
enable = true;
networking.adm.enable = false;
resticClient.enable = false;
services = {
resticServer = {
enable = true;
port = 4242;
};
};
};
system.stateVersion = "24.05";
}

View File

@ -0,0 +1,17 @@
{
name = "thot";
description = "Serveur de backup sous nixos utilisant Restic";
id = 14;
enable = true;
networking.adm.enable = false;
resticClient.enable = false;
services = {
resticServer = {
enable = true;
port = 4242;
};
};
}

View File

@ -0,0 +1,23 @@
{
name = "zamok";
description = "Serveur de calcul adhérent";
id = 31;
isDebian = true;
networking = {
adm.enable = true;
adh.enable = true;
san.enable = true;
switch = {
carapuce = 7;
arceus = 4;
};
};
ilo = {
id = 54;
switch.salameche = 14;
};
}

View File

@ -9,21 +9,6 @@
networking.hostName = "apprentix";
crans = {
enable = true;
networking = {
id = 150;
srvNat.enable = true;
};
resticClient.when = "01:23";
homeNounou.enable = false;
users.root.passwordFile = ../../../secrets/apprentix/root.age;
};
security.sudo.extraRules = [
{
groups = [ "_user" ];

View File

@ -0,0 +1,17 @@
{
name = "apprentix";
description = "VM pour les apprenti⋅es";
id = 150;
enable = true;
networking = {
srv-nat.enable = true;
};
resticClient.when = "01:23";
homeNounou.enable = false;
users.root.passwordFile = ../../../secrets/apprentix/root.age;
}

View File

@ -9,16 +9,5 @@
networking.hostName = "collabora";
boot.loader.grub.devices = [ "/dev/sda" ];
crans = {
enable = true;
networking = {
id = 149;
srvNat.enable = true;
};
resticClient.enable = false;
};
system.stateVersion = "25.09";
}

View File

@ -0,0 +1,13 @@
{
name = "collabora";
description = "Collabora du Crans";
id = 149;
enable = true;
networking = {
srv-nat.enable = true;
};
resticClient.enable = false;
}

View File

@ -9,23 +9,5 @@
networking.hostName = "jitsi";
boot.loader.grub.devices = [ "/dev/vda" ];
crans = {
enable = true;
networking = {
id = 163;
srv = {
enable = true;
ipv4 = "185.230.79.15";
};
};
resticClient.when = "02:34";
services = {
acme.enable = true;
};
};
system.stateVersion = "24.11";
}

View File

@ -0,0 +1,25 @@
{
name = "jitsi";
description = "Machine qui gère Jitsi";
id = 163;
enable = true;
networking = {
adm.enable = true;
srv = {
enable = true;
ipv4 = "185.230.79.15";
};
};
resticClient.when = "02:34";
services = {
acme.enable = true;
};
public-ssh = "";
}

View File

@ -9,16 +9,5 @@
networking.hostName = "livre";
boot.loader.grub.devices = [ "/dev/sda" ];
crans = {
enable = true;
networking = {
id = 140;
srvNat.enable = true;
};
resticClient.when = "03:45";
};
system.stateVersion = "24.11";
}

View File

@ -0,0 +1,13 @@
{
name = "livre";
description = "Editeur de PDF en ligne via Stirling-PDF";
id = 140;
enable = true;
networking = {
srv-nat.enable = true;
};
resticClient.when = "03:45";
}

View File

@ -12,17 +12,5 @@
networking.hostName = "mediakiwi";
boot.loader.grub.devices = [ "/dev/sda" ];
crans = {
enable = true;
networking = {
id = 144;
srvNat.enable = true;
};
# Enable when deploying the real mediakiwi
resticClient.when = "06:47";
};
system.stateVersion = "25.05";
}

View File

@ -0,0 +1,13 @@
{
name = "mediakiwi";
description = "Wiki du Crans";
id = 144;
enable = true;
networking = {
srv-nat.enable = true;
};
resticClient.when = "06:47";
}

View File

@ -12,24 +12,5 @@
networking.hostName = "neo";
crans = {
enable = true;
networking = {
id = 141;
srv = {
enable = true;
ipv4 = "185.230.79.5";
};
};
resticClient.when = "04:56";
services = {
acme.enable = true;
coturn.enable = true;
};
};
system.stateVersion = "24.11";
}

View File

@ -0,0 +1,21 @@
{
name = "neo";
description = "Matrix du Crans et bridge IRC/Matrix";
id = 141;
enable = true;
networking = {
srv = {
enable = true;
ipv4 = "185.230.79.5";
};
};
resticClient.when = "04:56";
services = {
acme.enable = true;
coturn.enable = true;
};
}

View File

@ -9,31 +9,11 @@
networking.hostName = "nextcloud";
boot.loader.grub.devices = [ "/dev/sda" ];
crans = {
enable = true;
networking = {
id = 146;
srvNat = {
enable = true;
interface = "ens20";
};
san = {
enable = true;
interface = "ens19";
};
};
homeAdh.enable = true;
resticClient.enable = false;
};
services.autofs =
let
autoMaster = pkgs.writeScript "home-nextcloud" ''
#!/usr/bin/env bash
USER=$(echo $1 | sed "s/_[1-9]*$//")
UHOME=/home-adh/$USER
USERID=$(ldapsearch -LLL -b "dc=crans,dc=org" -H ldap://172.16.10.157 -D "cn=admin,dc=crans,dc=org" -y ${config.age.secrets.nextcloud_ldap_pass.path} "uid=$USER" uidNumber | grep uidNumber | awk '{print $2}')

View File

@ -0,0 +1,22 @@
{
name = "nextcloud";
description = "Nextcloud du Crans";
id = 146;
enable = true;
networking = {
srv-nat = {
enable = true;
interface = "ens20";
};
san = {
enable = true;
interface = "ens19";
};
};
homeAdh.enable = true;
resticClient.enable = false;
}

View File

@ -9,16 +9,5 @@
networking.hostName = "periodique";
boot.loader.grub.devices = [ "/dev/sda" ];
crans = {
enable = true;
networking = {
id = 118;
srvNat.enable = true;
};
resticClient.when = "02:56";
};
system.stateVersion = "24.11";
}

View File

@ -0,0 +1,13 @@
{
name = "periodique";
description = "Frontend Matrix du Crans (element)";
id = 118;
enable = true;
networking = {
srv-nat.enable = true;
};
resticClient.when = "02:56";
}

View File

@ -9,16 +9,5 @@
networking.hostName = "redite";
boot.loader.grub.devices = [ "/dev/sda" ];
crans = {
enable = true;
networking = {
id = 139;
srvNat.enable = true;
};
resticClient.when = "06:18";
};
system.stateVersion = "23.11";
}

View File

@ -0,0 +1,13 @@
{
name = "redite";
description = "Frontend reddit libre";
id = 139;
enable = true;
networking = {
srv-nat.enable = true;
};
resticClient.when = "06:18";
}

View File

@ -13,22 +13,5 @@
users.users."nginx".home = "/var/lib/nginx";
users.users."anubis".extraGroups = [ "nginx" ];
crans = {
enable = true;
networking = {
id = 151;
srvNat.enable = true;
srv = {
enable = true;
interface = "ens20";
ipv4 = "185.230.79.42";
};
};
resticClient.when = "03:42";
};
system.stateVersion = "25.05";
}

View File

@ -0,0 +1,19 @@
{
name = "reverseproxy";
description = "reverse-proxy principale du Crans";
id = 151;
enable = true;
networking = {
srv-nat.enable = true;
srv = {
enable = true;
interface = "ens20";
ipv4 = "185.230.79.42";
};
};
resticClient.when = "03:42";
}

View File

@ -8,6 +8,8 @@ let
formatJSON = pkgs.formats.json { };
formatYAML = pkgs.formats.yaml { };
inherit (lib.crans) fetchFromCrans;
antiBot = formatYAML.generate "antibot.yaml" [
{
name = "whitelist-crans";
@ -160,16 +162,6 @@ let
];
};
fetchFromCrans =
opts:
pkgs.fetchFromGitLab (
{
domain = "gitlab.adm.crans.org";
owner = "nounous";
}
// opts
);
installPartySite = pkgs.python3Packages.buildPythonApplication {
name = "site-install-party";
pyproject = false;

View File

@ -8,19 +8,6 @@
networking.hostName = "two";
boot.loader.grub.devices = [ "/dev/sda" ];
crans = {
enable = true;
networking = {
id = 135;
srvNat = {
enable = true;
interface = "ens19";
};
};
resticClient.when = "07:29";
};
system.stateVersion = "23.11";
}

View File

@ -0,0 +1,16 @@
{
name = "two";
description = "VM de test";
id = 135;
enable = true;
networking = {
srv-nat = {
enable = true;
interface = "ens19";
};
};
resticClient.when = "07:29";
}

View File

@ -9,16 +9,5 @@
networking.hostName = "vaultwarden";
boot.loader.grub.devices = [ "/dev/sda" ];
crans = {
enable = true;
networking = {
id = 159;
srvNat.enable = true;
};
resticClient.when = "04:44";
};
system.stateVersion = "24.05";
}

View File

@ -0,0 +1,13 @@
{
name = "vaultwarden";
description = "Vaultarden du crans, gestionnaire de mot de passe";
id = 159;
enable = true;
networking = {
srv-nat.enable = true;
};
resticClient.when = "04:44";
}

19
lib/default.nix 100644
View File

@ -0,0 +1,19 @@
args@{ inputs, ... }:
let
pkgs = inputs.nixpkgs.legacyPackages.x86_64-linux;
in
{
crans = {
info = import ./info.nix args;
fetchFromCrans =
opts:
pkgs.fetchFromGitLab (
{
domain = "gitlab.adm.crans.org";
owner = "nounous";
}
// opts
);
};
}

82
lib/info.nix 100644
View File

@ -0,0 +1,82 @@
{ lib, inputs, ... }:
let
inherit (lib)
attrNames
attrsToList
isInt
isString
join
length
listToAttrs
filter
filterAttrs
mapAttrs
nameValuePair
nixosSystem
readDir
warn
warnIf
warnIfNot
;
infoRequired = {
name = isString;
description = isString;
id = isInt;
};
verifyAttrs =
info:
let
missing = filter (n: !(info ? ${n})) (attrNames infoRequired);
wrongType = filter (n: info ? ${n.name} && !(n.value info.${n.name})) (attrsToList infoRequired);
in
(warnIf (
length missing > 0
) "${info.name}/info.nix : les attributs « ${join ", " missing} » sont manquants")
(warnIf (length wrongType > 0)
"${info.name}/info.nix : les attributs « ${join ", " (map (i: i.name) wrongType)} » sont mal typés"
)
(warnIfNot (
(info.isDebian or false) || info ? enable
) "${info.name}/info.nix : cette machine nix ne définit pas l’attribut enable")
info;
get_hosts_names = path: attrNames (filterAttrs (name: type: type == "directory") (readDir path));
get_info =
path:
filter (x: x != null) (
map (
name:
let
filePath = path + "/${name}/info.nix";
in
if builtins.pathExists filePath then
verifyAttrs (import filePath)
else
warn "${toString filePath} not found" null
) (get_hosts_names path)
);
listInfoToAttrs = infos: add: listToAttrs (map (info: nameValuePair info.name (info // add)) infos);
in
rec {
attrsToNixosSystem =
path: all_hosts: hosts: baseModules:
mapAttrs (
name: info:
nixosSystem {
specialArgs = inputs // {
hosts = all_hosts;
};
modules = [
(path + "/${name}")
({ ... }: { config.crans = info; })
]
++ baseModules;
}
) (filterAttrs (name: info: !(info.isDebian or false)) hosts);
attrs_vm_info = listInfoToAttrs (get_info ../hosts/vm) { isVm = true; };
attrs_physique_info = listInfoToAttrs (get_info ../hosts/physiques) { isVm = false; };
attrs_all_info = attrs_physique_info // attrs_vm_info;
}

View File

@ -3,7 +3,13 @@
let
cfg = config.crans;
inherit (lib) mkEnableOption mkIf;
inherit (lib)
mkEnableOption
mkOption
mkIf
types
optional
;
in
{
imports = [
@ -20,11 +26,51 @@ in
./ssh.nix
./store.nix
./users.nix
./vlans.nix
./virtualisation.nix
];
options.crans = {
enable = mkEnableOption "Configuration commune à toutes les machines du Crans";
name = mkOption {
type = types.str;
example = "vm-test";
description = "Nom de la machine";
};
isVm = mkOption {
type = types.bool;
description = "Est-ce une machine virtuelle ?";
};
isDebian = mkOption {
type = types.bool;
default = false;
example = "true";
description = "Est-ce une machine Debian ?";
};
description = mkOption {
type = types.str;
example = "VM de test";
description = "Description de la machine";
};
id = mkOption {
type = types.int;
example = 135;
description = ''
ID de la machine :
- < 100 machine physique
- >= 100 VM ( id de la VM dans proxmox )
'';
};
public-ssh = mkOption {
type = types.str;
description = "Clé ssh public de la machine";
};
};
config = mkIf cfg.enable {
@ -32,7 +78,7 @@ in
homeNounou.enable = lib.mkDefault true;
monitoring.enable = true;
networking = {
enable = true;
enable = lib.mkDefault true;
adm.enable = lib.mkDefault true;
};
resticClient.enable = lib.mkDefault true;
@ -40,5 +86,11 @@ in
ldap.enable = true;
};
};
warnings = (
optional (
cfg.isVm != (cfg.id >= 100)
) "${cfg.name}: isVm (${toString cfg.isVm}) est incohérent avec son id (${toString cfg.id})"
);
};
}

View File

@ -1,207 +1,126 @@
{ lib, config, ... }:
{
lib,
config,
hosts,
...
}:
let
cfg = config.crans.networking;
cfg = config.crans;
cfg-net = cfg.networking;
inherit (lib)
mkEnableOption
mkIf
mkOption
mkDefault
types
mod
mapAttrs
mapAttrs'
filterAttrs
mergeAttrsList
optional
fixedWidthString
nameValuePair
;
idString = toString cfg.id;
hostId = lib.mod cfg.id 100;
hostIdString = lib.fixedWidthString 2 "0" (toString hostId);
isVm = cfg.id >= 100;
isVmString = toString isVm;
in
{
options.crans.networking = {
enable = mkEnableOption "Configuration réseaux commune à toutes les machines du Crans.";
id = mkOption {
type = types.int;
example = 135;
description = "Le numéro de la VM dans Proxmox.";
};
adm = {
enable = mkEnableOption "Configuration du VLAN adm.";
}
// mapAttrs (
vlan: conf:
let
vlanId = mod conf.id 100;
in
mergeAttrsList (
[
{
enable = mkEnableOption "Activation du réseau ${vlan}";
interface = mkOption {
type = types.str;
default = "ens18";
example = "ens20";
description = "Nom de l'interface réseau sur laquelle est située le VLAN adm.";
};
description = "Interface pour le réseau ${vlan}";
default = conf.interface;
};
srv = {
enable = mkEnableOption "Configuration du VLAN srv.";
interface = mkOption {
type = types.str;
default = "ens19";
example = "ens20";
description = "Nom de l'interface réseau sur laquelle est située le VLAN srv.";
defaultRoutes = mkOption {
type = types.bool;
default = true;
description = "Configuration par défaut des routes de ${vlan}";
};
}
]
++ optional ((conf.ipv4 or true) != null) {
ipv4 = mkOption {
type = types.str;
example = "185.230.79.1";
description = "Adresse IPv4 de la machine.";
description = "Adresse IPv4 de la machine sur le réseau ${vlan}";
default = "172.16.${toString vlanId}.${toString cfg.id}";
};
};
srvNat = {
enable = mkEnableOption "Configuration du VLAN srv-nat.";
interface = mkOption {
}
++ optional ((conf.ipv6 or true) != null) (
let
# XXX: Utilisation du masque pour le déterminer à la place ?
prefix =
if lib.hasPrefix "2a0c:700" conf.ipv6.address then
"2a0c:700"
else if lib.hasPrefix "fd00:0:0" conf.ipv6.address then
"fd00:0:0"
else
(builtins.warn "Le prefixe de ${conf.ipv6.address} n’est pas reconnu");
in
{
ipv6 = mkOption {
type = types.str;
default = "ens19";
example = "ens20";
description = "Nom de l'interface réseau sur laquelle est située le VLAN srv-nat.";
};
description = "Adresse IPv6 de la machine sur le réseau ${vlan}";
default = "${prefix}:${toString vlanId}::ff:fe0${toString (cfg.id / 100)}:${toString (mod cfg.id 100)}${
fixedWidthString 2 "0" (toString vlanId)
}";
};
}
)
)
) cfg.vlans;
san = {
enable = mkEnableOption "Configuration du VLAN san.";
interface = mkOption {
type = types.str;
example = "ens19";
description = "Nom de l'interface réseau sur laquelle est située le VLAN san.";
};
};
};
config = mkIf cfg.enable {
config = mkIf cfg-net.enable {
networking = {
hostName = cfg.name;
useDHCP = false;
firewall.enable = lib.mkDefault false;
nameservers = [ "172.16.10.128" ];
firewall.enable = mkDefault false;
nameservers = [
# Romanesco via adm
"172.16.10.128"
"fd00::10:0:ff:fe01:2810"
];
# La configuration des interfaces se fait de la manière suivante :
# elle est écrite de manière générique pour toutes les machines, puis
# on filtre pour ne garder que les interfaces activées. nix fait de
# l'évaluation paresseuse donc ça fonctionne bien !
interfaces =
# On change le nom des interfaces de "adm", "srv", ... pour leur vrai
# nom (on ne le met pas directement pour faire fonctionner le filter
# plus bas).
lib.attrsets.mapAttrs'
(interface: conf: {
name = cfg."${interface}".interface;
value = conf;
})
interfaces = mapAttrs' (
vlan: vconf:
let
conf = cfg-net.${vlan};
in
nameValuePair conf.interface (
# On itère ipv4 / ipv6
builtins.mapAttrs
(
# On filtre sur les interfaces activées
lib.attrsets.filterAttrs (interface: _: cfg."${interface}".enable) {
# Configuration du VLAN adm
adm = {
ipv4.addresses = [
{
address = "172.16.10.${idString}";
prefixLength = 24;
}
];
ipv6.addresses = [
{
address = "fd00::10:0:ff:fe0${isVmString}:${hostIdString}10";
prefixLength = 64;
}
];
};
# Configuration du VLAN srv
srv = {
ipv4 = {
ipvx: _:
mkIf (vconf.${ipvx} != null) {
addresses = [
{
address = cfg.srv.ipv4;
prefixLength = 26;
}
];
routes = [
{
address = "0.0.0.0";
via = "185.230.79.62";
prefixLength = 0;
}
];
};
ipv6 = {
addresses = [
{
address = "2a0c:700:2::ff:fe0${isVmString}:${hostIdString}02";
prefixLength = 64;
}
];
routes = [
{
address = "::";
via = "2a0c:700:2::ff:fe00:9902";
prefixLength = 0;
}
];
};
};
# Configuration du VLAN srv-nat
srvNat = {
ipv4 = {
addresses = [
{
address = "172.16.3.${idString}";
prefixLength = 24;
}
];
routes = [
{
address = "0.0.0.0";
via = "172.16.3.99";
prefixLength = 0;
}
];
};
ipv6 = {
addresses = [
{
address = "2a0c:700:3::ff:fe0${isVmString}:${hostIdString}03";
prefixLength = 64;
}
];
routes = [
{
address = "::";
via = "2a0c:700:3::ff:fe00:9903";
prefixLength = 0;
}
];
};
};
# Configuration du VLAN san
san = {
ipv4.addresses = [
{
address = "172.16.4.${idString}";
prefixLength = 24;
address = conf.${ipvx};
prefixLength = vconf.${ipvx}.prefixLength;
}
];
ipv6.addresses = [
routes = mkIf conf.defaultRoutes vconf.${ipvx}.routes;
}
)
{
address = "fd00::4:0:ff:fe0${isVmString}:${hostIdString}04";
prefixLength = 64;
"ipv4" = null;
"ipv6" = null;
}
];
};
}
);
)
) (filterAttrs (n: _: cfg-net.${n}.enable) cfg.vlans); # On filtre les interfaces désactivées.
};
};
}

View File

@ -0,0 +1,230 @@
{ lib, ... }:
let
inherit (lib)
mkOption
types
mkDefault
mkForce
;
vlanConf = {
srv = {
id = 2;
description = "Réseau public";
interface = "ens19";
ipv4 = {
address = mkForce "185.230.79.0";
prefixLength = 26;
routes = [
{
address = "0.0.0.0";
via = "185.230.79.62";
prefixLength = 0;
}
];
};
ipv6 = {
address = mkForce "2a0c:700:10::";
routes = [
{
address = "::";
via = "2a0c:700:2::ff:fe00:9902";
prefixLength = 0;
}
];
};
};
srv-nat = {
id = 3;
description = "Réseau derrière un NAT";
interface = "ens19";
ipv4.routes = [
{
address = "0.0.0.0";
via = "172.16.3.99";
prefixLength = 0;
}
];
ipv6 = {
address = mkForce "2a0c:700:3::";
routes = [
{
address = "::";
via = "2a0c:700:3::ff:fe00:9903";
prefixLength = 0;
}
];
};
};
san = {
id = 4;
description = "Accès aux baies de stockages";
interface = "ens19";
};
ceph = {
id = 6;
description = "Réseau interne à ceph";
interface = "ens20";
};
adm = {
id = 10;
description = "Réseau interne";
interface = "ens18";
};
adh = {
id = 12;
description = "Réseau adhérent";
ipv4 = {
address = mkForce "185.230.78.0";
routes = [
{
address = "0.0.0.0";
via = "185.230.78.12";
prefixLength = 0;
}
];
};
ipv6 = {
address = mkForce "2a0c:700:12::";
prefixLength = 48;
routes = [
{
address = "::";
via = "2a0c:700:12::ff:fe00:9912";
prefixLength = 0;
}
];
};
};
adh-adm = {
id = 13;
description = "Réseau d’administration du réseau adhérent";
};
ens = {
id = 2751;
description = "Interconnexion avec l’ENS.";
ipv4 = {
address = mkForce "138.231.136.0";
prefixLength = 29;
};
ipv6 = null;
};
ens-clubs = {
id = 2754;
description = "Réseau clubs interconnecté avec l’ENS";
ipv6 = null;
};
ens-lp = {
id = 2756;
description = "Réseau imprimante interconnecté avec l’ENS";
ipv6 = null;
};
};
ipOpt =
v:
let
maxPrefix = if v == 4 then 32 else 128;
in
types.submodule {
options = {
address = mkOption {
type = types.str;
description = "Adresses IPv${v} du réseau";
};
prefixLength = mkOption {
type = types.ints.between 0 maxPrefix;
default = if v == 4 then 24 else 64;
description = "Prefixe du réseau";
};
routes = mkOption {
default = [ ];
description = "Routes par défaut";
example = [
{
address = "0.0.0.0";
via = "172.16.3.99";
prefixLength = 0;
}
];
type = types.listOf (
types.submodule {
options = {
address = mkOption { type = types.str; };
via = mkOption { type = types.str; };
prefixLength = mkOption { type = types.ints.between 0 maxPrefix; };
};
}
);
};
};
};
in
{
options.crans.vlans = mkOption {
type = types.attrsOf (
types.submodule {
options = {
id = mkOption {
type = types.int;
example = "10";
description = "Id du VLAN";
};
description = mkOption {
type = types.str;
description = "Description du VLAN";
};
interface = mkOption {
type = types.nullOr types.str;
default = null;
example = "ens19";
description = "Interface par défaut du VLAN";
};
ipv4 = mkOption {
type = types.nullOr (ipOpt 4);
description = "Réseau IPv4 du VLAN.";
};
ipv6 = mkOption {
type = types.nullOr (ipOpt 6);
description = "Réseau IPv6 du VLAN.";
};
};
}
);
};
config.crans.vlans = (
builtins.mapAttrs (
vlan: conf:
let
vlan = lib.mod conf.id 100;
in
lib.mkMerge (
[ conf ]
++ lib.optional ((conf.ipv4 or true) != null) {
ipv4.address = mkDefault "172.16.${toString vlan}.0";
}
++ lib.optional ((conf.ipv6 or true) != null) {
ipv6.address = mkDefault "fd00:0:0:${toString vlan}::";
}
)
) vlanConf
);
}