Compare commits

..

21 commits

Author SHA1 Message Date
sinavir
3b7662e45a
feat(ap): init ap-dev
All checks were successful
Run pre-commit on all files / pre-commit (push) Successful in 22s
2025-02-20 01:06:56 +01:00
sinavir
e8d446d2b0
feat(hive): Add more personalisation for liminix hosts 2025-02-11 16:51:15 +01:00
sinavir
11391dc4f2
feat(ap-v01): Add usteer
Some checks failed
Check meta / check_dns (pull_request) Successful in 16s
Check meta / check_meta (pull_request) Successful in 16s
Build all the nodes / ap01 (pull_request) Failing after 18s
Build all the nodes / netcore02 (pull_request) Successful in 21s
Check workflows / check_workflows (pull_request) Failing after 29s
Run pre-commit on all files / pre-commit (push) Successful in 41s
Build the shell / build-shell (pull_request) Successful in 37s
Run pre-commit on all files / pre-commit (pull_request) Successful in 38s
Build all the nodes / hypervisor03 (pull_request) Successful in 1m42s
Build all the nodes / rescue01 (pull_request) Successful in 1m47s
Build all the nodes / geo01 (pull_request) Successful in 2m31s
Build all the nodes / hypervisor02 (pull_request) Successful in 2m43s
Build all the nodes / hypervisor01 (pull_request) Successful in 2m47s
Build all the nodes / build01 (pull_request) Successful in 2m51s
Build all the nodes / bridge01 (pull_request) Successful in 2m54s
Build all the nodes / geo02 (pull_request) Successful in 3m4s
Build all the nodes / web01 (pull_request) Successful in 2m50s
Build all the nodes / vault01 (pull_request) Successful in 2m53s
Build all the nodes / storage01 (pull_request) Successful in 3m11s
Build all the nodes / web02 (pull_request) Successful in 3m1s
Build all the nodes / web03 (pull_request) Successful in 3m3s
Build all the nodes / compute01 (pull_request) Successful in 3m31s
Build all the nodes / tower01 (pull_request) Successful in 4m14s
2025-02-10 09:44:44 +01:00
0c3062a5c5
refactor(liminix): Refactor liminix meta nodes
Some checks failed
Check meta / check_meta (pull_request) Successful in 15s
Check meta / check_dns (pull_request) Successful in 16s
Check workflows / check_workflows (pull_request) Failing after 16s
Build all the nodes / netcore02 (pull_request) Successful in 21s
Run pre-commit on all files / pre-commit (push) Successful in 27s
Build all the nodes / ap01 (pull_request) Failing after 31s
Build the shell / build-shell (pull_request) Successful in 24s
Run pre-commit on all files / pre-commit (pull_request) Successful in 24s
Build all the nodes / hypervisor03 (pull_request) Successful in 1m54s
Build all the nodes / bridge01 (pull_request) Successful in 1m55s
Build all the nodes / tower01 (pull_request) Successful in 1m54s
Build all the nodes / rescue01 (pull_request) Successful in 1m57s
Build all the nodes / build01 (pull_request) Successful in 2m44s
Build all the nodes / hypervisor02 (pull_request) Successful in 2m47s
Build all the nodes / storage01 (pull_request) Successful in 3m1s
Build all the nodes / hypervisor01 (pull_request) Successful in 3m9s
Build all the nodes / geo02 (pull_request) Successful in 3m11s
Build all the nodes / geo01 (pull_request) Successful in 3m41s
Build all the nodes / vault01 (pull_request) Successful in 3m40s
Build all the nodes / web03 (pull_request) Successful in 3m29s
Build all the nodes / compute01 (pull_request) Successful in 3m46s
Build all the nodes / web01 (pull_request) Successful in 3m45s
Build all the nodes / web02 (pull_request) Successful in 3m39s
2025-02-06 11:02:44 +01:00
sinavir
099fc058c8
feat(npins/liminix): Update
Some checks failed
Check meta / check_dns (pull_request) Successful in 16s
Check meta / check_meta (pull_request) Successful in 16s
Build all the nodes / ap01 (pull_request) Failing after 23s
Build all the nodes / netcore02 (pull_request) Successful in 23s
Run pre-commit on all files / pre-commit (push) Successful in 26s
Check workflows / check_workflows (pull_request) Failing after 29s
Build the shell / build-shell (pull_request) Successful in 28s
Run pre-commit on all files / pre-commit (pull_request) Successful in 41s
Build all the nodes / build01 (pull_request) Successful in 1m33s
Build all the nodes / hypervisor01 (pull_request) Successful in 1m38s
Build all the nodes / rescue01 (pull_request) Successful in 1m40s
Build all the nodes / tower01 (pull_request) Successful in 1m42s
Build all the nodes / bridge01 (pull_request) Successful in 1m43s
Build all the nodes / geo01 (pull_request) Successful in 1m47s
Build all the nodes / hypervisor03 (pull_request) Successful in 1m57s
Build all the nodes / geo02 (pull_request) Successful in 2m3s
Build all the nodes / hypervisor02 (pull_request) Successful in 2m6s
Build all the nodes / storage01 (pull_request) Successful in 2m5s
Build all the nodes / web02 (pull_request) Successful in 1m46s
Build all the nodes / web03 (pull_request) Successful in 1m45s
Build all the nodes / vault01 (pull_request) Successful in 1m55s
Build all the nodes / compute01 (pull_request) Successful in 2m26s
Build all the nodes / web01 (pull_request) Successful in 2m23s
This brings cosmetic stuff
2025-02-04 23:38:57 +01:00
sinavir
d0ac1b673e
feat(ap-v01): Use static address for admin vlan 2025-02-04 23:38:57 +01:00
9a4f9c2ca3
feat(ap01): WIP 2025-02-04 23:25:57 +01:00
sinavir
c9dc36ed08
feat(scripts): Add zyxel exploit script
All checks were successful
Check meta / check_meta (pull_request) Successful in 15s
Check meta / check_dns (pull_request) Successful in 15s
Run pre-commit on all files / pre-commit (push) Successful in 24s
Check workflows / check_workflows (pull_request) Successful in 25s
Build all the nodes / netcore02 (pull_request) Successful in 29s
Build all the nodes / ap01 (pull_request) Successful in 41s
Build the shell / build-shell (pull_request) Successful in 26s
Run pre-commit on all files / pre-commit (pull_request) Successful in 23s
Build all the nodes / hypervisor02 (pull_request) Successful in 1m46s
Build all the nodes / hypervisor01 (pull_request) Successful in 1m47s
Build all the nodes / hypervisor03 (pull_request) Successful in 2m6s
Build all the nodes / build01 (pull_request) Successful in 2m12s
Build all the nodes / bridge01 (pull_request) Successful in 2m15s
Build all the nodes / tower01 (pull_request) Successful in 2m15s
Build all the nodes / web02 (pull_request) Successful in 1m54s
Build all the nodes / geo02 (pull_request) Successful in 2m19s
Build all the nodes / web03 (pull_request) Successful in 1m52s
Build all the nodes / storage01 (pull_request) Successful in 2m26s
Build all the nodes / rescue01 (pull_request) Successful in 2m35s
Build all the nodes / vault01 (pull_request) Successful in 2m23s
Build all the nodes / geo01 (pull_request) Successful in 2m40s
Build all the nodes / web01 (pull_request) Successful in 2m31s
Build all the nodes / compute01 (pull_request) Successful in 2m59s
2025-02-03 13:30:03 +01:00
sinavir
6fffa8eb13
feat(ap01/lavitate): Add admin vlan dhcp in levitation
All checks were successful
Check meta / check_dns (pull_request) Successful in 15s
Check meta / check_meta (pull_request) Successful in 15s
Check workflows / check_workflows (pull_request) Successful in 16s
Run pre-commit on all files / pre-commit (push) Successful in 23s
Build all the nodes / netcore02 (pull_request) Successful in 21s
Build the shell / build-shell (pull_request) Successful in 24s
Build all the nodes / ap01 (pull_request) Successful in 1m15s
Run pre-commit on all files / pre-commit (pull_request) Successful in 23s
Build all the nodes / geo02 (pull_request) Successful in 1m25s
Build all the nodes / bridge01 (pull_request) Successful in 2m28s
Build all the nodes / geo01 (pull_request) Successful in 2m48s
Build all the nodes / compute01 (pull_request) Successful in 2m57s
Build all the nodes / storage01 (pull_request) Successful in 2m44s
Build all the nodes / web02 (pull_request) Successful in 2m42s
Build all the nodes / tower01 (pull_request) Successful in 2m45s
Build all the nodes / build01 (pull_request) Successful in 3m3s
Build all the nodes / hypervisor02 (pull_request) Successful in 2m53s
Build all the nodes / hypervisor01 (pull_request) Successful in 2m55s
Build all the nodes / web03 (pull_request) Successful in 2m49s
Build all the nodes / rescue01 (pull_request) Successful in 3m4s
Build all the nodes / vault01 (pull_request) Successful in 3m8s
Build all the nodes / hypervisor03 (pull_request) Successful in 3m23s
Build all the nodes / web01 (pull_request) Successful in 3m32s
Else we would need to change the switch config when rebuilding the AP
2025-02-03 12:47:59 +01:00
sinavir
8a9e5c16a5
fix(ap01/levitate): Add iproute to levitated system else we don't have the network 2025-02-03 12:47:54 +01:00
sinavir
69ebe92e2c
feat: Add TODO before release
All checks were successful
Check meta / check_meta (pull_request) Successful in 16s
Check workflows / check_workflows (pull_request) Successful in 17s
Check meta / check_dns (pull_request) Successful in 20s
Build all the nodes / ap01 (pull_request) Successful in 33s
Build all the nodes / netcore02 (pull_request) Successful in 34s
Run pre-commit on all files / pre-commit (push) Successful in 39s
Build the shell / build-shell (pull_request) Successful in 49s
Build all the nodes / hypervisor01 (pull_request) Successful in 1m31s
Build all the nodes / rescue01 (pull_request) Successful in 1m40s
Build all the nodes / web02 (pull_request) Successful in 1m41s
Build all the nodes / storage01 (pull_request) Successful in 2m4s
Build all the nodes / geo01 (pull_request) Successful in 2m7s
Build all the nodes / geo02 (pull_request) Successful in 2m12s
Build all the nodes / bridge01 (pull_request) Successful in 2m17s
Build all the nodes / build01 (pull_request) Successful in 2m19s
Build all the nodes / hypervisor02 (pull_request) Successful in 2m19s
Build all the nodes / tower01 (pull_request) Successful in 2m18s
Build all the nodes / hypervisor03 (pull_request) Successful in 2m26s
Build all the nodes / compute01 (pull_request) Successful in 2m40s
Build all the nodes / vault01 (pull_request) Successful in 2m27s
Build all the nodes / web03 (pull_request) Successful in 2m10s
Build all the nodes / web01 (pull_request) Successful in 2m50s
Run pre-commit on all files / pre-commit (pull_request) Successful in 24s
2025-01-31 17:41:15 +01:00
sinavir
966e1ed038
fix(ap01/radius-secret): Use environment variable for radius secret
This is a hack, please fix it in the next iteration of the project
2025-01-31 17:35:31 +01:00
sinavir
8b25a202c1
feat(ap01/ssid): Same SSID everywhere 2025-01-30 00:34:04 +01:00
sinavir
4991f19111
feat(ap01/networking): Enable dynamic vlans and drop useless bridge 2025-01-30 00:34:04 +01:00
sinavir
b21712efb4
fix(LICENSE): Add license information 2025-01-30 00:34:04 +01:00
1a06074607
chore(machines/ap01/recovery): better scope for pkgs and add zyxel-bootconfig to levitation
This is useful to reconfigure A/B in memory.

Signed-off-by: Ryan Lahfa <ryan@dgnum.eu>
2025-01-30 00:34:04 +01:00
94201ea7d0
feat(scripts/liminix): add a basic liminix rebuild
This script requires manual efforts on the operator end not to fuck up
too hard.

This adds min-copy-closure and min-garbage-collect to the development
shell.

Signed-off-by: Ryan Lahfa <ryan@dgnum.eu>
2025-01-30 00:34:04 +01:00
31488162d6
feat(scripts/liminix): make it easy to extract the firmware part of the Zyxel NWA FIT image
This is useful when reflashing the system from scratch in the levitation
mode.

Note that doing this will reset the UBI counter to zero, this is bad for
wear leveling.

Signed-off-by: Ryan Lahfa <ryan@dgnum.eu>
2025-01-30 00:34:04 +01:00
c86e1ec669
feat(machines/ap01/recovery): pass the parent hostname with live indicator
This makes the experience nicer.

Signed-off-by: Ryan Lahfa <ryan@dgnum.eu>
2025-01-30 00:34:04 +01:00
ad3cd0871a
feat(machines/ap01/recovery): fix levitation dependencies
We should use the right DHCPv4.

Signed-off-by: Ryan Lahfa <ryan@dgnum.eu>
2025-01-30 00:34:04 +01:00
af966bc6d1
feat(machines/ap01): add default VLAN and admin VLAN
Put DHCPv4 on the default VLAN now.

Signed-off-by: Ryan Lahfa <ryan@dgnum.eu>
2025-01-30 00:34:04 +01:00
168 changed files with 3069 additions and 3290 deletions

View file

@ -100,28 +100,6 @@ jobs:
STORE_USER: admin
name: Build and cache hypervisor03
run: nix-shell -A eval-nodes --run cache-node
netaccess01:
runs-on: nix
steps:
- uses: actions/checkout@v3
- env:
BUILD_NODE: netaccess01
STORE_ENDPOINT: https://tvix-store.dgnum.eu/infra-signing/
STORE_PASSWORD: ${{ secrets.STORE_PASSWORD }}
STORE_USER: admin
name: Build and cache netaccess01
run: nix-shell -A eval-nodes --run cache-node
netcore01:
runs-on: nix
steps:
- uses: actions/checkout@v3
- env:
BUILD_NODE: netcore01
STORE_ENDPOINT: https://tvix-store.dgnum.eu/infra-signing/
STORE_PASSWORD: ${{ secrets.STORE_PASSWORD }}
STORE_USER: admin
name: Build and cache netcore01
run: nix-shell -A eval-nodes --run cache-node
netcore02:
runs-on: nix
steps:

View file

@ -98,7 +98,7 @@ The general metadata is declared in `meta/nodes.nix`, the main values to declare
Create the directory `secrets` in the configuration folder, and add a `secrets.nix` file containing :
```nix
(import ../../../keys.nix).mkSecrets [ "host02" ] [
(import ../../../keys).mkSecrets [ "host02" ] [
# List of secrets for host02
]
```

View file

@ -23,12 +23,6 @@ SPDX-License-Identifier = "EUPL-1.2"
path = ["machines/nixos/compute01/ds-fr/01-smtp-tls.patch", "machines/nixos/compute01/librenms/kanidm.patch", "machines/nixos/compute01/stirling-pdf/*.patch", "machines/nixos/vault01/k-radius/packages/01-python_path.patch", "machines/nixos/web01/crabfit/*.patch", "machines/nixos/web02/cas-eleves/01-pytest-cas.patch", "patches/lix/01-disable-installChecks.patch", "patches/nixpkgs/01-pretalx-environment-file.patch", "patches/nixpkgs/03-crabfit-karla.patch", "patches/nixpkgs/05-netbird-relay.patch"]
precedence = "closest"
[[annotations]]
SPDX-FileCopyrightText = ["2024 Tom Hubrecht <tom.hubrecht@dgnum.eu>", "2024 Maurice Debray <maurice.debray@dgnum.eu>"]
SPDX-License-Identifier = "EUPL-1.2"
path = ["patches/nixpkgs/07-kanidm-groups-module.patch", "patches/nixpkgs/08-kanidm-groups-pkgs.patch"]
precedence = "closest"
[[annotations]]
SPDX-FileCopyrightText = "2024 Maurice Debray <maurice.debray@dgnum.eu>"
SPDX-License-Identifier = "EUPL-1.2"

View file

@ -1,33 +0,0 @@
# SPDX-FileCopyrightText: 2024 Ryan Lahfa <ryan.lahfa@dgnum.eu>
# SPDX-FileCopyrightText: 2024 Tom Hubrecht <tom.hubrecht@dgnum.eu>
# SPDX-FileContributor: Maurice Debray <maurice.debray@dgnum.eu>
#
# SPDX-License-Identifier: EUPL-1.2
let
unpatchedSources = import ./npins;
pkgs = import unpatchedSources.nixos-unstable { };
patch = (import ./lib/nix-patches { patchFile = ./patches; }).base {
inherit pkgs;
};
sources = builtins.mapAttrs (
k: src:
patch.applyPatches {
inherit src;
name = k;
}
) unpatchedSources;
overlays.lib = _: lib: { extra = import ./lib/nix-lib { inherit lib; }; };
in
{
inherit overlays sources unpatchedSources;
pkgs = pkgs // {
lib = pkgs.lib.extend overlays.lib;
};
}

View file

@ -3,13 +3,9 @@
#
# SPDX-License-Identifier: EUPL-1.2
let
bootstrap = import ./bootstrap.nix;
in
{
sources ? bootstrap.sources,
pkgs ? bootstrap.pkgs,
sources ? import ./npins,
pkgs ? import sources.nixos-unstable { },
}:
let
@ -105,16 +101,6 @@ let
];
copyright = "2024 Tom Hubrecht <tom.hubrecht@dgnum.eu>";
}
{
path = [
"patches/nixpkgs/07-kanidm-groups-module.patch"
"patches/nixpkgs/08-kanidm-groups-pkgs.patch"
];
copyright = [
"2024 Tom Hubrecht <tom.hubrecht@dgnum.eu>"
"2024 Maurice Debray <maurice.debray@dgnum.eu>"
];
}
{
path = [ "patches/nixpkgs/06-netbox-qrcode.patch" ];
copyright = "2024 Maurice Debray <maurice.debray@dgnum.eu>";
@ -201,11 +187,17 @@ in
}))
pkgs.npins
pkgs.rage
# SSO testing
pkgs.kanidm
pkgs.freeradius
pkgs.picocom # for serial access
# Daemon-less copy closure for Liminix systems.
(pkgs.callPackage (sources.liminix + "/pkgs/min-copy-closure") { nix = pkgs.lix; })
# Daemon-less garbage collection for Liminix systems.
(pkgs.callPackage (sources.liminix + "/pkgs/min-collect-garbage") { nix = pkgs.lix; })
(pkgs.callPackage ./lib/colmena {
colmena = pkgs.callPackage "${sources.colmena}/package.nix" { };
})

