Compare commits
1 commit
main
...
mattermost
Author | SHA1 | Date | |
---|---|---|---|
af1cf7606d |
62 changed files with 1790 additions and 1910 deletions
95
.forgejo/workflows/eval-nodes.yaml
generated
95
.forgejo/workflows/eval-nodes.yaml
generated
|
@ -1,44 +1,6 @@
|
|||
###
|
||||
# This file was automatically generated with nix-actions.
|
||||
jobs:
|
||||
Jaccess01:
|
||||
runs-on: nix-infra
|
||||
steps:
|
||||
- uses: actions/checkout@v3
|
||||
- env:
|
||||
BUILD_NODE: Jaccess01
|
||||
name: Eval Jaccess01
|
||||
run: "nix-shell -A eval-nodes --run 'set -o pipefail\nset -o nounset\nset -o
|
||||
errexit\nDRV=$(instantiate-node)\necho \"DRV=$DRV\" >> $GITHUB_ENV\n'"
|
||||
- name: Build Jaccess01
|
||||
run: "STORE_PATH=\"$(nix-store --realise \"$DRV\")\"\necho \"STORE_PATH=$STORE_PATH\"\
|
||||
\ >> $GITHUB_ENV\n"
|
||||
- env:
|
||||
STORE_ENDPOINT: https://snix-store.dgnum.eu/infra.signing/
|
||||
STORE_PASSWORD: ${{ secrets.STORE_PASSWORD }}
|
||||
STORE_USER: admin
|
||||
name: Cache Jaccess01
|
||||
run: "nix-shell -A eval-nodes --run 'set -o pipefail\nset -o nounset\nset -o
|
||||
errexit\npush-to-cache \"$STORE_PATH\"\n'"
|
||||
Jaccess04:
|
||||
runs-on: nix-infra
|
||||
steps:
|
||||
- uses: actions/checkout@v3
|
||||
- env:
|
||||
BUILD_NODE: Jaccess04
|
||||
name: Eval Jaccess04
|
||||
run: "nix-shell -A eval-nodes --run 'set -o pipefail\nset -o nounset\nset -o
|
||||
errexit\nDRV=$(instantiate-node)\necho \"DRV=$DRV\" >> $GITHUB_ENV\n'"
|
||||
- name: Build Jaccess04
|
||||
run: "STORE_PATH=\"$(nix-store --realise \"$DRV\")\"\necho \"STORE_PATH=$STORE_PATH\"\
|
||||
\ >> $GITHUB_ENV\n"
|
||||
- env:
|
||||
STORE_ENDPOINT: https://snix-store.dgnum.eu/infra.signing/
|
||||
STORE_PASSWORD: ${{ secrets.STORE_PASSWORD }}
|
||||
STORE_USER: admin
|
||||
name: Cache Jaccess04
|
||||
run: "nix-shell -A eval-nodes --run 'set -o pipefail\nset -o nounset\nset -o
|
||||
errexit\npush-to-cache \"$STORE_PATH\"\n'"
|
||||
ap01:
|
||||
runs-on: nix-infra
|
||||
steps:
|
||||
|
@ -286,6 +248,44 @@ jobs:
|
|||
name: Cache lab-router01
|
||||
run: "nix-shell -A eval-nodes --run 'set -o pipefail\nset -o nounset\nset -o
|
||||
errexit\npush-to-cache \"$STORE_PATH\"\n'"
|
||||
netaccess01:
|
||||
runs-on: nix-infra
|
||||
steps:
|
||||
- uses: actions/checkout@v3
|
||||
- env:
|
||||
BUILD_NODE: netaccess01
|
||||
name: Eval netaccess01
|
||||
run: "nix-shell -A eval-nodes --run 'set -o pipefail\nset -o nounset\nset -o
|
||||
errexit\nDRV=$(instantiate-node)\necho \"DRV=$DRV\" >> $GITHUB_ENV\n'"
|
||||
- name: Build netaccess01
|
||||
run: "STORE_PATH=\"$(nix-store --realise \"$DRV\")\"\necho \"STORE_PATH=$STORE_PATH\"\
|
||||
\ >> $GITHUB_ENV\n"
|
||||
- env:
|
||||
STORE_ENDPOINT: https://snix-store.dgnum.eu/infra.signing/
|
||||
STORE_PASSWORD: ${{ secrets.STORE_PASSWORD }}
|
||||
STORE_USER: admin
|
||||
name: Cache netaccess01
|
||||
run: "nix-shell -A eval-nodes --run 'set -o pipefail\nset -o nounset\nset -o
|
||||
errexit\npush-to-cache \"$STORE_PATH\"\n'"
|
||||
netcore00:
|
||||
runs-on: nix-infra
|
||||
steps:
|
||||
- uses: actions/checkout@v3
|
||||
- env:
|
||||
BUILD_NODE: netcore00
|
||||
name: Eval netcore00
|
||||
run: "nix-shell -A eval-nodes --run 'set -o pipefail\nset -o nounset\nset -o
|
||||
errexit\nDRV=$(instantiate-node)\necho \"DRV=$DRV\" >> $GITHUB_ENV\n'"
|
||||
- name: Build netcore00
|
||||
run: "STORE_PATH=\"$(nix-store --realise \"$DRV\")\"\necho \"STORE_PATH=$STORE_PATH\"\
|
||||
\ >> $GITHUB_ENV\n"
|
||||
- env:
|
||||
STORE_ENDPOINT: https://snix-store.dgnum.eu/infra.signing/
|
||||
STORE_PASSWORD: ${{ secrets.STORE_PASSWORD }}
|
||||
STORE_USER: admin
|
||||
name: Cache netcore00
|
||||
run: "nix-shell -A eval-nodes --run 'set -o pipefail\nset -o nounset\nset -o
|
||||
errexit\npush-to-cache \"$STORE_PATH\"\n'"
|
||||
netcore01:
|
||||
runs-on: nix-infra
|
||||
steps:
|
||||
|
@ -457,25 +457,6 @@ jobs:
|
|||
name: Cache web03
|
||||
run: "nix-shell -A eval-nodes --run 'set -o pipefail\nset -o nounset\nset -o
|
||||
errexit\npush-to-cache \"$STORE_PATH\"\n'"
|
||||
zulip01:
|
||||
runs-on: nix-infra
|
||||
steps:
|
||||
- uses: actions/checkout@v3
|
||||
- env:
|
||||
BUILD_NODE: zulip01
|
||||
name: Eval zulip01
|
||||
run: "nix-shell -A eval-nodes --run 'set -o pipefail\nset -o nounset\nset -o
|
||||
errexit\nDRV=$(instantiate-node)\necho \"DRV=$DRV\" >> $GITHUB_ENV\n'"
|
||||
- name: Build zulip01
|
||||
run: "STORE_PATH=\"$(nix-store --realise \"$DRV\")\"\necho \"STORE_PATH=$STORE_PATH\"\
|
||||
\ >> $GITHUB_ENV\n"
|
||||
- env:
|
||||
STORE_ENDPOINT: https://snix-store.dgnum.eu/infra.signing/
|
||||
STORE_PASSWORD: ${{ secrets.STORE_PASSWORD }}
|
||||
STORE_USER: admin
|
||||
name: Cache zulip01
|
||||
run: "nix-shell -A eval-nodes --run 'set -o pipefail\nset -o nounset\nset -o
|
||||
errexit\npush-to-cache \"$STORE_PATH\"\n'"
|
||||
name: Build all the nodes
|
||||
on:
|
||||
pull_request:
|
||||
|
|
2
REUSE.toml
generated
2
REUSE.toml
generated
|
@ -2,7 +2,7 @@ version = 1
|
|||
[[annotations]]
|
||||
SPDX-FileCopyrightText = "NONE"
|
||||
SPDX-License-Identifier = "CC0-1.0"
|
||||
path = ["**/.envrc", "**/Cargo.lock", "**/_hardware-configuration.nix", ".gitignore", "REUSE.toml", "shell.nix", "patches/colmena/0001-*", "pkgs/by-name/docuseal/rubyEnv/*", "pkgs/by-name/docuseal/deps.json", "pkgs/by-name/docuseal/yarn.lock"]
|
||||
path = ["**/.envrc", "**/Cargo.lock", "**/_hardware-configuration.nix", ".gitignore", "REUSE.toml", "shell.nix", "pkgs/by-name/docuseal/rubyEnv/*", "pkgs/by-name/docuseal/deps.json", "pkgs/by-name/docuseal/yarn.lock"]
|
||||
precedence = "closest"
|
||||
|
||||
[[annotations]]
|
||||
|
|
|
@ -75,9 +75,6 @@ let
|
|||
"REUSE.toml"
|
||||
"shell.nix"
|
||||
|
||||
# Commit revert
|
||||
"patches/colmena/0001-*"
|
||||
|
||||
# Docuseal
|
||||
"pkgs/by-name/docuseal/rubyEnv/*"
|
||||
"pkgs/by-name/docuseal/deps.json"
|
||||
|
|
|
@ -33,9 +33,6 @@ rec {
|
|||
# List of keys for the root group
|
||||
rootKeys = getMemberKeys meta.organization.groups.root;
|
||||
|
||||
# List of keys for the root group (for age encryption and decryption)
|
||||
rootAgeKeys = getAgeKeys meta.organization.groups.root;
|
||||
|
||||
# All admins for a node
|
||||
getNodeAdmins = node: meta.organization.groups.root ++ meta.nodes.${node}.admins;
|
||||
|
||||
|
@ -43,15 +40,15 @@ rec {
|
|||
getSecretKeys = node: lib.unique (getAgeKeys (getNodeAdmins node) ++ getNodeKeys [ node ]);
|
||||
|
||||
# List of keys for all machines wide secrets
|
||||
machineKeys = rootAgeKeys ++ (getNodeKeys (builtins.attrNames meta.nodes));
|
||||
machineKeys = rootKeys ++ (getNodeKeys (builtins.attrNames meta.nodes));
|
||||
|
||||
mkSecrets = nodes: setDefault { publicKeys = lib.unique (builtins.concatMap getSecretKeys nodes); };
|
||||
|
||||
mkRootSecrets = setDefault { publicKeys = lib.unique rootAgeKeys; };
|
||||
mkRootSecrets = setDefault { publicKeys = lib.unique rootKeys; };
|
||||
|
||||
machineKeysBySystem =
|
||||
system:
|
||||
rootAgeKeys
|
||||
rootKeys
|
||||
++ (getNodeKeys (
|
||||
builtins.attrNames (lib.filterAttrs (_: v: v.nixpkgs.system == system) meta.nodes)
|
||||
));
|
||||
|
|
|
@ -1,141 +0,0 @@
|
|||
# SPDX-FileCopyrightText: 2025 Lubin Bailly <lubin.bailly@dgnum.eu>
|
||||
#
|
||||
# SPDX-License-Identifier: EUPL-1.2
|
||||
|
||||
{ config, lib, ... }:
|
||||
let
|
||||
inherit (lib)
|
||||
concatImapStringsSep
|
||||
concatMapAttrsStringSep
|
||||
concatMapStrings
|
||||
mkOption
|
||||
;
|
||||
inherit (lib.types)
|
||||
attrsOf
|
||||
ints
|
||||
listOf
|
||||
str
|
||||
submodule
|
||||
;
|
||||
in
|
||||
{
|
||||
options = {
|
||||
access.address-assignment.pool = mkOption {
|
||||
type = attrsOf (
|
||||
submodule (
|
||||
{ name, config, ... }:
|
||||
{
|
||||
options = {
|
||||
family.inet = {
|
||||
network = mkOption {
|
||||
type = str;
|
||||
description = ''
|
||||
Network where this pool is located.
|
||||
'';
|
||||
};
|
||||
ranges = mkOption {
|
||||
type = listOf (submodule {
|
||||
options = {
|
||||
low = mkOption {
|
||||
type = str;
|
||||
description = ''
|
||||
Lowest IP of this range.
|
||||
'';
|
||||
};
|
||||
high = mkOption {
|
||||
type = str;
|
||||
description = ''
|
||||
Highest IP of this range.
|
||||
'';
|
||||
};
|
||||
};
|
||||
});
|
||||
description = ''
|
||||
IP ranges in this pool.
|
||||
'';
|
||||
};
|
||||
dhcp-attributes = {
|
||||
maximum-lease-time = mkOption {
|
||||
type = ints.unsigned;
|
||||
description = ''
|
||||
Maximum lease time for leases in this pool.
|
||||
'';
|
||||
};
|
||||
name-server = mkOption {
|
||||
type = listOf str;
|
||||
default = [ ];
|
||||
description = ''
|
||||
DNS servers to propose.
|
||||
'';
|
||||
};
|
||||
router = mkOption {
|
||||
type = listOf str;
|
||||
default = [ ];
|
||||
description = ''
|
||||
Router IP for default route.
|
||||
'';
|
||||
};
|
||||
};
|
||||
};
|
||||
xml = mkOption {
|
||||
type = str;
|
||||
readOnly = true;
|
||||
visible = false;
|
||||
};
|
||||
};
|
||||
config.xml =
|
||||
let
|
||||
inet-cfg = config.family.inet;
|
||||
in
|
||||
''
|
||||
<pool>
|
||||
<name>${name}</name>
|
||||
<family>
|
||||
<inet>
|
||||
<network>${inet-cfg.network}</network>
|
||||
${concatImapStringsSep "\n" (
|
||||
idx:
|
||||
{ low, high }:
|
||||
''
|
||||
<range>
|
||||
<name>${name}-${toString idx}</name>
|
||||
<low>${low}</low>
|
||||
<high>${high}</high>
|
||||
</range>
|
||||
''
|
||||
) inet-cfg.ranges}
|
||||
<dhcp-attributes>
|
||||
<maximum-lease-time>${toString inet-cfg.dhcp-attributes.maximum-lease-time}</maximum-lease-time>
|
||||
${concatMapStrings (
|
||||
dns: "<name-server><name>${dns}</name></name-server>"
|
||||
) inet-cfg.dhcp-attributes.name-server}
|
||||
${concatMapStrings (
|
||||
router: "<router><name>${router}</name></router>"
|
||||
) inet-cfg.dhcp-attributes.router}
|
||||
</dhcp-attributes>
|
||||
</inet>
|
||||
</family>
|
||||
</pool>
|
||||
'';
|
||||
}
|
||||
)
|
||||
);
|
||||
default = { };
|
||||
description = ''
|
||||
Address pools for DHCP configuration.
|
||||
'';
|
||||
};
|
||||
netconf.xmls.access = mkOption {
|
||||
type = str;
|
||||
visible = false;
|
||||
readOnly = true;
|
||||
};
|
||||
};
|
||||
config.netconf.xmls.access = ''
|
||||
<access operation="replace">
|
||||
<address-assignment>
|
||||
${concatMapAttrsStringSep "\n" (_: pool: pool.xml) config.access.address-assignment.pool}
|
||||
</address-assignment>
|
||||
</access>
|
||||
'';
|
||||
}
|
|
@ -34,14 +34,11 @@ let
|
|||
in
|
||||
{
|
||||
imports = [
|
||||
./access.nix
|
||||
./interfaces.nix
|
||||
./poe.nix
|
||||
./protocols.nix
|
||||
./system.nix
|
||||
./vlans.nix
|
||||
./routing-options.nix
|
||||
./snmp.nix
|
||||
];
|
||||
|
||||
options = {
|
||||
|
@ -101,9 +98,6 @@ in
|
|||
${protocols}
|
||||
${vlans}
|
||||
${poe}
|
||||
${access}
|
||||
${routing-options}
|
||||
${snmp}
|
||||
</configuration>
|
||||
'';
|
||||
rpc = pkgs.writeText "${name}.rpc" ''
|
||||
|
|
|
@ -25,7 +25,6 @@ let
|
|||
interface =
|
||||
{ name, config, ... }:
|
||||
let
|
||||
intf_cfg = config;
|
||||
unit =
|
||||
{ name, config, ... }:
|
||||
{
|
||||
|
@ -34,13 +33,6 @@ let
|
|||
default = true;
|
||||
example = false;
|
||||
};
|
||||
description = mkOption {
|
||||
type = str;
|
||||
default = intf_cfg.description + "." + name;
|
||||
description = ''
|
||||
Descriptive name of this interface unit.
|
||||
'';
|
||||
};
|
||||
family = {
|
||||
ethernet-switching = {
|
||||
enable = mkEnableOption "the ethernet switching on this logical interface";
|
||||
|
@ -105,17 +97,17 @@ let
|
|||
</ethernet-switching>
|
||||
'';
|
||||
|
||||
addr4 = map (addr: "<address><name>${addr}</name></address>") config.family.inet.addresses;
|
||||
addr4 = map (addr: "<name>${addr}</name>") config.family.inet.addresses;
|
||||
inet = optionalString config.family.inet.enable ''
|
||||
<inet>
|
||||
${builtins.concatStringsSep "" addr4}
|
||||
<address>${builtins.concatStringsSep "" addr4}</address>
|
||||
</inet>
|
||||
'';
|
||||
|
||||
addr6 = map (addr: "<address><name>${addr}</name></address>") config.family.inet6.addresses;
|
||||
addr6 = map (addr: "<name>${addr}</name>") config.family.inet6.addresses;
|
||||
inet6 = optionalString config.family.inet6.enable ''
|
||||
<inet6>
|
||||
${builtins.concatStringsSep "" addr6}
|
||||
<address>${builtins.concatStringsSep "" addr6}</address>
|
||||
</inet6>
|
||||
'';
|
||||
in
|
||||
|
@ -123,7 +115,6 @@ let
|
|||
<unit>
|
||||
<name>${name}</name>
|
||||
${optionalString (!config.enable) "<disable/>"}
|
||||
${optionalString config.enable "<description>${config.description}</description>"}
|
||||
<family>
|
||||
${eth}${inet}${inet6}
|
||||
</family>
|
||||
|
@ -140,13 +131,6 @@ let
|
|||
Configuration of the logical interfaces on this physical interface.
|
||||
'';
|
||||
};
|
||||
description = mkOption {
|
||||
type = str;
|
||||
default = name;
|
||||
description = ''
|
||||
Descriptive name of this interface.
|
||||
'';
|
||||
};
|
||||
xml = mkOption {
|
||||
type = str;
|
||||
visible = false;
|
||||
|
@ -160,7 +144,6 @@ let
|
|||
''
|
||||
<interface>
|
||||
<name>${name}</name>
|
||||
${optionalString config.enable "<description>${config.description}</description>"}
|
||||
${optionalString (!config.enable) "<disable/>"}
|
||||
${builtins.concatStringsSep "" units}
|
||||
</interface>
|
||||
|
|
|
@ -1,59 +0,0 @@
|
|||
# SPDX-FileCopyrightText: 2025 Lubin Bailly <lubin.bailly@dgnum.eu>
|
||||
#
|
||||
# SPDX-License-Identifier: EUPL-1.2
|
||||
|
||||
{ config, lib, ... }:
|
||||
let
|
||||
inherit (lib)
|
||||
concatMapStringsSep
|
||||
mkOption
|
||||
;
|
||||
inherit (lib.types)
|
||||
str
|
||||
listOf
|
||||
submodule
|
||||
;
|
||||
in
|
||||
{
|
||||
options = {
|
||||
routing-options.static.route = mkOption {
|
||||
type = listOf (submodule {
|
||||
options = {
|
||||
destination = mkOption {
|
||||
type = str;
|
||||
description = ''
|
||||
Destination network.
|
||||
'';
|
||||
};
|
||||
next-hop = mkOption {
|
||||
type = str;
|
||||
description = ''
|
||||
Gateway for this network.
|
||||
'';
|
||||
};
|
||||
};
|
||||
});
|
||||
default = [ ];
|
||||
description = ''
|
||||
Static routes.
|
||||
'';
|
||||
};
|
||||
netconf.xmls.routing-options = mkOption {
|
||||
type = str;
|
||||
readOnly = true;
|
||||
visible = false;
|
||||
};
|
||||
};
|
||||
config.netconf.xmls.routing-options = ''
|
||||
<routing-options operation="replace">
|
||||
<static>
|
||||
${concatMapStringsSep "\n" (route: ''
|
||||
<route>
|
||||
<name>${route.destination}</name>
|
||||
<next-hop>${route.next-hop}</next-hop>
|
||||
</route>
|
||||
'') config.routing-options.static.route}
|
||||
</static>
|
||||
</routing-options>
|
||||
'';
|
||||
}
|
|
@ -1,80 +0,0 @@
|
|||
# SPDX-FileCopyrightText: 2025 Lubin Bailly <lubin.bailly@dgnum.eu>
|
||||
#
|
||||
# SPDX-License-Identifier: EUPL-1.2
|
||||
|
||||
{ lib, config, ... }:
|
||||
let
|
||||
inherit (lib)
|
||||
concatMapAttrsStringSep
|
||||
mkOption
|
||||
optionalString
|
||||
;
|
||||
inherit (lib.types)
|
||||
attrsOf
|
||||
bool
|
||||
enum
|
||||
str
|
||||
submodule
|
||||
;
|
||||
in
|
||||
{
|
||||
options = {
|
||||
snmp = {
|
||||
filter-interfaces.all-internal-interfaces = mkOption {
|
||||
type = bool;
|
||||
default = false;
|
||||
description = ''
|
||||
Whether to filter internal interfaces.
|
||||
'';
|
||||
};
|
||||
community = mkOption {
|
||||
type = attrsOf (
|
||||
submodule (
|
||||
{ name, config, ... }:
|
||||
{
|
||||
options = {
|
||||
authorization = mkOption {
|
||||
type = enum [
|
||||
"read-only"
|
||||
"read-write"
|
||||
];
|
||||
description = ''
|
||||
Authorization type.
|
||||
'';
|
||||
};
|
||||
xml = mkOption {
|
||||
type = str;
|
||||
visible = false;
|
||||
readOnly = true;
|
||||
};
|
||||
};
|
||||
config.xml = ''
|
||||
<community>
|
||||
<name>${name}</name>
|
||||
<authorization>${config.authorization}</authorization>
|
||||
</community>
|
||||
'';
|
||||
}
|
||||
)
|
||||
);
|
||||
default = { };
|
||||
description = ''
|
||||
Communities for SNMPv2 access.
|
||||
'';
|
||||
};
|
||||
};
|
||||
netconf.xmls.snmp = mkOption {
|
||||
type = str;
|
||||
visible = false;
|
||||
readOnly = true;
|
||||
};
|
||||
};
|
||||
config.netconf.xmls.snmp = ''
|
||||
<snmp operation="replace">
|
||||
<filter-interfaces>
|
||||
${optionalString config.snmp.filter-interfaces.all-internal-interfaces "<all-internal-interfaces/>"}
|
||||
</filter-interfaces>
|
||||
${concatMapAttrsStringSep "" (_: comm: comm.xml) config.snmp.community}
|
||||
</snmp>
|
||||
'';
|
||||
}
|
|
@ -6,25 +6,20 @@
|
|||
|
||||
let
|
||||
inherit (lib)
|
||||
concatMapAttrsStringSep
|
||||
concatMapStrings
|
||||
concatStrings
|
||||
concatStringsSep
|
||||
filter
|
||||
hasPrefix
|
||||
length
|
||||
mkOption
|
||||
optionalString
|
||||
splitString
|
||||
;
|
||||
|
||||
inherit (lib.types)
|
||||
attrsOf
|
||||
enum
|
||||
listOf
|
||||
port
|
||||
str
|
||||
submodule
|
||||
;
|
||||
in
|
||||
|
||||
|
@ -60,20 +55,6 @@ in
|
|||
description = "Port to use for netconf.";
|
||||
default = 830;
|
||||
};
|
||||
dhcp-local-server.group = mkOption {
|
||||
type = attrsOf (submodule {
|
||||
options.interfaces = mkOption {
|
||||
type = listOf str;
|
||||
description = ''
|
||||
Interfaces managed by this group.
|
||||
'';
|
||||
};
|
||||
});
|
||||
default = { };
|
||||
description = ''
|
||||
Groups of configuration for DHCP server.
|
||||
'';
|
||||
};
|
||||
};
|
||||
};
|
||||
netconf.xmls.system = mkOption {
|
||||
|
@ -94,19 +75,6 @@ in
|
|||
ed25519 = map (key: "<ssh-ed25519><name>${key}</name></ssh-ed25519>") (
|
||||
filter (hasPrefix "ssh-ed25519 ") ssh-keys
|
||||
);
|
||||
|
||||
dhcp-local = optionalString (config.system.services.dhcp-local-server.group != { }) ''
|
||||
<dhcp-local-server>
|
||||
${concatMapAttrsStringSep "\n" (name: cfg: ''
|
||||
<group>
|
||||
<name>${name}</name>
|
||||
<interface>
|
||||
${concatMapStrings (intf: "<name>${intf}</name>") cfg.interfaces}
|
||||
</interface>
|
||||
</group>
|
||||
'') config.system.services.dhcp-local-server.group}
|
||||
</dhcp-local-server>
|
||||
'';
|
||||
in
|
||||
''
|
||||
<system>
|
||||
|
@ -121,7 +89,6 @@ in
|
|||
<ssh><port>${toString config.system.services.netconf.port}</port></ssh>
|
||||
<rfc-compliant/><yang-compliant/>
|
||||
</netconf>
|
||||
${dhcp-local}
|
||||
</services>
|
||||
</system>
|
||||
'';
|
||||
|
|
|
@ -1,93 +0,0 @@
|
|||
# SPDX-FileCopyrightText: 2024 Lubin Bailly <lubin.bailly@dgnum.eu>
|
||||
#
|
||||
# SPDX-License-Identifier: EUPL-1.2
|
||||
|
||||
{ lib, ... }:
|
||||
let
|
||||
inherit (lib) mapAttrs mod;
|
||||
inherit (lib.extra) genFuse;
|
||||
in
|
||||
{
|
||||
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"
|
||||
];
|
||||
admin-ip = "fd26:baf9:d250:8000::1001/64";
|
||||
};
|
||||
dgn-interfaces = {
|
||||
# oob
|
||||
"ge-0/0/42".ethernet-switching = {
|
||||
interface-mode = "trunk";
|
||||
vlans = [ "all" ];
|
||||
};
|
||||
# ilo
|
||||
"ge-0/0/47".ethernet-switching = {
|
||||
interface-mode = "access";
|
||||
vlans = [ "admin-core" ];
|
||||
};
|
||||
|
||||
# router
|
||||
"xe-0/1/0".ethernet-switching = {
|
||||
interface-mode = "trunk";
|
||||
vlans = [ "all" ];
|
||||
};
|
||||
# netaccess01
|
||||
"xe-0/1/1".ethernet-switching = {
|
||||
interface-mode = "trunk";
|
||||
vlans = [
|
||||
"users"
|
||||
"ap-staging"
|
||||
"admin-ap"
|
||||
"admin-core"
|
||||
];
|
||||
};
|
||||
# uplink
|
||||
"ge-0/1/3".ethernet-switching = {
|
||||
interface-mode = "trunk";
|
||||
vlans = [ "uplink-cri" ];
|
||||
};
|
||||
|
||||
# debug management
|
||||
"me0".inet.addresses = [ "192.168.42.6/24" ];
|
||||
};
|
||||
|
||||
interfaces =
|
||||
{
|
||||
"irb".unit."0".description = "Admin";
|
||||
}
|
||||
// mapAttrs (_: description: { inherit description; }) (
|
||||
{
|
||||
"xe-0/1/0" = "netcore01";
|
||||
"xe-0/1/1" = "Jaccess04";
|
||||
"ge-0/1/3" = "uplink-cri";
|
||||
"ge-0/0/42" = "oob";
|
||||
"ge-0/0/47" = "psu";
|
||||
}
|
||||
// genFuse (i: {
|
||||
"ge-0/0/${toString i}" = "AP_H1_${toString (i / 6)}_${toString (mod i 6 + 1)}";
|
||||
}) 18
|
||||
);
|
||||
snmp.community."public".authorization = "read-only";
|
||||
}
|
|
@ -2,11 +2,6 @@
|
|||
#
|
||||
# SPDX-License-Identifier: EUPL-1.2
|
||||
|
||||
{ lib, ... }:
|
||||
let
|
||||
inherit (lib) mapAttrs mod;
|
||||
inherit (lib.extra) genFuse;
|
||||
in
|
||||
{
|
||||
dgn-hardware.model = "EX2300-48P";
|
||||
dgn-isp = {
|
||||
|
@ -31,18 +26,4 @@ in
|
|||
# debug management
|
||||
"me0".inet.addresses = [ "192.168.42.6/24" ];
|
||||
};
|
||||
|
||||
interfaces =
|
||||
{
|
||||
"irb".unit."0".description = "Admin";
|
||||
}
|
||||
// mapAttrs (_: description: { inherit description; }) (
|
||||
{
|
||||
"xe-0/1/0" = "Jaccess01";
|
||||
}
|
||||
// genFuse (i: {
|
||||
"ge-0/0/${toString i}" = "AP_H2_${toString (i / 2)}_${toString (mod i 2 + 1)}";
|
||||
}) 6
|
||||
);
|
||||
snmp.community."public".authorization = "read-only";
|
||||
}
|
28
machines/netconf/netcore00.nix
Normal file
28
machines/netconf/netcore00.nix
Normal file
|
@ -0,0 +1,28 @@
|
|||
# SPDX-FileCopyrightText: 2025 Lubin Bailly <lubin.bailly@dgnum.eu>
|
||||
#
|
||||
# SPDX-License-Identifier: EUPL-1.2
|
||||
|
||||
{
|
||||
dgn-hardware = {
|
||||
model = "EX4400-24X";
|
||||
extensions = [ "EX4400-EM-4Y" ];
|
||||
};
|
||||
|
||||
dgn-isp = {
|
||||
enable = true;
|
||||
admin-ip = "fd26:baf9:d250:8000::1010/64";
|
||||
};
|
||||
dgn-interfaces = {
|
||||
"xe-0/2/0".ethernet-switching = {
|
||||
interface-mode = "trunk";
|
||||
vlans = [ "all" ];
|
||||
};
|
||||
"xe-0/0/23".ethernet-switching = {
|
||||
interface-mode = "trunk";
|
||||
vlans = [ "all" ];
|
||||
};
|
||||
|
||||
# debug management
|
||||
"me0".inet.addresses = [ "192.168.2.3/24" ];
|
||||
};
|
||||
}
|
|
@ -2,69 +2,51 @@
|
|||
#
|
||||
# SPDX-License-Identifier: EUPL-1.2
|
||||
|
||||
{ lib, ... }:
|
||||
let
|
||||
inherit (lib) mapAttrs;
|
||||
in
|
||||
{
|
||||
dgn-hardware = {
|
||||
model = "EX4400-24X";
|
||||
extensions = [ "EX4400-EM-4Y" ];
|
||||
};
|
||||
|
||||
dgn-hardware.model = "EX4100-F-48P";
|
||||
dgn-isp = {
|
||||
enable = true;
|
||||
admin-ip = "fd26:baf9:d250:8000::1010/64";
|
||||
core-links = [
|
||||
"xe-0/0/0"
|
||||
"xe-0/0/3"
|
||||
"xe-0/0/22"
|
||||
"xe-0/0/21"
|
||||
];
|
||||
admin-ip = "fd26:baf9:d250:8000::100f/64";
|
||||
};
|
||||
dgn-profiles = {
|
||||
"hypervisor" = {
|
||||
interfaces = [
|
||||
"ge-0/0/1"
|
||||
"ge-0/0/3"
|
||||
"ge-0/0/5"
|
||||
"ge-0/0/7"
|
||||
"ge-0/0/9"
|
||||
];
|
||||
configuration.ethernet-switching = {
|
||||
interface-mode = "access";
|
||||
vlans = [ "hypervisor" ];
|
||||
};
|
||||
};
|
||||
"idrac" = {
|
||||
interfaces = [
|
||||
"ge-0/0/0"
|
||||
"ge-0/0/2"
|
||||
"ge-0/0/4"
|
||||
"ge-0/0/6"
|
||||
"ge-0/0/8"
|
||||
|
||||
# PDU and PSU
|
||||
"ge-0/0/46"
|
||||
"ge-0/0/47"
|
||||
];
|
||||
configuration.ethernet-switching = {
|
||||
interface-mode = "access";
|
||||
vlans = [ "admin-core" ];
|
||||
};
|
||||
};
|
||||
};
|
||||
dgn-interfaces = {
|
||||
"ge-0/0/23".ethernet-switching = {
|
||||
"xe-0/2/0".ethernet-switching = {
|
||||
interface-mode = "trunk";
|
||||
vlans = [ "uplink-cri" ];
|
||||
vlans = [ "all" ];
|
||||
};
|
||||
"xe-0/0/0".ethernet-switching.vlans = [ "uplink-cri" ];
|
||||
"xe-0/0/21".ethernet-switching.vlans = [ "all" ];
|
||||
"xe-0/0/22".ethernet-switching.vlans = [ "all" ];
|
||||
|
||||
# debug management
|
||||
"me0".inet.addresses = [ "192.168.2.3/24" ];
|
||||
"me0".inet.addresses = [ "192.168.2.2/24" ];
|
||||
};
|
||||
dgn-profiles."hypervisor" = {
|
||||
interfaces = [
|
||||
"xe-0/0/4"
|
||||
"xe-0/0/5"
|
||||
"xe-0/0/6"
|
||||
"xe-0/0/7"
|
||||
"xe-0/0/8"
|
||||
"xe-0/0/9"
|
||||
];
|
||||
configuration.ethernet-switching = {
|
||||
interface-mode = "access";
|
||||
vlans = [ "hypervisor" ];
|
||||
};
|
||||
};
|
||||
|
||||
interfaces =
|
||||
{
|
||||
"irb".unit."0".description = "Admin";
|
||||
}
|
||||
// mapAttrs (_: description: { inherit description; }) {
|
||||
"xe-0/0/0" = "Jaccess01";
|
||||
"xe-0/0/3" = "Jaccess04";
|
||||
"xe-0/0/21" = "vault01";
|
||||
"xe-0/0/22" = "netcore02";
|
||||
"ge-0/0/23" = "uplink-cri";
|
||||
"xe-0/0/4" = "random02";
|
||||
"xe-0/0/5" = "random03";
|
||||
"xe-0/0/6" = "hypervisor01";
|
||||
"xe-0/0/7" = "hypervisor02";
|
||||
"xe-0/0/8" = "hypervisor03";
|
||||
"xe-0/0/9" = "build01";
|
||||
};
|
||||
snmp.community."public".authorization = "read-only";
|
||||
}
|
||||
|
|
|
@ -1,87 +1,77 @@
|
|||
# SPDX-FileCopyrightText: 2025 Lubin Bailly <lubin.bailly@dgnum.eu>
|
||||
# SPDX-FileCopyrightText: 2024 Lubin Bailly <lubin.bailly@dgnum.eu>
|
||||
#
|
||||
# SPDX-License-Identifier: EUPL-1.2
|
||||
|
||||
{ lib, ... }:
|
||||
let
|
||||
inherit (lib) mapAttrs;
|
||||
in
|
||||
{
|
||||
dgn-hardware.model = "EX4100-F-48P";
|
||||
dgn-hardware.model = "EX2300-48P";
|
||||
dgn-isp = {
|
||||
enable = true;
|
||||
admin-ip = "fd26:baf9:d250:8000::100f/64";
|
||||
};
|
||||
dgn-profiles = {
|
||||
"hypervisor" = {
|
||||
interfaces = [
|
||||
"ge-0/0/1"
|
||||
"ge-0/0/3"
|
||||
"ge-0/0/5"
|
||||
"ge-0/0/7"
|
||||
"ge-0/0/9"
|
||||
];
|
||||
configuration.ethernet-switching = {
|
||||
interface-mode = "access";
|
||||
vlans = [ "hypervisor" ];
|
||||
};
|
||||
};
|
||||
"idrac" = {
|
||||
interfaces = [
|
||||
"ge-0/0/0"
|
||||
"ge-0/0/2"
|
||||
"ge-0/0/4"
|
||||
"ge-0/0/6"
|
||||
"ge-0/0/8"
|
||||
"ge-0/0/10"
|
||||
"ge-0/0/12"
|
||||
"ge-0/0/14"
|
||||
|
||||
# PDU and PSU
|
||||
"ge-0/0/45"
|
||||
"ge-0/0/46"
|
||||
"ge-0/0/47"
|
||||
];
|
||||
configuration.ethernet-switching = {
|
||||
interface-mode = "access";
|
||||
vlans = [ "admin-core" ];
|
||||
};
|
||||
};
|
||||
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"
|
||||
];
|
||||
admin-ip = "fd26:baf9:d250:8000::1001/64";
|
||||
};
|
||||
dgn-interfaces = {
|
||||
"xe-0/2/0".ethernet-switching = {
|
||||
# oob
|
||||
"ge-0/0/42".ethernet-switching = {
|
||||
interface-mode = "trunk";
|
||||
vlans = [ "all" ];
|
||||
};
|
||||
# ilo
|
||||
"ge-0/0/47".ethernet-switching = {
|
||||
interface-mode = "access";
|
||||
vlans = [ "admin-core" ];
|
||||
};
|
||||
|
||||
# router
|
||||
"xe-0/1/0".ethernet-switching = {
|
||||
interface-mode = "trunk";
|
||||
vlans = [ "all" ];
|
||||
};
|
||||
# netaccess01
|
||||
"xe-0/1/1".ethernet-switching = {
|
||||
interface-mode = "trunk";
|
||||
vlans = [
|
||||
"users"
|
||||
"ap-staging"
|
||||
"admin-ap"
|
||||
"admin-core"
|
||||
];
|
||||
};
|
||||
# netcore01 (Potos)
|
||||
"xe-0/1/2".ethernet-switching = {
|
||||
interface-mode = "trunk";
|
||||
vlans = [
|
||||
"all"
|
||||
];
|
||||
};
|
||||
# uplink
|
||||
"ge-0/1/3".ethernet-switching = {
|
||||
interface-mode = "trunk";
|
||||
vlans = [ "uplink-cri" ];
|
||||
};
|
||||
|
||||
# debug management
|
||||
"me0".inet.addresses = [ "192.168.2.2/24" ];
|
||||
"me0".inet.addresses = [ "192.168.42.6/24" ];
|
||||
};
|
||||
|
||||
interfaces =
|
||||
{
|
||||
"irb".unit."0".description = "Admin";
|
||||
}
|
||||
// mapAttrs (_: description: { inherit description; }) {
|
||||
"xe-0/2/0" = "netcore01";
|
||||
"ge-0/0/0" = "hypervisor01_idrac";
|
||||
"ge-0/0/2" = "hypervisor02_idrac";
|
||||
"ge-0/0/4" = "hypervisor03_idrac";
|
||||
"ge-0/0/6" = "build01_idrac";
|
||||
"ge-0/0/8" = "random01_idrac";
|
||||
"ge-0/0/10" = "random02_idrac";
|
||||
"ge-0/0/12" = "random03_idrac";
|
||||
"ge-0/0/14" = "vault01_idrac";
|
||||
|
||||
"ge-0/0/1" = "hypervisor01";
|
||||
"ge-0/0/3" = "hypervisor02";
|
||||
"ge-0/0/5" = "hypervisor03";
|
||||
"ge-0/0/7" = "build01";
|
||||
"ge-0/0/9" = "random03";
|
||||
|
||||
"ge-0/0/47" = "psu";
|
||||
"ge-0/0/46" = "psu_pdu";
|
||||
"ge-0/0/45" = "pdu_32A";
|
||||
};
|
||||
snmp.community."public".authorization = "read-only";
|
||||
}
|
||||
|
|
|
@ -16,10 +16,4 @@ builtins.map pkgs.grafanaPlugins.grafanaPlugin [
|
|||
version = "0.13.1";
|
||||
zipHash = "sha256-n1LskeOzp32LZS3PcsRh8FwQVBFVlzczfO2aGbEClSo=";
|
||||
}
|
||||
|
||||
{
|
||||
pname = "knightss27-weathermap-panel";
|
||||
version = "0.4.3";
|
||||
zipHash = "sha256-N0jhFKYEgU8dZCJ1txcYg0rr17+FkGJjXjwyq2TSa74=";
|
||||
}
|
||||
]
|
||||
|
|
|
@ -203,21 +203,6 @@ in
|
|||
"email"
|
||||
];
|
||||
};
|
||||
|
||||
dgn_zulip = {
|
||||
displayName = "Zulip [Chat]";
|
||||
originUrl = "https://zulip.dgnum.eu/complete/oidc/";
|
||||
originLanding = "https://zulip.dgnum.eu";
|
||||
preferShortUsername = true;
|
||||
allowInsecureClientDisablePkce = true;
|
||||
enableLegacyCrypto = true;
|
||||
|
||||
scopeMaps.grp_active = [
|
||||
"openid"
|
||||
"profile"
|
||||
"email"
|
||||
];
|
||||
};
|
||||
};
|
||||
};
|
||||
};
|
||||
|
|
|
@ -23,19 +23,7 @@ in
|
|||
|
||||
hostname = host;
|
||||
|
||||
settings = {
|
||||
auth.socialite = {
|
||||
configs.kanidm = {
|
||||
listener = "\\SocialiteProviders\\Kanidm\\KanidmExtendSocialite";
|
||||
client_id = "$KANIDM_CLIENT_ID";
|
||||
client_secret = "$KANIDM_CLIENT_SECRET";
|
||||
redirect = "$KANIDM_REDIRECT_URI";
|
||||
base_url = "$KANIDM_BASE_URL";
|
||||
};
|
||||
default_role = "normal";
|
||||
register = true;
|
||||
};
|
||||
};
|
||||
settings = { };
|
||||
|
||||
database = {
|
||||
createLocally = true;
|
||||
|
|
|
@ -80,11 +80,3 @@ index 3d89a1530..a00c5f307 100644
|
|||
{
|
||||
"name": "socialiteproviders/manager",
|
||||
"version": "v4.6.0",
|
||||
index 3d89a1530..a00c5f307 100644
|
||||
--- a/app/Providers/EventServiceProvider.php
|
||||
+++ b/app/Providers/EventServiceProvider.php
|
||||
@@ -33,3 +33,4 @@
|
||||
\SocialiteProviders\Manager\SocialiteWasCalled::class => [
|
||||
+ \SocialiteProviders\Kanidm\KanidmExtendSocialite::class.'@handle',
|
||||
\App\Listeners\SocialiteWasCalledListener::class,
|
||||
],
|
||||
|
|
Binary file not shown.
|
@ -12,7 +12,6 @@
|
|||
# Becareful, jool will not translate ips. Prefer ipv6 proxy target
|
||||
redirects = {
|
||||
"kfet.lab.dgnum.eu" = "v6.labcore01.pav01.infra.lab.dgnum.eu:443";
|
||||
"zulip.dgnum.eu" = "v6.zulip01.pav01.infra.lab.dgnum.eu:443";
|
||||
};
|
||||
};
|
||||
};
|
||||
|
|
|
@ -33,8 +33,6 @@ in
|
|||
};
|
||||
|
||||
dashboard = {
|
||||
package = nixpkgs.nixos.unstable.netbird-dashboard;
|
||||
|
||||
settings = {
|
||||
AUTH_AUTHORITY = "https://sso.dgnum.eu/oauth2/openid/dgn_netbird";
|
||||
AUTH_AUDIENCE = "dgn_netbird";
|
||||
|
|
|
@ -15,7 +15,6 @@ in
|
|||
flags = {
|
||||
retentionPeriod = "4w";
|
||||
httpListenAddr = "${meta.network.${name}.netbirdIp}:${builtins.toString port}";
|
||||
maxConcurrentInserts = "200";
|
||||
};
|
||||
};
|
||||
|
||||
|
|
|
@ -14,7 +14,7 @@ lib.extra.mkConfig {
|
|||
"k-radius"
|
||||
"monitoring"
|
||||
"networking"
|
||||
# "ups"
|
||||
"ups"
|
||||
"ulogd"
|
||||
];
|
||||
|
||||
|
|
|
@ -5,6 +5,5 @@
|
|||
{
|
||||
imports = [
|
||||
./victorialogs.nix
|
||||
./snmp.nix
|
||||
];
|
||||
}
|
||||
|
|
|
@ -1,68 +0,0 @@
|
|||
# SPDX-FileCopyrightText: 2025 Lubin Bailly <lubin@dgnum.eu>
|
||||
#
|
||||
# SPDX-License-Identifier: EUPL-1.2
|
||||
|
||||
{
|
||||
pkgs,
|
||||
lib,
|
||||
meta,
|
||||
...
|
||||
}:
|
||||
let
|
||||
inherit (lib) elem filterAttrs mapAttrsToList;
|
||||
|
||||
port = 9004;
|
||||
in
|
||||
{
|
||||
dgn-monitoring = {
|
||||
exporters.ports.snmp = port;
|
||||
|
||||
scrapeConfigs = {
|
||||
"switches" = {
|
||||
static_configs =
|
||||
mapAttrsToList
|
||||
(hostname: cfg: {
|
||||
targets = [ cfg.deployment.targetHost ];
|
||||
labels = { inherit hostname; };
|
||||
})
|
||||
(
|
||||
filterAttrs (
|
||||
_: cfg:
|
||||
cfg.nixpkgs.system == "netconf"
|
||||
&& elem cfg.site [
|
||||
"pot01"
|
||||
"hyp01"
|
||||
"hyp02"
|
||||
]
|
||||
) meta.nodes
|
||||
);
|
||||
scrape_timeout = "30s";
|
||||
metrics_path = "/snmp";
|
||||
params = {
|
||||
auth = [ "public_v2" ];
|
||||
module = [ "if_mib" ];
|
||||
};
|
||||
relabel_configs = [
|
||||
{
|
||||
target_label = "__param_target";
|
||||
source_labels = [ "__address__" ];
|
||||
}
|
||||
{
|
||||
target_label = "instance";
|
||||
source_labels = [ "__param_target" ];
|
||||
}
|
||||
{
|
||||
target_label = "__address__";
|
||||
replacement = "localhost:${toString port}";
|
||||
}
|
||||
];
|
||||
};
|
||||
};
|
||||
};
|
||||
services.prometheus.exporters.snmp = {
|
||||
enable = true;
|
||||
|
||||
enableConfigCheck = false;
|
||||
configurationPath = pkgs.prometheus-snmp-exporter.src + "/snmp.yml";
|
||||
};
|
||||
}
|
|
@ -12,12 +12,7 @@
|
|||
}:
|
||||
|
||||
let
|
||||
inherit (lib)
|
||||
genList
|
||||
mapAttrs'
|
||||
mkOption
|
||||
nameValuePair
|
||||
;
|
||||
inherit (lib) mapAttrs' mkOption nameValuePair;
|
||||
inherit (lib.types) listOf attrs;
|
||||
|
||||
uplink = {
|
||||
|
@ -353,7 +348,6 @@ in
|
|||
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
|
||||
ip saddr 192.168.0.0/17 ip daddr != 192.168.0.0/17 snat ip to 129.199.195.130-129.199.195.157
|
||||
}
|
||||
'';
|
||||
};
|
||||
|
@ -389,7 +383,7 @@ in
|
|||
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 ip saddr != 192.168.0.0/17 jump forward_reject;
|
||||
ip saddr != 10.0.0.0/16 jump forward_reject;
|
||||
|
||||
# Can talk to us
|
||||
ip daddr 10.0.0.0/27 accept;
|
||||
|
|
|
@ -68,7 +68,7 @@ in
|
|||
};
|
||||
|
||||
plugins = {
|
||||
inherit (wp4nix.plugins) pages-with-category-and-tag user-role-editor;
|
||||
inherit (wp4nix.plugins) user-role-editor;
|
||||
};
|
||||
|
||||
languages = [ pkgs.wordpressPackages.languages.fr_FR ];
|
||||
|
|
|
@ -15,6 +15,7 @@ lib.extra.mkConfig {
|
|||
"cas-eleves"
|
||||
# "kadenios"
|
||||
"django-apps"
|
||||
"mattermost"
|
||||
];
|
||||
|
||||
extraConfig = {
|
||||
|
|
348
machines/nixos/web02/mattermost/0001-Login-page-ENS-theme.patch
Normal file
348
machines/nixos/web02/mattermost/0001-Login-page-ENS-theme.patch
Normal file
|
@ -0,0 +1,348 @@
|
|||
From ec1ffa5fc38cdd6d0cc5e8dea07d9a4730fc5a32 Mon Sep 17 00:00:00 2001
|
||||
From: hbarral <hbarral@clipper.ens.fr>
|
||||
Date: Fri, 25 Oct 2024 06:50:47 +0200
|
||||
Subject: [PATCH 1/2] Login page: ENS theme This commit should be cherry-picked
|
||||
on top of of new Mattermost releases
|
||||
MIME-Version: 1.0
|
||||
Content-Type: text/plain; charset=UTF-8
|
||||
Content-Transfer-Encoding: 8bit
|
||||
|
||||
Co-authored-by: Théophile Bastian <contact@tobast.fr>
|
||||
---
|
||||
.../channels/src/components/login/login.scss | 87 +++++++++++++++++-
|
||||
.../channels/src/components/login/login.tsx | 78 +++++++++++++---
|
||||
webapp/channels/src/images/emailLogo.png | Bin 0 -> 605 bytes
|
||||
webapp/channels/src/images/gitlabLogo.png | Bin 0 -> 1655 bytes
|
||||
webapp/channels/src/images/noaccountLogo.png | Bin 0 -> 693 bytes
|
||||
5 files changed, 153 insertions(+), 12 deletions(-)
|
||||
create mode 100644 webapp/channels/src/images/emailLogo.png
|
||||
create mode 100644 webapp/channels/src/images/gitlabLogo.png
|
||||
create mode 100644 webapp/channels/src/images/noaccountLogo.png
|
||||
|
||||
diff --git a/webapp/channels/src/components/login/login.scss b/webapp/channels/src/components/login/login.scss
|
||||
index e64aebccb4..ec7dafdafb 100644
|
||||
--- a/webapp/channels/src/components/login/login.scss
|
||||
+++ b/webapp/channels/src/components/login/login.scss
|
||||
@@ -3,6 +3,10 @@
|
||||
|
||||
@use 'utils/mixins';
|
||||
|
||||
+$clipper_color: #548;
|
||||
+$email_color: #4d8844;
|
||||
+$exte_color: #886344;
|
||||
+
|
||||
.login-body {
|
||||
display: flex;
|
||||
flex-direction: column;
|
||||
@@ -130,6 +134,88 @@
|
||||
margin: 20px 0 10px;
|
||||
}
|
||||
|
||||
+ .collapsed {
|
||||
+ display: none;
|
||||
+ }
|
||||
+
|
||||
+ .login-btn {
|
||||
+ @include mixins.primary-button;
|
||||
+ @include mixins.button-large;
|
||||
+
|
||||
+ display: flex;
|
||||
+ height: 64px;
|
||||
+ flex-direction: row;
|
||||
+ align-items: center;
|
||||
+ justify-content: flex-start;
|
||||
+ background-color: red;
|
||||
+ text-decoration: none;
|
||||
+
|
||||
+ .text {
|
||||
+ display: flex;
|
||||
+ width: 80%;
|
||||
+ flex-direction: column;
|
||||
+ align-items: center;
|
||||
+ justify-content: space-evenly;
|
||||
+
|
||||
+ & > span {
|
||||
+ display: inline-block;
|
||||
+
|
||||
+ &:nth-child(2) {
|
||||
+ font-size: 0.8em;
|
||||
+ font-style: italic;
|
||||
+ font-weight: normal;
|
||||
+ }
|
||||
+ }
|
||||
+ }
|
||||
+
|
||||
+ .icon {
|
||||
+ position: relative;
|
||||
+ display: inline-block;
|
||||
+ width: 42px;
|
||||
+ height: 42px;
|
||||
+ margin-right: 12px;
|
||||
+ background-size: 100% 100%;
|
||||
+ text-align: center;
|
||||
+ }
|
||||
+ }
|
||||
+
|
||||
+ .login-body-card-auth-clipper {
|
||||
+ background-color: $clipper_color;
|
||||
+
|
||||
+ &:hover {
|
||||
+ background-color: darken($clipper_color, 10%);
|
||||
+ }
|
||||
+
|
||||
+ .icon {
|
||||
+ background-image: url('../../images/gitlabLogo.png');
|
||||
+ }
|
||||
+ }
|
||||
+
|
||||
+ .login-body-card-auth-mail-toggle {
|
||||
+ background-color: $email_color;
|
||||
+
|
||||
+ &:hover {
|
||||
+ background-color: darken($email_color, 10%);
|
||||
+ }
|
||||
+
|
||||
+ .icon {
|
||||
+ background-image: url('../../images/emailLogo.png');
|
||||
+ }
|
||||
+ }
|
||||
+
|
||||
+ .login-body-card-auth-exte {
|
||||
+ background-color: $exte_color;
|
||||
+ margin-top: 10px;
|
||||
+
|
||||
+ &:hover {
|
||||
+ background-color: darken($exte_color, 10%);
|
||||
+ }
|
||||
+
|
||||
+ .icon {
|
||||
+ background-image: url('../../images/noaccountLogo.png');
|
||||
+ }
|
||||
+ }
|
||||
+
|
||||
.login-body-card-form {
|
||||
.login-body-card-form-input {
|
||||
margin-top: 22px;
|
||||
@@ -161,7 +246,7 @@
|
||||
display: flex;
|
||||
height: 1px;
|
||||
justify-content: center;
|
||||
- margin: 40px 0;
|
||||
+ margin: 20px 0;
|
||||
background: rgba(var(--center-channel-color-rgb), 0.08);
|
||||
text-align: center;
|
||||
|
||||
diff --git a/webapp/channels/src/components/login/login.tsx b/webapp/channels/src/components/login/login.tsx
|
||||
index 5668c029a7..d5e2794584 100644
|
||||
--- a/webapp/channels/src/components/login/login.tsx
|
||||
+++ b/webapp/channels/src/components/login/login.tsx
|
||||
@@ -121,6 +121,8 @@ const Login = ({onCustomizeHeader}: LoginProps) => {
|
||||
const [alertBanner, setAlertBanner] = useState<AlertBannerProps | null>(null);
|
||||
const [hasError, setHasError] = useState(false);
|
||||
const [isMobileView, setIsMobileView] = useState(false);
|
||||
+ const [showEmailForm, setShowEmailForm] = useState(false);
|
||||
+
|
||||
|
||||
const enableCustomBrand = EnableCustomBrand === 'true';
|
||||
const enableLdap = EnableLdap === 'true';
|
||||
@@ -460,6 +462,10 @@ const Login = ({onCustomizeHeader}: LoginProps) => {
|
||||
};
|
||||
}, []);
|
||||
|
||||
+ function toggleEmailForm() {
|
||||
+ setShowEmailForm(!showEmailForm);
|
||||
+ }
|
||||
+
|
||||
if (initializing) {
|
||||
return (<LoadingScreen/>);
|
||||
}
|
||||
@@ -780,6 +786,8 @@ const Login = ({onCustomizeHeader}: LoginProps) => {
|
||||
);
|
||||
}
|
||||
|
||||
+ const doShowEmailForm = (showEmailForm) ? '' : ' collapsed';
|
||||
+
|
||||
if (!enableBaseLogin && !enableExternalSignup) {
|
||||
return (
|
||||
<ColumnLayout
|
||||
@@ -848,13 +856,50 @@ const Login = ({onCustomizeHeader}: LoginProps) => {
|
||||
onDismiss={alertBanner.onDismiss ?? dismissAlert}
|
||||
/>
|
||||
)}
|
||||
+ {enableExternalSignup && (
|
||||
+ <a
|
||||
+ className='login-body-card-auth-clipper login-btn'
|
||||
+ id='gitlab'
|
||||
+ href={Client4.getOAuthRoute() + '/gitlab/login'}
|
||||
+ >
|
||||
+ <span className='icon'/>
|
||||
+ <span className='text'>
|
||||
+ <span>
|
||||
+ {formatMessage({id: 'login.clipper', defaultMessage: 'Clipper'})}
|
||||
+ </span>
|
||||
+ <span>
|
||||
+ {formatMessage({id: 'login.clipper_help', defaultMessage: '("Gitlab" sur mobile)'})}
|
||||
+ </span>
|
||||
+ </span>
|
||||
+ </a>
|
||||
+ )}
|
||||
+ {enableBaseLogin && enableExternalSignup && (
|
||||
+ <div className='login-body-card-form-divider'>
|
||||
+ <span className='login-body-card-form-divider-label'>
|
||||
+ {formatMessage({id: 'login.or', defaultMessage: 'or log in with'})}
|
||||
+ </span>
|
||||
+ </div>
|
||||
+ )}
|
||||
+ {enableBaseLogin && (
|
||||
+ <div
|
||||
+ className='login-body-card-auth-mail-toggle login-btn'
|
||||
+ onClick={toggleEmailForm}
|
||||
+ >
|
||||
+ <span className='icon'/>
|
||||
+ <span className='text'>
|
||||
+ <span>
|
||||
+ {formatMessage({id: 'login.email', defaultMessage: 'Adresse email'})}
|
||||
+ </span>
|
||||
+ </span>
|
||||
+ </div>
|
||||
+ )}
|
||||
{enableBaseLogin && (
|
||||
<form
|
||||
onSubmit={(event: FormEvent<HTMLFormElement>) => {
|
||||
preSubmit(event as unknown as React.MouseEvent);
|
||||
}}
|
||||
>
|
||||
- <div className='login-body-card-form'>
|
||||
+ <div className={'login-body-card-form' + doShowEmailForm}>
|
||||
<Input
|
||||
ref={loginIdInput}
|
||||
name='loginId'
|
||||
@@ -895,16 +940,27 @@ const Login = ({onCustomizeHeader}: LoginProps) => {
|
||||
</span>
|
||||
</div>
|
||||
)}
|
||||
- {enableExternalSignup && (
|
||||
- <div className={classNames('login-body-card-form-login-options', {column: !enableBaseLogin})}>
|
||||
- {getExternalLoginOptions().map((option) => (
|
||||
- <ExternalLoginButton
|
||||
- key={option.id}
|
||||
- direction={enableBaseLogin ? undefined : 'column'}
|
||||
- {...option}
|
||||
- />
|
||||
- ))}
|
||||
- </div>
|
||||
+ {enableBaseLogin && (
|
||||
+ <a
|
||||
+ className='login-body-card-auth-exte login-btn'
|
||||
+ href='@exte_login@'
|
||||
+ >
|
||||
+ <span className='icon'/>
|
||||
+ <span className='text'>
|
||||
+ <span>
|
||||
+ {formatMessage({
|
||||
+ id: 'login.noClipperAccount',
|
||||
+ defaultMessage: 'Pas de compte Clipper ?',
|
||||
+ })}
|
||||
+ </span>
|
||||
+ <span>
|
||||
+ {formatMessage({
|
||||
+ id: 'login.createExte',
|
||||
+ defaultMessage: 'Demander un compte extérieur',
|
||||
+ })}
|
||||
+ </span>
|
||||
+ </span>
|
||||
+ </a>
|
||||
)}
|
||||
</div>
|
||||
</div>
|
||||
diff --git a/webapp/channels/src/images/emailLogo.png b/webapp/channels/src/images/emailLogo.png
|
||||
new file mode 100644
|
||||
index 0000000000000000000000000000000000000000..098922ea6e827eca14dad9810cb953079a1a623d
|
||||
GIT binary patch
|
||||
literal 605
|
||||
zcmeAS@N?(olHy`uVBq!ia0y~yU~m9o4i*Lm28M*4p$rTROiAAEE)2Od`|PeWFfecy
|
||||
zctjR6Fz6|RFk{71`!WUw2KEw9Usv|WENsGR>R+M-zcDZ{zVmc(49U3nc80EpbD%`q
|
||||
z{)Ie(EuBqGY~4qV1X>SXnswG}_QkD|z0oGSN;Yar#caOmqc+)<O{}@8$x)z9da`ZX
|
||||
zYuW2>|Gk@6z5YSvZQ18<Z0+xt&nvbQ)CGaH@_`2yxVG=Oy0FzT@rK=TUC&p2mb?F2
|
||||
z&h{ysHRCVq<tLUK-|#+|94q+kXV=|5{&RV(w=f>QQ|;~Uv*Bp<ns4$slNY-Ef4)26
|
||||
z-2F?UmSH>l&;DyPP1~{MZxV;@e6?3kO!iLeQJJ^X<Lg1Cl|hFKo2?&7sF@l~$<#JB
|
||||
zci!_#<k6!`OHZ0q%1ymtU#YsYLPk{kOtI|Ee{HPO?)F=LeDTYz)00p6ru^ikCstQ8
|
||||
ze|&TAu|tdPuH>2DSN!@ut)aMrGdF)-{NeR8S#BM5o#u2%tANFG!TxGK&eh!yEL9d7
|
||||
zS#qp-vmwx;VZjEew%$vOKMrT{O!7E!<J%^Q?xhdeH#lAt4C7VP*dX_wVT~o<;Zse%
|
||||
zXQC7Movhcq+0d!W;ePpoRaRSK^0LIpTq!H&uf0N%?l(-X%DKFAcpJ3v5r=fE`$qkM
|
||||
z#Ru>3AHV8hVb{_2xWS>9?X$|dlz9fzUpVx#6@SnE=@)eU(-nEOmG)<Y>gO!`YvaGt
|
||||
zAy7_4!^OqIdxy*AKcR~R1ryD#DqWS=xSR<Bf0JvOmpne>k^WoC8<cE3UHx3vIVCg!
|
||||
E0QZ>*HUIzs
|
||||
|
||||
literal 0
|
||||
HcmV?d00001
|
||||
|
||||
diff --git a/webapp/channels/src/images/gitlabLogo.png b/webapp/channels/src/images/gitlabLogo.png
|
||||
new file mode 100644
|
||||
index 0000000000000000000000000000000000000000..bdc4422783b804cbaf45f13219354f38e080b654
|
||||
GIT binary patch
|
||||
literal 1655
|
||||
zcmeAS@N?(olHy`uVBq!ia0y~yV6bFhU~u4IVPIh3vJq!zU|?V>cJd72;0S%=1`^~f
|
||||
z@Q5sCU|=~8!i*D3zrJH&V2~_vjVKAuPb(=;EJ|f4FE7{2%*!rLPAo{(%P&fw{mw>;
|
||||
zfr0g#r;B4q#NoF$t9wGiWf>kYYl}Py^jdjp^;9v<++Y^ND|Rf=8`&o0K2_YJ<a*(5
|
||||
z(#9pc8x)sKZO`tVVG_}+cP*s1UnDwbmD>uT0#<I1iS7yuH+{O`#FaBqG(xQG`{(|>
|
||||
z*2VANoO`3wtfDsW^Z7f)=jXn^cYjWGoUqgGN#B3%;fj_m^;?^~Ei!f6_tyVzmrj~Y
|
||||
zJr|X|vGSD8#yd&=5oz63Q<uH2sXXY(cjI;7_ungpSA|-oE^l7(t*LWbW%SgQRxxtx
|
||||
z+NX!iPTtXL@osimMDl+5h?dr@53>ZPt=#Ii{?NhfH`|UYsJ=2;n*L!EoBxkF_bboX
|
||||
z72L~F{&Ux^mW$c?#)BD*&ocb3%3Xh;`DVj8NA5TNbG1vG7ynz6toTGk=R;n7sOV|-
|
||||
zoRHN0TA^Bhbwl@s%Nu{Z>2zY^xu``;WGnYAW)l;;^-=5AO#2v)^7i0k71s`nJ!{o9
|
||||
zI+WfMkbGt7q~eb|s%D3tQqSFXMo>7gYULA#(qkH?2ON8Hl&@Q+Gzcx8d;R|<=iR4t
|
||||
z*n1hT@4g>W9c^=)QPu9{->kxZt<AOjC&U+f^vJZ%l{370PGtLOk)v_PV-1T66jNFy
|
||||
zIfcq*Pg9cr<n~3=_ngif&Hb}JPARZ*oR{Nx?%S880m5rH$N1m9o40FU<z!}Gb02e8
|
||||
zufMmpf9BiBZrWu0t2Lp2_h+^DTeMpQ{+MamzFhU^{_$lc{v2<4b2yG2yH&jX&xwaC
|
||||
zxz&!IxIO2j*EK0Q<#^xiFKU=?Uk#Qzz$P1<Vjt|Y;nF^qpUbYM{oe9#<uhZK+LCPt
|
||||
zKWuY9{%+-Y`R=;&oSg^eeeH_mEZTK7%P1<Rc-M_*Gm<98=J6@Aa4TI<-K+9)%QD?h
|
||||
zS>CcA7>{o3=2A94n%42u?y6Pvs$2Pb(l;}TIJ$H~R$g47a`iIvvR^CoRte25OH_G2
|
||||
z#ohV-?3s7JKfF>qcmJ9cE7@<SZ$xLsTuc1^X`+y@;nK>9;<-lmj|)G^`26=?tIbKn
|
||||
z%%WVmCs(^{pBHp5U$f~_%JpZi_ipfr{roP<^=3oK<HFVx$;V75%I{24Sw5TniMIPS
|
||||
zvx(ZbUFUgCIDXr6UgoPv{b#<{B3@p*p=+1EL3Pz_$9dd}GbU{InkDn-blxTv(NoV1
|
||||
z)|*^OZhPi=jnz0Ly`(Vmgg}YWts7yVGUhs+m|UZwVR&MVOsJcd*%7lnm)-Kdv?+Gg
|
||||
zYN+2_{PV2N`KVN*ebc`iy|A7!>FXc0&x=L3oeWDq%lzf)<x4WAmnwJ8`}J!2;$zGY
|
||||
z|G%s^shqwruiW>vu<Ew-vrhx(st2oPKb~Ayo^r+CcV*1$-F~|l_%-t$oAvnk%hUIg
|
||||
zCzU>sUwOTHQRsu`fpZ)8JqfsSV}Ad{yFJ^zbhFkL#D9La@U?76Zr3?QiB#cNx#xKf
|
||||
zM!xZ%qU$^P;-SRw7Qgcymz`!k7M%J=@N$rQY))os>!Y<|DHCN2jaXEru0Gr{+h|+%
|
||||
z3>oWx3P-jJ+-=>PJ4sO@zwS}R8aDr?wN^(@u|K?b<0FrU-_+a_f4=bq=@&<5Hh#~%
|
||||
zpg8O7dJi4lBjsBcsUGV(vh{PwQ?+i{ytzD%^8a0ut9ln&yB&LVcLihbwAYigUgtXT
|
||||
z1x>V1QFk_ovh90)-Ab}ad~w^iZR=BGKUH$8Ptgp{Gv0Y(h3RI;K(S5jy(<Nm+*|$b
|
||||
zjN3o&R<8X;JA5}S{+dwuI)%gPms67GSK-)V)@`fj?mQ{*rJPCp?p-U%jgQwBDmq<H
|
||||
zf8(BRGT;4{lCwdaa^H)&y*;nKesyZGo6)`J;Q3oh&L4CtR=RetEr>og^}P96j@xgz
|
||||
zoG#p+R$@`(l)Q-hMUHjE1V_0~YkS_m<loq5%l=c;RPy%k&i%7_!kTyS6zyO9^6u0X
|
||||
zZ&dc(n`AR7aP9QRAC2NwiuI2lK3jY+;^w<E3cI{)JHu6_JYNM(-nZ<Md}8^VA5YKZ
|
||||
z>9h#^*}%G!mpAR0m)uePOYPfdz25pF?z=|#GM}0GF8hO1ITUxCb6W3Sx-II#t|K#c
|
||||
z>No$HTpse+_3@oYao%&ct9^@`HRE%AW93CDlgO&#N0#kByQ7ni`_Eo7d*?Olb@vR{
|
||||
fFZuoWKf}xkStZ|&E;z}+z`)??>gTe~DWM4fVgxXO
|
||||
|
||||
literal 0
|
||||
HcmV?d00001
|
||||
|
||||
diff --git a/webapp/channels/src/images/noaccountLogo.png b/webapp/channels/src/images/noaccountLogo.png
|
||||
new file mode 100644
|
||||
index 0000000000000000000000000000000000000000..b51eda513122fe8da10f2fe896b78f380811cc61
|
||||
GIT binary patch
|
||||
literal 693
|
||||
zcmeAS@N?(olHy`uVBq!ia0y~yU~m9o4i*Lm28M*4p$rTROiAAEE)2Od`|PeWFfecy
|
||||
zctjR6Fz6|RFk{71`!WUw2KEw9Usv|WENmijEG}<O{bFEXa`SX?49U3ncE*0c!v+G!
|
||||
zlvCHSBrWxJ7vK&ycbVU4+97^IXyc|5SJ9w*4Qp(i1!phU;W(z3w$|a*n^(t!LNDCf
|
||||
zDy#10xHIpn<@cX8-|x=Xc(r7*pVddPUn)<0W^PP4If>PH*%Os7v(0K<+89(=HI>=E
|
||||
zyf92~@oHpYk#zUHYwd2Be(1sq<CH@(u5r8dcQ`A0cCMXes3~+bw)WV0!2>t){;+o#
|
||||
zDp;&PT+_73WOwcH;wc)F0zOLy?6_Zhn4fh*>#X@Ku?a#9jVf3ENI3=Rei3oib&Oe{
|
||||
z)uP<=>G|!=zar1)z7z~r`ty0-{fY6i4kCsu`f&^TlXCuV&~DI3>iLx5Ui2jGRbjJB
|
||||
zQL^potIBSZc2Ada-Su@ni$j#Z^cRo7zSORspJrcKm^)@#8!<Ue|C{K)A&KRoSi=wF
|
||||
z{mG>V6a_rr<gMdzv?@@lwEdI*z@=Kv;O@DGTMSEl-g+6k^)gBrZr0Y7FkwqLaA@6@
|
||||
zCD$by<WAc&EcmKkz~OXm$J0*peE}N#Djs)6pL@mW<SkXydqAb>^#_wXjxKXP@Ep+o
|
||||
z9#eRV(a?~6PSH`@^$a$}LT)Z@TF;vN9~3^%_{LFFB<OUsE$N7&{GQ@W+xnB%@-kt1
|
||||
zZpVuL9O!<xIckNzO^Dv{V{J>G+_1dcr|B#uRO|gLbWzFkxzR?o!BQTMcD^h3>GHEY
|
||||
zxIXPQ+vEpnXUY>dTFzqKdB5J|cJsq6Uq9CHi-}ZkSah>l^{ST4?U>7JD;Mr{eL73_
|
||||
ucFfgvr$eewzlz_NksW*AQ+@6q@1JbVm+nZK2==9blB1`qpUXO@geCxL=_bDb
|
||||
|
||||
literal 0
|
||||
HcmV?d00001
|
||||
|
||||
--
|
||||
2.49.0
|
||||
|
|
@ -0,0 +1,3 @@
|
|||
SPDX-FileCopyrightText: 2025 hbarral <hbarral@clipper.ens.fr>
|
||||
|
||||
SPDX-License-Identifier: MIT
|
|
@ -0,0 +1,25 @@
|
|||
From 4b0ad3a8398511843393ea92cc12f0666465a13f Mon Sep 17 00:00:00 2001
|
||||
From: hbarral <hbarral@clipper.ens.fr>
|
||||
Date: Sat, 7 Dec 2024 12:24:09 +0100
|
||||
Subject: [PATCH 2/2] Remove annoying "FREE EDITION" badge from webapp UI This
|
||||
commit should be cherry-picked on top of new Mattermost releases.
|
||||
|
||||
---
|
||||
.../product_branding_team_edition.tsx | 1 -
|
||||
1 file changed, 1 deletion(-)
|
||||
|
||||
diff --git a/webapp/channels/src/components/global_header/left_controls/product_menu/product_branding_team_edition/product_branding_team_edition.tsx b/webapp/channels/src/components/global_header/left_controls/product_menu/product_branding_team_edition/product_branding_team_edition.tsx
|
||||
index 2773ba5184..018454c880 100644
|
||||
--- a/webapp/channels/src/components/global_header/left_controls/product_menu/product_branding_team_edition/product_branding_team_edition.tsx
|
||||
+++ b/webapp/channels/src/components/global_header/left_controls/product_menu/product_branding_team_edition/product_branding_team_edition.tsx
|
||||
@@ -43,7 +43,6 @@ const ProductBrandingTeamEdition = (): JSX.Element => {
|
||||
width={116}
|
||||
height={20}
|
||||
/>
|
||||
- <Badge>{'FREE EDITION'}</Badge>
|
||||
</ProductBrandingTeamEditionContainer>
|
||||
);
|
||||
};
|
||||
--
|
||||
2.49.0
|
||||
|
|
@ -0,0 +1,3 @@
|
|||
SPDX-FileCopyrightText: 2025 hbarral <hbarral@clipper.ens.fr>
|
||||
|
||||
SPDX-License-Identifier: MIT
|
50
machines/nixos/web02/mattermost/default.nix
Normal file
50
machines/nixos/web02/mattermost/default.nix
Normal file
|
@ -0,0 +1,50 @@
|
|||
# SPDX-FileCopyrightText: 2024 Tom Hubrecht <tom.hubrecht@dgnum.eu>
|
||||
#
|
||||
# SPDX-License-Identifier: EUPL-1.2
|
||||
|
||||
{ pkgs, ... }:
|
||||
|
||||
let
|
||||
host = "chat.dgnum.eu";
|
||||
port = 8065;
|
||||
|
||||
exte_login = "https://demarches.dgnum.eu/commencer/demande-compte-merle";
|
||||
in
|
||||
|
||||
{
|
||||
imports = [ ./module.nix ];
|
||||
|
||||
services.mattermost = {
|
||||
enable = true;
|
||||
|
||||
inherit port;
|
||||
|
||||
package = pkgs.mattermostLatest.overrideAttrs (old: {
|
||||
webapp = old.webapp.overrideAttrs (wOld: {
|
||||
nativeBuildInputs = wOld.nativeBuildInputs ++ [
|
||||
pkgs.git
|
||||
pkgs.gnused
|
||||
];
|
||||
|
||||
postPatch =
|
||||
(wOld.postPatch or "")
|
||||
+ ''
|
||||
sed -i 's/GitLab/Clipper/g' channels/src/i18n/*.json
|
||||
git apply -p2 < ${pkgs.replaceVars ./0001-Login-page-ENS-theme.patch { inherit exte_login; }}
|
||||
git apply -p2 < ${./0002-Remove-annoying-FREE-EDITION-badge-from-webapp-UI.patch}
|
||||
'';
|
||||
});
|
||||
});
|
||||
|
||||
siteName = "Merle [Discussions ENS]";
|
||||
siteUrl = "https://${host}";
|
||||
|
||||
mutableConfig = true;
|
||||
|
||||
database.peerAuth = true;
|
||||
};
|
||||
|
||||
dgn-web.simpleProxies.mattermost = {
|
||||
inherit host port;
|
||||
};
|
||||
}
|
996
machines/nixos/web02/mattermost/module.nix
Normal file
996
machines/nixos/web02/mattermost/module.nix
Normal file
|
@ -0,0 +1,996 @@
|
|||
# SPDX-FileCopyrightText: The nixpkgs contributors
|
||||
#
|
||||
# SPDX-License-Identifier: MIT
|
||||
|
||||
{
|
||||
config,
|
||||
pkgs,
|
||||
lib,
|
||||
...
|
||||
}:
|
||||
|
||||
let
|
||||
inherit (lib.strings)
|
||||
hasInfix
|
||||
hasSuffix
|
||||
escapeURL
|
||||
concatStringsSep
|
||||
escapeShellArg
|
||||
escapeShellArgs
|
||||
versionAtLeast
|
||||
optionalString
|
||||
;
|
||||
|
||||
inherit (lib.meta) getExe;
|
||||
|
||||
inherit (lib.lists) singleton;
|
||||
|
||||
inherit (lib.attrsets) mapAttrsToList recursiveUpdate optionalAttrs;
|
||||
|
||||
inherit (lib.options) mkOption mkPackageOption mkEnableOption;
|
||||
|
||||
inherit (lib.modules)
|
||||
mkRenamedOptionModule
|
||||
mkMerge
|
||||
mkIf
|
||||
mkDefault
|
||||
;
|
||||
|
||||
inherit (lib.trivial) warnIf throwIf;
|
||||
|
||||
inherit (lib) types;
|
||||
|
||||
cfg = config.services.mattermost;
|
||||
|
||||
# The directory to store mutable data within dataDir.
|
||||
mutableDataDir = "${cfg.dataDir}/data";
|
||||
|
||||
# The plugin directory. Note that this is the *pre-unpack* plugin directory,
|
||||
# since Mattermost looks in mutableDataDir for a directory called "plugins".
|
||||
# If Mattermost is installed with plugins defined in a Nix configuration, the plugins
|
||||
# are symlinked here. Otherwise, this is a real directory and the tarballs are uploaded here.
|
||||
pluginTarballDir = "${mutableDataDir}/plugins";
|
||||
|
||||
# We need a different unpack directory for Mattermost to sync things to at launch,
|
||||
# since the above may be a symlink to the store.
|
||||
pluginUnpackDir = "${mutableDataDir}/.plugins";
|
||||
|
||||
# Mattermost uses this as a staging directory to unpack plugins, among possibly other things.
|
||||
# Ensure that it's inside mutableDataDir since it can get rather large.
|
||||
tempDir = "${mutableDataDir}/tmp";
|
||||
|
||||
# Creates a database URI.
|
||||
mkDatabaseUri =
|
||||
{
|
||||
scheme,
|
||||
user ? null,
|
||||
password ? null,
|
||||
escapeUserAndPassword ? true,
|
||||
host ? null,
|
||||
escapeHost ? true,
|
||||
port ? null,
|
||||
path ? null,
|
||||
query ? { },
|
||||
}:
|
||||
let
|
||||
nullToEmpty = val: if val == null then "" else toString val;
|
||||
|
||||
# Converts a list of URI attrs to a query string.
|
||||
toQuery = mapAttrsToList (
|
||||
name: value: if value == null then null else (escapeURL name) + "=" + (escapeURL (toString value))
|
||||
);
|
||||
|
||||
schemePart = if scheme == null then "" else "${escapeURL scheme}://";
|
||||
userPart =
|
||||
let
|
||||
realUser = if escapeUserAndPassword then escapeURL user else user;
|
||||
realPassword = if escapeUserAndPassword then escapeURL password else password;
|
||||
in
|
||||
if user == null && password == null then
|
||||
""
|
||||
else if user != null && password != null then
|
||||
"${realUser}:${realPassword}"
|
||||
else if user != null then
|
||||
realUser
|
||||
else
|
||||
throw "Either user or username and password must be provided";
|
||||
hostPart =
|
||||
let
|
||||
realHost = if escapeHost then escapeURL (nullToEmpty host) else nullToEmpty host;
|
||||
in
|
||||
if userPart == "" then realHost else "@" + realHost;
|
||||
portPart = if port == null then "" else ":" + (toString port);
|
||||
pathPart = if path == null then "" else "/" + path;
|
||||
queryPart = if query == { } then "" else "?" + concatStringsSep "&" (toQuery query);
|
||||
in
|
||||
schemePart + userPart + hostPart + portPart + pathPart + queryPart;
|
||||
|
||||
database =
|
||||
let
|
||||
hostIsPath = hasInfix "/" cfg.database.host;
|
||||
in
|
||||
if cfg.database.driver == "postgres" then
|
||||
if cfg.database.peerAuth then
|
||||
mkDatabaseUri {
|
||||
scheme = cfg.database.driver;
|
||||
inherit (cfg.database) user;
|
||||
path = escapeURL cfg.database.name;
|
||||
query = {
|
||||
host = cfg.database.socketPath;
|
||||
} // cfg.database.extraConnectionOptions;
|
||||
}
|
||||
else
|
||||
mkDatabaseUri {
|
||||
scheme = cfg.database.driver;
|
||||
inherit (cfg.database) user password;
|
||||
host = if hostIsPath then null else cfg.database.host;
|
||||
port = if hostIsPath then null else cfg.database.port;
|
||||
path = escapeURL cfg.database.name;
|
||||
query =
|
||||
optionalAttrs hostIsPath { inherit (cfg.database) host; } // cfg.database.extraConnectionOptions;
|
||||
}
|
||||
else if cfg.database.driver == "mysql" then
|
||||
if cfg.database.peerAuth then
|
||||
mkDatabaseUri {
|
||||
scheme = null;
|
||||
inherit (cfg.database) user;
|
||||
escapeUserAndPassword = false;
|
||||
host = "unix(${cfg.database.socketPath})";
|
||||
escapeHost = false;
|
||||
path = escapeURL cfg.database.name;
|
||||
query = cfg.database.extraConnectionOptions;
|
||||
}
|
||||
else
|
||||
mkDatabaseUri {
|
||||
scheme = null;
|
||||
inherit (cfg.database) user password;
|
||||
escapeUserAndPassword = false;
|
||||
host =
|
||||
if hostIsPath then
|
||||
"unix(${cfg.database.host})"
|
||||
else
|
||||
"tcp(${cfg.database.host}:${toString cfg.database.port})";
|
||||
escapeHost = false;
|
||||
path = escapeURL cfg.database.name;
|
||||
query = cfg.database.extraConnectionOptions;
|
||||
}
|
||||
else
|
||||
throw "Invalid database driver: ${cfg.database.driver}";
|
||||
|
||||
mattermostPluginDerivations = map (
|
||||
plugin:
|
||||
pkgs.stdenvNoCC.mkDerivation {
|
||||
name = "${cfg.package.name}-plugin";
|
||||
installPhase = ''
|
||||
runHook preInstall
|
||||
mkdir -p $out/share
|
||||
ln -sf ${plugin} $out/share/plugin.tar.gz
|
||||
runHook postInstall
|
||||
'';
|
||||
dontUnpack = true;
|
||||
dontPatch = true;
|
||||
dontConfigure = true;
|
||||
dontBuild = true;
|
||||
preferLocalBuild = true;
|
||||
}
|
||||
) cfg.plugins;
|
||||
|
||||
mattermostPlugins =
|
||||
if mattermostPluginDerivations == [ ] then
|
||||
null
|
||||
else
|
||||
pkgs.stdenvNoCC.mkDerivation {
|
||||
name = "${cfg.package.name}-plugins";
|
||||
nativeBuildInputs = [ pkgs.autoPatchelfHook ] ++ mattermostPluginDerivations;
|
||||
buildInputs = [ cfg.package ];
|
||||
installPhase = ''
|
||||
runHook preInstall
|
||||
mkdir -p $out
|
||||
plugins=(${
|
||||
escapeShellArgs (map (plugin: "${plugin}/share/plugin.tar.gz") mattermostPluginDerivations)
|
||||
})
|
||||
for plugin in "''${plugins[@]}"; do
|
||||
hash="$(sha256sum "$plugin" | awk '{print $1}')"
|
||||
mkdir -p "$hash"
|
||||
tar -C "$hash" -xzf "$plugin"
|
||||
autoPatchelf "$hash"
|
||||
GZIP_OPT=-9 tar -C "$hash" -cvzf "$out/$hash.tar.gz" .
|
||||
rm -rf "$hash"
|
||||
done
|
||||
runHook postInstall
|
||||
'';
|
||||
|
||||
dontUnpack = true;
|
||||
dontPatch = true;
|
||||
dontConfigure = true;
|
||||
dontBuild = true;
|
||||
preferLocalBuild = true;
|
||||
};
|
||||
|
||||
mattermostConfWithoutPlugins = recursiveUpdate {
|
||||
ServiceSettings = {
|
||||
SiteURL = cfg.siteUrl;
|
||||
ListenAddress = "${cfg.host}:${toString cfg.port}";
|
||||
LocalModeSocketLocation = cfg.socket.path;
|
||||
EnableLocalMode = cfg.socket.enable;
|
||||
EnableSecurityFixAlert = cfg.telemetry.enableSecurityAlerts;
|
||||
};
|
||||
TeamSettings.SiteName = cfg.siteName;
|
||||
SqlSettings.DriverName = cfg.database.driver;
|
||||
SqlSettings.DataSource =
|
||||
if cfg.database.fromEnvironment then
|
||||
null
|
||||
else
|
||||
warnIf (!cfg.database.peerAuth && cfg.database.password != null) ''
|
||||
Database password is set in Mattermost config! This password will end up in the Nix store.
|
||||
|
||||
You may be able to simply set the following, if the database is on the same host
|
||||
and peer authentication is enabled:
|
||||
|
||||
services.mattermost.database.peerAuth = true;
|
||||
|
||||
Note that this is the default if you set system.stateVersion to 25.05 or later
|
||||
and the database host is localhost.
|
||||
|
||||
Alternatively, you can write the following to ${
|
||||
if cfg.environmentFile == null then "your environment file" else cfg.environmentFile
|
||||
}:
|
||||
|
||||
MM_SQLSETTINGS_DATASOURCE=${database}
|
||||
|
||||
Then set the following options:
|
||||
services.mattermost.environmentFile = "<your environment file>";
|
||||
services.mattermost.database.fromEnvironment = true;
|
||||
'' database;
|
||||
|
||||
# Note that the plugin tarball directory is not configurable, and is expected to be in FileSettings.Directory/plugins.
|
||||
FileSettings.Directory = mutableDataDir;
|
||||
PluginSettings.Directory = "${pluginUnpackDir}/server";
|
||||
PluginSettings.ClientDirectory = "${pluginUnpackDir}/client";
|
||||
|
||||
LogSettings = {
|
||||
FileLocation = cfg.logDir;
|
||||
|
||||
# Reaches out to Mattermost's servers for telemetry; disable it by default.
|
||||
# https://docs.mattermost.com/configure/environment-configuration-settings.html#enable-diagnostics-and-error-reporting
|
||||
EnableDiagnostics = cfg.telemetry.enableDiagnostics;
|
||||
};
|
||||
} cfg.settings;
|
||||
|
||||
mattermostConf = recursiveUpdate mattermostConfWithoutPlugins (
|
||||
if mattermostPlugins == null then
|
||||
{ }
|
||||
else
|
||||
{
|
||||
PluginSettings = {
|
||||
Enable = true;
|
||||
};
|
||||
}
|
||||
);
|
||||
|
||||
format = pkgs.formats.json { };
|
||||
finalConfig = format.generate "mattermost-config.json" mattermostConf;
|
||||
in
|
||||
{
|
||||
disabledModules = [ "services/web-apps/mattermost.nix" ];
|
||||
|
||||
imports = [
|
||||
(mkRenamedOptionModule
|
||||
[
|
||||
"services"
|
||||
"mattermost"
|
||||
"listenAddress"
|
||||
]
|
||||
[
|
||||
"services"
|
||||
"mattermost"
|
||||
"host"
|
||||
]
|
||||
)
|
||||
(mkRenamedOptionModule
|
||||
[
|
||||
"services"
|
||||
"mattermost"
|
||||
"localDatabaseCreate"
|
||||
]
|
||||
[
|
||||
"services"
|
||||
"mattermost"
|
||||
"database"
|
||||
"create"
|
||||
]
|
||||
)
|
||||
(mkRenamedOptionModule
|
||||
[
|
||||
"services"
|
||||
"mattermost"
|
||||
"localDatabasePassword"
|
||||
]
|
||||
[
|
||||
"services"
|
||||
"mattermost"
|
||||
"database"
|
||||
"password"
|
||||
]
|
||||
)
|
||||
(mkRenamedOptionModule
|
||||
[
|
||||
"services"
|
||||
"mattermost"
|
||||
"localDatabaseUser"
|
||||
]
|
||||
[
|
||||
"services"
|
||||
"mattermost"
|
||||
"database"
|
||||
"user"
|
||||
]
|
||||
)
|
||||
(mkRenamedOptionModule
|
||||
[
|
||||
"services"
|
||||
"mattermost"
|
||||
"localDatabaseName"
|
||||
]
|
||||
[
|
||||
"services"
|
||||
"mattermost"
|
||||
"database"
|
||||
"name"
|
||||
]
|
||||
)
|
||||
(mkRenamedOptionModule
|
||||
[
|
||||
"services"
|
||||
"mattermost"
|
||||
"extraConfig"
|
||||
]
|
||||
[
|
||||
"services"
|
||||
"mattermost"
|
||||
"settings"
|
||||
]
|
||||
)
|
||||
(mkRenamedOptionModule
|
||||
[
|
||||
"services"
|
||||
"mattermost"
|
||||
"statePath"
|
||||
]
|
||||
[
|
||||
"services"
|
||||
"mattermost"
|
||||
"dataDir"
|
||||
]
|
||||
)
|
||||
];
|
||||
|
||||
options = {
|
||||
services.mattermost = {
|
||||
enable = mkEnableOption "Mattermost chat server";
|
||||
|
||||
package = mkPackageOption pkgs "mattermost" { };
|
||||
|
||||
siteUrl = mkOption {
|
||||
type = types.str;
|
||||
example = "https://chat.example.com";
|
||||
description = ''
|
||||
URL this Mattermost instance is reachable under, without trailing slash.
|
||||
'';
|
||||
};
|
||||
|
||||
siteName = mkOption {
|
||||
type = types.str;
|
||||
default = "Mattermost";
|
||||
description = "Name of this Mattermost site.";
|
||||
};
|
||||
|
||||
host = mkOption {
|
||||
type = types.str;
|
||||
default = "127.0.0.1";
|
||||
example = "0.0.0.0";
|
||||
description = ''
|
||||
Host or address that this Mattermost instance listens on.
|
||||
'';
|
||||
};
|
||||
|
||||
port = mkOption {
|
||||
type = types.port;
|
||||
default = 8065;
|
||||
description = ''
|
||||
Port for Mattermost server to listen on.
|
||||
'';
|
||||
};
|
||||
|
||||
dataDir = mkOption {
|
||||
type = types.path;
|
||||
default = "/var/lib/mattermost";
|
||||
description = ''
|
||||
Mattermost working directory.
|
||||
'';
|
||||
};
|
||||
|
||||
socket = {
|
||||
enable = mkEnableOption "Mattermost control socket";
|
||||
|
||||
path = mkOption {
|
||||
type = types.path;
|
||||
default = "${cfg.dataDir}/mattermost.sock";
|
||||
defaultText = ''''${config.mattermost.dataDir}/mattermost.sock'';
|
||||
description = ''
|
||||
Default location for the Mattermost control socket used by `mmctl`.
|
||||
'';
|
||||
};
|
||||
|
||||
export = mkEnableOption "Export socket control to system environment variables";
|
||||
};
|
||||
|
||||
logDir = mkOption {
|
||||
type = types.path;
|
||||
default =
|
||||
if versionAtLeast config.system.stateVersion "25.05" then
|
||||
"/var/log/mattermost"
|
||||
else
|
||||
"${cfg.dataDir}/logs";
|
||||
defaultText = ''
|
||||
if versionAtLeast config.system.stateVersion "25.05" then "/var/log/mattermost"
|
||||
else "''${config.services.mattermost.dataDir}/logs";
|
||||
'';
|
||||
description = ''
|
||||
Mattermost log directory.
|
||||
'';
|
||||
};
|
||||
|
||||
configDir = mkOption {
|
||||
type = types.path;
|
||||
default =
|
||||
if versionAtLeast config.system.stateVersion "25.05" then
|
||||
"/etc/mattermost"
|
||||
else
|
||||
"${cfg.dataDir}/config";
|
||||
defaultText = ''
|
||||
if versionAtLeast config.system.stateVersion "25.05" then
|
||||
"/etc/mattermost"
|
||||
else
|
||||
"''${config.services.mattermost.dataDir}/config";
|
||||
'';
|
||||
description = ''
|
||||
Mattermost config directory.
|
||||
'';
|
||||
};
|
||||
|
||||
mutableConfig = mkOption {
|
||||
type = types.bool;
|
||||
default = false;
|
||||
description = ''
|
||||
Whether the Mattermost config.json is writeable by Mattermost.
|
||||
|
||||
Most of the settings can be edited in the system console of
|
||||
Mattermost if this option is enabled. A template config using
|
||||
the options specified in services.mattermost will be generated
|
||||
but won't be overwritten on changes or rebuilds.
|
||||
|
||||
If this option is disabled, persistent changes in the system
|
||||
console won't be possible (the default). If a config.json is
|
||||
present, it will be overwritten at service start!
|
||||
'';
|
||||
};
|
||||
|
||||
preferNixConfig = mkOption {
|
||||
type = types.bool;
|
||||
default = versionAtLeast config.system.stateVersion "25.05";
|
||||
defaultText = ''
|
||||
versionAtLeast config.system.stateVersion "25.05";
|
||||
'';
|
||||
description = ''
|
||||
If both mutableConfig and this option are set, the Nix configuration
|
||||
will take precedence over any settings configured in the server
|
||||
console.
|
||||
'';
|
||||
};
|
||||
|
||||
plugins = mkOption {
|
||||
type = with types; listOf (either path package);
|
||||
default = [ ];
|
||||
example = "[ ./com.github.moussetc.mattermost.plugin.giphy-2.0.0.tar.gz ]";
|
||||
description = ''
|
||||
Plugins to add to the configuration. Overrides any installed if non-null.
|
||||
This is a list of paths to .tar.gz files or derivations evaluating to
|
||||
.tar.gz files. You can use `mattermost.buildPlugin` to build plugins;
|
||||
see the NixOS documentation for more details.
|
||||
'';
|
||||
};
|
||||
|
||||
pluginsBundle = mkOption {
|
||||
type = with types; nullOr package;
|
||||
default = mattermostPlugins;
|
||||
defaultText = ''
|
||||
All entries in {config}`services.mattermost.plugins`, repacked
|
||||
'';
|
||||
description = ''
|
||||
Derivation building to a directory of plugin tarballs.
|
||||
This overrides {option}`services.mattermost.plugins` if provided.
|
||||
'';
|
||||
};
|
||||
|
||||
telemetry = {
|
||||
enableSecurityAlerts = mkOption {
|
||||
type = types.bool;
|
||||
default = true;
|
||||
description = ''
|
||||
True if we should enable security update checking. This reaches out to Mattermost's servers:
|
||||
https://docs.mattermost.com/manage/telemetry.html#security-update-check-feature
|
||||
'';
|
||||
};
|
||||
|
||||
enableDiagnostics = mkOption {
|
||||
type = types.bool;
|
||||
default = false;
|
||||
description = ''
|
||||
True if we should enable sending diagnostic data. This reaches out to Mattermost's servers:
|
||||
https://docs.mattermost.com/manage/telemetry.html#error-and-diagnostics-reporting-feature
|
||||
'';
|
||||
};
|
||||
};
|
||||
|
||||
environment = mkOption {
|
||||
type = with types; attrsOf (either int str);
|
||||
default = { };
|
||||
description = ''
|
||||
Extra environment variables to export to the Mattermost process
|
||||
from the systemd unit configuration.
|
||||
'';
|
||||
example = {
|
||||
MM_SERVICESETTINGS_SITEURL = "http://example.com";
|
||||
};
|
||||
};
|
||||
|
||||
environmentFile = mkOption {
|
||||
type = with types; nullOr path;
|
||||
default = null;
|
||||
description = ''
|
||||
Environment file (see {manpage}`systemd.exec(5)`
|
||||
"EnvironmentFile=" section for the syntax) which sets config options
|
||||
for mattermost (see [the Mattermost documentation](https://docs.mattermost.com/configure/configuration-settings.html#environment-variables)).
|
||||
|
||||
Settings defined in the environment file will overwrite settings
|
||||
set via Nix or via the {option}`services.mattermost.extraConfig`
|
||||
option.
|
||||
|
||||
Useful for setting config options without their value ending up in the
|
||||
(world-readable) Nix store, e.g. for a database password.
|
||||
'';
|
||||
};
|
||||
|
||||
database = {
|
||||
driver = mkOption {
|
||||
type = types.enum [
|
||||
"postgres"
|
||||
"mysql"
|
||||
];
|
||||
default = "postgres";
|
||||
description = ''
|
||||
The database driver to use (Postgres or MySQL).
|
||||
'';
|
||||
};
|
||||
|
||||
create = mkOption {
|
||||
type = types.bool;
|
||||
default = true;
|
||||
description = ''
|
||||
Create a local PostgreSQL or MySQL database for Mattermost automatically.
|
||||
'';
|
||||
};
|
||||
|
||||
peerAuth = mkOption {
|
||||
type = types.bool;
|
||||
default = versionAtLeast config.system.stateVersion "25.05" && cfg.database.host == "localhost";
|
||||
defaultText = ''
|
||||
versionAtLeast config.system.stateVersion "25.05" && config.services.mattermost.database.host == "localhost"
|
||||
'';
|
||||
description = ''
|
||||
If set, will use peer auth instead of connecting to a Postgres server.
|
||||
Use services.mattermost.database.socketPath to configure the socket path.
|
||||
'';
|
||||
};
|
||||
|
||||
socketPath = mkOption {
|
||||
type = types.path;
|
||||
default =
|
||||
if cfg.database.driver == "postgres" then "/run/postgresql" else "/run/mysqld/mysqld.sock";
|
||||
defaultText = ''
|
||||
if config.services.mattermost.database.driver == "postgres" then "/run/postgresql" else "/run/mysqld/mysqld.sock";
|
||||
'';
|
||||
description = ''
|
||||
The database (Postgres or MySQL) socket path.
|
||||
'';
|
||||
};
|
||||
|
||||
fromEnvironment = mkOption {
|
||||
type = types.bool;
|
||||
default = false;
|
||||
description = ''
|
||||
Use services.mattermost.environmentFile to configure the database instead of writing the database URI
|
||||
to the Nix store. Useful if you use password authentication with peerAuth set to false.
|
||||
'';
|
||||
};
|
||||
|
||||
name = mkOption {
|
||||
type = types.str;
|
||||
default = "mattermost";
|
||||
description = ''
|
||||
Local Mattermost database name.
|
||||
'';
|
||||
};
|
||||
|
||||
host = mkOption {
|
||||
type = types.str;
|
||||
default = "localhost";
|
||||
example = "127.0.0.1";
|
||||
description = ''
|
||||
Host to use for the database. Can also be set to a path if you'd like to connect
|
||||
to a socket using a username and password.
|
||||
'';
|
||||
};
|
||||
|
||||
port = mkOption {
|
||||
type = types.port;
|
||||
default = if cfg.database.driver == "postgres" then 5432 else 3306;
|
||||
defaultText = ''
|
||||
if config.services.mattermost.database.type == "postgres" then 5432 else 3306
|
||||
'';
|
||||
example = 3306;
|
||||
description = ''
|
||||
Port to use for the database.
|
||||
'';
|
||||
};
|
||||
|
||||
user = mkOption {
|
||||
type = types.str;
|
||||
default = "mattermost";
|
||||
description = ''
|
||||
Local Mattermost database username.
|
||||
'';
|
||||
};
|
||||
|
||||
password = mkOption {
|
||||
type = types.str;
|
||||
default = "mmpgsecret";
|
||||
description = ''
|
||||
Password for local Mattermost database user. If set and peerAuth is not true,
|
||||
will cause a warning nagging you to use environmentFile instead since it will
|
||||
end up in the Nix store.
|
||||
'';
|
||||
};
|
||||
|
||||
extraConnectionOptions = mkOption {
|
||||
type = with types; attrsOf (either int str);
|
||||
default =
|
||||
if cfg.database.driver == "postgres" then
|
||||
{
|
||||
sslmode = "disable";
|
||||
connect_timeout = 60;
|
||||
}
|
||||
else if cfg.database.driver == "mysql" then
|
||||
{
|
||||
charset = "utf8mb4,utf8";
|
||||
writeTimeout = "60s";
|
||||
readTimeout = "60s";
|
||||
}
|
||||
else
|
||||
throw "Invalid database driver ${cfg.database.driver}";
|
||||
defaultText = ''
|
||||
if config.mattermost.database.driver == "postgres" then
|
||||
{
|
||||
sslmode = "disable";
|
||||
connect_timeout = 60;
|
||||
}
|
||||
else if config.mattermost.database.driver == "mysql" then
|
||||
{
|
||||
charset = "utf8mb4,utf8";
|
||||
writeTimeout = "60s";
|
||||
readTimeout = "60s";
|
||||
}
|
||||
else
|
||||
throw "Invalid database driver";
|
||||
'';
|
||||
description = ''
|
||||
Extra options that are placed in the connection URI's query parameters.
|
||||
'';
|
||||
};
|
||||
};
|
||||
|
||||
user = mkOption {
|
||||
type = types.str;
|
||||
default = "mattermost";
|
||||
description = ''
|
||||
User which runs the Mattermost service.
|
||||
'';
|
||||
};
|
||||
|
||||
group = mkOption {
|
||||
type = types.str;
|
||||
default = "mattermost";
|
||||
description = ''
|
||||
Group which runs the Mattermost service.
|
||||
'';
|
||||
};
|
||||
|
||||
settings = mkOption {
|
||||
inherit (format) type;
|
||||
default = { };
|
||||
description = ''
|
||||
Additional configuration options as Nix attribute set in config.json schema.
|
||||
'';
|
||||
};
|
||||
|
||||
matterircd = {
|
||||
enable = mkEnableOption "Mattermost IRC bridge";
|
||||
package = mkPackageOption pkgs "matterircd" { };
|
||||
parameters = mkOption {
|
||||
type = types.listOf types.str;
|
||||
default = [ ];
|
||||
example = [
|
||||
"-mmserver chat.example.com"
|
||||
"-bind [::]:6667"
|
||||
];
|
||||
description = ''
|
||||
Set commandline parameters to pass to matterircd. See
|
||||
<https://github.com/42wim/matterircd#usage> for more information.
|
||||
'';
|
||||
};
|
||||
};
|
||||
};
|
||||
};
|
||||
|
||||
config = mkMerge [
|
||||
(mkIf cfg.enable {
|
||||
users.users = {
|
||||
${cfg.user} = {
|
||||
inherit (cfg) group;
|
||||
uid = mkIf (cfg.user == "mattermost") config.ids.uids.mattermost;
|
||||
home = cfg.dataDir;
|
||||
isSystemUser = true;
|
||||
packages = [ cfg.package ];
|
||||
};
|
||||
};
|
||||
|
||||
users.groups = {
|
||||
${cfg.group} = {
|
||||
gid = mkIf (cfg.group == "mattermost") config.ids.gids.mattermost;
|
||||
};
|
||||
};
|
||||
|
||||
services.postgresql = mkIf (cfg.database.driver == "postgres" && cfg.database.create) {
|
||||
enable = true;
|
||||
ensureDatabases = singleton cfg.database.name;
|
||||
ensureUsers = singleton {
|
||||
name =
|
||||
throwIf
|
||||
(cfg.database.peerAuth && (cfg.database.user != cfg.user || cfg.database.name != cfg.database.user))
|
||||
''
|
||||
Mattermost database peer auth is enabled and the user, database user, or database name mismatch.
|
||||
Peer authentication will not work.
|
||||
''
|
||||
cfg.database.user;
|
||||
ensureDBOwnership = true;
|
||||
};
|
||||
};
|
||||
|
||||
services.mysql = mkIf (cfg.database.driver == "mysql" && cfg.database.create) {
|
||||
enable = true;
|
||||
package = mkDefault pkgs.mariadb;
|
||||
ensureDatabases = singleton cfg.database.name;
|
||||
ensureUsers = singleton {
|
||||
name = cfg.database.user;
|
||||
ensurePermissions = {
|
||||
"${cfg.database.name}.*" = "ALL PRIVILEGES";
|
||||
};
|
||||
};
|
||||
settings = rec {
|
||||
mysqld = {
|
||||
collation-server = mkDefault "utf8mb4_general_ci";
|
||||
init-connect = mkDefault "SET NAMES utf8mb4";
|
||||
character-set-server = mkDefault "utf8mb4";
|
||||
};
|
||||
mysqld_safe = mysqld;
|
||||
};
|
||||
};
|
||||
|
||||
environment = {
|
||||
variables = mkIf cfg.socket.export {
|
||||
MMCTL_LOCAL = "true";
|
||||
MMCTL_LOCAL_SOCKET_PATH = cfg.socket.path;
|
||||
};
|
||||
};
|
||||
|
||||
systemd.tmpfiles.rules =
|
||||
[
|
||||
"d ${cfg.dataDir} 0750 ${cfg.user} ${cfg.group} - -"
|
||||
"d ${cfg.logDir} 0750 ${cfg.user} ${cfg.group} - -"
|
||||
"d ${cfg.configDir} 0750 ${cfg.user} ${cfg.group} - -"
|
||||
"d ${mutableDataDir} 0750 ${cfg.user} ${cfg.group} - -"
|
||||
|
||||
# Make sure tempDir exists and is not a symlink.
|
||||
"R- ${tempDir} - - - - -"
|
||||
"d= ${tempDir} 0750 ${cfg.user} ${cfg.group} - -"
|
||||
|
||||
# Ensure that pluginUnpackDir is a directory.
|
||||
# Don't remove or clean it out since it should be persistent, as this is where plugins are unpacked.
|
||||
"d= ${pluginUnpackDir} 0750 ${cfg.user} ${cfg.group} - -"
|
||||
|
||||
# Ensure that the plugin directories exist.
|
||||
"d= ${mattermostConf.PluginSettings.Directory} 0750 ${cfg.user} ${cfg.group} - -"
|
||||
"d= ${mattermostConf.PluginSettings.ClientDirectory} 0750 ${cfg.user} ${cfg.group} - -"
|
||||
|
||||
# Link in some of the immutable data directories.
|
||||
"L+ ${cfg.dataDir}/bin - - - - ${cfg.package}/bin"
|
||||
"L+ ${cfg.dataDir}/fonts - - - - ${cfg.package}/fonts"
|
||||
"L+ ${cfg.dataDir}/i18n - - - - ${cfg.package}/i18n"
|
||||
"L+ ${cfg.dataDir}/templates - - - - ${cfg.package}/templates"
|
||||
"L+ ${cfg.dataDir}/client - - - - ${cfg.package}/client"
|
||||
]
|
||||
++ (
|
||||
if cfg.pluginsBundle == null then
|
||||
# Create the plugin tarball directory to allow plugin uploads.
|
||||
[
|
||||
"d= ${pluginTarballDir} 0750 ${cfg.user} ${cfg.group} - -"
|
||||
]
|
||||
else
|
||||
# Symlink the plugin tarball directory, removing anything existing, since it's managed by Nix.
|
||||
[ "L+ ${pluginTarballDir} - - - - ${cfg.pluginsBundle}" ]
|
||||
);
|
||||
|
||||
systemd.services.mattermost = rec {
|
||||
description = "Mattermost chat service";
|
||||
wantedBy = [ "multi-user.target" ];
|
||||
after = mkMerge [
|
||||
[ "network.target" ]
|
||||
(mkIf (cfg.database.driver == "postgres" && cfg.database.create) [ "postgresql.service" ])
|
||||
(mkIf (cfg.database.driver == "mysql" && cfg.database.create) [ "mysql.service" ])
|
||||
];
|
||||
requires = after;
|
||||
|
||||
environment = mkMerge [
|
||||
{
|
||||
# Use tempDir as this can get rather large, especially if Mattermost unpacks a large number of plugins.
|
||||
TMPDIR = tempDir;
|
||||
}
|
||||
cfg.environment
|
||||
];
|
||||
|
||||
preStart =
|
||||
''
|
||||
dataDir=${escapeShellArg cfg.dataDir}
|
||||
configDir=${escapeShellArg cfg.configDir}
|
||||
logDir=${escapeShellArg cfg.logDir}
|
||||
package=${escapeShellArg cfg.package}
|
||||
nixConfig=${escapeShellArg finalConfig}
|
||||
''
|
||||
+ optionalString (versionAtLeast config.system.stateVersion "25.05") ''
|
||||
# Migrate configs in the pre-25.05 directory structure.
|
||||
oldConfig="$dataDir/config/config.json"
|
||||
newConfig="$configDir/config.json"
|
||||
if [ "$oldConfig" != "$newConfig" ] && [ -f "$oldConfig" ] && [ ! -f "$newConfig" ]; then
|
||||
# Migrate the legacy config location to the new config location
|
||||
echo "Moving legacy config at $oldConfig to $newConfig" >&2
|
||||
mkdir -p "$configDir"
|
||||
mv "$oldConfig" "$newConfig"
|
||||
touch "$configDir/.initial-created"
|
||||
fi
|
||||
|
||||
# Logs too.
|
||||
oldLogs="$dataDir/logs"
|
||||
newLogs="$logDir"
|
||||
if [ "$oldLogs" != "$newLogs" ] && [ -d "$oldLogs" ] && [ ! -f "$newLogs/.initial-created" ]; then
|
||||
# Migrate the legacy log location to the new log location.
|
||||
# Allow this to fail if there aren't any logs to move.
|
||||
echo "Moving legacy logs at $oldLogs to $newLogs" >&2
|
||||
mkdir -p "$newLogs"
|
||||
mv "$oldLogs"/* "$newLogs" || true
|
||||
touch "$newLogs/.initial-created"
|
||||
fi
|
||||
''
|
||||
+ optionalString (!cfg.mutableConfig) ''
|
||||
${getExe pkgs.jq} -s '.[0] * .[1]' "$package/config/config.json" "$nixConfig" > "$configDir/config.json"
|
||||
''
|
||||
+ optionalString cfg.mutableConfig ''
|
||||
if [ ! -e "$configDir/.initial-created" ]; then
|
||||
${getExe pkgs.jq} -s '.[0] * .[1]' "$package/config/config.json" "$nixConfig" > "$configDir/config.json"
|
||||
touch "$configDir/.initial-created"
|
||||
fi
|
||||
''
|
||||
+ optionalString (cfg.mutableConfig && cfg.preferNixConfig) ''
|
||||
echo "$(${getExe pkgs.jq} -s '.[0] * .[1]' "$configDir/config.json" "$nixConfig")" > "$configDir/config.json"
|
||||
'';
|
||||
|
||||
serviceConfig = mkMerge [
|
||||
{
|
||||
User = cfg.user;
|
||||
Group = cfg.group;
|
||||
ExecStart = "${getExe cfg.package} --config ${cfg.configDir}/config.json";
|
||||
ReadWritePaths = [
|
||||
cfg.dataDir
|
||||
cfg.logDir
|
||||
cfg.configDir
|
||||
];
|
||||
UMask = "0027";
|
||||
Restart = "always";
|
||||
RestartSec = 10;
|
||||
LimitNOFILE = 49152;
|
||||
LockPersonality = true;
|
||||
NoNewPrivileges = true;
|
||||
PrivateDevices = true;
|
||||
PrivateTmp = true;
|
||||
PrivateUsers = true;
|
||||
ProtectClock = true;
|
||||
ProtectControlGroups = true;
|
||||
ProtectHome = true;
|
||||
ProtectHostname = true;
|
||||
ProtectKernelLogs = true;
|
||||
ProtectKernelModules = true;
|
||||
ProtectKernelTunables = true;
|
||||
ProtectProc = "invisible";
|
||||
ProtectSystem = "strict";
|
||||
RestrictNamespaces = true;
|
||||
RestrictSUIDSGID = true;
|
||||
EnvironmentFile = cfg.environmentFile;
|
||||
WorkingDirectory = cfg.dataDir;
|
||||
}
|
||||
(mkIf (cfg.dataDir == "/var/lib/mattermost") {
|
||||
StateDirectory = baseNameOf cfg.dataDir;
|
||||
StateDirectoryMode = "0750";
|
||||
})
|
||||
(mkIf (cfg.logDir == "/var/log/mattermost") {
|
||||
LogsDirectory = baseNameOf cfg.logDir;
|
||||
LogsDirectoryMode = "0750";
|
||||
})
|
||||
(mkIf (cfg.configDir == "/etc/mattermost") {
|
||||
ConfigurationDirectory = baseNameOf cfg.configDir;
|
||||
ConfigurationDirectoryMode = "0750";
|
||||
})
|
||||
];
|
||||
|
||||
unitConfig.JoinsNamespaceOf = mkMerge [
|
||||
(mkIf (cfg.database.driver == "postgres" && cfg.database.create) [ "postgresql.service" ])
|
||||
(mkIf (cfg.database.driver == "mysql" && cfg.database.create) [ "mysql.service" ])
|
||||
];
|
||||
};
|
||||
|
||||
assertions = [
|
||||
{
|
||||
# Make sure the URL doesn't have a trailing slash
|
||||
assertion = !(hasSuffix "/" cfg.siteUrl);
|
||||
message = ''
|
||||
services.mattermost.siteUrl should not have a trailing "/".
|
||||
'';
|
||||
}
|
||||
{
|
||||
# Make sure this isn't a host/port pair
|
||||
assertion = !(hasInfix ":" cfg.host && !(hasInfix "[" cfg.host) && !(hasInfix "]" cfg.host));
|
||||
message = ''
|
||||
services.mattermost.host should not include a port. Use services.mattermost.host for the address
|
||||
or hostname, and services.mattermost.port to specify the port separately.
|
||||
'';
|
||||
}
|
||||
];
|
||||
})
|
||||
(mkIf cfg.matterircd.enable {
|
||||
systemd.services.matterircd = {
|
||||
description = "Mattermost IRC bridge service";
|
||||
wantedBy = [ "multi-user.target" ];
|
||||
serviceConfig = {
|
||||
User = "nobody";
|
||||
Group = "nogroup";
|
||||
ExecStart = "${getExe cfg.matterircd.package} ${escapeShellArgs cfg.matterircd.parameters}";
|
||||
WorkingDirectory = "/tmp";
|
||||
PrivateTmp = true;
|
||||
Restart = "always";
|
||||
RestartSec = "5";
|
||||
};
|
||||
};
|
||||
})
|
||||
];
|
||||
|
||||
meta.maintainers = with lib.maintainers; [ numinit ];
|
||||
}
|
|
@ -11,7 +11,6 @@
|
|||
./gestiocof.nix
|
||||
./gestiojeux.nix
|
||||
./interludes.nix
|
||||
./vector.nix
|
||||
./wikiens.nix
|
||||
];
|
||||
|
||||
|
|
|
@ -1,48 +0,0 @@
|
|||
# SPDX-FileCopyrightText: 2025 Tom Hubrecht <tom.hubrecht@dgnum.eu>
|
||||
#
|
||||
# SPDX-License-Identifier: EUPL-1.2
|
||||
|
||||
{ config, ... }:
|
||||
|
||||
{
|
||||
services.django-apps.sites.vector = {
|
||||
source = "https://git.dgnum.eu/DGNum/vector";
|
||||
branch = "main";
|
||||
domain = "photos.dgnum.eu";
|
||||
|
||||
nginx = {
|
||||
enableACME = true;
|
||||
forceSSL = true;
|
||||
};
|
||||
|
||||
webHookSecret = config.age.secrets."webhook-vector_token".path;
|
||||
|
||||
overlays.nix-pkgs = [
|
||||
# Required packages
|
||||
"authens"
|
||||
"django-browser-reload"
|
||||
"django-bulma-forms"
|
||||
"django-unfold"
|
||||
"loadcredential"
|
||||
|
||||
# Dependencies
|
||||
"python-cas"
|
||||
];
|
||||
|
||||
dependencies = ps: [
|
||||
ps.authens
|
||||
ps.django
|
||||
ps.django-browser-reload
|
||||
ps.django-bulma-forms
|
||||
ps.django-import-export
|
||||
ps.django-sesame
|
||||
ps.django-unfold
|
||||
ps.loadcredential
|
||||
ps.pillow
|
||||
];
|
||||
|
||||
credentials = {
|
||||
SECRET_KEY = config.age.secrets."dj_vector-secret_key_file".path;
|
||||
};
|
||||
};
|
||||
}
|
|
@ -1,34 +0,0 @@
|
|||
age-encryption.org/v1
|
||||
-> ssh-ed25519 ZIo4kw U9Awj0lxgjMUgaAzQL2WzYiMgfD+86sKsvNnbd7g1lY
|
||||
ss6ZQIANobWXxHjTykQE3nZqXJ+i+x3x6f7kAzWNbh0
|
||||
-> ssh-ed25519 9/PCvA Yzdb3ff9BW1AAL5JqprCiyAByqsaSmyyUt5DVFq1IBw
|
||||
UxTfF4o9wSk3+XKKTNuWGSLMOPYrgA+ipumR5AzlNgk
|
||||
-> ssh-ed25519 prNEsA VkEG8GR5wWU+V3Dne9UtNK8lOPnMy7lbh9ea+kiTLik
|
||||
gY8l0Uj3ayMkPIVuMHG+BGvm+BYCR1n3HOEcAZWVLWs
|
||||
-> ssh-ed25519 jIXfPA mzhgIxTRN7ZtlRuZTkz0P/Zdl/QVetQHylH6KgL5fQE
|
||||
6dJo93aqlNqC6Kno8958r6+c552CPCW0sPD+sf9x678
|
||||
-> ssh-ed25519 QlRB9Q 8GZjCubDXSt/uNfchgoY4nC+nmq7h0mHH5PzaVwS8Gw
|
||||
WfCIpHHSL/ZzCrCGonXzov5aiEG8nEabRYc61Sot6W0
|
||||
-> ssh-ed25519 r+nK/Q dxq/i0WDDxRd2o2RapDZUTmink7pQpWbEp+6TByjYSY
|
||||
c/Z2Y2jXeAYZJ3ltI3XEb2qU2dM9WuBCfn4DmdLWuoc
|
||||
-> ssh-rsa krWCLQ
|
||||
DyMp39BeLJYmgfgyeVqcAUKWVSmqXj7Z24bu4JJ1TSjO9jWB61gp7K3rR/ascaZ3
|
||||
E+TkzK4DOUs81anTI1A6nUr3a5/PONU8y1M78OBRhaUkgA0EawUYWCvk7ITTri9N
|
||||
5U9m7yYXVjFImbPDmTuS496KEqqrYKF9hMU54MzAVjl7Glz3mw2sJmD3oyWX3lx+
|
||||
XgzS4O/tmL7WxsaHqzAnojr32aJH52Es0VNZRplCff4sgZl+1U+RPpi4kLk8E1+p
|
||||
QnXDyUEYpkJ4OlslT7+WrURumZhEfBhvDtJUIkILc650lJcxeO5kSgw9s46RmEwW
|
||||
tFtkMsG+M+sPqcgiqdpp1A
|
||||
-> ssh-ed25519 /vwQcQ C8NLKCeZRYT1hFAX7QWjaPXnlN8iiMXeSQEmdPMWhx0
|
||||
gHagG9v72kxa9LIs4aIV5CZsq60i62s4HkDwh6ostew
|
||||
-> ssh-ed25519 0R97PA /9uUwdq1jdah4pJsFBm8Lubc3bkpBtqDh2VCDZegJDo
|
||||
WD17gOJkv4INdNUIX0erAjNOeeWQZCQ1rXdc68KFLbw
|
||||
-> ssh-ed25519 JGx7Ng GpCSAEFl4Y/0pNYWXX5+iMfRqPIbJ2cTS6YPjNLiJW0
|
||||
KZNU1H+MVNUb5aJMkEurBPDd9h9b023CqK0TLTrd4y4
|
||||
-> ssh-ed25519 bUjjig GIZfUJbejtNHD7ezMM/KsNetxwLBYGHJ3ql5tn6sYwY
|
||||
U9jkfmRTM1WXvExskdponMb9/kTwzeZYA3CBUBq5PI8
|
||||
-> ssh-ed25519 VQSaNw YUZzVKlzWxTgDUZyKToDR3fvMSGDPCQL5hOD/fyW8lI
|
||||
S5IJ5E325zHj3VBq6jcQmZmhXgLDAceGMBrRUP0po5g
|
||||
-> ,`:sK>-grease
|
||||
1Jkp/UVsxUfBFXRGT1ADI97FkgaK/jTSj+Gu/mv3Kjhk3kCHCwrN2emrILvK
|
||||
--- 6tPIZn536nfhB/4+hiKitxMpYKdj42N+Xxw7gz+cCuQ
|
||||
¾Ú‡u™ŒhŠhŠ%Å$<24>¯^þrÒ3Üëi¯‘ð8§qK‹§½9‡ˆd®Ø&±<>X4ŠØ'lœ%ršCƒ™–„€“R”Ÿß=®ëƒ_ïì>XÙilO
|
|
@ -27,7 +27,6 @@
|
|||
"dj_gestiojeux-secret_key_file"
|
||||
"dj_interludes-email_host_password_file"
|
||||
"dj_interludes-secret_key_file"
|
||||
"dj_vector-secret_key_file"
|
||||
"dj_wikiens-secret_key_file"
|
||||
"webhook-annuaire_token"
|
||||
"webhook-bocal_token"
|
||||
|
@ -36,6 +35,5 @@
|
|||
"webhook-gestiocof_token"
|
||||
"webhook-gestiojeux_token"
|
||||
"webhook-interludes_token"
|
||||
"webhook-vector_token"
|
||||
"webhook-wikiens_token"
|
||||
]
|
||||
|
|
|
@ -1,36 +0,0 @@
|
|||
age-encryption.org/v1
|
||||
-> ssh-ed25519 ZIo4kw nixtliB448Qelkkhdy4Njr4V5gGJtlzR5z2mdjxENhs
|
||||
529gFsnjUhI/yFnphje0jhoszNrRoc1OmV1tc8QgTVk
|
||||
-> ssh-ed25519 9/PCvA eFSvkx9G++qeJWsAusXUz+V5IyVoW3kRuhL8M6LITSs
|
||||
Die/10zkmScdj5wmWKlVHtbIZ3n7Tw5O9xvmLrNittM
|
||||
-> ssh-ed25519 prNEsA +GGlW+gSP7WEvvjBNpNhzG8FSV3cVLu6A/2IbD51Wzo
|
||||
wTNAoE5Wk/ZzhuKPLuBbE40rHpuXqOFuTE2fn1Nw1kQ
|
||||
-> ssh-ed25519 jIXfPA qROvOffeaatJSsqQ+bNgXcZc0tlZDhNawcUsybu0YQo
|
||||
GgsBWLQuFbL4CghDOxbyaJ4dMJtuWV5IJWxr/aNDE5I
|
||||
-> ssh-ed25519 QlRB9Q K07kQAeVxZlkp4RFRPgAbX8ny5bqB9klZEGUyLaUtzg
|
||||
Oe7IAxrU+4onN8V6M178yTbXPPqkh++JSB+WKEXocQ8
|
||||
-> ssh-ed25519 r+nK/Q RFCuFtv3kdHjFHT4PcbVFfLUdD3kUBoO1XSfqB4ae2Q
|
||||
39RVcTVbte9KNt3vEHE0aEcSLJyhASqlNp+/+AFkrB0
|
||||
-> ssh-rsa krWCLQ
|
||||
LEFifhwKhjyaqSRtNpwVv9PTKmMmkz0tQLccZLTMQ4suKo3+YzLpBNrpIoi3xvuZ
|
||||
75Xv/MtcemPoVX5qBgJwkxZyV5roAtOpvRo+iTBiQ7awgFpiWcn+cILOyr3a/LER
|
||||
Xu92Wiotzv9WFJMsZd1DfeOvNl1YkxD2QqRdd6jF13vt8NwuogEY2GzgS/PerKi1
|
||||
YJ0ntGhecsy7n13kapA9VsTt8/e9dywZ/ZZIkmDG7ma0tqYnn1VzQTbZXjPMTl04
|
||||
kZ7Rg+u1C0Q1mCzSnJJtpbmDj0M8OyqHfEjg1DoWR3uBizH3BOjQjbnLPhnp0mL3
|
||||
cInvK02DW7JGazJDsuJblw
|
||||
-> ssh-ed25519 /vwQcQ bRu/3avtfAEqsAzlOdM/fjVoUaOPoJuD2lbvovojoz8
|
||||
7CO/CcO1kDXTrSjzy1z4KhcVnLwhOZEuMN+LySUaeyI
|
||||
-> ssh-ed25519 0R97PA Hb/RO8mCBX445wyyAXSnilOzE6HMhTGuw0Urz2Y6YVc
|
||||
BdZ98IodA3Tp5k0Tau+Iv8qrVf/CJRfYseicHyP1fCs
|
||||
-> ssh-ed25519 JGx7Ng gdEebhCXIuHzA3bDWltgnRo2XvGHszVScTfNXGBVX3A
|
||||
X5ZLnUcX9cjIrvpqw2jEveLcljE/idPD0BfX5V7QVwE
|
||||
-> ssh-ed25519 bUjjig f/pw/bL37yroIaiv4y9EqJqAVwh06vC9VcaMQPW40Qw
|
||||
LScPAIupupgpR1OL4oqG87pRYKSctQip3rHnnjBrCGg
|
||||
-> ssh-ed25519 VQSaNw BxWJoLzSaZwbO+XU0Hd61t2JaukDmcAzQphYKaAtWBI
|
||||
4RoGyHkU926BomYSLj6KquJ74OwMeVYQeBAV84wu57c
|
||||
-> R?\kyN-grease gO`2zD 7eWdp ,_h
|
||||
ZkiJSlbbGvaHYu0mUfMyW+hOZNDTZ4Fvql+0hsSgaJ9h5sGLMijNzinflWaUg2JE
|
||||
NTcZv5Xy77Y+j1Ch
|
||||
--- TrMQG6BDUx1tuCujCZM2u/g5DhfpSv6MVKtR+zC1S+w
|
||||
ÝÔ¾TVs]“VBYZ)iÁ®Ù‰HˆeþRî‹’bÂêòÂ.(&²
|
||||
N'3¡¢œD-Íè‰_V¯î
|
|
@ -1,26 +0,0 @@
|
|||
# SPDX-FileCopyrightText: 2024 Tom Hubrecht <tom.hubrecht@dgnum.eu>
|
||||
#
|
||||
# SPDX-License-Identifier: EUPL-1.2
|
||||
|
||||
{ lib, ... }:
|
||||
|
||||
lib.extra.mkConfig {
|
||||
enabledModules = [
|
||||
# List of modules to enable
|
||||
"dgn-web"
|
||||
];
|
||||
|
||||
enabledServices = [
|
||||
# List of services to enable
|
||||
];
|
||||
|
||||
extraConfig = {
|
||||
# Disable monitoring
|
||||
dgn-monitoring.enable = false;
|
||||
dgn-records.enable = false;
|
||||
dgn-notify.enable = false;
|
||||
dgn-backups.jobs = lib.mkForce { };
|
||||
};
|
||||
|
||||
root = ./.;
|
||||
}
|
|
@ -1,33 +0,0 @@
|
|||
# SPDX-FileCopyrightText: 2024 Tom Hubrecht <tom.hubrecht@dgnum.eu>
|
||||
#
|
||||
# SPDX-License-Identifier: EUPL-1.2
|
||||
|
||||
# Do not modify this file! It was generated by ‘nixos-generate-config’
|
||||
# and may be overwritten by future invocations. Please make changes
|
||||
# to /etc/nixos/configuration.nix instead.
|
||||
{ modulesPath, sources, ... }:
|
||||
|
||||
{
|
||||
imports = [
|
||||
(modulesPath + "/profiles/qemu-guest.nix")
|
||||
(sources.disko + "/module.nix")
|
||||
./disko.nix
|
||||
];
|
||||
|
||||
boot = {
|
||||
initrd = {
|
||||
availableKernelModules = [
|
||||
"ata_piix"
|
||||
"uhci_hcd"
|
||||
"ehci_pci"
|
||||
"virtio_pci"
|
||||
"sr_mod"
|
||||
"virtio_blk"
|
||||
];
|
||||
kernelModules = [ ];
|
||||
};
|
||||
|
||||
kernelModules = [ "kvm-intel" ];
|
||||
extraModulePackages = [ ];
|
||||
};
|
||||
}
|
|
@ -1,37 +0,0 @@
|
|||
# SPDX-FileCopyrightText: 2024 Maurice Debray <maurice.debray@dgnum.eu>
|
||||
#
|
||||
# SPDX-License-Identifier: EUPL-1.2
|
||||
|
||||
_: {
|
||||
disko.devices = {
|
||||
disk = {
|
||||
main = {
|
||||
device = "/dev/sda";
|
||||
type = "disk";
|
||||
content = {
|
||||
type = "gpt";
|
||||
partitions = {
|
||||
ESP = {
|
||||
type = "EF00";
|
||||
size = "1G";
|
||||
content = {
|
||||
type = "filesystem";
|
||||
format = "vfat";
|
||||
mountpoint = "/boot";
|
||||
mountOptions = [ "umask=0077" ];
|
||||
};
|
||||
};
|
||||
root = {
|
||||
size = "100%";
|
||||
content = {
|
||||
type = "filesystem";
|
||||
format = "ext4";
|
||||
mountpoint = "/";
|
||||
};
|
||||
};
|
||||
};
|
||||
};
|
||||
};
|
||||
};
|
||||
};
|
||||
}
|
|
@ -1,5 +0,0 @@
|
|||
# SPDX-FileCopyrightText: 2024 La Délégation Générale Numérique <contact@dgnum.eu>
|
||||
#
|
||||
# SPDX-License-Identifier: EUPL-1.2
|
||||
|
||||
(import ../../../../keys.nix).mkSecrets [ "zulip01" ] [ ]
|
34
meta/dns.nix
34
meta/dns.nix
|
@ -12,7 +12,6 @@ let
|
|||
mapAttrs'
|
||||
nameValuePair
|
||||
optional
|
||||
optionalAttrs
|
||||
;
|
||||
|
||||
inherit (lib.extra) fuseAttrs mapSingleFuse;
|
||||
|
@ -29,7 +28,6 @@ let
|
|||
dual ? [ ],
|
||||
v4 ? [ ],
|
||||
v6 ? [ ],
|
||||
proxied ? [ ],
|
||||
}:
|
||||
let
|
||||
base = "${server}.${meta.nodes.${server}.site}.infra";
|
||||
|
@ -39,7 +37,6 @@ let
|
|||
(mkHost base dual)
|
||||
(mkHost "v4.${base}" v4)
|
||||
(mkHost "v6.${base}" v6)
|
||||
(mkHost "proxied.${base}" proxied)
|
||||
];
|
||||
|
||||
cnames = builtins.mapAttrs (_: to: { CNAME = [ to ]; }) {
|
||||
|
@ -170,17 +167,10 @@ let
|
|||
];
|
||||
|
||||
web03.dual = [
|
||||
"photos" # Vector
|
||||
|
||||
# Django Apps
|
||||
"*.webapps"
|
||||
"apps-webhook"
|
||||
];
|
||||
|
||||
zulip01.proxied = [
|
||||
"zulip"
|
||||
"z"
|
||||
];
|
||||
}
|
||||
)
|
||||
);
|
||||
|
@ -259,21 +249,23 @@ in
|
|||
{ site, ... }:
|
||||
let
|
||||
net = meta.network.${host};
|
||||
inherit (net.addresses) A AAAA;
|
||||
f =
|
||||
x:
|
||||
if x == [ ] then
|
||||
[ ]
|
||||
else if net.singleIpRecord then
|
||||
[ (builtins.head x) ]
|
||||
else
|
||||
x;
|
||||
inherit (net.addresses) ipv4 ipv6;
|
||||
in
|
||||
nameValuePair "${host}.${site}" {
|
||||
inherit A AAAA;
|
||||
|
||||
A = f ipv4;
|
||||
AAAA = f ipv6;
|
||||
subdomains = {
|
||||
v4 = { inherit A; };
|
||||
v6 = { inherit AAAA; };
|
||||
v4.A = f ipv4;
|
||||
v6.AAAA = f ipv6;
|
||||
private.A = optional (net.netbirdIp != null) net.netbirdIp;
|
||||
proxied = optionalAttrs (net.proxy != null) {
|
||||
# NOTE: We assume that we want to proxy ipv4 to an ipv6-only node
|
||||
# This might change in the future but is not planned yet.
|
||||
inherit (meta.network.${net.proxy}.addresses) A;
|
||||
inherit AAAA;
|
||||
};
|
||||
};
|
||||
}
|
||||
) (filterAttrs (_: { nixpkgs, ... }: nixpkgs.system == "nixos") meta.nodes);
|
||||
|
|
|
@ -18,12 +18,12 @@
|
|||
hostId = "f57f3ba0";
|
||||
|
||||
interfaces = { };
|
||||
netbirdIp = "100.80.9.42";
|
||||
netbirdIp = null;
|
||||
};
|
||||
|
||||
build01 = {
|
||||
interfaces = {
|
||||
enp35s0f1np1 = {
|
||||
enp35s0f0np0 = {
|
||||
ipv4 = [
|
||||
{
|
||||
address = "10.0.254.21";
|
||||
|
@ -31,19 +31,6 @@
|
|||
}
|
||||
];
|
||||
|
||||
gateways = [ "10.0.254.1" ];
|
||||
enableDefaultDNS = true;
|
||||
};
|
||||
enp66s0f1np1 = {
|
||||
ipv4 = [
|
||||
{
|
||||
address = "10.0.254.21";
|
||||
prefixLength = 24;
|
||||
}
|
||||
];
|
||||
|
||||
metric = 500;
|
||||
|
||||
gateways = [ "10.0.254.1" ];
|
||||
enableDefaultDNS = true;
|
||||
};
|
||||
|
@ -154,20 +141,6 @@
|
|||
gateways = [ "10.0.254.1" ];
|
||||
enableDefaultDNS = true;
|
||||
};
|
||||
|
||||
eno1 = {
|
||||
ipv4 = [
|
||||
{
|
||||
address = "10.0.254.11";
|
||||
prefixLength = 24;
|
||||
}
|
||||
];
|
||||
|
||||
metric = 500;
|
||||
|
||||
gateways = [ "10.0.254.1" ];
|
||||
enableDefaultDNS = true;
|
||||
};
|
||||
};
|
||||
|
||||
hostId = "4dbbd76a";
|
||||
|
@ -187,20 +160,6 @@
|
|||
gateways = [ "10.0.254.1" ];
|
||||
enableDefaultDNS = true;
|
||||
};
|
||||
|
||||
eno1 = {
|
||||
ipv4 = [
|
||||
{
|
||||
address = "10.0.254.12";
|
||||
prefixLength = 24;
|
||||
}
|
||||
];
|
||||
|
||||
metric = 500;
|
||||
|
||||
gateways = [ "10.0.254.1" ];
|
||||
enableDefaultDNS = true;
|
||||
};
|
||||
};
|
||||
|
||||
hostId = "d0b48483";
|
||||
|
@ -220,20 +179,6 @@
|
|||
gateways = [ "10.0.254.1" ];
|
||||
enableDefaultDNS = true;
|
||||
};
|
||||
|
||||
enp66s0f0 = {
|
||||
ipv4 = [
|
||||
{
|
||||
address = "10.0.254.13";
|
||||
prefixLength = 24;
|
||||
}
|
||||
];
|
||||
|
||||
metric = 500;
|
||||
|
||||
gateways = [ "10.0.254.1" ];
|
||||
enableDefaultDNS = true;
|
||||
};
|
||||
};
|
||||
|
||||
hostId = "1c407ea8";
|
||||
|
@ -425,27 +370,5 @@
|
|||
netbirdIp = "100.80.157.46";
|
||||
singleIpRecord = true;
|
||||
};
|
||||
|
||||
zulip01 = {
|
||||
interfaces = {
|
||||
ens18 = {
|
||||
ipv6 = [
|
||||
{
|
||||
address = "2a0e:e701:1120:1000::dead:beef";
|
||||
prefixLength = 64;
|
||||
}
|
||||
];
|
||||
|
||||
gateways = [ "2a0e:e701:1120:1000::1" ];
|
||||
dns = [ "2a0e:e701:1120:1000::f:1" ];
|
||||
};
|
||||
};
|
||||
|
||||
hostId = "b551861d";
|
||||
netbirdIp = null; # zulip01 is not to be connected on the VPN for now
|
||||
|
||||
# This node does not have ipv4 connectivity
|
||||
proxy = "lab-router01";
|
||||
};
|
||||
};
|
||||
}
|
||||
|
|
|
@ -7,6 +7,7 @@
|
|||
versions = [
|
||||
# Supported nixpkgs versions
|
||||
"unstable"
|
||||
"22.11"
|
||||
"23.11"
|
||||
"24.05"
|
||||
"24.11"
|
||||
|
|
|
@ -1,61 +1,106 @@
|
|||
# SPDX-FileCopyrightText: 2024 Lubin Bailly <lubin.bailly@dgnum.eu>
|
||||
#
|
||||
# SPDX-License-Identifier: EUPL-1.2
|
||||
{ lib, ... }:
|
||||
let
|
||||
inherit (lib) mapAttrs;
|
||||
{
|
||||
nodes = {
|
||||
netcore00 = {
|
||||
site = "pot01";
|
||||
|
||||
hashedPassword = "$2b$05$3h26h8rJ5yks1vJYXZG.fuHagYBwrVMlGR7iFmsV1FTJlMUj97fl2";
|
||||
mkSwitch =
|
||||
{
|
||||
site,
|
||||
ip,
|
||||
entry,
|
||||
}:
|
||||
{
|
||||
inherit site hashedPassword;
|
||||
hashedPassword = "$6$BKetIIfT$JVyE0B7F4O.fJwQFu5jVrVExAZROrEMLW5HkDkhjMShJ9cRIgxSm2VM9OThDowsnLmAewqDN7eAY.EQt4UR4U0";
|
||||
|
||||
stateVersion = null;
|
||||
|
||||
adminGroups = [ "fai" ];
|
||||
|
||||
deployment = {
|
||||
targetHost = ip;
|
||||
targetHost = "fd26:baf9:d250:8000::1010";
|
||||
sshOptions = [
|
||||
"-J"
|
||||
entry
|
||||
"root@vault01.hyp01.infra.dgnum.eu"
|
||||
"-p"
|
||||
"830"
|
||||
];
|
||||
};
|
||||
|
||||
nixpkgs = {
|
||||
version = "unstable";
|
||||
version = "24.05"; # FIXME: meaningless
|
||||
system = "netconf";
|
||||
};
|
||||
};
|
||||
in
|
||||
{
|
||||
nodes = mapAttrs (_: mkSwitch) {
|
||||
|
||||
netcore01 = {
|
||||
site = "pot01";
|
||||
ip = "fd26:baf9:d250:8000::1010";
|
||||
entry = "root@vault01.hyp01.infra.dgnum.eu";
|
||||
|
||||
hashedPassword = "$6$BKetIIfT$JVyE0B7F4O.fJwQFu5jVrVExAZROrEMLW5HkDkhjMShJ9cRIgxSm2VM9OThDowsnLmAewqDN7eAY.EQt4UR4U0";
|
||||
|
||||
stateVersion = null;
|
||||
|
||||
adminGroups = [ "fai" ];
|
||||
|
||||
deployment = {
|
||||
targetHost = "fd26:baf9:d250:8000::100f";
|
||||
sshOptions = [
|
||||
"-J"
|
||||
"root@vault01.hyp01.infra.dgnum.eu"
|
||||
"-p"
|
||||
"830"
|
||||
];
|
||||
};
|
||||
|
||||
nixpkgs = {
|
||||
version = "24.05"; # FIXME: meaningless
|
||||
system = "netconf";
|
||||
};
|
||||
};
|
||||
|
||||
netcore02 = {
|
||||
site = "pot01";
|
||||
ip = "fd26:baf9:d250:8000::100f";
|
||||
entry = "root@vault01.hyp01.infra.dgnum.eu";
|
||||
};
|
||||
|
||||
Jaccess01 = {
|
||||
site = "hyp01";
|
||||
ip = "fd26:baf9:d250:8000::1001";
|
||||
entry = "root@vault01.hyp01.infra.dgnum.eu";
|
||||
|
||||
hashedPassword = "$6$BKetIIfT$JVyE0B7F4O.fJwQFu5jVrVExAZROrEMLW5HkDkhjMShJ9cRIgxSm2VM9OThDowsnLmAewqDN7eAY.EQt4UR4U0";
|
||||
|
||||
stateVersion = null;
|
||||
|
||||
adminGroups = [ "fai" ];
|
||||
|
||||
deployment = {
|
||||
targetHost = "fd26:baf9:d250:8000::1001";
|
||||
sshOptions = [
|
||||
"-J"
|
||||
"root@vault01.hyp01.infra.dgnum.eu"
|
||||
"-p"
|
||||
"830"
|
||||
];
|
||||
};
|
||||
|
||||
nixpkgs = {
|
||||
version = "24.05"; # FIXME: meaningless
|
||||
system = "netconf";
|
||||
};
|
||||
};
|
||||
|
||||
Jaccess04 = {
|
||||
netaccess01 = {
|
||||
site = "hyp02";
|
||||
ip = "fd26:baf9:d250:8000::2001";
|
||||
entry = "root@vault01.hyp01.infra.dgnum.eu";
|
||||
|
||||
hashedPassword = "$6$BKetIIfT$JVyE0B7F4O.fJwQFu5jVrVExAZROrEMLW5HkDkhjMShJ9cRIgxSm2VM9OThDowsnLmAewqDN7eAY.EQt4UR4U0";
|
||||
|
||||
stateVersion = null;
|
||||
|
||||
adminGroups = [ "fai" ];
|
||||
|
||||
deployment = {
|
||||
targetHost = "fd26:baf9:d250:8000::2001";
|
||||
sshOptions = [
|
||||
"-J"
|
||||
"root@vault01.hyp01.infra.dgnum.eu"
|
||||
"-p"
|
||||
"830"
|
||||
];
|
||||
};
|
||||
|
||||
nixpkgs = {
|
||||
version = "24.05"; # FIXME: meaningless
|
||||
system = "netconf";
|
||||
};
|
||||
};
|
||||
};
|
||||
}
|
||||
|
|
|
@ -58,10 +58,16 @@
|
|||
|
||||
adminGroups = [ "fai" ];
|
||||
|
||||
deployment.targetHost = "bridge01.dgnum";
|
||||
deployment = {
|
||||
targetHost = "fd26:baf9:d250:8000::ffff";
|
||||
sshOptions = [
|
||||
"-J"
|
||||
"root@vault01.hyp01.infra.dgnum.eu"
|
||||
];
|
||||
};
|
||||
|
||||
nixpkgs = {
|
||||
version = "25.05";
|
||||
version = "24.11";
|
||||
system = "nixos";
|
||||
};
|
||||
};
|
||||
|
@ -331,7 +337,7 @@
|
|||
stateVersion = "23.11";
|
||||
|
||||
nixpkgs = {
|
||||
version = "25.05";
|
||||
version = "24.11";
|
||||
system = "nixos";
|
||||
};
|
||||
|
||||
|
@ -389,20 +395,5 @@
|
|||
|
||||
admins = [ "catvayor" ];
|
||||
};
|
||||
|
||||
zulip01 = {
|
||||
site = "pav01";
|
||||
|
||||
hashedPassword = "$y$j9T$7NuClEAftCG0O7AA0KLK10$/ZLXV73tiZVMXFdgKfa4yVeYk.Qdea6uIgQTrtWHIbA";
|
||||
|
||||
sshKeys = [ "ssh-ed25519 AAAAC3NzaC1lZDI1NTE5AAAAIDnYjoGAfJGeMAds7RoqtqRJlfm2f6aBbb9SIPNizIof" ];
|
||||
|
||||
stateVersion = "24.11";
|
||||
|
||||
nixpkgs = {
|
||||
version = "unstable";
|
||||
system = "nixos";
|
||||
};
|
||||
};
|
||||
};
|
||||
}
|
||||
|
|
|
@ -21,7 +21,6 @@ let
|
|||
attrs
|
||||
attrsOf
|
||||
bool
|
||||
int
|
||||
enum
|
||||
ints
|
||||
listOf
|
||||
|
@ -375,14 +374,6 @@ in
|
|||
'';
|
||||
};
|
||||
|
||||
metric = mkOption {
|
||||
type = int;
|
||||
default = 1000;
|
||||
description = ''
|
||||
Metric of routes created by this interface.
|
||||
'';
|
||||
};
|
||||
|
||||
DHCP = mkOption {
|
||||
type = nullOr str;
|
||||
default = null;
|
||||
|
@ -412,50 +403,22 @@ in
|
|||
);
|
||||
};
|
||||
|
||||
addresses =
|
||||
let
|
||||
select = b: x: if (b && x != [ ]) then [ (builtins.head x) ] else x;
|
||||
in
|
||||
{
|
||||
ipv4 = mkOption {
|
||||
type = listOf str;
|
||||
default = [ ];
|
||||
description = ''
|
||||
List of public ipv4 addresses of the node.
|
||||
'';
|
||||
};
|
||||
|
||||
ipv6 = mkOption {
|
||||
type = listOf str;
|
||||
default = [ ];
|
||||
description = ''
|
||||
List of public ipv6 addresses of the node.
|
||||
'';
|
||||
};
|
||||
|
||||
A = mkOption {
|
||||
type = listOf str;
|
||||
default = select config.singleIpRecord config.addresses.ipv4;
|
||||
description = ''
|
||||
List of ipv4 addresses used for the A record.
|
||||
'';
|
||||
};
|
||||
|
||||
AAAA = mkOption {
|
||||
type = listOf str;
|
||||
default = select config.singleIpRecord config.addresses.ipv6;
|
||||
description = ''
|
||||
List of ipv6 addresses used for the AAAA record.
|
||||
'';
|
||||
};
|
||||
addresses = {
|
||||
ipv4 = mkOption {
|
||||
type = listOf str;
|
||||
default = [ ];
|
||||
description = ''
|
||||
List of public ipv4 addresses of the node.
|
||||
'';
|
||||
};
|
||||
|
||||
proxy = mkOption {
|
||||
type = nullOr str;
|
||||
default = null;
|
||||
description = ''
|
||||
If not `null`, then a SNI proxy will be created to passthrough ipv4 traffic to this node via ipv6.
|
||||
'';
|
||||
ipv6 = mkOption {
|
||||
type = listOf str;
|
||||
default = [ ];
|
||||
description = ''
|
||||
List of public ipv6 addresses of the node.
|
||||
'';
|
||||
};
|
||||
};
|
||||
|
||||
hostId = mkOption {
|
||||
|
|
|
@ -23,14 +23,6 @@ in
|
|||
options.dgn-isp = {
|
||||
enable = mkEnableOption "Common isp configuration";
|
||||
|
||||
core-links = mkOption {
|
||||
type = listOf str;
|
||||
default = [ ];
|
||||
description = ''
|
||||
Interfaces of link between switches
|
||||
'';
|
||||
};
|
||||
|
||||
AP = mkOption {
|
||||
type = listOf str;
|
||||
default = [ ];
|
||||
|
@ -77,18 +69,6 @@ in
|
|||
dgn-interfaces."irb".inet6.addresses = [ cfg.admin-ip ];
|
||||
|
||||
dgn-profiles = {
|
||||
core = {
|
||||
interfaces = cfg.core-links;
|
||||
configuration.ethernet-switching = {
|
||||
interface-mode = "trunk";
|
||||
vlans = [
|
||||
"users"
|
||||
"ap-staging"
|
||||
"admin-ap"
|
||||
"admin-core"
|
||||
];
|
||||
};
|
||||
};
|
||||
AP = {
|
||||
interfaces = cfg.AP;
|
||||
configuration = {
|
||||
|
|
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
|
@ -1,39 +1,62 @@
|
|||
age-encryption.org/v1
|
||||
-> ssh-ed25519 ZIo4kw 4Dvbj86lTQ6xC73sI8eEU6GyGo/Qzv3Htq3jZCzaWSA
|
||||
5sbbvnKk6Ef6zacjMV2EK9optOKVUIqfk/IAuFd3M5o
|
||||
-> ssh-ed25519 9/PCvA b5eEu4H7gu2Jxta0J9pVUJjCBqy3sa9fl4/Glwxatwk
|
||||
JAcfuZyUGyEHsTrOpfcYKGlmoc6WHLQdJCm6mVc7Bq4
|
||||
-> ssh-ed25519 prNEsA DC648/P8gUL0kTjuXdM34wT+lo4wkTwtk0CghxWumjU
|
||||
SZaiXJXPjL+gYkPn5mVlw7vQ4otKVSKX5VIdkgsgURA
|
||||
-> ssh-ed25519 jIXfPA an1P3n+ZiKaUOYMZCcWJXwkmL8ZzehP2of1DunzlugE
|
||||
w0tyvbo/Dkl9ovbi2jbveuu/9fQ6JYox3711Ke+PL7c
|
||||
-> ssh-ed25519 QlRB9Q iyFxHQBFLBVKMv2Uv97p2cQCizTOSrQDYMctdoafmXk
|
||||
nMemf/k6qdrY91waHLxG7L4AuZCZWexPsC0pUI/dKdc
|
||||
-> ssh-ed25519 r+nK/Q NRJzo86V7hd9M9mLkZS/SFv+3wyzQUIAxSop1t0NIk4
|
||||
kB+sIcPPx80o276zRVwOJ1kZlrmZRagAS+J2K9pIs54
|
||||
-> ssh-ed25519 jIXfPA IBDWE9Xn6wliGbftDIGWXHa7HKUMNefpFqPbyM1hGyE
|
||||
g3RFQAd1fr04JDJWNOiA5Az+Th5y4KQsMoZtDUTChII
|
||||
-> ssh-ed25519 QlRB9Q wUwww3D9NqymfeRaiTlPqSQs+d4jgeU5et7t5Bh16G0
|
||||
vQMO+HmuvKUouppp1fPSVzF88WWnWtTfHm+c6WJeJNs
|
||||
-> ssh-ed25519 r+nK/Q CyIT2nwckqhLB5WojCJOzKw+62qejILHOyUI91IJMyc
|
||||
pStkO3bVXBwsoadaJ+FyjwY/SxNneaLjGreqlGXy7MI
|
||||
-> ssh-rsa krWCLQ
|
||||
Vu4hzL2lpYaPlT0M5Dq7i2sYZQiHtc0wx/+Ol7yX6imT+36ZYGWOr5etTWNsG5H1
|
||||
r4POK1efijLJDcDXdG9H0aIRKYk0LIWu8Lc8mXQicS4sI/DAuHcwd4yEHoiqBroB
|
||||
HrIEtpctjszOUwcORPPnVeuxrc7qV7dZHQOTFb37m5wB1mOWQPf9+aEZ8Pa9N3HB
|
||||
MYyCiZdkjnB+GV2CRdpg3Nrn5MBYzTk6qKc/4Dt97fSjnZp7mEAUu3MwJN6xwZvt
|
||||
edoxH7qH/pyjn6L4F3BOzoXi0OGp7UhZrWdSm9rpP9bQoSDl2xPlfyQltAx6F5L/
|
||||
rWCxDh1tMzKTkjfLdA5yYg
|
||||
-> ssh-ed25519 /vwQcQ ed+mwY1AiYksn4D74JVHIHCXdujK+T4M5fqRertiXDE
|
||||
dZ27Pab3C8OesdLbHREAkQs76fk2+HQFsC5vrqHenU8
|
||||
-> ssh-ed25519 0R97PA /SJIhnQqyJ30Igm3lD58ASvHDDVVHvGOVBCQPHXDyn4
|
||||
N4Q7XsCTpgVDEl9BC5D+W559VZGzRBmZT7zdHH2TxVw
|
||||
-> ssh-ed25519 JGx7Ng kOpYTaE79ToAfe21Y4Rj6OzarTviMcZrr/XPeORY/Gs
|
||||
pTJv9SEeCj/c7WoXsS9/C7Ur0GObvNXQN82P2Vpv/ks
|
||||
-> ssh-ed25519 bUjjig R+nYaUJc2bnGlu7MfwH2l4UZPCyp//JA6XIcTPQ76Vw
|
||||
GkXas4s/L+cPmw9/gFi/vlfEGDvOJ4bHxpNmHx1lIXE
|
||||
-> ssh-ed25519 rHotTw vR1ALL0WuY0iD3XlIbgTXDw+BlHaeqWvo0xLRfg4PA8
|
||||
SzI7LrCzE14oHrnVfgUWr01iB6HFDEHDqYw4rnGu8Hs
|
||||
-> ssh-ed25519 oRtTqQ ZsVQ29JKayWapAJ8Ni3p5XTtHM6V13kPI+9Y+QHPBxs
|
||||
mAKmtdqpq+VhI2mCIpW8JIC4k2R8MI4ZH73yFuluWAg
|
||||
-> ssh-ed25519 IxxZqA gIpd8G6cBK+KjQXbVgDWbtHdtcQhmZbruODpFyQajzk
|
||||
Gi1rQGYakrkDDTlGobnv4bQhrJdWb1jF54W2jBcNPY8
|
||||
-> oa~]37NU-grease &> o~hy` 5>|
|
||||
Brm0NbNjpmLUrPn/REprmi00Gdsu+1VX5Oqt7jrguA4ushkDL9KbhhmLfaE1Bih4
|
||||
wwtPwaAnWoYGhLEFQ/Z4IMhZ
|
||||
--- KFSjNpmZ/nktxjdYS+2Cg/RztxprVrb5VRpOol5vHtM
|
||||
dH<EFBFBD> -üä¯mÒ¾<C392>§ÂË <09>B'Û9š ²³Y*™1J&:§Ï¦Ü,g~ëi’ÍEÜŠ<0B>¶²àM¡zôR[)Ifûóˆ²ñu—
|
||||
xSBrLm6xfBZC2NSVjWOlw1PdAfV4SsrUr6FuLeMa291otjMyz5o/RhxVeU6uEh2F
|
||||
B6lk7WdEsYWl6lp98ha1bz4udabPJZdMHO1dj0uOx2Qnt5F5P+Dk/dOsZlbylX7n
|
||||
oKLm7w+P0xKMZyy4VoK0UWuwAwNZ+Rvh0aiqRxWQK+fh6W9pii/MDssCn/cwqsP3
|
||||
0ehUupmTP1GPWzXufVdvdV3EUuD6wczYMit3XhVpHWs3rh8nCY8WEw2kaF/YJ3kq
|
||||
QAzT1MGn2Bd9qJxPmnThJPr669cdX0FxRT8tirskBwGD50/AGzkGHmrDxhJ+lA+a
|
||||
oaAOAH2JuzxVU8eZTNzBaA
|
||||
-> ssh-ed25519 /vwQcQ wnnNXgdxTHBfy1m9Q85dE6qiQ1SGk40NSXEKFhJhoUg
|
||||
VRpUiwOot1uuTyp9zoBdoHVH/Sk/ZQvXZ/OlJrFLJNw
|
||||
-> ssh-ed25519 0R97PA 3NnOUAVFDA6jGIImHHaY5neOksXHY5W3SRvQjSMHIhE
|
||||
0fpC7PKc2Ih/ZaUamsiXMya+cRHFo47pu+/+VPPh1mY
|
||||
-> ssh-ed25519 JGx7Ng wjLJcV9WaZzaXL9G4+gWLrJwlQHpu2wNauNGCKHlcjE
|
||||
KXtlcgvCx4IjWKZYcdrc/+ptN89TYdztcKx3D8SOGJQ
|
||||
-> ssh-ed25519 bUjjig 1anXdq+bgCUIgtwdb3r107avA454AmvzCZ/9Gg6KJRY
|
||||
jZ+57yUb5S2o4jYIfle2Cosnr244lyT6OovC6pki3aM
|
||||
-> ssh-ed25519 DqHxWQ IRL5LMBRyHEuerrJLXwmFLn60w9kPLFfdwJ+B98B4ys
|
||||
+WLwLTWwswxa6q/okI+h8lMjAk8qEiOT/eODA8K6o4Q
|
||||
-> ssh-ed25519 IxxZqA susvyhJg3BFg25/w0u8HlbyuuUVBUkKt4OYdDyrs3SY
|
||||
kShLE/m+WjpHFe9rp1u1myVVT92wTSX9/LbBCBBEDGM
|
||||
-> ssh-ed25519 /fsvPA 8v8ltxt9mHugEPxI6+oIrVhV5z63QExUl2FF81hvoDY
|
||||
3UyQnrt9ZUQgoFWa+sOhUyfW8ayE1hT6iJktRUqsPCs
|
||||
-> ssh-ed25519 tDqJRg 0TyPeokIZ2VEJIefa771p/mgPKXNn9N1gFfJZNzJ5g4
|
||||
9c+48/+JkSNjIpbdLS1gMqCJsVR++aTd2fAtq+Vf5mU
|
||||
-> ssh-ed25519 9pVK7Q zGCbrGgD9+ZJWRjOmxXG+NTK3sXaRtVa5nFUd16dkgY
|
||||
5KplC/lMmYROpQXez04Fek7csTAKhCDTFMvi1gTkZLg
|
||||
-> ssh-ed25519 /BRpBQ BaEwBZBU4V86HQJL//Y7yZgNiIsVe14NrgHqXNdVIjI
|
||||
o23RVqBoMazA5FcvvrxTsO/8YY6v/Fi2fe0vHCuMXP8
|
||||
-> ssh-ed25519 t0vvHQ 3ry3IKDCwvHlya5gRl1WvWWg9eyvzoscLFIkSS+0W0M
|
||||
ARJQYM8UOxL4MKYeVTm4iuqRmKKt5WVA7vyHxBeSbFE
|
||||
-> ssh-ed25519 E6cGqw l8mjNJC/Rv8H8RAJJ6YPFh1giAELtq6YwOg9NGfpPEI
|
||||
3LZG3xs9yWKzDiIfXK5WuT5DBoKRRZXvMW4wrvD0Yz4
|
||||
-> ssh-ed25519 EEPmeQ vST8LKLp2Z5KqAVyGRedZ0UYrvTeBOh6VktNovlh+BE
|
||||
h67yS6SCGgDAbaVZFGPJWSTZjyKihR4lU2WI0ddtPS0
|
||||
-> ssh-ed25519 /x+F2Q MGL5T94LGLWkGMDHWgsYSklh9bNNS5wQ4UsHd2DhIAw
|
||||
wN9w+g0v4Ai9/LLBp0AVFPxGlYb9TFvFMherfQ1HAII
|
||||
-> ssh-ed25519 +MNHsw MmeQYG3LMRYshE1iW8c0aK+4ClW4cdmL0IRNOG4b0xE
|
||||
H172Nrg6evAabW0tiPkbmtqM0pJd2V+AXqbcrqizO50
|
||||
-> ssh-ed25519 rHotTw jAf0aGFc8O4Q6kFT/bvDvMgsng+P7McydHsf3XGXOU4
|
||||
hVU16P3uqnBXN0VM1k0D/yUB/4qXPJHlucZYaEeotu0
|
||||
-> ssh-ed25519 NaIdrw RDQ5Pt+Q3pDI7jNEFuOJj6FhyQ+rOs7tjW7aZ6juvU8
|
||||
l84vMl7TqapmfSpM0n7OqSGPzpxckppENDVsH1UfUOk
|
||||
-> ssh-ed25519 +mFdtQ TCPW7Vv185tMyBUD1kKUYiLCjs2BODC6/yk1bnCNLAw
|
||||
uCRPJ7/vD5IsGiclvSDUccqghHpJafw6bOnuCd1hSTU
|
||||
-> ssh-ed25519 0IVRbA zQ1t9aOeOZsoyG5PYe/qmQhz5zTwRaZOH1w747gcOV8
|
||||
/6kyxLF7RhGo5csn1FRzutUur5dEe95L8OJ1xuUGbp0
|
||||
-> ssh-ed25519 IY5FSQ fg14TlFknPaqzzhvOBj1xUPK+SXdVwE1kVrqsXguQhQ
|
||||
JM2jK91iWXF4NoOimeFgYBRr5Y51C1qKGW/bQh1I2wk
|
||||
-> ssh-ed25519 VQSaNw KRupcX4ff19rhTEE7T7OYbX5R7N8FN/6dKZOw1BfRCc
|
||||
v5K8+gyqx8v5qp48hFCblLWdmm1dTjqr8Tnjz/PsLgs
|
||||
-> )-grease >`MLFR
|
||||
AzmLKWjXTSMRbDzD9U0wWgH8Llfigdh3Ks2EAHWp3Rrbb1lyfsjnTBkPGTz3oaKx
|
||||
Ucpzmu+rcVhNfb7S9RGnJXAm1bcdFGj+fipRUsLqcfxtG8+7Gy9WyZkgxKdJqRcn
|
||||
|
||||
--- BcXdoymLtYCqMH5BALUywcLlG1MVXoAmxH4/p4BBxgw
|
||||
|êamxòD[¾±OЦ*;%`³å®uŒ4eƹjÜü¸g•$Vi´LGï×~½µY®¬@–žÊiƒÚ¬GÈã§Äy®äòSAÇm·<6D>)
|
|
@ -1,8 +1,5 @@
|
|||
# SPDX-FileCopyrightText: 2024 La Délégation Générale Numérique <contact@dgnum.eu>
|
||||
#
|
||||
# SPDX-License-Identifier: EUPL-1.2
|
||||
(import ../../../keys.nix).mkSecrets
|
||||
[ "storage01" "build01" ]
|
||||
[
|
||||
"forgejo_runners-token_file"
|
||||
]
|
||||
|
||||
{ forgejo_runners-token_file.publicKeys = (import ../../../keys.nix).machineKeysBySystem "nixos"; }
|
||||
|
|
|
@ -17,8 +17,8 @@ let
|
|||
net' = meta.network.${name};
|
||||
|
||||
mkAddress = { address, prefixLength, ... }: "${address}/${builtins.toString prefixLength}";
|
||||
mkRoute = Metric: Gateway: {
|
||||
inherit Gateway Metric;
|
||||
mkRoute = Gateway: {
|
||||
inherit Gateway;
|
||||
GatewayOnLink = true;
|
||||
};
|
||||
|
||||
|
@ -27,7 +27,7 @@ let
|
|||
value = {
|
||||
name = interface;
|
||||
address = builtins.map mkAddress (net.ipv4 ++ net.ipv6);
|
||||
routes = builtins.map (mkRoute net.metric) net.gateways;
|
||||
routes = builtins.map mkRoute net.gateways;
|
||||
|
||||
inherit (net) DHCP dns;
|
||||
};
|
||||
|
|
|
@ -74,9 +74,9 @@
|
|||
},
|
||||
"branch": "main",
|
||||
"submodules": false,
|
||||
"revision": "fbf6385e65400802a3f9f75f7cd91d5c01373d1b",
|
||||
"revision": "904eb7058b9a61250fbfcb0b0bfa71e214bf1067",
|
||||
"url": null,
|
||||
"hash": "sha256-aOUI69wbMm9+KVWwcMw5TgVnk3DfjOzE4OEyYTD8XPU="
|
||||
"hash": "sha256-tDqte7MuOn0Gcj0a94m//wcjJvssnEZprtt5o/IpXlU="
|
||||
},
|
||||
"disko": {
|
||||
"type": "GitRelease",
|
||||
|
@ -143,9 +143,9 @@
|
|||
},
|
||||
"branch": "master",
|
||||
"submodules": false,
|
||||
"revision": "ee58919c0a34a478820dda72e756f5db45a068f4",
|
||||
"revision": "2df4e901590ebd139364d1df140a6ccb2cd0a5a7",
|
||||
"url": null,
|
||||
"hash": "sha256-9mnQk8mcRlV3wOcJkXU/fIUSLUSj9Jg8HrqzD8/hx+w="
|
||||
"hash": "sha256-W4pGBZs1+iPnuios88kbqb2ITdLalYq65G8IWGm+EKY="
|
||||
},
|
||||
"liminix": {
|
||||
"type": "Git",
|
||||
|
@ -290,8 +290,8 @@
|
|||
"nixos-25.05": {
|
||||
"type": "Channel",
|
||||
"name": "nixos-25.05",
|
||||
"url": "https://releases.nixos.org/nixos/25.05/nixos-25.05.803579.70c74b02eac4/nixexprs.tar.xz",
|
||||
"hash": "sha256-0RxtgAd4gHYPFFwICal8k8hvJBOkCeTjFkh4HsqYDbE="
|
||||
"url": "https://releases.nixos.org/nixos/25.05/nixos-25.05beta801800.ca49c4304acf/nixexprs.tar.xz",
|
||||
"hash": "sha256-O+9sQ6QEoKcM/lJXDumDdUZbuxs2TMuBf7xi3ivOXCo="
|
||||
},
|
||||
"nixos-unstable": {
|
||||
"type": "Channel",
|
||||
|
|
|
@ -1,639 +0,0 @@
|
|||
From f49797f5a589b88e6ad938038e53570fdaa37fa8 Mon Sep 17 00:00:00 2001
|
||||
From: Tom Hubrecht <tom.hubrecht@dgnum.eu>
|
||||
Date: Mon, 26 May 2025 13:47:07 +0200
|
||||
Subject: [PATCH] Revert "add aliases, refactor eval logic"
|
||||
|
||||
This reverts commit 3ef5ba8658f68564ed268828ccee39a363200188.
|
||||
---
|
||||
src/error.rs | 14 +-
|
||||
src/nix/hive/mod.rs | 94 +++----------
|
||||
src/nix/hive/options.nix | 9 --
|
||||
src/nix/mod.rs | 2 -
|
||||
src/nix/node_filter.rs | 290 ++++++++++++++-------------------------
|
||||
5 files changed, 122 insertions(+), 287 deletions(-)
|
||||
|
||||
diff --git a/src/error.rs b/src/error.rs
|
||||
index cbc41ba..f0fbe11 100644
|
||||
--- a/src/error.rs
|
||||
+++ b/src/error.rs
|
||||
@@ -6,7 +6,7 @@ use std::process::ExitStatus;
|
||||
use snafu::{Backtrace, Snafu};
|
||||
use validator::ValidationErrors;
|
||||
|
||||
-use crate::nix::{key, NodeName, Profile, StorePath};
|
||||
+use crate::nix::{key, Profile, StorePath};
|
||||
|
||||
pub type ColmenaResult<T> = Result<T, ColmenaError>;
|
||||
|
||||
@@ -76,18 +76,6 @@ pub enum ColmenaError {
|
||||
#[snafu(display("Filter rule cannot be empty"))]
|
||||
EmptyFilterRule,
|
||||
|
||||
- #[snafu(display(
|
||||
- "Alias \"{}\" is already taken by {} \"{}\"",
|
||||
- what.as_str(),
|
||||
- if *is_node_name { "node name" } else { "alias" },
|
||||
- with.as_str(),
|
||||
- ))]
|
||||
- DuplicateAlias {
|
||||
- what: NodeName,
|
||||
- is_node_name: bool,
|
||||
- with: NodeName,
|
||||
- },
|
||||
-
|
||||
#[snafu(display("Deployment already executed"))]
|
||||
DeploymentAlreadyExecuted,
|
||||
|
||||
diff --git a/src/nix/hive/mod.rs b/src/nix/hive/mod.rs
|
||||
index 8ebf6de..63ae08e 100644
|
||||
--- a/src/nix/hive/mod.rs
|
||||
+++ b/src/nix/hive/mod.rs
|
||||
@@ -3,7 +3,7 @@ mod assets;
|
||||
#[cfg(test)]
|
||||
mod tests;
|
||||
|
||||
-use std::collections::{HashMap, HashSet};
|
||||
+use std::collections::HashMap;
|
||||
use std::convert::AsRef;
|
||||
use std::path::{Path, PathBuf};
|
||||
use std::str::FromStr;
|
||||
@@ -14,7 +14,6 @@ use tokio::sync::OnceCell;
|
||||
use validator::Validate;
|
||||
|
||||
use super::deployment::TargetNode;
|
||||
-use super::node_filter::{NeedsEval, PartialNodeConfig};
|
||||
use super::{
|
||||
Flake, MetaConfig, NixExpression, NixFlags, NodeConfig, NodeFilter, NodeName,
|
||||
ProfileDerivation, RegistryConfig, SerializedNixExpression, StorePath,
|
||||
@@ -262,66 +261,39 @@ impl Hive {
|
||||
ssh_config: Option<PathBuf>,
|
||||
ssh_only: bool,
|
||||
) -> ColmenaResult<HashMap<NodeName, TargetNode>> {
|
||||
+ let mut node_configs = None;
|
||||
+
|
||||
log::info!("Enumerating systems...");
|
||||
let registry = self.get_registry_config().await?;
|
||||
|
||||
log::info!("Enumerating nodes...");
|
||||
+
|
||||
let all_nodes = self.node_names().await?;
|
||||
-
|
||||
- // try to quickly evaluate the filter without any data to see if it's trivial to evaluate
|
||||
- let filter_trivial = filter.as_ref().and_then(|filter| filter.try_eval_trivial());
|
||||
-
|
||||
let selected_nodes = match filter {
|
||||
- Some(filter) if filter_trivial.is_none() => {
|
||||
- log::debug!("Retrieving deployment info for all nodes...");
|
||||
+ Some(filter) => {
|
||||
+ if filter.has_node_config_rules() {
|
||||
+ log::debug!("Retrieving deployment info for all nodes...");
|
||||
|
||||
- let needs_eval = filter.needs_eval();
|
||||
+ let all_node_configs = self.deployment_info().await?;
|
||||
+ let filtered = filter
|
||||
+ .filter_node_configs(all_node_configs.iter())
|
||||
+ .into_iter()
|
||||
+ .collect();
|
||||
|
||||
- let all_node_configs = self.deployment_info_partial(needs_eval).await?;
|
||||
+ node_configs = Some(all_node_configs);
|
||||
|
||||
- // Check for collisions between node names and aliases
|
||||
- // Returns error if:
|
||||
- // - A node has an alias matching another node's name
|
||||
- // - A node has an alias matching its own name
|
||||
- // - A node has an alias already used by another node
|
||||
- if needs_eval.aliases {
|
||||
- let mut taken_aliases = HashSet::new();
|
||||
- for (name, config) in all_node_configs.iter() {
|
||||
- for alias in config.aliases.as_ref().unwrap().iter() {
|
||||
- let overlaps_this = alias == name;
|
||||
- let overlaps_names = all_node_configs.contains_key(alias);
|
||||
- let overlaps_aliases = !taken_aliases.insert(alias.clone());
|
||||
- if overlaps_this || overlaps_names || overlaps_aliases {
|
||||
- return Err(ColmenaError::DuplicateAlias {
|
||||
- what: alias.clone(),
|
||||
- is_node_name: overlaps_this || overlaps_names,
|
||||
- with: name.clone(),
|
||||
- });
|
||||
- }
|
||||
- }
|
||||
- }
|
||||
+ filtered
|
||||
+ } else {
|
||||
+ filter.filter_node_names(&all_nodes)?.into_iter().collect()
|
||||
}
|
||||
-
|
||||
- let filtered = filter
|
||||
- .filter_nodes(all_node_configs.iter())
|
||||
- .into_iter()
|
||||
- .collect();
|
||||
-
|
||||
- filtered
|
||||
}
|
||||
- _ => match filter_trivial {
|
||||
- // Filter is known to always evaluate to no nodes
|
||||
- Some(false) => vec![],
|
||||
- _ => all_nodes.clone(),
|
||||
- },
|
||||
+ None => all_nodes.clone(),
|
||||
};
|
||||
|
||||
let n_selected = selected_nodes.len();
|
||||
- log::debug!("Filtered {n_selected} node names for deployment");
|
||||
|
||||
- let mut node_configs = if n_selected == all_nodes.len() {
|
||||
- log::debug!("Retrieving deployment info for all nodes...");
|
||||
- self.deployment_info().await?
|
||||
+ let mut node_configs = if let Some(configs) = node_configs {
|
||||
+ configs.into_iter().filter(|(name, _)| selected_nodes.contains(name)).collect()
|
||||
} else {
|
||||
log::debug!("Retrieving deployment info for selected nodes...");
|
||||
self.deployment_info_selected(&selected_nodes).await?
|
||||
@@ -425,34 +397,6 @@ impl Hive {
|
||||
Ok(configs)
|
||||
}
|
||||
|
||||
- pub async fn deployment_info_partial(
|
||||
- &self,
|
||||
- needs_eval: NeedsEval,
|
||||
- ) -> ColmenaResult<HashMap<NodeName, PartialNodeConfig>> {
|
||||
- if !needs_eval.any() {
|
||||
- // Need just the un-aliased names
|
||||
- return Ok(self
|
||||
- .node_names()
|
||||
- .await?
|
||||
- .into_iter()
|
||||
- .map(|name| (name, PartialNodeConfig::default()))
|
||||
- .collect());
|
||||
- }
|
||||
-
|
||||
- let expr = format!(
|
||||
- "(mapAttrs (name: attrs: {{ inherit (attrs) {} {}; }}) hive.deploymentConfig)",
|
||||
- needs_eval.aliases.then_some("aliases").unwrap_or_default(),
|
||||
- needs_eval.tags.then_some("tags").unwrap_or_default(),
|
||||
- );
|
||||
- let configs: HashMap<NodeName, PartialNodeConfig> = self
|
||||
- .nix_instantiate(&expr)
|
||||
- .eval_with_builders()
|
||||
- .await?
|
||||
- .capture_json()
|
||||
- .await?;
|
||||
- Ok(configs)
|
||||
- }
|
||||
-
|
||||
/// Retrieve deployment info for a single node.
|
||||
#[cfg_attr(not(target_os = "linux"), allow(dead_code))]
|
||||
pub async fn deployment_info_single(
|
||||
diff --git a/src/nix/hive/options.nix b/src/nix/hive/options.nix
|
||||
index 0d13642..0db53c5 100644
|
||||
--- a/src/nix/hive/options.nix
|
||||
+++ b/src/nix/hive/options.nix
|
||||
@@ -179,15 +179,6 @@ with builtins; rec {
|
||||
type = types.listOf types.str;
|
||||
default = [];
|
||||
};
|
||||
- aliases = lib.mkOption {
|
||||
- description = ''
|
||||
- A list of aliases for the node.
|
||||
-
|
||||
- Can be used to select a node with another name.
|
||||
- '';
|
||||
- type = types.listOf types.str;
|
||||
- default = [];
|
||||
- };
|
||||
keys = lib.mkOption {
|
||||
description = ''
|
||||
A set of secrets to be deployed to the node.
|
||||
diff --git a/src/nix/mod.rs b/src/nix/mod.rs
|
||||
index 6728270..4823f74 100644
|
||||
--- a/src/nix/mod.rs
|
||||
+++ b/src/nix/mod.rs
|
||||
@@ -75,8 +75,6 @@ pub struct NodeConfig {
|
||||
|
||||
tags: Vec<String>,
|
||||
|
||||
- aliases: Vec<NodeName>,
|
||||
-
|
||||
#[serde(rename = "replaceUnknownProfiles")]
|
||||
replace_unknown_profiles: bool,
|
||||
|
||||
diff --git a/src/nix/node_filter.rs b/src/nix/node_filter.rs
|
||||
index 434fb95..886ad50 100644
|
||||
--- a/src/nix/node_filter.rs
|
||||
+++ b/src/nix/node_filter.rs
|
||||
@@ -7,7 +7,6 @@ use std::str::FromStr;
|
||||
|
||||
use clap::Args;
|
||||
use glob::Pattern as GlobPattern;
|
||||
-use serde::Deserialize;
|
||||
|
||||
use super::{ColmenaError, ColmenaResult, NodeConfig, NodeName};
|
||||
|
||||
@@ -29,53 +28,6 @@ The list is comma-separated and globs are supported. To match tags, prepend the
|
||||
pub on: Option<NodeFilter>,
|
||||
}
|
||||
|
||||
-/// Which fields need to be evaluated
|
||||
-/// in order to execute the node filter.
|
||||
-#[derive(Clone, Copy, Debug, Default)]
|
||||
-pub struct NeedsEval {
|
||||
- /// Need to evaluate deployment.aliases of all nodes.
|
||||
- pub aliases: bool,
|
||||
- /// Need to evaluate deployment.tags of all nodes.
|
||||
- pub tags: bool,
|
||||
-}
|
||||
-
|
||||
-impl NeedsEval {
|
||||
- pub fn any(&self) -> bool {
|
||||
- self.aliases || self.tags
|
||||
- }
|
||||
-}
|
||||
-
|
||||
-impl std::ops::BitOr for NeedsEval {
|
||||
- type Output = Self;
|
||||
- fn bitor(self, rhs: Self) -> Self::Output {
|
||||
- Self {
|
||||
- aliases: self.aliases || rhs.aliases,
|
||||
- tags: self.tags || rhs.tags,
|
||||
- }
|
||||
- }
|
||||
-}
|
||||
-
|
||||
-impl std::ops::BitOrAssign for NeedsEval {
|
||||
- fn bitor_assign(&mut self, rhs: Self) {
|
||||
- *self = *self | rhs;
|
||||
- }
|
||||
-}
|
||||
-
|
||||
-#[derive(Debug, Default, Deserialize)]
|
||||
-pub struct PartialNodeConfig {
|
||||
- pub aliases: Option<Vec<NodeName>>,
|
||||
- pub tags: Option<Vec<String>>,
|
||||
-}
|
||||
-
|
||||
-impl From<NodeConfig> for PartialNodeConfig {
|
||||
- fn from(node_config: NodeConfig) -> Self {
|
||||
- Self {
|
||||
- aliases: Some(node_config.aliases),
|
||||
- tags: Some(node_config.tags),
|
||||
- }
|
||||
- }
|
||||
-}
|
||||
-
|
||||
/// A filter rule.
|
||||
#[derive(Debug, Clone, Eq, PartialEq)]
|
||||
pub enum NodeFilter {
|
||||
@@ -288,47 +240,30 @@ impl NodeFilter {
|
||||
}
|
||||
}
|
||||
|
||||
- /// Returns which NodeConfig information is needed to evaluate the filter.
|
||||
+ /// Returns whether the filter has any rule matching NodeConfig information.
|
||||
///
|
||||
/// Evaluating `config.deployment` can potentially be very expensive,
|
||||
/// especially when its values (e.g., tags) depend on other parts of
|
||||
/// the configuration.
|
||||
- pub fn needs_eval(&self) -> NeedsEval {
|
||||
- // XXX: is the hashset overkill?
|
||||
+ pub fn has_node_config_rules(&self) -> bool {
|
||||
match self {
|
||||
- Self::MatchName(_) => NeedsEval {
|
||||
- aliases: true,
|
||||
- ..Default::default()
|
||||
- },
|
||||
- Self::MatchTag(_) => NeedsEval {
|
||||
- tags: true,
|
||||
- ..Default::default()
|
||||
- },
|
||||
- Self::Union(v) | Self::Inter(v) => v
|
||||
- .iter()
|
||||
- .fold(NeedsEval::default(), |acc, e| acc | e.needs_eval()),
|
||||
- Self::Not(e) => e.needs_eval(),
|
||||
- Self::Empty => NeedsEval::default(),
|
||||
+ Self::MatchName(_) => false,
|
||||
+ Self::MatchTag(_) => true,
|
||||
+ Self::Union(v) => v.iter().any(|e| e.has_node_config_rules()),
|
||||
+ Self::Inter(v) => v.iter().any(|e| e.has_node_config_rules()),
|
||||
+ Self::Not(e) => e.has_node_config_rules(),
|
||||
+ Self::Empty => false,
|
||||
}
|
||||
}
|
||||
|
||||
/// Decides whether a node is accepted by the filter or not.
|
||||
- /// panic if the filter depends on tags or aliases and they're None
|
||||
- fn is_accepted(&self, name: &NodeName, config: &PartialNodeConfig) -> bool {
|
||||
+ /// panic if the filter depends on tags and config is None
|
||||
+ fn is_accepted(&self, name: &NodeName, config: Option<&NodeConfig>) -> bool {
|
||||
match self {
|
||||
- Self::MatchName(pat) => {
|
||||
- pat.matches(name.as_str())
|
||||
- || config
|
||||
- .aliases
|
||||
- .as_ref()
|
||||
- .expect("aliases missing")
|
||||
- .iter()
|
||||
- .any(|alias| pat.matches(&alias.0))
|
||||
- }
|
||||
+ Self::MatchName(pat) => pat.matches(name.as_str()),
|
||||
Self::MatchTag(pat) => config
|
||||
- .tags
|
||||
- .as_ref()
|
||||
- .expect("tags missing")
|
||||
+ .unwrap()
|
||||
+ .tags()
|
||||
.iter()
|
||||
.any(|tag| pat.matches(tag.as_str())),
|
||||
Self::Union(v) => v.iter().any(|e| e.is_accepted(name, config)),
|
||||
@@ -339,17 +274,17 @@ impl NodeFilter {
|
||||
}
|
||||
|
||||
/// Runs the filter against a set of NodeConfigs and returns the matched ones.
|
||||
- pub fn filter_nodes<'a, I>(&self, nodes: I) -> HashSet<NodeName>
|
||||
+ pub fn filter_node_configs<'a, I>(&self, nodes: I) -> HashSet<NodeName>
|
||||
where
|
||||
- I: Iterator<Item = (&'a NodeName, &'a PartialNodeConfig)>,
|
||||
+ I: Iterator<Item = (&'a NodeName, &'a NodeConfig)>,
|
||||
{
|
||||
if self == &Self::Empty {
|
||||
return HashSet::new();
|
||||
}
|
||||
|
||||
nodes
|
||||
- .filter_map(|(name, config)| {
|
||||
- if self.is_accepted(name, config) {
|
||||
+ .filter_map(|(name, node)| {
|
||||
+ if self.is_accepted(name, Some(node)) {
|
||||
Some(name)
|
||||
} else {
|
||||
None
|
||||
@@ -359,34 +294,26 @@ impl NodeFilter {
|
||||
.collect()
|
||||
}
|
||||
|
||||
- /// In case of trivial filters which dont actually use any node info
|
||||
- /// Try to eval them immediately
|
||||
- pub fn try_eval_trivial(&self) -> Option<bool> {
|
||||
- match self {
|
||||
- Self::MatchName(_) => None,
|
||||
- Self::MatchTag(_) => None,
|
||||
- Self::Union(fs) => {
|
||||
- for f in fs {
|
||||
- match f.try_eval_trivial() {
|
||||
- None => return None,
|
||||
- Some(true) => return Some(true),
|
||||
- Some(false) => continue,
|
||||
+ /// Runs the filter against a set of node names and returns the matched ones.
|
||||
+ pub fn filter_node_names(&self, nodes: &[NodeName]) -> ColmenaResult<HashSet<NodeName>> {
|
||||
+ if self.has_node_config_rules() {
|
||||
+ Err(ColmenaError::Unknown {
|
||||
+ message: format!(
|
||||
+ "Not enough information to run rule {:?} - We only have node names",
|
||||
+ self
|
||||
+ ),
|
||||
+ })
|
||||
+ } else {
|
||||
+ Ok(nodes
|
||||
+ .iter()
|
||||
+ .filter_map(|name| {
|
||||
+ if self.is_accepted(name, None) {
|
||||
+ Some(name.clone())
|
||||
+ } else {
|
||||
+ None
|
||||
}
|
||||
- }
|
||||
- Some(false)
|
||||
- }
|
||||
- Self::Inter(fs) => {
|
||||
- for f in fs {
|
||||
- match f.try_eval_trivial() {
|
||||
- None => return None,
|
||||
- Some(true) => continue,
|
||||
- Some(false) => return Some(false),
|
||||
- }
|
||||
- }
|
||||
- Some(true)
|
||||
- }
|
||||
- Self::Not(f) => f.try_eval_trivial().map(|b| !b),
|
||||
- Self::Empty => Some(true),
|
||||
+ })
|
||||
+ .collect())
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -395,36 +322,6 @@ impl NodeFilter {
|
||||
mod tests {
|
||||
use super::*;
|
||||
|
||||
- impl PartialNodeConfig {
|
||||
- fn known_empty() -> Self {
|
||||
- Self {
|
||||
- aliases: Some(vec![]),
|
||||
- tags: Some(vec![]),
|
||||
- }
|
||||
- }
|
||||
-
|
||||
- pub fn known_aliases_tags(
|
||||
- aliases: Option<Vec<NodeName>>,
|
||||
- tags: Option<Vec<String>>,
|
||||
- ) -> Self {
|
||||
- Self { aliases, tags }
|
||||
- }
|
||||
-
|
||||
- fn known_tags(tags: Vec<String>) -> Self {
|
||||
- Self {
|
||||
- aliases: Some(vec![]),
|
||||
- tags: Some(tags),
|
||||
- }
|
||||
- }
|
||||
-
|
||||
- fn known_aliases(aliases: Vec<NodeName>) -> Self {
|
||||
- Self {
|
||||
- aliases: Some(aliases),
|
||||
- tags: Some(vec![]),
|
||||
- }
|
||||
- }
|
||||
- }
|
||||
-
|
||||
use std::collections::{HashMap, HashSet};
|
||||
|
||||
macro_rules! node {
|
||||
@@ -527,109 +424,126 @@ mod tests {
|
||||
}
|
||||
|
||||
#[test]
|
||||
- fn test_filter_nodes_names_only() {
|
||||
- let nodes = vec![
|
||||
- (node!("lax-alpha"), PartialNodeConfig::known_empty()),
|
||||
- (node!("lax-beta"), PartialNodeConfig::known_empty()),
|
||||
- (node!("sfo-gamma"), PartialNodeConfig::known_empty()),
|
||||
- ];
|
||||
+ fn test_filter_node_names() {
|
||||
+ let nodes = vec![node!("lax-alpha"), node!("lax-beta"), node!("sfo-gamma")];
|
||||
|
||||
assert_eq!(
|
||||
&HashSet::from_iter([node!("lax-alpha")]),
|
||||
&NodeFilter::new("lax-alpha")
|
||||
.unwrap()
|
||||
- .filter_nodes(nodes.iter().map(|x| (&x.0, &x.1))),
|
||||
+ .filter_node_names(&nodes)
|
||||
+ .unwrap(),
|
||||
);
|
||||
|
||||
assert_eq!(
|
||||
&HashSet::from_iter([node!("lax-alpha"), node!("lax-beta")]),
|
||||
&NodeFilter::new("lax-*")
|
||||
.unwrap()
|
||||
- .filter_nodes(nodes.iter().map(|x| (&x.0, &x.1))),
|
||||
+ .filter_node_names(&nodes)
|
||||
+ .unwrap(),
|
||||
);
|
||||
}
|
||||
|
||||
#[test]
|
||||
- fn test_filter_nodes() {
|
||||
- let nodes: HashMap<NodeName, PartialNodeConfig> = HashMap::from([
|
||||
- (
|
||||
- node!("alpha"),
|
||||
- PartialNodeConfig::known_tags(vec!["web".to_string(), "infra-lax".to_string()]),
|
||||
- ),
|
||||
- (
|
||||
- node!("beta"),
|
||||
- PartialNodeConfig::known_tags(vec!["router".to_string(), "infra-sfo".to_string()]),
|
||||
- ),
|
||||
- (
|
||||
- node!("gamma-a"),
|
||||
- PartialNodeConfig::known_tags(vec!["controller".to_string()]),
|
||||
- ),
|
||||
- (
|
||||
- node!("gamma-b"),
|
||||
- PartialNodeConfig::known_tags(vec!["ewaste".to_string()]),
|
||||
- ),
|
||||
- (
|
||||
- node!("aliases-test"),
|
||||
- PartialNodeConfig::known_aliases_tags(
|
||||
- Some(vec![node!("whatever-alias1"), node!("whatever-alias2")]),
|
||||
- Some(vec!["testing".into()]),
|
||||
- ),
|
||||
- ),
|
||||
- ]);
|
||||
- assert_eq!(5, nodes.len());
|
||||
+ fn test_filter_node_configs() {
|
||||
+ // TODO: Better way to mock
|
||||
+ let template = NodeConfig {
|
||||
+ tags: vec![],
|
||||
+ target_host: None,
|
||||
+ target_user: None,
|
||||
+ target_port: None,
|
||||
+ allow_local_deployment: false,
|
||||
+ build_on_target: false,
|
||||
+ replace_unknown_profiles: false,
|
||||
+ privilege_escalation_command: vec![],
|
||||
+ extra_ssh_options: vec![],
|
||||
+ keys: HashMap::new(),
|
||||
+ system_type: None,
|
||||
+ };
|
||||
+
|
||||
+ let mut nodes = HashMap::new();
|
||||
+
|
||||
+ nodes.insert(
|
||||
+ node!("alpha"),
|
||||
+ NodeConfig {
|
||||
+ tags: vec!["web".to_string(), "infra-lax".to_string()],
|
||||
+ ..template.clone()
|
||||
+ },
|
||||
+ );
|
||||
+
|
||||
+ nodes.insert(
|
||||
+ node!("beta"),
|
||||
+ NodeConfig {
|
||||
+ tags: vec!["router".to_string(), "infra-sfo".to_string()],
|
||||
+ ..template.clone()
|
||||
+ },
|
||||
+ );
|
||||
+
|
||||
+ nodes.insert(
|
||||
+ node!("gamma-a"),
|
||||
+ NodeConfig {
|
||||
+ tags: vec!["controller".to_string()],
|
||||
+ ..template.clone()
|
||||
+ },
|
||||
+ );
|
||||
+
|
||||
+ nodes.insert(
|
||||
+ node!("gamma-b"),
|
||||
+ NodeConfig {
|
||||
+ tags: vec!["ewaste".to_string()],
|
||||
+ ..template
|
||||
+ },
|
||||
+ );
|
||||
+
|
||||
+ assert_eq!(4, nodes.len());
|
||||
|
||||
assert_eq!(
|
||||
&HashSet::from_iter([node!("alpha")]),
|
||||
- &NodeFilter::new("@web").unwrap().filter_nodes(nodes.iter()),
|
||||
+ &NodeFilter::new("@web")
|
||||
+ .unwrap()
|
||||
+ .filter_node_configs(nodes.iter()),
|
||||
);
|
||||
|
||||
assert_eq!(
|
||||
&HashSet::from_iter([node!("alpha"), node!("beta")]),
|
||||
&NodeFilter::new("@infra-*")
|
||||
.unwrap()
|
||||
- .filter_nodes(nodes.iter()),
|
||||
+ .filter_node_configs(nodes.iter()),
|
||||
);
|
||||
|
||||
assert_eq!(
|
||||
&HashSet::from_iter([node!("beta"), node!("gamma-a")]),
|
||||
&NodeFilter::new("@router,@controller")
|
||||
.unwrap()
|
||||
- .filter_nodes(nodes.iter()),
|
||||
+ .filter_node_configs(nodes.iter()),
|
||||
);
|
||||
|
||||
assert_eq!(
|
||||
&HashSet::from_iter([node!("beta"), node!("gamma-a"), node!("gamma-b")]),
|
||||
&NodeFilter::new("@router,gamma-*")
|
||||
.unwrap()
|
||||
- .filter_nodes(nodes.iter()),
|
||||
+ .filter_node_configs(nodes.iter()),
|
||||
);
|
||||
|
||||
assert_eq!(
|
||||
&HashSet::from_iter([]),
|
||||
&NodeFilter::new("@router&@controller")
|
||||
.unwrap()
|
||||
- .filter_nodes(nodes.iter()),
|
||||
+ .filter_node_configs(nodes.iter()),
|
||||
);
|
||||
|
||||
assert_eq!(
|
||||
&HashSet::from_iter([node!("beta")]),
|
||||
&NodeFilter::new("@router&@infra-*")
|
||||
.unwrap()
|
||||
- .filter_nodes(nodes.iter()),
|
||||
+ .filter_node_configs(nodes.iter()),
|
||||
);
|
||||
|
||||
assert_eq!(
|
||||
&HashSet::from_iter([node!("alpha")]),
|
||||
&NodeFilter::new("!@router&@infra-*")
|
||||
.unwrap()
|
||||
- .filter_nodes(nodes.iter()),
|
||||
- );
|
||||
-
|
||||
- assert_eq!(
|
||||
- &HashSet::from_iter([node!("aliases-test")]),
|
||||
- &NodeFilter::new("whatever-alias1")
|
||||
- .unwrap()
|
||||
- .filter_nodes(nodes.iter()),
|
||||
+ .filter_node_configs(nodes.iter()),
|
||||
);
|
||||
}
|
||||
}
|
||||
--
|
||||
2.49.0
|
||||
|
|
@ -12,10 +12,6 @@ with {
|
|||
};
|
||||
|
||||
{
|
||||
colmena = [
|
||||
(local ./colmena/0001-Revert-add-aliases-refactor-eval-logic.patch)
|
||||
];
|
||||
|
||||
lix = [
|
||||
(local ./lix/01-disable-installChecks.patch)
|
||||
(local ./lix/02-fetchGit-locked.patch)
|
||||
|
@ -48,9 +44,6 @@ with {
|
|||
"nixos-unstable" = [
|
||||
# Build netbird-relay
|
||||
(local ./nixpkgs/05-netbird-relay.patch)
|
||||
|
||||
# netbird-dashboard: 2.9.0 -> 2.12.0
|
||||
(npr 403844 "sha256-oQUc/UEvWOdZ5IyemnZeFS5dVysblqdV9fm6t790Kms=")
|
||||
];
|
||||
|
||||
"agenix" = [
|
||||
|
|
Loading…
Add table
Add a link
Reference in a new issue