feat: init ap01 #178
23 changed files with 594 additions and 52 deletions
|
@ -1,4 +1,15 @@
|
|||
jobs:
|
||||
ap01:
|
||||
runs-on: nix
|
||||
steps:
|
||||
- uses: actions/checkout@v3
|
||||
- env:
|
||||
BUILD_NODE: ap01
|
||||
STORE_ENDPOINT: https://tvix-store.dgnum.eu/infra-signing/
|
||||
STORE_PASSWORD: ${{ secrets.STORE_PASSWORD }}
|
||||
STORE_USER: admin
|
||||
name: Build and cache ap01
|
||||
run: nix-shell -A eval-nodes --run cache-node
|
||||
bridge01:
|
||||
runs-on: nix
|
||||
steps:
|
||||
|
|
|
@ -111,6 +111,11 @@ in
|
|||
}))
|
||||
pkgs.npins
|
||||
|
||||
# SSO testing
|
||||
pkgs.kanidm
|
||||
pkgs.freeradius
|
||||
pkgs.picocom # for serial access
|
||||
|
||||
(pkgs.callPackage ./lib/colmena {
|
||||
colmena = pkgs.callPackage "${sources.colmena}/package.nix" { };
|
||||
})
|
||||
|
|
32
hive.nix
32
hive.nix
|
@ -81,6 +81,7 @@ in
|
|||
|
||||
{
|
||||
meta = {
|
||||
nixpkgs = import nixpkgs.nixos.unstable.path;
|
||||
nodeNixpkgs = mapSingleFuse nodePkgs nodes;
|
||||
|
||||
specialArgs = {
|
||||
|
@ -93,13 +94,40 @@ in
|
|||
};
|
||||
|
||||
registry = {
|
||||
zyxel-nwa50ax = {
|
||||
evalConfig =
|
||||
args:
|
||||
(import "${sources.liminix}/lib/eval-config.nix" {
|
||||
nixpkgs = args.specialArgs.sourcePkgs.path;
|
||||
})
|
||||
args;
|
||||
|
||||
defaults =
|
||||
{ name, nodePath, ... }:
|
||||
{
|
||||
# Import the default modules
|
||||
imports = [
|
||||
# Import the base configuration for each node
|
||||
./${nodePath}/_configuration.nix
|
||||
./modules/generic
|
||||
./modules/${category name}
|
||||
];
|
||||
# It's impure, but who cares?
|
||||
# Can Flakes even do that? :)
|
||||
nixpkgs.buildPlatform = builtins.currentSystem;
|
||||
};
|
||||
};
|
||||
|
||||
nixos = {
|
||||
evalConfig = args: import "${args.specialArgs.sourcePkgs.path}/nixos/lib/eval-config.nix" args;
|
||||
defaults =
|
||||
{
|
||||
lib,
|
||||
name,
|
||||
nodes,
|
||||
nodeMeta,
|
||||
nodePath,
|
||||
meta,
|
||||
sourcePkgs,
|
||||
...
|
||||
}:
|
||||
|
@ -113,6 +141,10 @@ in
|
|||
./modules/${category name}
|
||||
];
|
||||
|
||||
_module.args.serverNodes = lib.filterAttrs (
|
||||
name: _: meta.nodes.${name}.nixpkgs.system == "nixos"
|
||||
) nodes;
|
||||
|
||||
# Include default secrets
|
||||
age-secrets.sources = [ ./${nodePath}/secrets ];
|
||||
|
||||
|
|
40
machines/liminix/ap01/_configuration.nix
Normal file
40
machines/liminix/ap01/_configuration.nix
Normal file
|
@ -0,0 +1,40 @@
|
|||
{
|
||||
modulesPath,
|
||||
sourcePkgs,
|
||||
...
|
||||
}:
|
||||
{
|
||||
imports = [
|
||||
"${modulesPath}/wlan.nix"
|
||||
"${modulesPath}/network"
|
||||
"${modulesPath}/hostapd"
|
||||
"${modulesPath}/ssh"
|
||||
"${modulesPath}/ntp"
|
||||
"${modulesPath}/vlan"
|
||||
"${modulesPath}/bridge"
|
||||
"${modulesPath}/jitter-rng"
|
||||
"${modulesPath}/pki"
|
||||
"${modulesPath}/ubus"
|
||||
# System-level configuration
|
||||
./system.nix
|
||||
# Configures our own WLAN.
|
||||
./wlan.nix
|
||||
# Configures our LAN interfaces, e.g. bridge + VLANs.
|
||||
./lan.nix
|
||||
# Configures our IPv4/IPv6 addresses, e.g. DHCPv4 on VLAN 0, SLAAC on VLAN 3001.
|
||||
./addresses.nix
|
||||
# Configures a basic local DNS.
|
||||
./dns.nix
|
||||
# Configures our management layer, e.g. SSH server + DGNum FAI keys.
|
||||
./management.nix
|
||||
# Configures our recovery system, e.g. a levitation script.
|
||||
./recovery.nix
|
||||
# Metadata on the system for field recovery.
|
||||
./metadata.nix
|
||||
# TODO: god that's so a fucking hack.
|
||||
(import "${modulesPath}/../devices/zyxel-nwa50ax").module
|
||||
];
|
||||
|
||||
hostname = "ap01-prototype";
|
||||
nixpkgs.source = sourcePkgs.path;
|
||||
}
|
18
machines/liminix/ap01/addresses.nix
Normal file
18
machines/liminix/ap01/addresses.nix
Normal file
|
@ -0,0 +1,18 @@
|
|||
{ config, ... }:
|
||||
let
|
||||
svc = config.system.service;
|
||||
in
|
||||
{
|
||||
services.dhcpv4 = svc.network.dhcp.client.build {
|
||||
interface = config.services.int;
|
||||
dependencies = [
|
||||
config.services.bridge.components.lan
|
||||
];
|
||||
};
|
||||
|
||||
services.defaultroute4 = svc.network.route.build {
|
||||
via = "$(output ${config.services.dhcpv4} router)";
|
||||
target = "default";
|
||||
dependencies = [ config.services.dhcpv4 ];
|
||||
};
|
||||
}
|
30
machines/liminix/ap01/dns.nix
Normal file
30
machines/liminix/ap01/dns.nix
Normal file
|
@ -0,0 +1,30 @@
|
|||
{ config, pkgs, ... }:
|
||||
let
|
||||
inherit (pkgs.liminix.services) oneshot;
|
||||
inherit (pkgs.pseudofile) dir symlink;
|
||||
inherit (pkgs) serviceFns;
|
||||
in
|
||||
{
|
||||
# TODO: support dynamic reconfiguration once we are in the target VLAN?
|
||||
services.resolvconf = oneshot rec {
|
||||
name = "resolvconf";
|
||||
up = ''
|
||||
. ${serviceFns}
|
||||
( in_outputs ${name}
|
||||
for i in $(output ${config.services.dhcpv4} dns); do
|
||||
echo "nameserver $i" >> resolv.conf
|
||||
done
|
||||
)
|
||||
'';
|
||||
|
||||
dependencies = [
|
||||
config.services.dhcpv4
|
||||
];
|
||||
};
|
||||
|
||||
filesystem = dir {
|
||||
etc = dir {
|
||||
"resolv.conf" = symlink "${config.services.resolvconf}/.outputs/resolv.conf";
|
||||
};
|
||||
};
|
||||
}
|
8
machines/liminix/ap01/ipc.nix
Normal file
8
machines/liminix/ap01/ipc.nix
Normal file
|
@ -0,0 +1,8 @@
|
|||
{ config, ... }:
|
||||
let
|
||||
svc = config.system.service;
|
||||
in
|
||||
{
|
||||
# ubus socket for various needs.
|
||||
services.ubus = svc.ubus.build { };
|
||||
}
|
39
machines/liminix/ap01/lan.nix
Normal file
39
machines/liminix/ap01/lan.nix
Normal file
|
@ -0,0 +1,39 @@
|
|||
{ config, ... }:
|
||||
let
|
||||
svc = config.system.service;
|
||||
in
|
||||
{
|
||||
services.int = svc.bridge.primary.build {
|
||||
ifname = "int";
|
||||
macAddressFromInterface = config.hardware.networkInterfaces.lan;
|
||||
};
|
||||
|
||||
services.bridge = svc.bridge.members.build {
|
||||
primary = config.services.int;
|
||||
members = {
|
||||
lan.member = config.hardware.networkInterfaces.lan;
|
||||
wlan0 = {
|
||||
member = config.hardware.networkInterfaces.wlan0;
|
||||
# Bridge only once hostapd is ready.
|
||||
dependencies = [ config.services.hostap-1-ready ];
|
||||
};
|
||||
wlan1 = {
|
||||
member = config.hardware.networkInterfaces.wlan1;
|
||||
# Bridge only once hostapd is ready.
|
||||
dependencies = [ config.services.hostap-2-ready ];
|
||||
};
|
||||
};
|
||||
};
|
||||
|
||||
# Default VLAN
|
||||
# services.vlan-apro = svc.vlan.build {
|
||||
# vlanId = 0;
|
||||
# interface = config.services.int;
|
||||
# };
|
||||
|
||||
# # Administration VLAN
|
||||
# services.vlan-admin = svc.vlan.build {
|
||||
# vlan = 3001;
|
||||
# interface = config.services.int;
|
||||
# };
|
||||
}
|
12
machines/liminix/ap01/management.nix
Normal file
12
machines/liminix/ap01/management.nix
Normal file
|
@ -0,0 +1,12 @@
|
|||
{ config, ... }:
|
||||
let
|
||||
svc = config.system.service;
|
||||
in
|
||||
{
|
||||
# SSH keys are handled by the access control module.
|
||||
dgn-access-control.enable = true;
|
||||
users.root = {
|
||||
passwd = "$6$Z2MiaMXkpUJRPl2/$fxVE3iD/n208CISM2F6OnWj0Qq0QG2tTQqLCjU80PFJJGIwNLLyOp6SeYH3dH20OvJX1loZRETrThZfIPw.rb/";
|
||||
};
|
||||
services.sshd = svc.ssh.build { allowRoot = true; };
|
||||
}
|
15
machines/liminix/ap01/metadata.nix
Normal file
15
machines/liminix/ap01/metadata.nix
Normal file
|
@ -0,0 +1,15 @@
|
|||
{ pkgs, ... }:
|
||||
let
|
||||
inherit (pkgs.pseudofile) dir;
|
||||
in
|
||||
{
|
||||
filesystem = dir {
|
||||
etc = dir {
|
||||
"nixpkgs.version" = {
|
||||
type = "f";
|
||||
file = "${pkgs.lib.version}";
|
||||
mode = "0444";
|
||||
};
|
||||
};
|
||||
};
|
||||
}
|
45
machines/liminix/ap01/recovery.nix
Normal file
45
machines/liminix/ap01/recovery.nix
Normal file
|
@ -0,0 +1,45 @@
|
|||
{
|
||||
config,
|
||||
pkgs,
|
||||
modulesPath,
|
||||
...
|
||||
}:
|
||||
let
|
||||
svc = config.system.service;
|
||||
in
|
||||
{
|
||||
defaultProfile.packages = with pkgs; [
|
||||
# Levitate enable us to mass-reinstall the system on the fly.
|
||||
(levitate.override {
|
||||
config = {
|
||||
imports = [
|
||||
"${modulesPath}/network"
|
||||
"${modulesPath}/ssh"
|
||||
"${modulesPath}/hardware.nix"
|
||||
"${modulesPath}/kernel"
|
||||
"${modulesPath}/outputs/tftpboot.nix"
|
||||
"${modulesPath}/outputs.nix"
|
||||
];
|
||||
nixpkgs.buildPlatform = builtins.currentSystem;
|
||||
services = {
|
||||
# In this situation, we fallback to the appro VLAN.
|
||||
# TODO: add support for the admin VLAN.
|
||||
# Simplest DHCPv4 we can find.
|
||||
dhcpv4 = svc.network.dhcp.client.build {
|
||||
interface = config.hardware.networkInterfaces.lan;
|
||||
};
|
||||
inherit (config.services) sshd;
|
||||
defaultroute4 = svc.network.route.build {
|
||||
via = "$(output ${config.services.dhcpv4} router)";
|
||||
target = "default";
|
||||
dependencies = [ config.services.dhcpv4 ];
|
||||
};
|
||||
};
|
||||
|
||||
defaultProfile.packages = [ mtdutils ];
|
||||
# Only keep root, which should inherit from DGN access control's root permissions.
|
||||
users.root = config.users.root;
|
||||
};
|
||||
})
|
||||
];
|
||||
}
|
28
machines/liminix/ap01/system.nix
Normal file
28
machines/liminix/ap01/system.nix
Normal file
|
@ -0,0 +1,28 @@
|
|||
{ pkgs, config, ... }:
|
||||
let
|
||||
svc = config.system.service;
|
||||
in
|
||||
{
|
||||
# Get moar random please
|
||||
services = {
|
||||
jitter = svc.jitter-rng.build { };
|
||||
packet_forwarding = svc.network.forward.build { };
|
||||
ntp = config.system.service.ntp.build {
|
||||
pools = {
|
||||
"pool.ntp.org" = [ "iburst" ];
|
||||
};
|
||||
|
||||
dependencies = [ config.services.jitter ];
|
||||
};
|
||||
};
|
||||
|
||||
boot.tftp = {
|
||||
serverip = "192.0.2.10";
|
||||
ipaddr = "192.0.2.12";
|
||||
};
|
||||
|
||||
defaultProfile.packages = with pkgs; [
|
||||
zyxel-bootconfig
|
||||
min-collect-garbage
|
||||
];
|
||||
}
|
93
machines/liminix/ap01/wlan.nix
Normal file
93
machines/liminix/ap01/wlan.nix
Normal file
|
@ -0,0 +1,93 @@
|
|||
{ config, pkgs, ... }:
|
||||
let
|
||||
svc = config.system.service;
|
||||
secrets-1 = {
|
||||
ssid = "DGNum 2G (N)";
|
||||
};
|
||||
secrets-2 = {
|
||||
ssid = "DGNum 5G (AX)";
|
||||
};
|
||||
baseParams = {
|
||||
country_code = "FR";
|
||||
hw_mode = "g";
|
||||
channel = 6;
|
||||
wmm_enabled = 1;
|
||||
ieee80211n = 1;
|
||||
ht_capab = "[LDPC][GF][HT40-][HT40+][SHORT-GI-40][MAX-AMSDU-7935][TX-STBC]";
|
||||
auth_algs = 1;
|
||||
wpa = 2;
|
||||
wpa_pairwise = "TKIP CCMP";
|
||||
rsn_pairwise = "CCMP";
|
||||
};
|
||||
|
||||
radiusKeyMgmt = {
|
||||
wpa_key_mgmt = "WPA-EAP";
|
||||
};
|
||||
|
||||
modernParams = {
|
||||
hw_mode = "a";
|
||||
he_su_beamformer = 1;
|
||||
he_su_beamformee = 1;
|
||||
he_mu_beamformer = 1;
|
||||
preamble = 1;
|
||||
# Allow radar detection.
|
||||
ieee80211d = 1;
|
||||
ieee80211h = 1;
|
||||
ieee80211ac = 1;
|
||||
ieee80211ax = 1;
|
||||
vht_capab = "[MAX-MPDU-7991][SU-BEAMFORMEE][SU-BEAMFORMER][RXLDPC][SHORT-GI-80][MAX-A-MPDU-LEN-EXP3][RX-ANTENNA-PATTERN][TX-ANTENNA-PATTERN][TX-STBC-2BY1][RX-STBC-1][MU-BEAMFORMER]";
|
||||
vht_oper_chwidth = 1;
|
||||
he_oper_chwidth = 1;
|
||||
channel = 36;
|
||||
vht_oper_centr_freq_seg0_idx = 42;
|
||||
he_oper_centr_freq_seg0_idx = 42;
|
||||
require_vht = 1;
|
||||
};
|
||||
|
||||
clientRadius = {
|
||||
ieee8021x = 1;
|
||||
eapol_version = 2;
|
||||
use_pae_group_addr = 1;
|
||||
dynamic_vlan = 0;
|
||||
vlan_tagged_interface = "lan";
|
||||
};
|
||||
|
||||
externalRadius = {
|
||||
# TODO: when we have proper IPAM, set the right value here.
|
||||
own_ip_addr = "127.0.0.1";
|
||||
nas_identifier = "ap01.dgnum.eu";
|
||||
|
||||
# No DNS here, hostapd do not support this mode.
|
||||
auth_server_addr = "129.199.195.129";
|
||||
auth_server_port = 1812;
|
||||
auth_server_shared_secret = "read it online";
|
||||
};
|
||||
|
||||
mkWifiSta =
|
||||
params: interface: secrets:
|
||||
svc.hostapd.build {
|
||||
inherit interface;
|
||||
package = pkgs.hostapd-radius;
|
||||
params = params // secrets;
|
||||
dependencies = [ config.services.jitter ];
|
||||
};
|
||||
in
|
||||
{
|
||||
services = {
|
||||
# wlan0 is the 2.4GHz interface.
|
||||
hostap-1 = mkWifiSta (
|
||||
baseParams // radiusKeyMgmt
|
||||
) config.hardware.networkInterfaces.wlan0 secrets-1;
|
||||
hostap-1-ready = svc.hostapd-ready.build {
|
||||
interface = config.hardware.networkInterfaces.wlan0;
|
||||
};
|
||||
# wlan1 is the 5GHz interface, e.g. AX capable.
|
||||
hostap-2 = mkWifiSta (
|
||||
baseParams // clientRadius // externalRadius // radiusKeyMgmt // modernParams
|
||||
) config.hardware.networkInterfaces.wlan1 secrets-2;
|
||||
# Oneshot that waits until the hostapd has set the interface in operational state.
|
||||
hostap-2-ready = svc.hostapd-ready.build {
|
||||
interface = config.hardware.networkInterfaces.wlan1;
|
||||
};
|
||||
};
|
||||
}
|
|
@ -1,7 +1,7 @@
|
|||
{
|
||||
config,
|
||||
lib,
|
||||
nodes,
|
||||
serverNodes,
|
||||
sources,
|
||||
...
|
||||
}:
|
||||
|
@ -28,16 +28,18 @@ let
|
|||
|
||||
port = 3001;
|
||||
|
||||
httpExcludes = [
|
||||
"localhost"
|
||||
"ens.cal.dgnum.eu"
|
||||
"luj-current.cal.dgnum.eu"
|
||||
"s3.dgnum.eu"
|
||||
"cdn.dgnum.eu"
|
||||
"saml-idp.dgnum.eu"
|
||||
"status.dgnum.eu"
|
||||
"radius.dgnum.eu"
|
||||
] ++ (concatLists (mapAttrsToList (_: { config, ... }: config.dgn-redirections.retired) nodes));
|
||||
httpExcludes =
|
||||
[
|
||||
"localhost"
|
||||
"ens.cal.dgnum.eu"
|
||||
"luj-current.cal.dgnum.eu"
|
||||
"s3.dgnum.eu"
|
||||
"cdn.dgnum.eu"
|
||||
"saml-idp.dgnum.eu"
|
||||
"status.dgnum.eu"
|
||||
"radius.dgnum.eu"
|
||||
]
|
||||
++ (concatLists (mapAttrsToList (_: { config, ... }: config.dgn-redirections.retired) serverNodes));
|
||||
|
||||
extraProbes = {
|
||||
monitors = {
|
||||
|
@ -88,7 +90,7 @@ let
|
|||
};
|
||||
|
||||
pingProbes = pingProbesFromHive {
|
||||
inherit nodes;
|
||||
nodes = serverNodes;
|
||||
mkHost = _: config: config.networking.fqdn;
|
||||
tags = [ { name = "Ping"; } ];
|
||||
excludes = [
|
||||
|
@ -99,7 +101,7 @@ let
|
|||
};
|
||||
|
||||
vpnProbes = pingProbesFromHive {
|
||||
inherit nodes;
|
||||
nodes = serverNodes;
|
||||
prefix = "VPN - ";
|
||||
mkHost = node: _: "${node}.dgnum";
|
||||
tags = [ { name = "VPN"; } ];
|
||||
|
@ -110,7 +112,7 @@ let
|
|||
};
|
||||
|
||||
httpProbes = fromHive {
|
||||
inherit nodes;
|
||||
nodes = serverNodes;
|
||||
builder =
|
||||
_: module:
|
||||
httpProbesFromConfig {
|
||||
|
|
|
@ -1,6 +1,6 @@
|
|||
{
|
||||
config,
|
||||
nodes,
|
||||
serverNodes,
|
||||
lib,
|
||||
...
|
||||
}:
|
||||
|
@ -19,7 +19,7 @@ let
|
|||
host = node;
|
||||
};
|
||||
}
|
||||
) nodes
|
||||
) serverNodes
|
||||
);
|
||||
in
|
||||
|
||||
|
|
|
@ -177,4 +177,18 @@
|
|||
system = "nixos";
|
||||
};
|
||||
};
|
||||
|
||||
ap01 = {
|
||||
site = "unknown";
|
||||
adminGroups = [ "fai" ];
|
||||
|
||||
hashedPassword = "$y$j9T$DMOQEWOYFHjNS0myrXp4x/$MG33VSdXGvib.99eN.AbvyVdNNJw4ERjAwK4.ULJe/A";
|
||||
|
||||
stateVersion = null;
|
||||
|
||||
nixpkgs = {
|
||||
system = "zyxel-nwa50ax";
|
||||
version = "24.05";
|
||||
};
|
||||
};
|
||||
}
|
||||
|
|
|
@ -6,6 +6,7 @@ let
|
|||
mkDefault
|
||||
mkIf
|
||||
mkOption
|
||||
optionalAttrs
|
||||
;
|
||||
|
||||
inherit (lib.types)
|
||||
|
@ -133,7 +134,7 @@ in
|
|||
};
|
||||
|
||||
stateVersion = mkOption {
|
||||
type = str;
|
||||
type = nullOr str;
|
||||
description = ''
|
||||
State version of the node.
|
||||
'';
|
||||
|
@ -203,15 +204,18 @@ in
|
|||
};
|
||||
|
||||
config = {
|
||||
deployment = {
|
||||
tags = [ "infra-${config.site}" ];
|
||||
targetHost = mkIf (builtins.hasAttr name args.config.network) (
|
||||
let
|
||||
ip = with args.config.network.${name}.addresses; ipv4 ++ ipv6;
|
||||
in
|
||||
mkIf (ip != [ ]) (mkDefault (builtins.head ip))
|
||||
);
|
||||
};
|
||||
deployment =
|
||||
{
|
||||
tags = [ "infra-${config.site}" ];
|
||||
}
|
||||
// (optionalAttrs (builtins.hasAttr name args.config.network) {
|
||||
targetHost =
|
||||
let
|
||||
ip = with args.config.network.${name}.addresses; ipv4 ++ ipv6;
|
||||
in
|
||||
mkIf (ip != [ ]) (mkDefault (builtins.head ip));
|
||||
|
||||
});
|
||||
};
|
||||
}
|
||||
)
|
||||
|
|
6
modules/liminix/default.nix
Normal file
6
modules/liminix/default.nix
Normal file
|
@ -0,0 +1,6 @@
|
|||
{
|
||||
imports = [
|
||||
# List of modules to import
|
||||
./dgn-access-control.nix
|
||||
];
|
||||
}
|
89
modules/liminix/dgn-access-control.nix
Normal file
89
modules/liminix/dgn-access-control.nix
Normal file
|
@ -0,0 +1,89 @@
|
|||
# Copyright :
|
||||
# - Tom Hubrecht <tom.hubrecht@dgnum.eu> 2023
|
||||
#
|
||||
# Ce logiciel est un programme informatique servant à déployer des
|
||||
# configurations de serveurs via NixOS.
|
||||
#
|
||||
# Ce logiciel est régi par la licence CeCILL soumise au droit français et
|
||||
# respectant les principes de diffusion des logiciels libres. Vous pouvez
|
||||
# utiliser, modifier et/ou redistribuer ce programme sous les conditions
|
||||
# de la licence CeCILL telle que diffusée par le CEA, le CNRS et l'INRIA
|
||||
# sur le site "http://www.cecill.info".
|
||||
#
|
||||
# En contrepartie de l'accessibilité au code source et des droits de copie,
|
||||
# de modification et de redistribution accordés par cette licence, il n'est
|
||||
# offert aux utilisateurs qu'une garantie limitée. Pour les mêmes raisons,
|
||||
# seule une responsabilité restreinte pèse sur l'auteur du programme, le
|
||||
# titulaire des droits patrimoniaux et les concédants successifs.
|
||||
#
|
||||
# A cet égard l'attention de l'utilisateur est attirée sur les risques
|
||||
# associés au chargement, à l'utilisation, à la modification et/ou au
|
||||
# développement et à la reproduction du logiciel par l'utilisateur étant
|
||||
# donné sa spécificité de logiciel libre, qui peut le rendre complexe à
|
||||
# manipuler et qui le réserve donc à des développeurs et des professionnels
|
||||
# avertis possédant des connaissances informatiques approfondies. Les
|
||||
# utilisateurs sont donc invités à charger et tester l'adéquation du
|
||||
# logiciel à leurs besoins dans des conditions permettant d'assurer la
|
||||
# sécurité de leurs systèmes et ou de leurs données et, plus généralement,
|
||||
# à l'utiliser et l'exploiter dans les mêmes conditions de sécurité.
|
||||
#
|
||||
# Le fait que vous puissiez accéder à cet en-tête signifie que vous avez
|
||||
# pris connaissance de la licence CeCILL, et que vous en avez accepté les
|
||||
# termes.
|
||||
|
||||
{
|
||||
config,
|
||||
lib,
|
||||
dgn-keys,
|
||||
meta,
|
||||
nodeMeta,
|
||||
...
|
||||
}:
|
||||
|
||||
let
|
||||
inherit (lib)
|
||||
mkDefault
|
||||
mkEnableOption
|
||||
mkIf
|
||||
mkOption
|
||||
|
||||
types
|
||||
;
|
||||
|
||||
admins =
|
||||
meta.organization.groups.root
|
||||
++ nodeMeta.admins
|
||||
++ (builtins.concatMap (g: meta.organization.groups.${g}) nodeMeta.adminGroups);
|
||||
|
||||
cfg = config.dgn-access-control;
|
||||
in
|
||||
|
||||
{
|
||||
options.dgn-access-control = {
|
||||
enable = mkEnableOption "DGNum access control." // {
|
||||
default = true;
|
||||
};
|
||||
|
||||
users = mkOption {
|
||||
type = with types; attrsOf (listOf str);
|
||||
default = { };
|
||||
description = ''
|
||||
Attribute set describing which member has access to which user on the node.
|
||||
Members must be declared in `meta/members.nix`.
|
||||
'';
|
||||
example = ''
|
||||
{
|
||||
user1 = [ "member1" "member2" ];
|
||||
}
|
||||
'';
|
||||
};
|
||||
};
|
||||
|
||||
config = mkIf cfg.enable {
|
||||
# Admins have root access to the node
|
||||
dgn-access-control.users.root = mkDefault admins;
|
||||
users = builtins.mapAttrs (_: members: {
|
||||
openssh.authorizedKeys.keys = dgn-keys.getKeys members;
|
||||
}) cfg.users;
|
||||
};
|
||||
}
|
|
@ -45,8 +45,8 @@ let
|
|||
mkDefault
|
||||
mkEnableOption
|
||||
mkIf
|
||||
mkMerge
|
||||
mkOption
|
||||
optionalAttrs
|
||||
|
||||
types
|
||||
;
|
||||
|
@ -80,22 +80,16 @@ in
|
|||
};
|
||||
};
|
||||
|
||||
config = mkIf cfg.enable (mkMerge [
|
||||
{
|
||||
# Admins have root access to the node
|
||||
dgn-access-control.users.root = mkDefault admins;
|
||||
|
||||
users.users = builtins.mapAttrs (_: members: {
|
||||
config = mkIf cfg.enable {
|
||||
# Admins have root access to the node
|
||||
dgn-access-control.users.root = mkDefault admins;
|
||||
users.mutableUsers = false;
|
||||
users.users = builtins.mapAttrs (
|
||||
username: members:
|
||||
{
|
||||
openssh.authorizedKeys.keys = dgn-keys.getKeys members;
|
||||
}) cfg.users;
|
||||
}
|
||||
{
|
||||
users = {
|
||||
mutableUsers = false;
|
||||
users.root = {
|
||||
inherit (nodeMeta) hashedPassword;
|
||||
};
|
||||
};
|
||||
}
|
||||
]);
|
||||
}
|
||||
// optionalAttrs (username == "root") { inherit (nodeMeta) hashedPassword; }
|
||||
) cfg.users;
|
||||
};
|
||||
}
|
||||
|
|
|
@ -127,14 +127,13 @@
|
|||
"liminix": {
|
||||
"type": "Git",
|
||||
"repository": {
|
||||
"type": "GitHub",
|
||||
"owner": "RaitoBezarius",
|
||||
"repo": "liminix"
|
||||
"type": "Git",
|
||||
"url": "https://git.dgnum.eu/DGNum/liminix"
|
||||
},
|
||||
"branch": "nwa50ax",
|
||||
"revision": "a4aa10dcc30225a8bb8eb465abfe908629175f2c",
|
||||
"url": "https://github.com/RaitoBezarius/liminix/archive/a4aa10dcc30225a8bb8eb465abfe908629175f2c.tar.gz",
|
||||
"hash": "1m1sc6agg5z65lmyjl48i7sddlwm8d0zgvs8z81iammfy4jpy7qd"
|
||||
"branch": "main",
|
||||
"revision": "473d6acc3de70bd6dbbb4a77af54f508f25c3c9c",
|
||||
"url": null,
|
||||
"hash": "00slsh0yqd8n8jcx3sbxgcmw1z28bnszy87pfs0ynfkl3bldzs3d"
|
||||
},
|
||||
"linkal": {
|
||||
"type": "Git",
|
||||
|
|
23
scripts/cache-node.sh
Normal file → Executable file
23
scripts/cache-node.sh
Normal file → Executable file
|
@ -3,7 +3,28 @@ set -o nounset
|
|||
set -o pipefail
|
||||
shopt -s lastpipe
|
||||
|
||||
drv=$(colmena eval --instantiate -E "{ nodes, ... }: nodes.${BUILD_NODE}.config.system.build.toplevel")
|
||||
# Remove the `nixpkgs=` default input.
|
||||
export NIX_PATH="nixpkgs="
|
||||
|
||||
system_type="$(colmena eval -E "{ nodes, ... }: nodes.${BUILD_NODE}.config.deployment.systemType" --show-trace)"
|
||||
# Get rid of surrounding quotes.
|
||||
system_type="${system_type%\"}"
|
||||
system_type="${system_type#\"}"
|
||||
|
||||
case "$system_type" in
|
||||
nixos)
|
||||
toplevel_path="config.system.build.toplevel"
|
||||
;;
|
||||
zyxel-nwa50ax)
|
||||
toplevel_path="config.system.outputs.zyxel-nwa-fit"
|
||||
;;
|
||||
*)
|
||||
echo "Unsupported system type '$system_type' for caching; add an entry in 'scripts/cache-node.sh'"
|
||||
exit 1
|
||||
;;
|
||||
esac
|
||||
|
||||
drv=$(colmena eval --instantiate -E "{ nodes, ... }: nodes.${BUILD_NODE}.${toplevel_path}" --show-trace)
|
||||
|
||||
# Build the derivation and send it to the great beyond
|
||||
nix-store --query --requisites --force-realise --include-outputs "$drv" | grep -v '.*\.drv' >paths.txt
|
||||
|
|
37
scripts/push-to-cache.sh
Executable file
37
scripts/push-to-cache.sh
Executable file
|
@ -0,0 +1,37 @@
|
|||
#!/usr/bin/env bash
|
||||
|
||||
set -o errexit
|
||||
set -o nounset
|
||||
set -o pipefail
|
||||
shopt -s lastpipe
|
||||
|
||||
output_path="$1"
|
||||
|
||||
if [ "$STORE_ENDPOINT" == "" ]; then
|
||||
echo "No endpoint given for the remote cache, uploading cannot take place."
|
||||
exit 0
|
||||
fi
|
||||
|
||||
if [ "$STORE_USER" == "" ]; then
|
||||
echo "No user given for the remote cache, uploading cannot take place."
|
||||
exit 0
|
||||
fi
|
||||
|
||||
if [ "$STORE_PASSWORD" == "" ]; then
|
||||
echo "No password given for the remote cache, uploading cannot take place."
|
||||
exit 1
|
||||
fi
|
||||
|
||||
cat <<EOF >.netrc
|
||||
default
|
||||
login $STORE_USER
|
||||
password $STORE_PASSWORD
|
||||
EOF
|
||||
|
||||
nix copy \
|
||||
--extra-experimental-features nix-command \
|
||||
--to "$STORE_ENDPOINT?compression=none" \
|
||||
--netrc-file .netrc \
|
||||
"$output_path"
|
||||
|
||||
rm .netrc
|
Loading…
Add table
Reference in a new issue