View file

@ -4,26 +4,45 @@
#
# SPDX-License-Identifier: EUPL-1.2
# TODO: change comments to ### \n # [text] \n #
let
### Init some tooling
sources' = import ./npins;
bootstrap = import ./bootstrap.nix;
# Patch sources directly
sources =
builtins.mapAttrs (patch.base { pkgs = import sources'.nixos-unstable { }; }).applyPatches'
sources';
inherit (bootstrap.pkgs) lib;
inherit (lib.extra) mapSingleFuse;
nix-lib = import ./lib/nix-lib;
inherit (nix-lib) mapSingleFuse;
inherit (bootstrap) sources;
patch = import ./lib/nix-patches { patchFile = ./patches; };
### Let's build meta
metadata = (import ./meta) lib;
nodes' = import ./meta/nodes;
nodes = builtins.attrNames nodes';
nodes = builtins.attrNames metadata.nodes;
### Nixpkgs instanciation
mkNode = node: {
deployment.systemType = system node;
};
nixpkgs' = import ./meta/nixpkgs.nix;
# All supported nixpkgs versions × systems, instanciated
nixpkgs = mapSingleFuse (s: mapSingleFuse (mkSystemNixpkgs s) nixpkgs'.versions) nixpkgs'.systems;
# Get the configured nixos version for the node,
# defaulting to the one defined in meta/nixpkgs
version = node: nodes'.${node}.nixpkgs.version;
system = node: nodes'.${node}.nixpkgs.system;
category = node: nixpkgs'.categories.${system node};
nodePkgs = node: nixpkgs.${system node}.${version node};
# Builds a patched version of nixpkgs, only as the source
mkNixpkgs' =
v:
patch.mkNixpkgsSrc rec {
src = sources'.${name};
name = "nixos-${v}";
};
# Build up the nixpkgs configuration for Liminix embedded systems
mkLiminixConfig =
@ -43,47 +62,29 @@ let
mkNixpkgsConfig =
system:
{
nixos = _: { }; # TODO: add nix-pkgs overlay here
nixos = _: { };
zyxel-nwa50ax = mkLiminixConfig system;
netconf = _: { };
}
.${system} or (throw "Unknown system: ${system} for nixpkgs configuration instantiation");
# Instanciates the required nixpkgs version
mkSystemNixpkgs =
system: version: import sources."nixos-${version}" (mkNixpkgsConfig system version);
mkSystemNixpkgs = system: version: import (mkNixpkgs' version) (mkNixpkgsConfig system version);
# All supported nixpkgs versions × systems, instanciated
nixpkgs = mapSingleFuse (s: mapSingleFuse (mkSystemNixpkgs s) nixpkgs'.versions) nixpkgs'.systems;
# Get the configured nixos version for the node,
# defaulting to the one defined in meta/nixpkgs
version = node: metadata.nodes.${node}.nixpkgs.version;
system = node: metadata.nodes.${node}.nixpkgs.system;
category = node: nixpkgs'.categories.${system node};
nodePkgs = node: nixpkgs.${system node}.${version node};
##########
###
# Function to create arguments based on the node
#
mkArgs = node: rec {
lib = sourcePkgs.lib.extend bootstrap.overlays.lib;
lib = sourcePkgs.lib // {
extra = nix-lib;
};
sourcePkgs = nodePkgs node;
meta = metadata;
meta = (import ./meta) lib;
nodeMeta = metadata.nodes.${node};
nodePath = "machines/${category node}/${node}";
nodeMeta = meta.nodes.${node};
nodePath = "machines/${category node}/${nodeMeta.nodeDir}";
};
##########
# Module for each node (quite empty since almost everything is in the default module)
#
mkNode = node: {
deployment.systemType = system node;
};
in
{
@ -94,10 +95,7 @@ in
specialArgs = {
inherit nixpkgs sources;
dgn-keys = import ./lib/keys {
meta = metadata;
inherit lib;
};
dgn-keys = import ./keys;
};
nodeSpecialArgs = mapSingleFuse mkArgs nodes;
@ -221,6 +219,5 @@ in
};
};
};
}
// (mapSingleFuse mkNode nodes)

View file

@ -5,9 +5,9 @@
{ lib, pkgs, ... }:
let
dgn-keys = import ../keys.nix;
dgn-keys = import ../keys;
dgn-members = (import ../meta lib).config.organization.groups.root;
dgn-members = (import ../meta lib).organization.groups.root;
in
{

View file

@ -1,13 +0,0 @@
# SPDX-FileCopyrightText: 2024 Tom Hubrecht <tom.hubrecht@dgnum.eu>
#
# SPDX-License-Identifier: EUPL-1.2
let
bootstrap = import ./bootstrap.nix;
inherit (bootstrap.pkgs) lib;
meta = import ./meta lib;
in
import ./lib/keys { inherit meta lib; }

109
keys/default.nix Normal file
View file

@ -0,0 +1,109 @@
# SPDX-FileCopyrightText: 2024 Tom Hubrecht <tom.hubrecht@dgnum.eu>
#
# SPDX-License-Identifier: EUPL-1.2
let
_sources = import ../npins;
inherit (import _sources.nixos-unstable { }) lib;
meta = import ../meta lib;
inherit (import ../lib/nix-lib) setDefault unique;
in
rec {
# WARNING: When updating this list, make sure that the nodes and members are alphabetically sorted
# If not, you will face an angry maintainer
_keys = {
# SSH keys of the nodes
bridge01 = [ "ssh-ed25519 AAAAC3NzaC1lZDI1NTE5AAAAIP5bS3iBXz8wycBnTvI5Qi79WLu0h4IVv/EOdKYbP5y7" ];
build01 = [ "ssh-ed25519 AAAAC3NzaC1lZDI1NTE5AAAAIIYJcEMQpOyKInqtd2/brnSQuzwgv6fNPlTSQx9tcvPu" ];
compute01 = [ "ssh-ed25519 AAAAC3NzaC1lZDI1NTE5AAAAIE/YluSVS+4h3oV8CIUj0OmquyJXju8aEQy0Jz210vTu" ];
geo01 = [ "ssh-ed25519 AAAAC3NzaC1lZDI1NTE5AAAAIEl6Pubbau+usQkemymoSKrTBbrX8JU5m5qpZbhNx8p4" ];
geo02 = [ "ssh-ed25519 AAAAC3NzaC1lZDI1NTE5AAAAIFNXaCS0/Nsu5npqQk1TP6wMHCVIOaj4pblp2tIg6Ket" ];
hypervisor01 = [
"ssh-ed25519 AAAAC3NzaC1lZDI1NTE5AAAAINPE0typcnvSioMfdLUloIfR5zcf/X0k6201xMHoQBCr"
];
hypervisor02 = [
"ssh-ed25519 AAAAC3NzaC1lZDI1NTE5AAAAIPETkWlOfESXQic+HgfGLV/T4Nqg0WjdDbEqtgDwkH+S"
];
hypervisor03 = [
"ssh-ed25519 AAAAC3NzaC1lZDI1NTE5AAAAIFLF0mxSGitsDE3/YXfrHNjtOMUt4HT2MbryyUKPLSBI"
];
rescue01 = [ "ssh-ed25519 AAAAC3NzaC1lZDI1NTE5AAAAIEJa02Annu8o7ggPjTH/9ttotdNGyghlWfU9E8pnuLUf" ];
storage01 = [ "ssh-ed25519 AAAAC3NzaC1lZDI1NTE5AAAAIA0s+rPcEcfWCqZ4B2oJiWT/60awOI8ijL1rtDM2glXZ" ];
tower01 = [ "ssh-ed25519 AAAAC3NzaC1lZDI1NTE5AAAAICVpR+TMRLGAfhn7Q0C3tKOydYYjfoC/e1ZYbKpby01Z" ];
vault01 = [ "ssh-ed25519 AAAAC3NzaC1lZDI1NTE5AAAAIAJA6VA7LENvTRlKdcrqt8DxDOPvX3bg3Gjy9mNkdFEW" ];
web01 = [ "ssh-ed25519 AAAAC3NzaC1lZDI1NTE5AAAAIPR+lewuJ/zhCyizJGJOH1UaAB699ItNKEaeuoK57LY5" ];
web02 = [ "ssh-ed25519 AAAAC3NzaC1lZDI1NTE5AAAAID+QDE+GgZs6zONHvzRW15BzGJNW69k2BFZgB/Zh/tLX" ];
web03 = [ "ssh-ed25519 AAAAC3NzaC1lZDI1NTE5AAAAICrWsMEfK86iaO9SubMqE2UvZNtHkLY5VUod/bbqKC0L" ];
# SSH keys of the DGNum members
agroudiev = [
"ssh-rsa AAAAB3NzaC1yc2EAAAADAQABAAABgQDgyt3ntpcoI/I2n97R1hzjBiNL6R98S73fSi7pkSE/8mQbI8r9GzsPUBcxQ+tIg0FgwkLxTwF8DwLf0E+Le/rPznxBS5LUQaAktSQSrxz/IIID1+jN8b03vf5PjfKS8H2Tu3Q8jZXa8HNsj3cpySpGMqGrE3ieUmknd/YfppRRf+wM4CsGKZeS3ZhB9oZi3Jn22A0U/17AOJTnv4seq+mRZWRQt3pvQvpp8/2M7kEqizie/gTr/DnwxUr45wisqYYH4tat9Cw6iDr7LK10VCrK37BfFagMIZ08Hkh3c46jghjYNQWe+mBUWJByWYhTJ0AtYrbaYeUV1HVYbsRJ6bNx25K6794QQPaE/vc2Z/VK/ILgvJ+9myFSAWVylCWdyYpwUu07RH/jDBl2aqH62ESwAG7SDUUcte6h9N+EryAQLWc8OhsGAYLpshhBpiqZwzX90m+nkbhx1SqMbtt6TS+RPDEHKFYn8E6FBrf1FK34482ndq/hHXZ88mqzGb1nOnM="
];
catvayor = [
"ssh-ed25519 AAAAC3NzaC1lZDI1NTE5AAAAIAA16foz+XzwKwyIR4wFgNIAE3Y7AfXyEsUZFVVz8Rie catvayor@katvayor"
"ssh-ed25519 AAAAC3NzaC1lZDI1NTE5AAAAIFfIJ8BToZ9EDxBsEJXQhUju7gm+rUDjGCNMvFSZCl1o openpgp:0x5CADCA1B"
"ssh-ed25519 AAAAC3NzaC1lZDI1NTE5AAAAICdOxx4I8BSbYPdouvuzDepwTwzQzGSBCNIV8TB5dduT openpgp:0xF6018131"
];
cst1 = [
"ssh-ed25519 AAAAC3NzaC1lZDI1NTE5AAAAIKrijwPlb7KQkYPLznMPVzPPT69cLzhEsJzZi9tmxzTh cst1@x270"
];
ecoppens = [ "ssh-ed25519 AAAAC3NzaC1lZDI1NTE5AAAAIIGmU7yEOCGuGNt4PlQbzd0Cms1RePpo8yEA7Ij/+TdA" ];
gdd = [
"ssh-ed25519 AAAAC3NzaC1lZDI1NTE5AAAAICE7TN5NQKGojNGIeTFiHjLHTDQGT8i05JFqX/zLW2zc"
"ssh-ed25519 AAAAC3NzaC1lZDI1NTE5AAAAIIFbkPWWZzOBaRdx4+7xQUgxDwuncSl2fxAeVuYfVUPZ"
];
jemagius = [
"ssh-ed25519 AAAAC3NzaC1lZDI1NTE5AAAAIOoxmou5OU74GgpIUkhVt6GiB+O9Jy4ge0TwK5MDFJ2F"
"ssh-rsa AAAAB3NzaC1yc2EAAAADAQABAAABgQCxQX0JLRah3GfIOkua4ZhEJhp5Ykv55RO0SPrSUwCBs5arnALg8gq12YLr09t4bzW/NA9/jn7flhh4S54l4RwBUhmV4JSQhGu71KGhfOj5ZBkDoSyYqzbu206DfZP5eQonSmjfP6XghcWOr/jlBzw9YAAQkFxsQgXEkr4kdn0ZXfZGz6b0t3YUjYIuDNbptFsGz2V9iQVy1vnxrjnLSfc25j4et8z729Vpy4M7oCaE6a6hgon4V1jhVbg43NAE5gu2eYFAPIzO3E7ZI8WjyLu1wtOBClk1f+HMen3Tr+SX2PXmpPGb+I2fAkbzu/C4X/M3+2bL1dYjxuvQhvvpAjxFwmdoXW4gWJ3J/FRiFrKsiAY0rYC+yi8SfacJWCv4EEcV/yQ4gYwpmU9xImLaro6w5cOHGCqrzYqjZc4Wi6AWFGeBSNzNs9PXLgMRWeUyiIDOFnSep2ebZeVjTB16m+o/YDEhE10uX9kCCx3Dy/41iJ1ps7V4JWGFsr0Fqaz8mu8="
];
luj = [
"ssh-ed25519 AAAAC3NzaC1lZDI1NTE5AAAAIDMBW7rTtfZL9wtrpCVgariKdpN60/VeAzXkh9w3MwbO julien@enigma"
"ssh-ed25519 AAAAC3NzaC1lZDI1NTE5AAAAIGa+7n7kNzb86pTqaMn554KiPrkHRGeTJ0asY1NjSbpr julien@tower"
];
mboyer = [ "ssh-ed25519 AAAAC3NzaC1lZDI1NTE5AAAAIGYnwZaFYvUxtJeNvpaA20rLfq8fOO4dFp7cIXsD8YNx" ];
mdebray = [
"ssh-ed25519 AAAAC3NzaC1lZDI1NTE5AAAAIEpwF+XD3HgX64kqD42pcEZRNYAWoO4YNiOm5KO4tH6o maurice@polaris"
"ssh-ed25519 AAAAC3NzaC1lZDI1NTE5AAAAIFdDnSl3cyWil+S5JiyGqOvBR3wVh+lduw58S5WvraoL maurice@fekda"
];
raito = [
"ssh-rsa AAAAB3NzaC1yc2EAAAADAQABAAABAQDcEkYM1r8QVNM/G5CxJInEdoBCWjEHHDdHlzDYNSUIdHHsn04QY+XI67AdMCm8w30GZnLUIj5RiJEWXREUApby0GrfxGGcy8otforygfgtmuUKAUEHdU2MMwrQI7RtTZ8oQ0USRGuqvmegxz3l5caVU7qGvBllJ4NUHXrkZSja2/51vq80RF4MKkDGiz7xUTixI2UcBwQBCA/kQedKV9G28EH+1XfvePqmMivZjl+7VyHsgUVj9eRGA1XWFw59UPZG8a7VkxO/Eb3K9NF297HUAcFMcbY6cPFi9AaBgu3VC4eetDnoN/+xT1owiHi7BReQhGAy/6cdf7C/my5ehZwD"
"ssh-ed25519 AAAAC3NzaC1lZDI1NTE5AAAAIE0xMwWedkKosax9+7D2OlnMxFL/eV4CvFZLsbLptpXr"
"ssh-ed25519 AAAAC3NzaC1lZDI1NTE5AAAAIKiXXYkhRh+s7ixZ8rvG8ntIqd6FELQ9hh7HoaHQJRPU"
];
thubrecht = [
"ssh-ed25519 AAAAC3NzaC1lZDI1NTE5AAAAIL+EZXYziiaynJX99EW8KesnmRTZMof3BoIs3mdEl8L3"
"ssh-ed25519 AAAAC3NzaC1lZDI1NTE5AAAAIHL4M4HKjs4cjRAYRk9pmmI8U0R4+T/jQh6Fxp/i1Eoy"
"ssh-ed25519 AAAAC3NzaC1lZDI1NTE5AAAAIPM1jpXR7BWQa7Sed7ii3SbvIPRRlKb3G91qC0vOwfJn"
];
};
getKeys = ls: builtins.concatLists (builtins.map (member: _keys.${member} or [ ]) ls);
mkSecrets =
nodes: setDefault { publicKeys = unique (rootKeys ++ (builtins.concatMap getNodeKeys' nodes)); };
getNodeKeys' =
node:
let
names = builtins.foldl' (names: group: names ++ meta.organization.groups.${group}) (
meta.nodes.${node}.admins ++ [ node ]
) meta.nodes.${node}.adminGroups;
in
unique (getKeys names);
getNodeKeys = node: rootKeys ++ getNodeKeys' node;
# List of keys for the root group
rootKeys = getKeys meta.organization.groups.root;
# List of 'machine' keys
machineKeys = rootKeys ++ (getKeys (builtins.attrNames meta.nodes));
nixosMachineKeys =
rootKeys
++ (getKeys (builtins.attrNames (lib.filterAttrs (_: v: v.nixpkgs.system == "nixos") meta.nodes)));
}

View file

@ -28,4 +28,4 @@ if [[ $1 == 'apply' ]]; then
doChecks
fi
exec @colmena@ --nix-option nix-path "" "$@"
exec @colmena@ "$@"

View file

@ -1,51 +0,0 @@
# SPDX-FileCopyrightText: 2024 Ryan Lahfa <ryan.lahfa@dgnum.eu>
# SPDX-FileCopyrightText: 2024 Tom Hubrecht <tom.hubrecht@dgnum.eu>
# SPDX-FileContributor: Maurice Debray <maurice.debray@dgnum.eu>
#
# SPDX-License-Identifier: EUPL-1.2
{ meta, lib }:
let
inherit (lib.extra) setDefault unique;
getAttr = lib.flip builtins.getAttr;
in
rec {
_memberKeys = builtins.mapAttrs (_: v: v.sshKeys) meta.organization.members;
_builderKeys = builtins.mapAttrs (_: v: v.builderKeys) meta.organization.members;
_nodeKeys = builtins.mapAttrs (_: v: v.sshKeys) meta.nodes;
# Get keys of the users
getMemberKeys = name: builtins.concatLists (builtins.map (getAttr _memberKeys) name);
# Get builder keys of the users
getBuilderKeys = getAttr _builderKeys;
# Get keys of the ssh server
getNodeKeys = name: builtins.concatLists (builtins.map (getAttr _nodeKeys) name);
# List of keys for the root group
rootKeys = getMemberKeys meta.organization.groups.root;
# All admins for a node
getNodeAdmins = node: meta.organization.groups.root ++ meta.nodes.${node}.admins;
# All keys needed for secret encryption
getSecretKeys = node: unique (getMemberKeys (getNodeAdmins node) ++ getNodeKeys [ node ]);
# List of keys for all machines wide secrets
machineKeys = rootKeys ++ (getNodeKeys (builtins.attrNames meta.nodes));
mkSecrets = nodes: setDefault { publicKeys = unique (builtins.concatMap getSecretKeys nodes); };
mkRootSecrets = setDefault { publicKeys = unique rootKeys; };
machineKeysBySystem =
system:
rootKeys
++ (getNodeKeys (
builtins.attrNames (lib.filterAttrs (_: v: v.nixpkgs.system == system) meta.nodes)
));
}

View file

@ -2,13 +2,17 @@
# SPDX-FileCopyrightText: 2024 Tom Hubrecht <tom.hubrecht@dgnum.eu>
#
# SPDX-License-Identifier: EUPL-1.2
{ lib }:
let
# Reimplement optional functions
_optional =
default: b: value:
if b then value else default;
in
rec {
inherit (lib)
inherit (import ./nixpkgs.nix)
flip
optionals
optionalString
hasPrefix
recursiveUpdate
splitString
@ -49,24 +53,6 @@ rec {
attrsList:
fuseAttrs (builtins.map f attrsList);
/*
Generate an `attrsList` of given size with the generator before fusing
the resulting list of attribute sets.
Type: (Int -> attrs) -> Int -> attrs
Example:
f = s: { "a${toString s}" = s + s; }
genFuse f 3
=> { a0 = 0; a1 = 2; a2 = 4; }
*/
genFuse =
# Int -> attrs
f:
# Int
size:
fuseAttrs (builtins.genList f size);
/*
Equivalent of lib.singleton but for an attribute set.
@ -126,8 +112,11 @@ rec {
subAttrs = attrs: builtins.map (subAttr attrs);
optionalList = optionals;
optionalList = _optional [ ];
optionalAttrs = _optional { };
optionalString = _optional "";
/*
Same as fuseAttrs but using `lib.recursiveUpdate` to merge attribute
sets together.

468
lib/nix-lib/nixpkgs.nix Normal file
View file

@ -0,0 +1,468 @@
# SPDX-FileCopyrightText: 2024 Tom Hubrecht <tom.hubrecht@dgnum.eu>
#
# SPDX-License-Identifier: EUPL-1.2
###
# Collection of nixpkgs library functions, those are necessary for defining our own lib
#
# They have been simplified and builtins are used in some places, instead of lib shims.
rec {
/**
Does the same as the update operator '//' except that attributes are
merged until the given predicate is verified. The predicate should
accept 3 arguments which are the path to reach the attribute, a part of
the first attribute set and a part of the second attribute set. When
the predicate is satisfied, the value of the first attribute set is
replaced by the value of the second attribute set.
# Inputs
`pred`
: Predicate, taking the path to the current attribute as a list of strings for attribute names, and the two values at that path from the original arguments.
`lhs`
: Left attribute set of the merge.
`rhs`
: Right attribute set of the merge.
# Type
```
recursiveUpdateUntil :: ( [ String ] -> AttrSet -> AttrSet -> Bool ) -> AttrSet -> AttrSet -> AttrSet
```
# Examples
:::{.example}
## `lib.attrsets.recursiveUpdateUntil` usage example
```nix
recursiveUpdateUntil (path: l: r: path == ["foo"]) {
# first attribute set
foo.bar = 1;
foo.baz = 2;
bar = 3;
} {
#second attribute set
foo.bar = 1;
foo.quz = 2;
baz = 4;
}
=> {
foo.bar = 1; # 'foo.*' from the second set
foo.quz = 2; #
bar = 3; # 'bar' from the first set
baz = 4; # 'baz' from the second set
}
```
:::
*/
recursiveUpdateUntil =
pred: lhs: rhs:
let
f =
attrPath:
builtins.zipAttrsWith (
n: values:
let
here = attrPath ++ [ n ];
in
if builtins.length values == 1 || pred here (builtins.elemAt values 1) (builtins.head values) then
builtins.head values
else
f here values
);
in
f
[ ]
[
rhs
lhs
];
/**
A recursive variant of the update operator //. The recursion
stops when one of the attribute values is not an attribute set,
in which case the right hand side value takes precedence over the
left hand side value.
# Inputs
`lhs`
: Left attribute set of the merge.
`rhs`
: Right attribute set of the merge.
# Type
```
recursiveUpdate :: AttrSet -> AttrSet -> AttrSet
```
# Examples
:::{.example}
## `lib.attrsets.recursiveUpdate` usage example
```nix
recursiveUpdate {
boot.loader.grub.enable = true;
boot.loader.grub.device = "/dev/hda";
} {
boot.loader.grub.device = "";
}
returns: {
boot.loader.grub.enable = true;
boot.loader.grub.device = "";
}
```
:::
*/
recursiveUpdate =
lhs: rhs:
recursiveUpdateUntil (
_: lhs: rhs:
!(builtins.isAttrs lhs && builtins.isAttrs rhs)
) lhs rhs;
/**
Determine whether a string has given prefix.
# Inputs
`pref`
: Prefix to check for
`str`
: Input string
# Type
```
hasPrefix :: string -> string -> bool
```
# Examples
:::{.example}
## `lib.strings.hasPrefix` usage example
```nix
hasPrefix "foo" "foobar"
=> true
hasPrefix "foo" "barfoo"
=> false
```
:::
*/
hasPrefix = pref: str: (builtins.substring 0 (builtins.stringLength pref) str == pref);
/**
Escape occurrence of the elements of `list` in `string` by
prefixing it with a backslash.
# Inputs
`list`
: 1\. Function argument
`string`
: 2\. Function argument
# Type
```
escape :: [string] -> string -> string
```
# Examples
:::{.example}
## `lib.strings.escape` usage example
```nix
escape ["(" ")"] "(foo)"
=> "\\(foo\\)"
```
:::
*/
escape = list: builtins.replaceStrings list (builtins.map (c: "\\${c}") list);
/**
Convert a string `s` to a list of characters (i.e. singleton strings).
This allows you to, e.g., map a function over each character. However,
note that this will likely be horribly inefficient; Nix is not a
general purpose programming language. Complex string manipulations
should, if appropriate, be done in a derivation.
Also note that Nix treats strings as a list of bytes and thus doesn't
handle unicode.
# Inputs
`s`
: 1\. Function argument
# Type
```
stringToCharacters :: string -> [string]
```
# Examples
:::{.example}
## `lib.strings.stringToCharacters` usage example
```nix
stringToCharacters ""
=> [ ]
stringToCharacters "abc"
=> [ "a" "b" "c" ]
stringToCharacters "🦄"
=> [ "<EFBFBD>" "<EFBFBD>" "<EFBFBD>" "<EFBFBD>" ]
```
:::
*/
stringToCharacters = s: builtins.genList (p: builtins.substring p 1 s) (builtins.stringLength s);
/**
Turn a string `s` into an exact regular expression
# Inputs
`s`
: 1\. Function argument
# Type
```
escapeRegex :: string -> string
```
# Examples
:::{.example}
## `lib.strings.escapeRegex` usage example
```nix
escapeRegex "[^a-z]*"
=> "\\[\\^a-z]\\*"
```
:::
*/
escapeRegex = escape (stringToCharacters "\\[{()^$?*+|.");
/**
Appends string context from string like object `src` to `target`.
:::{.warning}
This is an implementation
detail of Nix and should be used carefully.
:::
Strings in Nix carry an invisible `context` which is a list of strings
representing store paths. If the string is later used in a derivation
attribute, the derivation will properly populate the inputDrvs and
inputSrcs.
# Inputs
`src`
: The string to take the context from. If the argument is not a string,
it will be implicitly converted to a string.
`target`
: The string to append the context to. If the argument is not a string,
it will be implicitly converted to a string.
# Type
```
addContextFrom :: string -> string -> string
```
# Examples
:::{.example}
## `lib.strings.addContextFrom` usage example
```nix
pkgs = import <nixpkgs> { };
addContextFrom pkgs.coreutils "bar"
=> "bar"
```
The context can be displayed using the `toString` function:
```nix
nix-repl> builtins.getContext (lib.strings.addContextFrom pkgs.coreutils "bar")
{
"/nix/store/m1s1d2dk2dqqlw3j90jl3cjy2cykbdxz-coreutils-9.5.drv" = { ... };
}
```
:::
*/
addContextFrom = src: target: builtins.substring 0 0 src + target;
/**
Cut a string with a separator and produces a list of strings which
were separated by this separator.
# Inputs
`sep`
: 1\. Function argument
`s`
: 2\. Function argument
# Type
```
splitString :: string -> string -> [string]
```
# Examples
:::{.example}
## `lib.strings.splitString` usage example
```nix
splitString "." "foo.bar.baz"
=> [ "foo" "bar" "baz" ]
splitString "/" "/usr/local/bin"
=> [ "" "usr" "local" "bin" ]
```
:::
*/
splitString =
sep: s:
let
splits = builtins.filter builtins.isString (
builtins.split (escapeRegex (builtins.toString sep)) (builtins.toString s)
);
in
builtins.map (addContextFrom s) splits;
/**
Remove duplicate elements from the `list`. O(n^2) complexity.
# Inputs
`list`
: Input list
# Type
```
unique :: [a] -> [a]
```
# Examples
:::{.example}
## `lib.lists.unique` usage example
```nix
unique [ 3 2 3 4 ]
=> [ 3 2 4 ]
```
:::
*/
unique = builtins.foldl' (acc: e: if builtins.elem e acc then acc else acc ++ [ e ]) [ ];
/**
Flip the order of the arguments of a binary function.
# Inputs
`f`
: 1\. Function argument
`a`
: 2\. Function argument
`b`
: 3\. Function argument
# Type
```
flip :: (a -> b -> c) -> (b -> a -> c)
```
# Examples
:::{.example}
## `lib.trivial.flip` usage example
```nix
flip concat [1] [2]
=> [ 2 1 ]
```
:::
*/
flip =
f: a: b:
f b a;
/**
`warn` *`message`* *`value`*
Print a warning before returning the second argument.
See [`builtins.warn`](https://nix.dev/manual/nix/latest/language/builtins.html#builtins-warn) (Nix >= 2.23).
On older versions, the Nix 2.23 behavior is emulated with [`builtins.trace`](https://nix.dev/manual/nix/latest/language/builtins.html#builtins-warn), including the [`NIX_ABORT_ON_WARN`](https://nix.dev/manual/nix/latest/command-ref/conf-file#conf-abort-on-warn) behavior, but not the `nix.conf` setting or command line option.
# Inputs
*`message`* (String)
: Warning message to print before evaluating *`value`*.
*`value`* (any value)
: Value to return as-is.
# Type
```
String -> a -> a
```
*/
warn =
# Since Nix 2.23, https://github.com/NixOS/nix/pull/10592
builtins.warn or (
let
mustAbort = builtins.elem (builtins.getEnv "NIX_ABORT_ON_WARN") [
"1"
"true"
"yes"
];
in
# Do not eta reduce v, so that we have the same strictness as `builtins.warn`.
msg: v:
# `builtins.warn` requires a string message, so we enforce that in our implementation, so that callers aren't accidentally incompatible with newer Nix versions.
assert builtins.isString msg;
if mustAbort then
builtins.trace "evaluation warning: ${msg}" (
abort "NIX_ABORT_ON_WARN=true; warnings are treated as unrecoverable errors."
)
else
builtins.trace "evaluation warning: ${msg}" v
);
}

View file

@ -0,0 +1,46 @@
# SPDX-FileCopyrightText: 2024 Ryan Lahfa <ryan.lahfa@dgnum.eu>
#
# SPDX-License-Identifier: EUPL-1.2
{
modulesPath,
sourcePkgs,
name,
...
}:
{
imports = [
"${modulesPath}/wlan.nix"
"${modulesPath}/network"
"${modulesPath}/hostapd"
"${modulesPath}/usteer"
"${modulesPath}/ssh"
"${modulesPath}/ntp"
"${modulesPath}/vlan"
"${modulesPath}/bridge"
"${modulesPath}/jitter-rng"
"${modulesPath}/pki"
"${modulesPath}/ubus"
# System-level configuration
./system.nix
# Configures our own WLAN.
./wlan.nix
# Configures our IPv4/IPv6 addresses, e.g. DHCPv4 on VLAN 0, SLAAC on VLAN 3001.
./addresses.nix
# Configures a basic local DNS.
./dns.nix
# Configures our management layer, e.g. SSH server + DGNum FAI keys.
./management.nix
# Configures our recovery system, e.g. a levitation script.
./recovery.nix
# ubus
./ipc.nix
# Metadata on the system for field recovery.
./metadata.nix
# TODO: god that's so a fucking hack.
(import "${modulesPath}/../devices/zyxel-nwa50ax").module
];
hostname = name;
nixpkgs.source = sourcePkgs.path;
}

View file

@ -0,0 +1,27 @@
# SPDX-FileCopyrightText: 2024 Ryan Lahfa <ryan.lahfa@dgnum.eu>
#
# SPDX-License-Identifier: EUPL-1.2
{ config, nodeMeta, ... }:
let
svc = config.system.service;
inherit (nodeMeta.extraNodeSettings) ap-no;
adminIp = "192.168.1.${builtins.toString (ap-no + 10)}";
in
{
# Our bridging is a bit complicated, therefore, we need iproute2.
programs.iproute2.enable = true;
services.admin-ip = svc.network.address.build {
interface = config.hardware.networkInterfaces.lan;
address = adminIp;
prefixLength = 24;
family = "inet";
};
services.admin-defaultroute4 = svc.network.route.build {
via = "192.168.1.254";
target = "default";
dependencies = [ config.services.admin-ip ];
};
}

View file

@ -0,0 +1,25 @@
# SPDX-FileCopyrightText: 2024 Ryan Lahfa <ryan.lahfa@dgnum.eu>
#
# SPDX-License-Identifier: EUPL-1.2
{ pkgs, lib, ... }:
let
inherit (pkgs.pseudofile) dir symlink;
# TODO: imho, DNS should be static and provided by the router?
dns = [
"8.8.8.8"
"8.8.4.4"
"1.0.0.1"
];
resolvconf = pkgs.writeText "resolv.conf" (
lib.concatMapStringsSep "\n" (dns: ''echo "nameserver ${dns}" >> resolv.conf'') dns
);
in
{
# TODO: support dynamic reconfiguration once we are in the target VLAN?
filesystem = dir {
etc = dir {
"resolv.conf" = symlink "${resolvconf}";
};
};
}

View file

@ -10,6 +10,7 @@ in
# SSH keys are handled by the access control module.
dgn-access-control.enable = true;
users.root = {
# TODO: Change this well-known password
passwd = "$6$Z2MiaMXkpUJRPl2/$fxVE3iD/n208CISM2F6OnWj0Qq0QG2tTQqLCjU80PFJJGIwNLLyOp6SeYH3dH20OvJX1loZRETrThZfIPw.rb/";
};
services.sshd = svc.ssh.build { allowRoot = true; };

View file

@ -0,0 +1,53 @@
# SPDX-FileCopyrightText: 2024 Ryan Lahfa <ryan.lahfa@dgnum.eu>
#
# SPDX-License-Identifier: EUPL-1.2
{
config,
pkgs,
modulesPath,
...
}:
let
parentConfig = config;
in
{
defaultProfile.packages = [
# Levitate enable us to mass-reinstall the system on the fly.
# TODO: Test levitation
(pkgs.levitate.override {
config = {
imports = [
"${modulesPath}/network"
"${modulesPath}/ssh"
"${modulesPath}/hardware.nix"
"${modulesPath}/kernel"
"${modulesPath}/outputs/tftpboot.nix"
"${modulesPath}/outputs.nix"
# FIXME: DHCP has a hidden deps on this, shoud be done in a more intelligent way upstream
"${modulesPath}/iproute2.nix"
(_: {
# FIXME: DHCP has a hidden deps on this, shoud be done in a more intelligent way upstream
programs.iproute2.enable = true;
services = {
inherit (parentConfig.services)
sshd
admin-ip
admin-defaultroute4
;
};
})
];
hostname = "${parentConfig.hostname}-live";
nixpkgs.buildPlatform = builtins.currentSystem;
defaultProfile.packages = with pkgs; [
mtdutils
zyxel-bootconfig
];
# Only keep root, which should inherit from DGN access control's root permissions.
users.root = config.users.root;
};
})
];
}

View file

@ -0,0 +1,34 @@
# SPDX-FileCopyrightText: 2024 Ryan Lahfa <ryan.lahfa@dgnum.eu>
#
# SPDX-License-Identifier: EUPL-1.2
{ pkgs, config, ... }:
let
svc = config.system.service;
in
{
# Get moar random please
services = {
jitter = svc.jitter-rng.build { };
packet_forwarding = svc.network.forward.build { };
ntp = config.system.service.ntp.build {
pools = {
"pool.ntp.org" = [ "iburst" ];
};
dependencies = [ config.services.jitter ];
};
};
boot.tftp = {
serverip = "192.0.2.10";
ipaddr = "192.0.2.12";
};
defaultProfile.packages = with pkgs; [
zyxel-bootconfig
iw
min-collect-garbage
ubus
];
}

View file

@ -2,14 +2,28 @@
#
# SPDX-License-Identifier: EUPL-1.2
{ config, pkgs, ... }:
{
config,
pkgs,
lib,
nodeMeta,
...
}:
let
svc = config.system.service;
inherit (nodeMeta.extraNodeSettings) ap-no;
hex = x: lib.fixedWidthString 2 "0" (lib.toHexString x);
mac-1 = "02:5B:6B:00:00:${hex ap-no}";
mac-2 = "02:5B:6B:01:00:${hex ap-no}";
secrets-1 = {
ssid = "DGNum 2G (N)";
ssid = "DGNum";
};
secrets-2 = {
ssid = "DGNum 5G (AX)";
ssid = "DGNum";
};
baseParams = {
country_code = "FR";
@ -22,6 +36,9 @@ let
wpa = 2;
wpa_pairwise = "TKIP CCMP";
rsn_pairwise = "CCMP";
bss_transition = 1;
rrm_neighbor_report = 1;
rrm_beacon_report = 1;
};
radiusKeyMgmt = {
@ -42,7 +59,7 @@ let
vht_capab = "[MAX-MPDU-7991][SU-BEAMFORMEE][SU-BEAMFORMER][RXLDPC][SHORT-GI-80][MAX-A-MPDU-LEN-EXP3][RX-ANTENNA-PATTERN][TX-ANTENNA-PATTERN][TX-STBC-2BY1][RX-STBC-1][MU-BEAMFORMER]";
vht_oper_chwidth = 1;
he_oper_chwidth = 1;
channel = 36;
channel = 36; # TODO understand interferences
vht_oper_centr_freq_seg0_idx = 42;
he_oper_centr_freq_seg0_idx = 42;
require_vht = 1;
@ -52,7 +69,7 @@ let
ieee8021x = 1;
eapol_version = 2;
use_pae_group_addr = 1;
dynamic_vlan = 0;
dynamic_vlan = 3;
vlan_tagged_interface = "lan";
};
@ -64,7 +81,14 @@ let
# No DNS here, hostapd do not support this mode.
auth_server_addr = "129.199.195.129";
auth_server_port = 1812;
auth_server_shared_secret = "read it online";
auth_server_shared_secret =
let
secret = builtins.getEnv "RADIUS_SECRET";
in
if secret == "" then
lib.warn "Using a dummy RADIUS secret. Please do not use in production" "DUMMYSECRET"
else
secret;
};
mkWifiSta =
@ -77,10 +101,22 @@ let
};
in
{
hardware.wlanMacAddresses = {
wlan0 = mac-1;
wlan1 = mac-2;
};
services = {
usteer = svc.usteer.build {
ifname = "lan";
dependencies = [
# TODO is it the right stuff to deend on ?
config.services.hostap-1-ready
config.services.hostap-2-ready
];
};
# wlan0 is the 2.4GHz interface.
hostap-1 = mkWifiSta (
baseParams // radiusKeyMgmt
baseParams // clientRadius // externalRadius // radiusKeyMgmt
) config.hardware.networkInterfaces.wlan0 secrets-1;
hostap-1-ready = svc.hostapd-ready.build {
interface = config.hardware.networkInterfaces.wlan0;

View file

@ -5,6 +5,7 @@
{
modulesPath,
sourcePkgs,
name,
...
}:
{
@ -12,6 +13,7 @@
"${modulesPath}/wlan.nix"
"${modulesPath}/network"
"${modulesPath}/hostapd"
"${modulesPath}/usteer"
"${modulesPath}/ssh"
"${modulesPath}/ntp"
"${modulesPath}/vlan"
@ -29,6 +31,8 @@
./addresses.nix
# Configures a basic local DNS.
./dns.nix
# Add ubus daemon
./ipc.nix
# Configures our management layer, e.g. SSH server + DGNum FAI keys.
./management.nix
# Configures our recovery system, e.g. a levitation script.
@ -39,6 +43,6 @@
(import "${modulesPath}/../devices/zyxel-nwa50ax").module
];
hostname = "ap01-prototype";
hostname = name;
nixpkgs.source = sourcePkgs.path;
}

View file

@ -0,0 +1,25 @@
# SPDX-FileCopyrightText: 2024 Ryan Lahfa <ryan.lahfa@dgnum.eu>
#
# SPDX-License-Identifier: EUPL-1.2
{ config, nodeMeta, ... }:
let
svc = config.system.service;
inherit (nodeMeta.extraNodeSettings) building floor ap-no;
# FIXME switch to ipv6 tu be able to scale
adminIp = "10.0.253.${builtins.toString (ap-no + floor * 8 + building * 32 + 2)}";
in
{
services.admin-ip = svc.network.address.build {
interface = config.services.admin-vlan;
address = adminIp;
prefixLength = 24;
family = "inet";
};
services.admin-defaultroute4 = svc.network.route.build {
via = "10.0.253.1";
target = "default";
dependencies = [ config.services.admin-ip ];
};
}

View file

@ -0,0 +1,25 @@
# SPDX-FileCopyrightText: 2024 Ryan Lahfa <ryan.lahfa@dgnum.eu>
#
# SPDX-License-Identifier: EUPL-1.2
{ pkgs, lib, ... }:
let
inherit (pkgs.pseudofile) dir symlink;
# TODO: imho, DNS should be static and provided by the router?
dns = [
"8.8.8.8"
"8.8.4.4"
"1.0.0.1"
];
resolvconf = pkgs.writeText "resolv.conf" (
lib.concatMapStringsSep "\n" (dns: ''echo "nameserver ${dns}" >> resolv.conf'') dns
);
in
{
# TODO: support dynamic reconfiguration once we are in the target VLAN?
filesystem = dir {
etc = dir {
"resolv.conf" = symlink "${resolvconf}";
};
};
}

View file

@ -0,0 +1,12 @@
# SPDX-FileCopyrightText: 2024 Ryan Lahfa <ryan.lahfa@dgnum.eu>
#
# SPDX-License-Identifier: EUPL-1.2
{ config, ... }:
let
svc = config.system.service;
in
{
# ubus socket for various needs.
services.ubus = svc.ubus.build { };
}

View file

@ -0,0 +1,20 @@
# SPDX-FileCopyrightText: 2024 Ryan Lahfa <ryan.lahfa@dgnum.eu>
#
# SPDX-License-Identifier: EUPL-1.2
{ config, ... }:
let
svc = config.system.service;
in
{
# Our bridging is a bit complicated, therefore, we need iproute2.
programs.iproute2.enable = true;
services = {
admin-vlan = svc.vlan.build {
ifname = "admin";
primary = config.hardware.networkInterfaces.lan;
vid = "3001";
};
};
}

View file

@ -0,0 +1,17 @@
# SPDX-FileCopyrightText: 2024 Ryan Lahfa <ryan.lahfa@dgnum.eu>
#
# SPDX-License-Identifier: EUPL-1.2
{ config, ... }:
let
svc = config.system.service;
in
{
# SSH keys are handled by the access control module.
dgn-access-control.enable = true;
users.root = {
# TODO: Change this well-known password
passwd = "$6$Z2MiaMXkpUJRPl2/$fxVE3iD/n208CISM2F6OnWj0Qq0QG2tTQqLCjU80PFJJGIwNLLyOp6SeYH3dH20OvJX1loZRETrThZfIPw.rb/";
};
services.sshd = svc.ssh.build { allowRoot = true; };
}

View file

@ -0,0 +1,19 @@
# SPDX-FileCopyrightText: 2024 Ryan Lahfa <ryan.lahfa@dgnum.eu>
#
# SPDX-License-Identifier: EUPL-1.2
{ pkgs, ... }:
let
inherit (pkgs.pseudofile) dir;
in
{
filesystem = dir {
etc = dir {
"nixpkgs.version" = {
type = "f";
file = "${pkgs.lib.version}";
mode = "0444";
};
};
};
}

View file

@ -0,0 +1,68 @@
# SPDX-FileCopyrightText: 2024 Ryan Lahfa <ryan.lahfa@dgnum.eu>
#
# SPDX-License-Identifier: EUPL-1.2
{
config,
pkgs,
modulesPath,
...
}:
let
svc = config.system.service;
parentConfig = config;
in
{
defaultProfile.packages = [
# Levitate enable us to mass-reinstall the system on the fly.
# TODO: Test levitation
(pkgs.levitate.override {
config = {
imports = [
"${modulesPath}/network"
"${modulesPath}/ssh"
"${modulesPath}/hardware.nix"
"${modulesPath}/kernel"
"${modulesPath}/outputs/tftpboot.nix"
"${modulesPath}/outputs.nix"
# FIXME: DHCP has a hidden deps on this, shoud be done in a more intelligent way upstream
"${modulesPath}/iproute2.nix"
(
{ config, ... }:
{
# FIXME: DHCP has a hidden deps on this, shoud be done in a more intelligent way upstream
programs.iproute2.enable = true;
services = {
# In this situation, we fallback to the appro VLAN but keep admin vlan.
# Simplest DHCPv4 we can find.
dhcpv4 = svc.network.dhcp.client.build {
interface = parentConfig.hardware.networkInterfaces.lan;
};
inherit (parentConfig.services)
sshd
admin-vlan
admin-ip
admin-defaultroute4
;
defaultroute4 = svc.network.route.build {
via = "$(output ${config.services.dhcpv4} router)";
target = "default";
dependencies = [ config.services.dhcpv4 ];
};
};
}
)
];
hostname = "${parentConfig.hostname}-live";
nixpkgs.buildPlatform = builtins.currentSystem;
defaultProfile.packages = with pkgs; [
mtdutils
zyxel-bootconfig
];
# Only keep root, which should inherit from DGN access control's root permissions.
users.root = config.users.root;
};
})
];
}

View file

@ -0,0 +1,131 @@
# SPDX-FileCopyrightText: 2024 Ryan Lahfa <ryan.lahfa@dgnum.eu>
#
# SPDX-License-Identifier: EUPL-1.2
{
config,
pkgs,
lib,
nodeMeta,
...
}:
let
svc = config.system.service;
inherit (nodeMeta.extraNodeSettings) building floor ap-no;
hex = x: lib.fixedWidthString 2 "0" (lib.toHexString x);
mac-1 = "02:5B:6A:${hex (building * 4)}:${hex floor}:${hex ap-no}";
mac-2 = "02:5B:6A:${hex (building * 4 + 1)}:${hex floor}:${hex ap-no}";
secrets-1 = {
ssid = "DGNum 2G";
};
secrets-2 = {
ssid = "DGNum 5G";
};
baseParams = {
country_code = "FR";
hw_mode = "g";
channel = 6;
wmm_enabled = 1;
ieee80211n = 1;
ht_capab = "[LDPC][GF][HT40-][HT40+][SHORT-GI-40][MAX-AMSDU-7935][TX-STBC]";
auth_algs = 1;
wpa = 2;
wpa_pairwise = "TKIP CCMP";
rsn_pairwise = "CCMP";
};
radiusKeyMgmt = {
wpa_key_mgmt = "WPA-EAP";
};
modernParams = {
hw_mode = "a";
he_su_beamformer = 1;
he_su_beamformee = 1;
he_mu_beamformer = 1;
preamble = 1;
# Allow radar detection.
ieee80211d = 1;
ieee80211h = 1;
ieee80211ac = 1;
ieee80211ax = 1;
vht_capab = "[MAX-MPDU-7991][SU-BEAMFORMEE][SU-BEAMFORMER][RXLDPC][SHORT-GI-80][MAX-A-MPDU-LEN-EXP3][RX-ANTENNA-PATTERN][TX-ANTENNA-PATTERN][TX-STBC-2BY1][RX-STBC-1][MU-BEAMFORMER]";
vht_oper_chwidth = 1;
he_oper_chwidth = 1;
channel = 36; # TODO understand interferences
vht_oper_centr_freq_seg0_idx = 42;
he_oper_centr_freq_seg0_idx = 42;
require_vht = 1;
};
clientRadius = {
ieee8021x = 1;
eapol_version = 2;
use_pae_group_addr = 1;
dynamic_vlan = 3;
vlan_tagged_interface = "lan";
};
externalRadius = {
# TODO: when we have proper IPAM, set the right value here.
own_ip_addr = "127.0.0.1";
nas_identifier = "ap01.dgnum.eu";
# No DNS here, hostapd do not support this mode.
auth_server_addr = "129.199.195.129";
auth_server_port = 1812;
auth_server_shared_secret =
let
secret = builtins.getEnv "RADIUS_SECRET";
in
if secret == "" then
lib.warn "Using a dummy RADIUS secret. Please do not use in production" "DUMMYSECRET"
else
secret;
};
mkWifiSta =
params: interface: secrets:
svc.hostapd.build {
inherit interface;
package = pkgs.hostapd-radius;
params = params // secrets;
dependencies = [ config.services.jitter ];
};
in
{
hardware.wlanMacAddresses = {
wlan0 = mac-1;
wlan1 = mac-2;
};
services = {
# wlan0 is the 2.4GHz interface.
hostap-1 = mkWifiSta (
baseParams // clientRadius // externalRadius // radiusKeyMgmt
) config.hardware.networkInterfaces.wlan0 secrets-1;
hostap-1-ready = svc.hostapd-ready.build {
interface = config.hardware.networkInterfaces.wlan0;
};
# wlan1 is the 5GHz interface, e.g. AX capable.
hostap-2 = mkWifiSta (
baseParams // clientRadius // externalRadius // radiusKeyMgmt // modernParams
) config.hardware.networkInterfaces.wlan1 secrets-2;
# Oneshot that waits until the hostapd has set the interface in operational state.
hostap-2-ready = svc.hostapd-ready.build {
interface = config.hardware.networkInterfaces.wlan1;
};
usteer = svc.usteer.build {
ifname = "lan";
dependencies = with config.services; [
# FIXME: is it the right stuff to depend on
hostap-1-ready
hostap-2-ready
admin-defaultroute4
];
};
};
}

View file

@ -1,22 +0,0 @@
# SPDX-FileCopyrightText: 2024 Ryan Lahfa <ryan.lahfa@dgnum.eu>
#
# SPDX-License-Identifier: EUPL-1.2
{ config, ... }:
let
svc = config.system.service;
in
{
services.dhcpv4 = svc.network.dhcp.client.build {
interface = config.services.int;
dependencies = [
config.services.bridge.components.lan
];
};
services.defaultroute4 = svc.network.route.build {
via = "$(output ${config.services.dhcpv4} router)";
target = "default";
dependencies = [ config.services.dhcpv4 ];
};
}

View file

@ -1,34 +0,0 @@
# SPDX-FileCopyrightText: 2024 Ryan Lahfa <ryan.lahfa@dgnum.eu>
#
# SPDX-License-Identifier: EUPL-1.2
{ config, pkgs, ... }:
let
inherit (pkgs.liminix.services) oneshot;
inherit (pkgs.pseudofile) dir symlink;
inherit (pkgs) serviceFns;
in
{
# TODO: support dynamic reconfiguration once we are in the target VLAN?
services.resolvconf = oneshot rec {
name = "resolvconf";
up = ''
. ${serviceFns}
( in_outputs ${name}
for i in $(output ${config.services.dhcpv4} dns); do
echo "nameserver $i" >> resolv.conf
done
)
'';
dependencies = [
config.services.dhcpv4
];
};
filesystem = dir {
etc = dir {
"resolv.conf" = symlink "${config.services.resolvconf}/.outputs/resolv.conf";
};
};
}

View file

@ -1,43 +0,0 @@
# SPDX-FileCopyrightText: 2024 Ryan Lahfa <ryan.lahfa@dgnum.eu>
#
# SPDX-License-Identifier: EUPL-1.2
{ config, ... }:
let
svc = config.system.service;
in
{
services.int = svc.bridge.primary.build {
ifname = "int";
macAddressFromInterface = config.hardware.networkInterfaces.lan;
};
services.bridge = svc.bridge.members.build {
primary = config.services.int;
members = {
lan.member = config.hardware.networkInterfaces.lan;
wlan0 = {
member = config.hardware.networkInterfaces.wlan0;
# Bridge only once hostapd is ready.
dependencies = [ config.services.hostap-1-ready ];
};
wlan1 = {
member = config.hardware.networkInterfaces.wlan1;
# Bridge only once hostapd is ready.
dependencies = [ config.services.hostap-2-ready ];
};
};
};
# Default VLAN
# services.vlan-apro = svc.vlan.build {
# vlanId = 0;
# interface = config.services.int;
# };
# # Administration VLAN
# services.vlan-admin = svc.vlan.build {
# vlan = 3001;
# interface = config.services.int;
# };
}

View file

@ -1,49 +0,0 @@
# SPDX-FileCopyrightText: 2024 Ryan Lahfa <ryan.lahfa@dgnum.eu>
#
# SPDX-License-Identifier: EUPL-1.2
{
config,
pkgs,
modulesPath,
...
}:
let
svc = config.system.service;
in
{
defaultProfile.packages = with pkgs; [
# Levitate enable us to mass-reinstall the system on the fly.
(levitate.override {
config = {
imports = [
"${modulesPath}/network"
"${modulesPath}/ssh"
"${modulesPath}/hardware.nix"
"${modulesPath}/kernel"
"${modulesPath}/outputs/tftpboot.nix"
"${modulesPath}/outputs.nix"
];
nixpkgs.buildPlatform = builtins.currentSystem;
services = {
# In this situation, we fallback to the appro VLAN.
# TODO: add support for the admin VLAN.
# Simplest DHCPv4 we can find.
dhcpv4 = svc.network.dhcp.client.build {
interface = config.hardware.networkInterfaces.lan;
};
inherit (config.services) sshd;
defaultroute4 = svc.network.route.build {
via = "$(output ${config.services.dhcpv4} router)";
target = "default";
dependencies = [ config.services.dhcpv4 ];
};
};
defaultProfile.packages = [ mtdutils ];
# Only keep root, which should inherit from DGN access control's root permissions.
users.root = config.users.root;
};
})
];
}

View file

@ -1,29 +0,0 @@
# SPDX-FileCopyrightText: 2025 Lubin Bailly <lubin.bailly@dgnum.eu>
#
# SPDX-License-Identifier: EUPL-1.2
{
dgn-hardware.model = "EX2300-48P";
dgn-isp = {
enable = true;
AP = [
"ge-0/0/0"
"ge-0/0/1"
"ge-0/0/2"
"ge-0/0/3"
"ge-0/0/4"
"ge-0/0/5"
];
admin-ip = "fd26:baf9:d250:8000::2001/64";
};
dgn-interfaces = {
# netcore02
"xe-0/1/0".ethernet-switching = {
interface-mode = "trunk";
vlans = [ "all" ];
};
# debug management
"me0".inet.addresses = [ "192.168.42.6/24" ];
};
}

View file

@ -1,36 +0,0 @@
# SPDX-FileCopyrightText: 2025 Lubin Bailly <lubin.bailly@dgnum.eu>
#
# SPDX-License-Identifier: EUPL-1.2
{
dgn-hardware.model = "EX2300-48P";
dgn-isp = {
enable = true;
admin-ip = "fd26:baf9:d250:8000::100f/64";
};
dgn-profiles."hypervisor" = {
interfaces = [
"ge-0/0/0"
"ge-0/0/1"
"ge-0/0/2"
"ge-0/0/3"
"ge-0/0/4"
"ge-0/0/5"
"ge-0/0/6"
"ge-0/0/7"
];
configuration.ethernet-switching = {
interface-mode = "access";
vlans = [ "hypervisor" ];
};
};
dgn-interfaces = {
"xe-0/2/0".ethernet-switching = {
interface-mode = "trunk";
vlans = [ "all" ];
};
# debug management
"me0".inet.addresses = [ "192.168.2.2/24" ];
};
}

View file

@ -2,41 +2,76 @@
#
# SPDX-License-Identifier: EUPL-1.2
{
dgn-hardware.model = "EX2300-48P";
dgn-isp = {
enable = true;
AP = [
# H1-00
"ge-0/0/0"
"ge-0/0/1"
"ge-0/0/2"
"ge-0/0/3"
"ge-0/0/4"
"ge-0/0/5"
# H1-01
"ge-0/0/6"
"ge-0/0/7"
"ge-0/0/8"
"ge-0/0/9"
"ge-0/0/10"
"ge-0/0/11"
# H1-02
"ge-0/0/12"
"ge-0/0/13"
"ge-0/0/14"
"ge-0/0/15"
"ge-0/0/16"
"ge-0/0/17"
let
#TODO: meta
vlansPlan = {
"uplink-cri".id = 223;
"admin-core" = {
id = 3000;
l3-interface = "irb.0";
};
"admin-ap".id = 3001;
"users".id-list = [
{
begin = 3045;
end = 4094;
}
];
admin-ip = "fd26:baf9:d250:8000::1001/64";
"ap-staging".id = 2000;
};
#TODO: additionnal module (always the same for APs)
AP-staging = {
poe = true;
ethernet-switching = {
interface-mode = "access";
vlans = [ "ap-staging" ];
};
};
in
{
vlans = vlansPlan;
dgn-hardware.model = "EX2300-48P";
dgn-interfaces = {
# "ge-0/0/0" = AP-staging;
# "ge-0/0/1" = AP-staging;
# "ge-0/0/2" = AP-staging;
# "ge-0/0/3" = AP-staging;
"ge-0/0/4" = AP-staging;
# "ge-0/0/5" = AP-staging;
# "ge-0/0/6" = AP-staging;
# "ge-0/0/7" = AP-staging;
# "ge-0/0/8" = AP-staging;
# "ge-0/0/9" = AP-staging;
# "ge-0/0/10" = AP-staging;
# "ge-0/0/11" = AP-staging;
# "ge-0/0/12" = AP-staging;
# "ge-0/0/13" = AP-staging;
# "ge-0/0/14" = AP-staging;
# "ge-0/0/15" = AP-staging;
# "ge-0/0/16" = AP-staging;
# "ge-0/0/17" = AP-staging;
# oob
"ge-0/0/42".ethernet-switching = {
interface-mode = "trunk";
vlans = [ "all" ];
};
# AP de test
"ge-0/0/43" = {
poe = true;
ethernet-switching = {
interface-mode = "access";
vlans = [ 4000 ];
};
};
# uplink oob
"ge-0/0/46".ethernet-switching = {
interface-mode = "access";
vlans = [ 222 ];
rstp = false;
};
# ilo
"ge-0/0/47".ethernet-switching = {
interface-mode = "access";
@ -60,9 +95,9 @@
};
# netcore01 (Potos)
"xe-0/1/2".ethernet-switching = {
interface-mode = "trunk";
interface-mode = "access";
vlans = [
"all"
"ap-staging"
];
};
# uplink
@ -71,7 +106,8 @@
vlans = [ "uplink-cri" ];
};
# debug management
# management
"me0".inet.addresses = [ "192.168.42.6/24" ];
"irb".inet6.addresses = [ "fd26:baf9:d250:8000::1001/64" ];
};
}

View file

@ -3,17 +3,8 @@
#
# SPDX-License-Identifier: EUPL-1.2
{
pkgs,
utils,
lib,
...
}:
let
inherit (lib)
getExe'
;
in
_:
{
networking = {
useNetworkd = true;
@ -23,84 +14,70 @@ in
firewall.allowedUDPPorts = [ 67 ];
};
systemd = {
services."arp-resolve-router" = {
wantedBy = [ "systemd-networkd.service" ];
after = [ "systemd-networkd-wait-online.service" ];
bindsTo = [ "systemd-networkd-wait-online.service" ];
serviceConfig.ExecStart = utils.escapeSystemdExecArgs [
(getExe' pkgs.iputils "ping")
"-c"
1
"10.120.33.245"
];
};
network = {
wait-online.anyInterface = true;
networks = {
"10-enp1s0f0" = {
name = "enp1s0f0";
# description = "To the switch";
networkConfig = {
VLAN = [
"vlan-admin"
];
LinkLocalAddressing = false;
LLDP = false;
EmitLLDP = false;
IPv6AcceptRA = false;
IPv6SendRA = false;
};
};
"10-eno1" = {
name = "eno1";
# description = "Uplink cri";
address = [
"10.120.33.246/30"
"129.199.195.158/32"
];
routes = [
{
PreferredSource = "129.199.195.158";
Gateway = "10.120.33.245";
}
];
};
"10-vlan-admin" = {
name = "vlan-admin";
# DHCP for the BMC
networkConfig.DHCPServer = "yes";
dhcpServerConfig = {
PoolOffset = 128;
EmitDNS = false;
EmitNTP = false;
EmitSIP = false;
EmitPOP3 = false;
EmitSMTP = false;
EmitLPR = false;
UplinkInterface = ":none";
};
address = [
"fd26:baf9:d250:8000::ffff/64"
"192.168.222.1/24"
systemd.network = {
networks = {
"10-eno1" = {
name = "eno1";
networkConfig = {
VLAN = [
"vlan-admin"
"vlan-uplink-oob"
];
LinkLocalAddressing = false;
LLDP = false;
EmitLLDP = false;
IPv6AcceptRA = false;
IPv6SendRA = false;
};
# address = [ "192.168.222.1/24" ];
};
netdevs = {
"10-vlan-admin" = {
netdevConfig = {
Name = "vlan-admin";
Kind = "vlan";
};
vlanConfig.Id = 3000;
"10-vlan-admin" = {
name = "vlan-admin";
# DHCP for the BMC
networkConfig.DHCPServer = "yes";
dhcpServerConfig = {
PoolOffset = 128;
EmitDNS = false;
EmitNTP = false;
EmitSIP = false;
EmitPOP3 = false;
EmitSMTP = false;
EmitLPR = false;
UplinkInterface = ":none";
};
address = [
"fd26:baf9:d250:8000::ffff/64"
"192.168.222.1/24"
];
};
"10-vlan-uplink-oob" = {
name = "vlan-uplink-oob";
networkConfig.DHCP = "ipv4";
};
};
netdevs = {
"10-vlan-admin" = {
netdevConfig = {
Name = "vlan-admin";
Kind = "vlan";
};
vlanConfig.Id = 3000;
};
"10-vlan-uplink-oob" = {
netdevConfig = {
Name = "vlan-uplink-oob";
Kind = "vlan";
};
vlanConfig.Id = 500;
};
};
};

View file

@ -2,7 +2,7 @@
#
# SPDX-License-Identifier: EUPL-1.2
(import ../../../../keys.nix).mkSecrets
(import ../../../../keys).mkSecrets
[ "bridge01" ]
[
# List of secrets for bridge01

View file

@ -5,7 +5,6 @@
{
pkgs,
lib,
dgn-keys,
meta,
...
}:
@ -13,14 +12,6 @@
config = {
dgn-access-control.users = lib.genAttrs meta.organization.groups.nix-builder (u: lib.singleton u);
# FIXME(Raito): this should really go into `dgn-access-control` but I don't
# know what is the desired architecture for it. Leaving it for the people with opinions™.
users.groups.nix-builders = { };
users.users = lib.genAttrs meta.organization.groups.nix-builder (u: {
extraGroups = [ "nix-builders" ];
openssh.authorizedKeys.keys = dgn-keys.getBuilderKeys u;
});
security.pam.loginLimits = [
{
domain = "*";
@ -52,10 +43,6 @@
nrBuildUsers = 128;
settings = {
trusted-users = [
"@wheel"
"@nix-builders"
];
keep-outputs = false;
keep-derivations = false;
use-cgroups = true;

View file

@ -2,7 +2,7 @@
#
# SPDX-License-Identifier: EUPL-1.2
(import ../../../../keys.nix).mkSecrets
(import ../../../../keys).mkSecrets
[ "build01" ]
[
"forgejo_runners-token_file"

View file

@ -25,7 +25,6 @@ lib.extra.mkConfig {
"kanidm"
"librenms"
"mastodon"
# "netbox"
"nextcloud"
"ollama-proxy"
"outline"

View file

@ -40,7 +40,6 @@ let
ps.gunicorn
ps.psycopg
ps.django-compressor
ps.django-htmx
ps.django-import-export
# Local packages
@ -158,8 +157,6 @@ in
DGSI_ARCHIVES_ROOT = "/var/lib/django-apps/dgsi/archives";
DGSI_ARCHIVES_INTERNAL = "_archives";
DGSI_STAFF_GROUP = "grp_bureau@sso.dgnum.eu";
DGSI_DATABASES = builtins.toJSON {
default = {
ENGINE = "django.db.backends.postgresql";

View file

@ -4,9 +4,7 @@
{
lib,
meta,
sources,
dgn-keys,
...
}:
let
@ -39,7 +37,7 @@ in
"DGNum Infrastructure" =
let
# prefer a non-patched nixpkgs
infra-nixpkgs = (import "${hive-root}/bootstrap.nix").pkgs;
infra-nixpkgs = (import "${hive-root}/hive.nix").meta.nixpkgs { };
infra-modulesPath = "${infra-nixpkgs.path}/nixos/modules/";
in
{
@ -47,7 +45,7 @@ in
"modules/generic"
"modules/nixos"
];
ignored-modules = (import "${infra-modulesPath}/module-list.nix") ++ [
ignored-modules = import "${infra-modulesPath}/module-list.nix" ++ [
"${sources.agenix}/modules/age.nix"
"${sources.arkheon}/module.nix"
"${sources."microvm.nix"}/nixos-modules/host"
@ -55,18 +53,20 @@ in
{ system.stateVersion = "25.05"; }
];
specialArgs = {
inherit meta sources;
modulesPath = builtins.storePath infra-modulesPath;
inherit sources;
lib = infra-nixpkgs.lib // {
inherit (lib) extra;
};
modulesPath = infra-modulesPath;
pkgs = infra-nixpkgs;
inherit (infra-nixpkgs) lib;
name = "nodeName";
nodeMeta = {
nix-modules = [ ];
admins = [ ];
adminGroups = [ ];
};
dgn-keys = dgn-keys // {
getNodeAdmins = _: [ ];
meta = {
organization.groups.root = [ ];
};
};
path-translations = [

View file

@ -2,12 +2,7 @@
#
# SPDX-License-Identifier: EUPL-1.2
{
config,
pkgs,
meta,
...
}:
{ config, ... }:
let
host = "grafana.dgnum.eu";
@ -67,27 +62,6 @@ in
auto_assign_org_role = "Admin";
};
};
declarativePlugins = import ./plugins.nix { inherit pkgs; };
provision = {
enable = true;
datasources.settings.datasources = [
{
name = "VictoriaLogs";
type = "victoriametrics-logs-datasource";
access = "proxy";
url = "http://${meta.network.storage01.netbirdIp}:9428";
}
{
name = "VictoriaMetrics";
type = "victoriametrics-metrics-datasource";
access = "proxy";
url = "http://${meta.network.storage01.netbirdIp}:8428";
}
];
};
};
postgresql = {

View file

@ -1,19 +0,0 @@
# SPDX-FileCopyrightText: 2025 Tom Hubrecht <tom.hubrecht@dgnum.eu>
#
# SPDX-License-Identifier: EUPL-1.2
{ pkgs, ... }:
builtins.map pkgs.grafanaPlugins.grafanaPlugin [
{
pname = "victoriametrics-logs-datasource";
version = "0.14.3";
zipHash = "sha256-g/ntmNyWJ9h/eYpZ0gqiESvVfm2fU6/Ci8R7FHIV7AQ=";
}
{
pname = "victoriametrics-metrics-datasource";
version = "0.13.1";
zipHash = "sha256-n1LskeOzp32LZS3PcsRh8FwQVBFVlzczfO2aGbEClSo=";
}
]

View file

@ -14,10 +14,12 @@ let
inherit (lib)
attrValues
catAttrs
concatLists
escapeRegex
concatStringsSep
mapAttrs'
nameValuePair
unique
;
domain = "sso.dgnum.eu";
@ -81,16 +83,25 @@ in
) meta.organization.members;
groups =
(lib.extra.genFuse (id: { "vlan_${builtins.toString (4094 - id)}".memberless = true; }) 850)
// {
{
grp_active.members = catAttrs "username" (attrValues meta.organization.members);
grp-ext_cri.memberless = true;
}
// (mapAttrs' (
name: members: nameValuePair "grp_${name}" { members = builtins.map usernameFor members; }
) meta.organization.groups)
// (mapAttrs' (
name: srv: nameValuePair "grp-admin_${name}" { members = builtins.map usernameFor srv.admins; }
name:
{
admins ? [ ],
adminGroups ? [ ],
}:
nameValuePair "grp-admin_${name}" {
members = unique (
builtins.map usernameFor (
admins ++ (concatLists (builtins.map (group: meta.organization.groups.${group}) adminGroups))
)
);
}
) meta.organization.services);
# INFO: The authentication resources declared here can only be for internal services,
@ -144,10 +155,7 @@ in
displayName = "Netbox [Inventory]";
enableLegacyCrypto = true;
originLanding = "https://netbox.dgnum.eu";
originUrl = [
"https://netbox.dgnum.eu/oauth/complete/oidc/"
"https://netbox-v2.dgnum.eu/oauth/complete/oidc/"
];
originUrl = "https://netbox.dgnum.eu/oauth/complete/oidc/";
preferShortUsername = true;
scopeMaps.grp_active = [
@ -155,12 +163,6 @@ in
"profile"
"email"
];
scopeMaps.grp-ext_cri = [
"openid"
"profile"
"email"
];
};
dgn_outline = {

View file

@ -2,7 +2,7 @@
#
# SPDX-License-Identifier: EUPL-1.2
(import ../../../../../keys.nix).mkSecrets
(import ../../../../../keys).mkSecrets
[ "compute01" ]
[
"kanidm-password_admin"

View file

@ -1,74 +0,0 @@
# SPDX-FileCopyrightText: 2024 Maurice Debray <maurice.debray@dgnum.eu>
#
# SPDX-License-Identifier: EUPL-1.2
{
config,
lib,
nixpkgs,
...
}:
let
EnvironmentFile = [ config.age.secrets."netbox-environment_file".path ];
in
{
services = {
netbox = {
enable = true;
package = nixpkgs.nixos.unstable.netbox_4_1;
secretKeyFile = "/dev/null";
listenAddress = "127.0.0.1";
plugins = p: [ p.netbox-qrcode ];
settings = {
ALLOWED_HOSTS = [ "netbox-v2.dgnum.eu" ];
REMOTE_AUTH_BACKEND = "social_core.backends.open_id_connect.OpenIdConnectAuth";
PLUGINS = [ "netbox_qrcode" ];
PLUGINS_CONFIG = {
netbox_qrcode = {
custom_text = "DGNum. contact@dgnum.eu";
font = "Tahoma";
};
};
};
extraConfig = lib.mkForce ''
from os import environ as env
SECRET_KEY = env["SECRET_KEY"]
SOCIAL_AUTH_OIDC_OIDC_ENDPOINT = env["NETBOX_OIDC_URL"]
SOCIAL_AUTH_OIDC_KEY = env["NETBOX_OIDC_KEY"]
SOCIAL_AUTH_OIDC_SECRET = env["NETBOX_OIDC_SECRET"]
'';
};
};
systemd.services = {
netbox.serviceConfig = {
inherit EnvironmentFile;
TimeoutStartSec = 600;
};
netbox-housekeeping.serviceConfig = {
inherit EnvironmentFile;
};
netbox-rq.serviceConfig = {
inherit EnvironmentFile;
};
};
users.users.nginx.extraGroups = [ "netbox" ];
dgn-web.simpleProxies.netbox = {
inherit (config.services.netbox) port;
host = "netbox-v2.dgnum.eu";
vhostConfig.locations."/static/".alias = "${config.services.netbox.dataDir}/static/";
};
# dgn-backups.jobs.netbox.settings.paths = [ "/var/lib/netbox" ];
# dgn-backups.postgresDatabases = [ "netbox" ];
}

View file

@ -76,7 +76,7 @@ in
database.createLocally = true;
configureRedis = true;
autoUpdateApps.enable = false;
autoUpdateApps.enable = true;
settings = {
overwriteprotocol = "https";

View file

@ -2,7 +2,7 @@
#
# SPDX-License-Identifier: EUPL-1.2
(import ../../../../keys.nix).mkSecrets
(import ../../../../keys).mkSecrets
[ "compute01" ]
[
# List of secrets for compute01
@ -22,7 +22,6 @@
"librenms-environment_file"
"mastodon-extra_env_file"
"mastodon-smtp-password"
"netbox-environment_file"
"nextcloud-adminpass_file"
"nextcloud-s3_secret_file"
"outline-oidc_client_secret_file"

View file

@ -2,7 +2,7 @@
#
# SPDX-License-Identifier: EUPL-1.2
(import ../../../../keys.nix).mkSecrets
(import ../../../../keys).mkSecrets
[ "geo01" ]
[
# List of secrets for geo01

View file

@ -2,7 +2,7 @@
#
# SPDX-License-Identifier: EUPL-1.2
(import ../../../../keys.nix).mkSecrets
(import ../../../../keys).mkSecrets
[ "geo02" ]
[
# List of secrets for geo02

View file

@ -2,7 +2,7 @@
#
# SPDX-License-Identifer: EUPL-1.2
(import ../../../../keys.nix).mkSecrets
(import ../../../../keys).mkSecrets
[ "hypervisor01" ]
[

View file

@ -2,7 +2,7 @@
#
# SPDX-License-Identifer: EUPL-1.2
(import ../../../../keys.nix).mkSecrets
(import ../../../../keys).mkSecrets
[ "hypervisor02" ]
[

View file

@ -2,7 +2,7 @@
#
# SPDX-License-Identifer: EUPL-1.2
(import ../../../../keys.nix).mkSecrets
(import ../../../../keys).mkSecrets
[ "hypervisor03" ]
[

View file

@ -2,7 +2,7 @@
#
# SPDX-License-Identifier: EUPL-1.2
(import ../../../../keys.nix).mkSecrets
(import ../../../../keys).mkSecrets
[ "rescue01" ]
[
# List of secrets for rescue01

View file

@ -23,8 +23,6 @@ lib.extra.mkConfig {
"peertube"
"prometheus"
"redirections"
"victorialogs"
"victoriametrics"
];
extraConfig = {

View file

@ -14,14 +14,12 @@ let
"lanuit.ens.fr"
"simi.normalesup.eu"
"pub.dgnum.eu"
"actes-administratifs.dgnum.eu"
];
buckets = [
"monorepo-terraform-state"
"banda-website"
"actes-administratifs-website"
"castopod-dgnum"
"hackens-website"
"nuit-website"

View file

@ -17,9 +17,9 @@ let
lib.mapAttrsToList (
node:
{ config, ... }:
lib.optional config.dgn-monitoring.exporters.enable {
lib.optional config.dgn-node-monitoring.enable {
targets = map (p: "${node}.dgnum:${builtins.toString p}") (
builtins.attrValues config.dgn-monitoring.exporters.ports
builtins.attrValues config.dgn-node-monitoring.ports
);
labels = {
host = node;

View file

@ -2,7 +2,7 @@
#
# SPDX-License-Identifier: EUPL-1.2
(import ../../../../keys.nix).mkSecrets
(import ../../../../keys).mkSecrets
[ "storage01" ]
[
# List of secrets for storage01

View file

@ -0,0 +1,20 @@
# SPDX-FileCopyrightText: 2024 Tom Hubrecht <tom.hubrecht@dgnum.eu>
#
# SPDX-License-Identifier: EUPL-1.2
let
host = "victoria-metrics.dgnum.eu";
port = 9099;
in
{
services.victoriametrics = {
enable = true;
listenAddress = "127.0.0.1:${builtins.toString port}";
};
dgn-web.simpleProxies.victoria-metrics = {
inherit host port;
};
}

View file

@ -1,22 +0,0 @@
# SPDX-FileCopyrightText: 2024 Tom Hubrecht <tom.hubrecht@dgnum.eu>
#
# SPDX-License-Identifier: EUPL-1.2
{ meta, name, ... }:
let
port = 9428;
in
{
services.victorialogs = {
enable = true;
flags = {
retentionPeriod = "4w";
httpListenAddr = "${meta.network.${name}.netbirdIp}:${builtins.toString port}";
};
};
networking.firewall.interfaces.wt0.allowedTCPPorts = [ port ];
}

View file

@ -1,23 +0,0 @@
# SPDX-FileCopyrightText: 2024 Tom Hubrecht <tom.hubrecht@dgnum.eu>
#
# SPDX-License-Identifier: EUPL-1.2
{ meta, name, ... }:
let
port = 8428;
in
{
services.victoriametrics = {
enable = true;
flags = {
# INFO: We keep the data for 2 years (24 months)
retentionPeriod = "24";
httpListenAddr = "${meta.network.${name}.netbirdIp}:${builtins.toString port}";
};
};
networking.firewall.interfaces.wt0.allowedTCPPorts = [ port ];
}

View file

@ -2,8 +2,7 @@
#
# SPDX-License-Identifer: EUPL-1.2
(import ../../../../keys.nix).mkSecrets
(import ../../../../keys).mkSecrets
[ "tower01" ]
[
]

View file

@ -12,7 +12,6 @@ lib.extra.mkConfig {
enabledServices = [
# List of services to enable
"k-radius"
"monitoring"
"networking"
"ups"
"ulogd"

View file

@ -1,9 +0,0 @@
# SPDX-FileCopyrightText: 2024 Tom Hubrecht <tom.hubrecht@dgnum.eu>
#
# SPDX-License-Identifier: EUPL-1.2
{
imports = [
./victorialogs.nix
];
}

View file

@ -1,37 +0,0 @@
# SPDX-FileCopyrightText: 2024 Tom Hubrecht <tom.hubrecht@dgnum.eu>
#
# SPDX-License-Identifier: EUPL-1.2
{ meta, ... }:
let
port = 9428;
in
{
services = {
nginx = {
enable = true;
streamConfig = ''
server {
listen 10.0.253.1:${toString port};
listen ${meta.network.vault01.netbirdIp}:${toString port};
proxy_pass 127.0.0.1:${toString port};
}
'';
};
victorialogs = {
enable = true;
flags = {
retentionPeriod = "52w";
httpListenAddr = "127.0.0.1:${builtins.toString port}";
};
};
};
networking.firewall.interfaces = {
wt0.allowedTCPPorts = [ port ];
vlan-admin-ap.allowedTCPPorts = [ port ];
};
}

View file

@ -303,12 +303,10 @@ in
];
script = ''
if ping -c 1 8.8.8.8 > /dev/null || ping -c 1 1.1.1.1 > /dev/null; then
echo network is up
${lib.concatMapStringsSep "\n " (
{ interfaceName, ... }: "networkctl up ${interfaceName}"
) userVlans}
else
echo network is down
${lib.concatMapStringsSep "\n " (
{ interfaceName, ... }: "networkctl down ${interfaceName}"
) userVlans}
@ -338,58 +336,18 @@ in
] ++ userVlans;
nftables = {
enable = true;
tables = {
nat = {
family = "ip";
content = ''
chain postrouting {
type nat hook postrouting priority 100;
ip saddr 10.0.0.0/16 ip daddr != 10.0.0.0/16 snat ip to 129.199.195.130-129.199.195.157
}
'';
};
filter = {
family = "inet";
content = ''
chain forward {
type filter hook forward priority filter; policy accept;
ct state vmap {
invalid: drop,
established: accept,
related: accept,
new: jump forward_decide,
untracked: jump forward_decide,
};
}
chain forward_decide {
# Block access to vpn
ip daddr {
10.10.17.0/30,
100.80.0.0/16,
} jump forward_reject;
# And administrative vlans
ip6 daddr {
fd26:baf9:d250::/48,
} jump forward_reject;
# These are being deployed, and so are not trusted
ip saddr 10.0.255.0/24 jump forward_reject;
# We only forward for ISP clients and our stuff
ip saddr != 10.0.0.0/16 jump forward_reject;
# Can talk to us
ip daddr 10.0.0.0/27 accept;
# Not others nor CRI
ip daddr 10.0.0.0/8 jump forward_reject;
}
chain forward_reject {
reject with icmpx type admin-prohibited;
}
'';
};
tables.nat = {
family = "ip";
content = ''
chain postrouting {
type nat hook postrouting priority 100;
ip saddr 10.0.0.0/16 ip saddr != 10.0.255.0/24 snat ip to 129.199.195.130-129.199.195.157
ether saddr { e0:2e:0b:bd:97:73, e8:d5:2b:0d:fe:4a } snat to 129.199.195.130 comment "Elias"
ether saddr { 1c:1b:b5:14:9c:e5, e6:ce:e2:b6:e3:82 } snat to 129.199.195.131 comment "Lubin"
ether saddr d0:49:7c:46:f6:39 snat to 129.199.195.132 comment "Jean-Marc"
ether saddr { 5c:64:8e:f4:09:06 } snat to 129.199.195.158 comment "APs"
}
'';
};
};
firewall = {
@ -397,9 +355,7 @@ in
67
1194
];
# FIXME: I dont't remember why it's here, and it doesn't seems right
# comes from https://git.dgnum.eu/DGNum/infrastructure/commit/411795c664374549e5e831722a80180b51fbf0d5
# checkReversePath = false;
checkReversePath = false;
};
};

View file

@ -1,32 +1,32 @@
age-encryption.org/v1
-> ssh-ed25519 jIXfPA 2nFaxyP7O4GWU7U3wmET5sNrnFq72b9DEhiKEgWVrFk
l8uXfCBkTHogzVoUY0WOYhA99fodoT+N0HunacULydI
-> ssh-ed25519 QlRB9Q qDalihZE404oPOVHYQR5GIvozXNh4wNxhUa5Zwfz2DU
X8qvWf7qprbh0xu/uOHGsNLTQc8efYsgveH9R9kZZZw
-> ssh-ed25519 r+nK/Q mksHDhPoKKxQpk4sQPHapdq87EaJmgdmoVxMYjsAang
FTYHyxLp4nGOWJu1135yN/lQkGgAD9Jy4JJpMKFktrk
-> ssh-ed25519 jIXfPA TdfYeqsPJBf26CO1Bh74K8qxqR1MX3VUvZ/e73+oDXQ
KoA/I5kVXxryQ86qjfzq67Aiar+qDZF9OoF4MsNDqe4
-> ssh-ed25519 QlRB9Q ZaPziTdzqf0vCkCiLWAUJbnROaZ7Mz+Xgw1viEMWM2s
I0peAEQPbaXL9eHQ/OraNuqJPCxIwjpxIxhvgAifATY
-> ssh-ed25519 r+nK/Q kgmK60IgdW4QFdKqBQ6S9JmQVoRvpmffVaoNWzfV5Bc
ru8etu+7QOmnAoJv8BLtEK0SuDfhB75l525ORrDirvM
-> ssh-rsa krWCLQ
jEPt5eWP6NmpOikLhs1uPVo7kxHgg1y7WwdOPyR0z2vpFD2BWGlIi/BvnlE3OO5n
jtvDjAauWU0X2JarfdY9mY8MoPjT9qQ/ukxuVAHi5CoL/I1JCqcbuftssYY0B7Ab
SMfbyxjK8aIT1/4EQhMoWm0tuIylvgTBagL03Lw5mbyRqDkbpI/6YC9401YjT7Ts
dCDGIFAYM2BA7TuJiZr881ypUdU9rlm5rss1ZLMj90jyJPJC4SDYbzE0BoBat9l0
dYUrYGhGgZ1cDd6D6mPf6H95muiGHIhxaE8c+LdK/rKCSH9Rf6mfn/Ab/xvnaDNn
GW/WD0EpmdzpWVPby68+KA
-> ssh-ed25519 /vwQcQ 5DoMxdoK+KiHXKwwOpb7/1FZIEzAa/2/1l8yyxey6iw
RzmUkqZQLM5/jDXG9fxhZmfAywgVMjH9Y3O66BnhCSQ
-> ssh-ed25519 0R97PA g+uW/jfwHB3m0AdWxb9vPRjeaowhEx1Uoc2R0CVStlA
m5XvSEVQ8DiA7BSTsxVn6S1zv92CpbyZxSgUI3ObE4c
-> ssh-ed25519 JGx7Ng BtdJpskbfPyywYeFbmQw3HGPTLv5ri6x4bFocr9l6H8
88aFw+MCJLqMU/W/ikYDUZEAi0ImaPVbSc7cAZPbs/I
-> ssh-ed25519 5SY7Kg +JUMQfaxl7Orym43LVeqUyno0JfUbVnB+xv7smpdRhE
6K+Ewq1FhrXB2eYdljlsYpIfmVv49E4jSBsphgDpRJk
-> ssh-ed25519 p/Mg4Q AITnEN+Q41fEA2tkvVOKGCDZiuCXanG+qaiF5X4ukiA
NvP/HXOliNvi8tngH9PU90E616CPlh/QgkZ052H8wtk
-> ssh-ed25519 +mFdtQ RuaXIQNZ3s9C27XtpVTExJlAhYDYXRQni+Hwot0wrzU
WctqqoGS2hVfOZSU3ihCg5eI7PnxM7dkOJKM9DJ90Wk
-> ssh-ed25519 5rrg4g cAqJQ8z6T46YwzahtcTJxXZHklCGrupVCja5U/g+ZmM
wERu5T6rOi5/0qPSXeOnfA0Szg7/pbYFTW0Ys1yWq40
-> ssh-ed25519 oRtTqQ NF73c0d1qM4nVt2bEdWTEDjDcz/ZMCObn/7cDZfkVGA
Mivm+WWVqAfNs5pLwGmINIsmxlEZi7m7bQIRxGkf3/Q
--- 8R1h+xsovrLq+5QI1CoTXc9TBTQugnROZpOAHWBwG1w
G“Þ"û¤‡ã8ƒÈî&NF}x£ksyÖ\£.i§<69>קF¢¯}ê-ÍÁÓšLbì;{
QsgW7OvOB3cOz9MZI1PQ6Fe208WS+Sv/TWcucjD9i28U6Bty1KYeSwMH/zyzLuSe
51TqJTnkb+xGcqw3RvKiM58HMFcl6INmOI8otGxfCQSX7p3/QxiGQBbIgRblxtWB
8Jf55hgfh+1+vwTcM+BlBRWz4K581MeQiF2jj6ihfJNwTZ7Q9jNvgzF42znEyZyE
QTHoR9ROA/HqLgcrui1L7QnBlP1Y9Bt/oMCh4jFwHfcc6NeHF+I6AEeQNAHH9iNX
2+1RsJnQrTM+H204GrpVK78e1B5uCjvq/LeoWSQ3pFD9PwdM6JW2WfkB4FSCriAI
7ZAg64qNahyjX+J+KDlrwQ
-> ssh-ed25519 /vwQcQ MBPiBQdz65VVKMxJDlTCFUfG084K0ZcGpPJc5RKKND4
jH9fRJ/tcGQpZQ+pGNw9lXcRbPS8LLsuwe4EUsaFGDM
-> ssh-ed25519 0R97PA bvY5a3GO1CfVmCPJwBfFGJcS+Zkr2QRENa0WyzqspGc
YgxthAE4TIPlweuH8cWaOmVGqomc2yfLdzjO8G8bytw
-> ssh-ed25519 JGx7Ng 11We2girRvmkDm8eWkTZnazm7Ly0tmECFTdSFnBKIQQ
VQ+jlP1sk+SPkHARgAly9U7W0HVbpvZvxLN4V5l6JwE
-> ssh-ed25519 bUjjig Zt2Br6ls9INAJ5aQZ/az+6+rIpDCf/NCJP2zusdggms
3k0NOSVDpbQFEflEvyTzKv1/zXUBVN5ub9jjOe4EybM
-> ssh-ed25519 +mFdtQ inTgQzJVaYt8JZjtrjVzZzW9PscvBnZWkXIpEQYtdFI
O/Z7ccZam386C6r2UVJS+OMwG8nZ57RmUy+VJEgWJEY
-> ssh-ed25519 5rrg4g ApGMepP+32epekSxCfLGJs6uI38WPjWxtdk+q1Lvx0I
huEBiiNzTcz5hPUs+INfDyfeqKtl+mYE38PUizHktyI
-> ssh-ed25519 oRtTqQ QBBeZ0kLMPuDmO0hT7LvMs31WuVZATUSyxtCxgMzHgQ
HooCKv78+xzYnOwaYXbRNVH1XpG1e8tY0PB246nkFU8
-> G8<-grease
58RFQqg54Xu8pavoh6wbEnJl7J8XJ5rgaVq1bxokhQ
--- +gYhV/IjEqBw3YKDEeSbepgAIIO6A/BcpsYrwCy+Ezs
萠%7図殤チx盟~YヨワZチ{儖情リM<EFBE98>Hハ<48>ソ Xセ<58>ナk@モ9<EFBE93>

View file

@ -2,7 +2,7 @@
#
# SPDX-License-Identifier: EUPL-1.2
(import ../../../../keys.nix).mkSecrets
(import ../../../../keys).mkSecrets
[ "vault01" ]
[
# List of secrets for vault01

View file

@ -57,13 +57,4 @@
fi
'';
};
environment.defaultPackages = [
(pkgs.callPackage ./fill-vlan_prefixes.nix {
inherit (config.networking) vlans-info;
postgresql = config.services.postgresql.package;
})
(pkgs.callPackage ./nat-request-daddr.nix {
postgresql = config.services.postgresql.package;
})
];
}

View file

@ -1,39 +0,0 @@
# SPDX-FileCopyrightText: 2025 Lubin Bailly <lubin.bailly@dgnum.eu>
#
# SPDX-License-Identifier: EUPL-1.2
{
lib,
writeShellApplication,
writeText,
vlans-info,
postgresql,
}:
let
inherit (lib) concatMapStringsSep;
sql-script = writeText "vlan-filling.sql" ''
DROP TABLE IF EXISTS vlan_prefixes;
CREATE TABLE vlan_prefixes (
vlan_id smallint PRIMARY KEY UNIQUE NOT NULL,
prefix inet NOT NULL
);
INSERT INTO vlan_prefixes VALUES
${concatMapStringsSep ",\n " (
{
vlan,
netIP,
prefixLen,
...
}:
"(${toString vlan}, inet '${netIP}/${toString prefixLen}')"
) vlans-info}
;
'';
in
writeShellApplication {
name = "fill-vlan_prefixes";
runtimeInputs = [ postgresql ];
text = ''
psql -d ulogd -U ulogd -f ${sql-script}
'';
}

View file

@ -1,35 +0,0 @@
# SPDX-FileCopyrightText: 2025 Lubin Bailly <lubin.bailly@dgnum.eu>
#
# SPDX-License-Identifier: EUPL-1.2
{
writeShellApplication,
postgresql,
}:
writeShellApplication {
name = "nat-request-daddr";
runtimeInputs = [ postgresql ];
text = ''
TARGET_TIMESTAMP=$2
TARGET_PREFIX=$1
psql -d ulogd -U ulogd -c "
select
vlan_id,
reply_ip_daddr_str as used_ip,
reply_l4_dport as used_port,
orig_ip_daddr_str as daddr,
orig_l4_dport as dport,
flow_start_sec, flow_end_sec
from ulog2_ct
join vlan_prefixes on ulog2_ct.orig_ip_saddr_str <<= vlan_prefixes.prefix
where
-- if we don't have conn start, we considered it started before the target time
( flow_start_sec IS NULL or flow_start_sec <= $TARGET_TIMESTAMP )
and
-- similar for conn end
( flow_end_sec IS NULL or flow_end_sec >= $TARGET_TIMESTAMP )
and
orig_ip_daddr_str <<= inet '$TARGET_PREFIX'
;"
'';
}

View file

@ -2,7 +2,7 @@
#
# SPDX-License-Identifier: EUPL-1.2
(import ../../../../keys.nix).mkSecrets
(import ../../../../keys).mkSecrets
[ "web01" ]
[
# List of secrets for web01

View file

@ -61,18 +61,6 @@ in
languages = [ pkgs.wordpressPackages.languages.fr_FR ];
};
"npr.wp.dgnum.eu" = {
themes = {
inherit (wp4nix.themes) twentytwentyfive;
};
plugins = {
inherit (wp4nix.plugins) user-role-editor;
};
languages = [ pkgs.wordpressPackages.languages.fr_FR ];
};
};
};

View file

@ -13,8 +13,7 @@ lib.extra.mkConfig {
enabledServices = [
# List of services to enable
"cas-eleves"
# "kadenios"
"django-apps"
"kadenios"
];
extraConfig = {
@ -22,7 +21,7 @@ lib.extra.mkConfig {
dgn-access-control.users.root = [ "thubrecht" ];
# Disable monitoring
dgn-monitoring.enable = false;
dgn-node-monitoring.enable = false;
# Enable Postgres databases
services.postgresql = {

View file

@ -1,22 +0,0 @@
# SPDX-FileCopyrightText: 2024 Tom Hubrecht <tom.hubrecht@dgnum.eu>
#
# SPDX-License-Identifier: EUPL-1.2
{
imports = [
./kadenios.nix
];
services.django-apps = {
enable = true;
webhook = {
domain = "web02.dj-hooks.dgnum.eu";
nginx = {
enableACME = true;
forceSSL = true;
};
};
};
}

View file

@ -1,66 +0,0 @@
# SPDX-FileCopyrightText: 2024 Tom Hubrecht <tom.hubrecht@dgnum.eu>
#
# SPDX-License-Identifier: EUPL-1.2
{ config, ... }:
{
services.django-apps.sites.kadenios = {
source = "https://git.dgnum.eu/DGNum/kadenios";
branch = "production";
domain = "vote.dgnum.eu";
nginx = {
enableACME = true;
forceSSL = true;
};
webHookSecret = config.age.secrets."webhook-kadenios_token".path;
overlays.nix-pkgs = [
# Required packages
"authens"
"django-background-tasks"
"django-bulma-forms"
"django-translated-fields"
"loadcredential"
# Dependencies
"python-cas"
];
dependencies = ps: [
ps.authens
ps.django
ps.django-background-tasks
ps.django-bulma-forms
ps.django-translated-fields
ps.gunicorn
ps.loadcredential
ps.markdown
ps.networkx
ps.numpy
ps.psycopg
];
environment = {
KADENIOS_EMAIL_HOST_USER = "web-services@infra.dgnum.eu";
KADENIOS_EMAIL_USE_SSL = true;
KADENIOS_FROM_EMAIL = "Kadenios <vote@infra.dgnum.eu>";
KADENIOS_SERVER_EMAIL = "kadenios@infra.dgnum.eu";
};
credentials = {
SECRET_KEY = config.age.secrets."dj_kadenios-secret_key_file".path;
EMAIL_HOST_PASSWORD = config.age.secrets."dj_kadenios-email_password_file".path;
};
extraServices.tasks = {
script = "python3 manage.py process_tasks";
serviceConfig = {
WorkingDirectory = "/var/lib/django-apps/kadenios/source";
};
};
};
}

View file

@ -0,0 +1,190 @@
# SPDX-FileCopyrightText: 2024 Tom Hubrecht <tom.hubrecht@dgnum.eu>
#
# SPDX-License-Identifier: EUPL-1.2
{
config,
lib,
pkgs,
sources,
...
}:
let
inherit (lib) mapAttrsToList optionals;
host = "vote.dgnum.eu";
port = 9888;
python3 =
let
nix-pkgs = import sources.nix-pkgs { inherit pkgs; };
in
pkgs.python3.override {
packageOverrides = _: _: {
inherit (nix-pkgs)
authens
django-background-tasks
django-browser-reload
django-bulma-forms
django-translated-fields
loadcredential
;
};
};
pythonEnv =
{
debug ? false,
}:
python3.withPackages (
ps:
[
ps.django
ps.gunicorn
ps.markdown
ps.numpy
ps.networkx
ps.psycopg
ps.authens
ps.django-background-tasks
ps.django-bulma-forms
ps.django-translated-fields
ps.loadcredential
]
++ (optionals debug [
ps.django-browser-reload
ps.django-debug-toolbar
])
);
manage = pkgs.writeShellApplication {
name = "kadenios-manage";
runtimeInputs = path ++ [
config.systemd.package
pkgs.util-linux
];
text = ''
MainPID=$(systemctl show -p MainPID --value django-kadenios.service)
nsenter -e -a -t "$MainPID" -G follow -S follow python ${sources.kadenios}/manage.py "$@"
'';
};
staticDrv = pkgs.stdenv.mkDerivation {
name = "kadenios-static";
src = sources.kadenios;
nativeBuildInputs = [ (pythonEnv { debug = true; }) ];
configurePhase = ''
export KADENIOS_STATIC_ROOT=$out/static
export KADENIOS_DEBUG=true
export CREDENTIALS_DIRECTORY=$(pwd)/.credentials
'';
doBuild = false;
installPhase = ''
mkdir -p $out/static
python3 manage.py collectstatic
'';
};
environment = builtins.mapAttrs (_: builtins.toJSON) {
KADENIOS_ALLOWED_HOSTS = [ "vote.dgnum.eu" ];
KADENIOS_STATIC_ROOT = staticDrv;
KADENIOS_DATABASES = {
default = {
ENGINE = "django.db.backends.postgresql";
NAME = "kadenios";
};
};
KADENIOS_EMAIL_HOST_USER = "web-services@infra.dgnum.eu";
KADENIOS_EMAIL_USE_SSL = true;
KADENIOS_FROM_EMAIL = "Kadenios <vote@infra.dgnum.eu>";
KADENIOS_SERVER_EMAIL = "kadenios@infra.dgnum.eu";
};
path = [ (pythonEnv { }) ];
in
{
environment.systemPackages = [ manage ];
systemd.services = {
django-kadenios = {
description = "ENS simple voting server";
wantedBy = [ "multi-user.target" ];
after = [
"network.target"
"postgresql.service"
];
serviceConfig = {
DynamicUser = true;
LoadCredential = mapAttrsToList (name: value: "${name}:${value}") {
SECRET_KEY = config.age.secrets."kadenios-secret_key_file".path;
EMAIL_HOST_PASSWORD = config.age.secrets."kadenios-email_password_file".path;
};
StateDirectory = "django-kadenios";
User = "kadenios";
};
inherit environment path;
script = ''
python3 ${sources.kadenios}/manage.py migrate
gunicorn app.wsgi --pythonpath ${sources.kadenios} -b 127.0.0.1:${builtins.toString port} --workers=2 --threads=4
'';
};
django-kadenios-tasks = {
description = "Background tasks worker for Kadenios";
wantedBy = [ "multi-user.target" ];
after = [
"network.target"
"postgresql.service"
"django-kadenios.service"
];
serviceConfig = {
DynamicUser = true;
LoadCredential = mapAttrsToList (name: value: "${name}:${value}") {
SECRET_KEY = config.age.secrets."kadenios-secret_key_file".path;
EMAIL_HOST_PASSWORD = config.age.secrets."kadenios-email_password_file".path;
};
StateDirectory = "django-kadenios";
User = "kadenios";
WorkingDirectory = sources.kadenios;
};
inherit environment path;
script = ''
python3 manage.py process_tasks
'';
};
};
dgn-web.simpleProxies.kadenios = {
inherit host port;
vhostConfig.locations."/static/".root = staticDrv;
};
services.postgresql = {
ensureDatabases = [ "kadenios" ];
ensureUsers = [
{
name = "kadenios";
ensureDBOwnership = true;
}
];
};
}

View file

@ -2,13 +2,11 @@
#
# SPDX-License-Identifier: EUPL-1.2
(import ../../../../keys.nix).mkSecrets
(import ../../../../keys).mkSecrets
[ "web02" ]
[
# List of secrets for web02
"bupstash-put_key"
"cas_eleves-secret_key_file"
"dj_kadenios-secret_key_file"
"dj_kadenios-email_password_file"
"webhook-kadenios_token"
"kadenios-secret_key_file"
"kadenios-email_password_file"
]

View file

@ -1,29 +0,0 @@
age-encryption.org/v1
-> ssh-ed25519 jIXfPA miVq8rZazx0Y0NYZklZh8ITlY7fOTwbPsAPcHwvJ3jI
Vs0xx9ulk2++7+DfD+HqhISSvYMtuSJIs9zyGlnW8Wk
-> ssh-ed25519 QlRB9Q z5TQpHovWNJ+Dq4GEcPfByMpTcTojIamJbU3kNKlmHQ
U+ZFJ/0TVcfo85xAWYqcnzpMfU0KcY8QJ8jqWlyt1U0
-> ssh-ed25519 r+nK/Q l5oBCnALC2HSoszpawrJZZUEFHjjGwei4Fd1Y+f7OjI
PLgEu00ItWIbT3ZSNioZ3oXwBBVQTD/wf8I8akEDNWs
-> ssh-rsa krWCLQ
2rt9GmpSxUJSArSOlXKQscrApgLLIWuTo/IXensBP1uCnrpLl4IdcpEJNTs7wtZq
h4OLCaLDoZvB3ZT3k+CXXXeBqLqz1DdBGo08RgfcUADTsm2Z9LsEyLo0GtHGEFjw
m1r/VF8githDxaEK52+znr1FG8CE7+DBQAU9ZydhKKjjFS7ckDHw0qFXyGqpyWk4
KnL7FGPX2z07V3nwauElDbaD1LLt0xHhqqEjmiRskhE2UU6q35IrLyKFHC1VHsFy
ItsONTu8lDiqXSi7Z5b5Iv+iAWWTtt/glTv3WFa8u7CIahuZIfemr8NzjD2Z+Vxh
yOEqBKyVgz8sFh1U7CgxCg
-> ssh-ed25519 /vwQcQ dcnBNyypzMkxHwh76v7bKhGckPjIOL2vP2aDWhB8WxQ
tTxcMXcLrFhD7u2xTOhsjWErSiCOfsVIDZgJldVePMw
-> ssh-ed25519 0R97PA stdF6UFkWDCwNUAv+aAetpku7O9XRvtaxafCjok9yhI
gXVXcwlY4Xue9WGk+WlByXvSgMju+VWKTBTXIngWYvE
-> ssh-ed25519 JGx7Ng e+Ux4HK63pAM4scQCi4wHTUmo28z105Ok59dlki0OS8
ulkU6zhXNpa3OswEC005BZ/YIExPysg25a4/O60fcWQ
-> ssh-ed25519 bUjjig SEnDWloeuVgCGLUJNvsBL1HPYJGBSBhqdDngkQk+KiE
MYL9SudJNuFyS4Inaod2Xxldi3d/kDwlIT9rVWs8vFc
-> ssh-ed25519 IY5FSQ TO9BPLBwdlqyKXOBiohCzfZWrTDwqhLjZYeq9rZgH2c
7Hqrqe+A3wg11H3wg9Cd+6F7mDwsLpzoh70sba32gCw
-> 1DV;-grease
9Ul6qKgH063H/HI1op+Gyk2+JRUGHwRG/SlOPTAnvBtq7xEy7yrR4lblBK8bcJNY
lwmI4xOokAnIveVaPS8SAig
--- GpJyGpk3QxJljiR6FZw8hdX0dXvEAIPZEZpL6oorLcM
}­o÷ÕŸ¦A¹qç ™Ò™ö>áp™€M Õ¬Ía“ zþƒÍT VVƒvI«f®<17>!>µ\Ö-þèÿ

View file

@ -8,7 +8,7 @@
services.django-apps.sites.bocal = {
source = "https://git.dgnum.eu/DGNum/www-bocal";
branch = "main";
domain = "bocal.cof.ens.fr";
domain = "bocal.webapps.dgnum.eu";
nginx = {
enableACME = true;
@ -50,7 +50,8 @@
};
environment = {
BOCAL_RHOSTS_PATH = "/users/guests/bocal/.rhosts";
BOCAL_ALLOWED_HOSTS = [ "bocal.webapps.dgnum.eu" ];
BOCAL_RHOSTS_PATH = "/var/lib/django-apps/bocal/.rhosts";
};
};
}

View file

@ -42,7 +42,6 @@
credentials = {
SECRET_KEY = config.age.secrets."dj_ernestophone-secret_key_file".path;
ACCOUNT_CREATION_PASS = config.age.secrets."dj_ernestophone-password_file".path;
};
};
}

View file

@ -7,8 +7,8 @@
{
services.django-apps.sites.gestiobds = {
source = "https://git.dgnum.eu/DGNum/gestioCOF";
branch = "bds-prod";
domain = "gestion.bds.ens.fr";
branch = "django-apps";
domain = "gestiobds.webapps.dgnum.eu";
nginx = {
enableACME = true;
@ -46,8 +46,6 @@
credentials = {
SECRET_KEY = config.age.secrets."dj_gestiobds-secret_key_file".path;
SYMPA_PASSWORD = config.age.secrets."dj_gestiobds-sympa_password_file".path;
SYMPA_USERNAME = config.age.secrets."dj_gestiobds-sympa_username_file".path;
};
};
}

View file

@ -11,8 +11,8 @@ in
{
services.django-apps.sites.gestiocof = {
source = "https://git.dgnum.eu/DGNum/gestioCOF";
branch = "cof-prod";
domain = "cof.ens.fr";
branch = "cof-staging";
domain = "gestiocof.webapps.dgnum.eu";
nginx = {
enableACME = true;
@ -98,9 +98,6 @@ in
HCAPTCHA_SECRET = config.age.secrets."dj_gestiocof-hcaptcha_secret_file".path;
HCAPTCHA_SITEKEY = config.age.secrets."dj_gestiocof-hcaptcha_sitekey_file".path;
KFETOPEN_TOKEN = config.age.secrets."dj_gestiocof-kfetopen_token_file".path;
SYMPA_PASSWORD = config.age.secrets."dj_gestiocof-sympa_password_file".path;
SYMPA_USERNAME = config.age.secrets."dj_gestiocof-sympa_username_file".path;
EMAIL_HOST = config.age.secrets."dj_gestiocof-email_host_file".path;
};
environment = {
@ -115,7 +112,6 @@ in
GESTIOCOF_CORS_ALLOWED_ORIGINS = [
"https://${config.services.django-apps.sites.gestiocof.domain}"
];
GESTIOCOF_SERVER_EMAIL = "gestion@cof.ens.fr";
};
extraServices.worker = {
@ -126,26 +122,6 @@ in
SupplementaryGroups = [ "redis-gestiocof" ];
};
};
timers = {
rappel-negatifs = {
script = ''
python3 manage.py sendrappelsnegatifs
'';
startAt = "*-*-* 1,13:17:19";
};
rappel-bda = {
script = ''
python3 manage.py sendrappels
'';
startAt = "*-*-* 2,14:17:19";
};
manage-reventes = {
script = ''
python3 manage.py manage_reventes
'';
startAt = "*-*-* *:01..56/5:29";
};
};
};
services.redis.servers.gestiocof = {

View file

@ -8,7 +8,7 @@
services.django-apps.sites.gestiojeux = {
source = "https://git.dgnum.eu/DGNum/gestiojeux";
branch = "production";
domain = "jeux.cof.ens.fr";
domain = "gestiojeux.webapps.dgnum.eu";
nginx = {
enableACME = true;

View file

@ -6,7 +6,6 @@
dgn-redirections = {
permanent = {
"www.ernestophone.ens.fr" = "ernestophone.ens.fr";
"www.cof.ens.fr" = "cof.ens.fr";
};
};
}

View file

@ -1,33 +1,30 @@
age-encryption.org/v1
-> ssh-ed25519 jIXfPA w23oZwRdOmR6ZmJ/u1UVJX3aDjvFlP9J/0DX421EzTk
GwBhoK4pLMph83ufQSh/DaKtDsQv2Vc/31kN4ahx1O0
-> ssh-ed25519 QlRB9Q bx2P8KY31nlurmjEsq6rOGz4RivuubPRr/pwJi8vZR4
pHUYj6nCuQfv9Y6oJmLqmIWw9rSrb7YgFIGh4/DDBxk
-> ssh-ed25519 r+nK/Q xX3R7A7Pq+l98C/4rDzZfLa5IyoW4mS1RXCg8jmCVBg
pZZ91CQNMfv+A9nUGM7FCHt79YsEIP8SA4UZ7NmIYyg
-> ssh-ed25519 jIXfPA HF+w4Kuk7Wo2s94SeNxAB3zFZhKNn1fPabJhUK/xGH0
KY5tknNrICYq0HTfNRX760OPyWPJ8B4Sasq8BjN9a6k
-> ssh-ed25519 QlRB9Q OGcCe/S1aIQckJGzt4Wz+DFebTZpNV+YCevnVOPDMXQ
keDckjD4Vjhj3gmQnW0V8nJ1Soubkhb9WP28fsanhMA
-> ssh-ed25519 r+nK/Q lO6xwuhfQ6gMlJzFBF5J9c2elEg1J3leAt5x1uTYGSk
HQG0VQXvn72CIOqe6FRGrSX8TIa7sBB3cOZZQzXBl8w
-> ssh-rsa krWCLQ
JSYdRpvAP/pb8v9Rviw+DcwTGmlVbes8LNW/Hjjc3eKNYT6f5TR56Ma0C+ZXA8hC
BiEoDyvV631v7jf1NQENWgOrx8kIaMlJyJlndEUviFesoUXvBsrRVxZkPo9+q8gm
2jx8uLxRlq04fIh39YOcxayNPU6ZE0k4iV5Sv8bgNdPPsiSDPEcoGh4ptB/L7PqC
qa73mSskFsWLMdkhlF2PmobhFYBbJw76ekctHK4enABJR0wnpw76MB/1xaRysO0Z
cE1yXy0TKPeQ6tBs+TgEbWPdjs7q2cCe78Cx14ob/bDTrSxn1VXxlTSEa+jZ8ES2
aRJM0RnnbulZJMu8vD+ztw
-> ssh-ed25519 /vwQcQ +etnXlMmCofk42qEtdvIZyzpdGPTUR44Ur3rNiYpqQY
+h+hNOOJHWXi4vqsBDudgiQ3BPHVOA1bl+R4d5zCs2g
-> ssh-ed25519 0R97PA VuTnbuLdQANqvVDvIEOJVFWh3IgOKLHXROxSCx5E0C0
euVIt58WGFPxL5IgE0Stce7q9MaQCLkWOGpLyxhszJk
-> ssh-ed25519 JGx7Ng /1DGw0uUQ99aDlw5AdNIKZNZbRSXoxCwJZU4iotnMVA
v9B+dF8KmmVLjYh7IT61p757x+CeJQ0qY+kU69Ced3s
-> ssh-ed25519 bUjjig tvi0aragAV8TvSAvVVYwgAe4D/iFPy8Hmo5BFIiMigc
ixKZkBQDFDoM3ntd43TPb5gzQmJKiuYHuPRvh+wlLwg
-> ssh-ed25519 ZIo4kw 4mpL5GIsgcXQH3+DTwo1wBO2IGtwqYX71sSj3HRTUD8
FyiH/fpn6rFmw6L1nbxqnlEQwHdgq2kacvkl4dDSpDA
-> ssh-ed25519 9/PCvA rwGsoEUqcUK/bj0wpo/2GIcPgJPdUCs/y/0MacBXlTQ
4IRzAh7PgafkdUGOoUnTFZwQwpupt+09tNCuMQPtNow
-> ssh-ed25519 VQSaNw if6Cp0uuuBCn5/sIEhhiD3Xa3MGOgxNhpA5jk/sNaxk
tZLZbxe2EswPA2DOzm1XILWxPJOfvtQEBb3J/g7gOdg
-> p0A#yj-grease
GR/rBHQQMBRnEs3FdKUmaxDXNLeZuXXftbiAi+6dzv4SsZoJ5oqi4UKivc5DYLfO
C8GywA
--- XSYpA1AoDYYWRAjVBKAfn9s/nI7d6hE2j57BKVdMQ5Q
#žSõ/ éž5Õn%´ªžô‰w9EŒ­¨¦TüMƒýP»?â…œ¡˜(<28>PGrj4$*<2A>Cû èü8´‡¤ô¥Jpt=H`Âî½n
pvF18GVS3dHr2jiss4sn00UqVVM2f/6BmkpYMgAVQ3FNpgnimQGsgCssuBo3Hjrc
BTO4v2U6cQ28LTUsruWdPhRChT0zfGRtx1QIn0tPzy3XKUxjt2XkBeblxtLhCHmI
muQ0yA15bP+aQfZn0dE1Eb4krw1unKWE4f82L/BQ5Y/i1P2rubhyBhBoQRb6atHv
S2EWBafaNr3orbFl9FPMjhWW3WZX/zKJxlu0saN88I6ZU2967mdR4PogMpL9iqST
atraraA1jG6mR9Ojloyrf8FG6wTlplDlZk8Sgtg88FD1iHMN1q0DQv1LwRoD3QUa
ywIn9MABMufNXQ+jm/DQpw
-> ssh-ed25519 /vwQcQ 83MxgOJhIBBGU6IRcTQPtxtyR4MapAxhdKT634w/em4
scNxodN5j1HXOIPCB3glvc08Gb4wW9gmZ5gkWMCbm4E
-> ssh-ed25519 0R97PA LBFUS7zx26+rjiWqVwQ4UBqRxr+3Sx+j+GGrRaBbz08
fnFwvJz36SiKnEoJr+0+enNVcT7wduZUrYe7bWhyxfE
-> ssh-ed25519 JGx7Ng iXjAn4Y7+yHASx4ZbIrvFffLzgX52DbQy9hIcTScHAs
6AJZoV33mBryiCaquKTAkw8yB1NQs38QlG2p4LIcoMc
-> ssh-ed25519 bUjjig 0cqMXUVHqhyYhygR7meIyWRr/c7H8ZGB5eO7tTHhRUk
GYKKGB02ElJXpObmBJKF4Bvoswd3o83vvVYIHIpDprg
-> ssh-ed25519 VQSaNw xHhzKnYeKxrN2MJz84v7Mjg3Nh69UJ6Q/eAyVAvC3V0
/bvauGesQw9/tl4DhCNFY9Rq+qWv12O4TcqzdxTCWzk
-> T:){{-grease NuQ <}vLGT%
0JSFYPMWs6LXpWacfiHNdwqvs/eHecFwj6cg0eLZEQe96shxy8/WSUBMpgasKufB
Nc4tpfiOVWVRGm4arhunwJ+1sgg37X35PWde89Qpg5g
--- Y6N6GuCpRLdD25EWW+05qbUAadrT3z2Pzc5golCBHJw
ßNê¯3'8ú³€@/¨0,zWêS¦‘ï;ßñì)§e<C2A7>ßÉïèÞí
qMjÏŒrçHBÇR2šš E2H+d­% ¶Ò–®

View file

@ -1,32 +1,28 @@
age-encryption.org/v1
-> ssh-ed25519 jIXfPA EsnCV2WNHwC5zZpIqMiOnpixioiS32MkPW2gvPW0hlA
SdJ0CVIn+xIw851NfAVq2xi4eyIkjE5OBSjWjmXMbrA
-> ssh-ed25519 QlRB9Q pSqgkPUwNF0ahPyz+bRXfnJqlhiis8+JLtGVXMJFkGs
gEovHZ0L9Hf0FxITH7Pw82GmtpSry9AttmYyzOget/g
-> ssh-ed25519 r+nK/Q abHRhq9gLkRJZnW16AkJUNkuDkFx6ZEgcfcPKD7qkl8
TZOo2qI9wtTr5EFyLa7XwcNu9t4TiBTjYFfDcXF5WzY
-> ssh-ed25519 jIXfPA kBFUMktUZ09T8ujSXHRIo4OIWxIiwysmRv+UTiH+02M
TvefF7CMKZIASBYaVQA22PzLr2rgZ3i7Q8ENBOmpQmI
-> ssh-ed25519 QlRB9Q 0R2BthIX790DAiL36WPOemUa04tOnN0Drpg6u72j7UE
nFGbwKZvSXo0SpO8AMfAGcZkphcXhX+GoFxYwadNzwQ
-> ssh-ed25519 r+nK/Q cs+vGq5RzK/AogpcGjRG3KZjl4fp2Ghhv2ngHjTdvlE
AyXbgDlQbe3HurX7lodUrMZyRSWADSFWmTndnHjh0dY
-> ssh-rsa krWCLQ
NiW6aPN5sW1w8AWe66x5wkyJTYPnPqlmPdwkRMH62Z9rdRGoplPaThh46N1F7iSN
R7YfTRNy/xcSq612Wf1PbEGtcaEBU4snLwBUMxzgCEf7lLebnBFEv+wM46c6M4Vh
sRHm7LJP4EIFtC/OVi4Po3AOxnzWie6sgMtwVO1dxA92F52ANJm85+S9v4LyKf6B
3j1CTlQnST4Jz+NFR1lIWkAzawQkrObj1XNw0JjAH5cCFPNX8KJwGPPtRaw6qdE2
NN6boxJRuw015LFoT2REg8hFUj9mvKi1CF7zzAorlU8U5tGsTzWopFaz8sw6uw1e
hnLDEWU79TB/Ytc9mk+VgQ
-> ssh-ed25519 /vwQcQ uGDPoAidrjD4YOahlB14fECk3q7JYAgK2U3AwiTZp3Q
VMBSpbWgh9/+vNsxb31DztSAmuXQ2OT8PhGY8e5oEyg
-> ssh-ed25519 0R97PA dneC7N5KN3lOt+tf+SBVHac5PiFuzah+kxPCL7taES0
2ax/oATQ3RCZJrwa6rhRFjP/Pb83SE/K/JqzkDe4q5s
-> ssh-ed25519 JGx7Ng e+gbiPqeQvqH5SsMLtJjO1Yamqf/T3zMx9sZP/lE1WM
ZaLKy2fNia1FOO/8McmHLCTs7mU02UhIEcfnWR8Rmo0
-> ssh-ed25519 bUjjig YG96Anu4XdeqjveqgPKBg9DXRgQWzbZyqUh4zyp7NW8
XOW98Ncs7wa8+J7bdcni1BTvi0yt157YsqS37SyE1UE
-> ssh-ed25519 ZIo4kw 0bsqX9eZWnobso+67zX7mv4NZHN0iLJgREpEAjsSog8
chztA4fSI+l/hFC1JG/I8csRjW6nRL5nD8H2BIvKhtc
-> ssh-ed25519 9/PCvA u1TmEMmSAY01VT5KSkHIeGZyFR/AjO04fbdaQMOzWUU
KgNuPOluctxdmyoRQKGhxzUdM+lJYijOTZTppx1x8Ig
-> ssh-ed25519 VQSaNw y6+jgJvBopK1AkLk+FRsd1hOKyYhU3udCmpSqH73F2Y
qZyA/Fe6kxaIaYBtEWdIt69phdcpPgPr6hvHslYGZV8
-> ~Ef{]c0-grease ]bzX}@u' 23 } pjfN*GE
cHkSTFWSdWHGclY
--- 9GRqhQV1hb50rv2MYPgyJBP6eEm5KQUEUNqJnMMMx/0
j ·!½DÚ'×­(ã°<C3A3>!³€É݈ço&Þˆo) ü½Ô~Ñå
AnU8JBZXw8xIHA3L+220wCHwddC51Fx+sQx58tYsFg7eVH1NM2PKUr57a7+0KlxH
TkIDMUuBotY4QPA0tzv212wnWaTw9ddV+T+Xe+l7JNyurCQRj1g1gWP3NLYIyYFC
i/eXHg3XxByQG1BfBSL2nnUEiy6eJ2bLMFsJ9P6baB6hpdEnoFIuGdV4Bg3k/KGl
Zp+Q1a7Ov0l/G7sRCw4WLQtq59otI2lxeKRSonCqSNOmDXyZBr82GMr/BmhebtK4
h19K+EXU+Ze57lUf2kDCe0b4RSHbSGU1T1fSEMNcXFV0952r6zO9YClTsQeKl+ev
1O7xqUhcRXgFUbDYRjTsLw
-> ssh-ed25519 /vwQcQ AtEImZ61sgC2OzZvDldY7ttRf9I5+zmL2I7hZkmBoTY
zQiLX4L6t+jZqzAJmN7iuRTeadD1jbs3E/NZZj/25UA
-> ssh-ed25519 0R97PA JVheI/2kfdkqgM5Jf/py32lyYLtWjpmcx4zkHYMZl3g
z/+qXmvziQo8yZ6f+2y5XVDv6d/uAghCVDQ9tpLXt54
-> ssh-ed25519 JGx7Ng 41ZgklG6LmM5Mk6BkGWAf8N3j1safWPBKBAHKN2EQG0
yOiGIHkyoMFI6NQMLCZavCaz+qxAy9jhf+vctWQ2z4k
-> ssh-ed25519 bUjjig 0o9QkwuPZPOl/db1sQ9YL50DL1uyZqQ6ICxMEIupQ20
FwFbAYzLUNwoAQNcbcwWckhqRSEicQTe4O4BMK7wHyg
-> ssh-ed25519 VQSaNw iaWBGmaWmBxMJILFyob6CyVXyY24edPtT2itTQGP7xM
EGmCuYElC5EgwqXtcXLAy7nNFt75Hl/gAehvfh+0sgg
-> /Wa)P<iw-grease (;ag_e g#LM+oA Y n(M-1K+.
lWfOmA
--- k01yU9ZR8KIyG0JEfcYoP4iBlvqq7J676oPfDLpbvfs
ÎD—èŒ<C3A8>Ptáçø4Õ•?6”N|ÐïZƒ³åM/œqo¨[ÄNä

View file

@ -1,33 +1,29 @@
age-encryption.org/v1
-> ssh-ed25519 jIXfPA iQr5+V3ESwwPQ0N5TWvKPQllxl51JbvY1pQ/LWFoGRM
mmPi5TEsoKaqqCNR9wFOW9m/ZO+LybILeAr0IltAA6A
-> ssh-ed25519 QlRB9Q uWG5fTIkrcvoZPwTjeUIvUBb9SSw/tqLVXQ5EgPEpA4
NxUobR435SRYhgtfqeL4nCTyBimMFQDeHkv1EXxyeW0
-> ssh-ed25519 r+nK/Q mWebzwprS5rda66lWzpTXkeLBJ1cQr92jt1IKiGuhmI
s5C7BIJioGzDafwDDsBBEy9FfSDLhVI8loGPMI59ITE
-> ssh-ed25519 jIXfPA hAdsxHTIT08JvDQGzY0Vz+Jxd48Kw3XNpf6TEjiGiTc
hZgLRBDGwpfIFMhTRExY6JJ0poJ+nqrBK8Fy3ukINFI
-> ssh-ed25519 QlRB9Q AyfmPVVcb9WVzrbyh2KdPQMwPypQ0uq3q6kkPFcMyjw
S2h//+6MMnUiBWrznI/1+qS83Gw1vpFmU8Hlma40bdA
-> ssh-ed25519 r+nK/Q 741XzH0HZf/y8HR1AQIn+qgn0+L+2kcdPsepRcXx7w8
5aNoPnRTYHB5FTXipQV+8C/s8t1s5/ZF9PwnJfYy8bM
-> ssh-rsa krWCLQ
O0u81IdCYXC/caM9tEUD21d06Uq+AEaUWauHd3T4uBzx6k8KxZQsXL7FlmpyHMQy
jWKX3lni54qWZqyGi3AVBWwrdT3C59vAUUtOPsR9BdhuETjuNhUVgOQhfygbpNTP
Z+1xv/H+6iY4iaijkneUqjO+Zf8XzNiBjV1jxAEgVSMAYfYi2IUKaNGfTCxsf7z6
FbcOZiwKffzF9ml3jRbi0zacy2YfBVA3HLtr0G2konocqB2blx0yQx+CUN66vODT
Dg2Rvjvxj/UILT6DHfhSEienmIyRVcEV4FMyDRAqVnSWvY+5rQu7Q193lsdwxu1V
imAsspRLp7cLTHO13E7HEQ
-> ssh-ed25519 /vwQcQ D7UkEEde5wt6JLVwgw09YpI1jda5PpseNb3/oYXeuxY
mAyubu6vZt9WGQz7LN66OFLysMJnggQM3Lzp1WL2WIw
-> ssh-ed25519 0R97PA KELROPFrMKhwm6qZa3pDGUwL46djU6KXuEvvJdvPVTY
TLnuP2JD9KWnJyFG/TniJ7SZA8MwEGWRm/slgexr6Ws
-> ssh-ed25519 JGx7Ng frq2JO+UyHShB9/ho6SSO4gpm1x5gsT/FWNcce4FejI
0yjxhYvLi6BJCV04liQ8EUfvd/QQDfvQW/+69k81SLI
-> ssh-ed25519 bUjjig V8kyKJYS7AEddNQ/A1dDofL72gZhQx8S7CWXXDhO11M
70GSlCUdlM1C2TtWO34E/AeP6ESA2q/2hiRsG3yKa5M
-> ssh-ed25519 ZIo4kw Q9v6Hj82FPt0vOADqZZvrA1C5zw5Xi54TdkWFQhY1GY
/bbWn0eVMOcKMuxhSlHL5YNBAdNGkOEWDtKFbXfl5kI
-> ssh-ed25519 9/PCvA umec3ZH6etHJWPhH350dg89jPisIen+g+V1biOk8uQg
nrkdFNMpVaeYmxaXh9f5ZBwxjdPoCbbB0NMIGP6rgJA
-> ssh-ed25519 VQSaNw jcBuMSisYemI6teXpAXmIfzmkCnQRUhzR02oIED7mw4
mRPa20AN2KGqp5Sh5rxqMbTLCd6N3eNNNKRzu1TrBN8
-> ;yNT#P-grease bzX
MQVFOK4d6Iy4B1TtfEhvVM1nNBec24na1BPH++gbZE1n1dHxyy65O998u1oVml/V
3PBkae5UTR62Hm/2oSTih/TIfGRSzT+MrjxzkRAxsWFaS+wNx3I8J3/kXg
--- cevd2eHQSfWzGNPVrJB3XVoqxblBsDQEKKQn2HtbFBc
¾‡ÃŽÌ¿ì +^FdÎÍ<C38E>†Õ^yGx·í$åF7 <öŽT»¶˜.ƒ0µ ³ºOÇ'“â9ÕŽIxÕ³³ï_ŠóTÎŽ')“†<E2809C>Ý
HhSOliN7XQZngyyrJ++S2JMBytkPjSt/dEUlJNbJP5n6HY5H7QKqd9rsc4LLu/Hz
BXKC9T3IVeuabMPNOBhE6SiOUejGv/txbMHPMdPTCju6JL4wP/2gqIK696kP62pL
CAS/cOZXrHS8etEFkpqSuEVquNIXbivXNHEwFMH/GkNut0SCpafvQHrN1wZdveH5
rp60R9ULzTzS3ztjEomAt9gWN6s7CtqZEozCMExPTXSW+OmBJprY+/Ae/uxeKZMS
x6pscBbZSEazZ476sZCWKTpeej7iFlSrIvLfkwYn9PtKqmaInoM/0F2thkqpVPkZ
/pcg11dUQpXJdaIiPEowlg
-> ssh-ed25519 /vwQcQ m01BxY0nPTfcW0D/iFRbCNbFFp+lE/XLW315aPyNbTM
hiKCfZH9k5GcUAkCJ/+x5V20SCeql8031lOge0Y9WXk
-> ssh-ed25519 0R97PA oGfUKErY65Jd0ZlcVox/HXA3itOI5KImRqDwH+UR6XI
32BtXjqImmG6TjUKoDU2QaJiMxldZdZoAP9SKPfGuHA
-> ssh-ed25519 JGx7Ng FJCtkG+Ig5dC+ftTClgrKtIt/D8s9Dr97eWObbNEZDs
i6tf7p5FDsdTZMJuBNmcTgVnL6eQDZFkjjH7AaBakqE
-> ssh-ed25519 bUjjig mOfri52IdeSNAawjBR5rhvL2eZNlVOwYK6u1uHv98xw
nx0Ko3omL+OVq3JHuCIacYfjn96kb78IgyvECEGq0G4
-> ssh-ed25519 VQSaNw gEQeKOEwwR8QlykdFlo7iqrsmhemiS02v8Kfx2ER9Xc
jpAEZx64/AXpA8HahtJq9OdcZYbqIFti5mxaPztvul8
-> $5-grease (y&6%5f<
YSrHrNaXa7b7Ivv1yVP3idg8t4iIdu5NX3hzczFp64bY7Bjp/g7jK+bWnDG26ryd
G+fhmUbFuDj8ZtXg6yk
--- YmnVS7kPp6h4pC9u28A32/xh67NwhIXwB1dxolI1DCg
.¼Zs‡…n} ®ì,èémõR€ÏêeÞ)¾bOª¶<C2AA>îնܷ†m8¼z£RyúìT/¦@¿CÜÝôW™¨F5ˆ?<ð.[Ö†r¡Ó[°M

Some files were not shown because too many files have changed in this diff Show more