feat(shell): Add pre-commit hooks and reformat the repo

This commit is contained in:
Tom Hubrecht 2024-02-02 10:51:31 +01:00
parent 988c44d461
commit 5e3819c9b2
91 changed files with 3772 additions and 2282 deletions

1
.pre-commit-config.yaml Symbolic link
View File

@ -0,0 +1 @@
/nix/store/sbc33iwjwgwj0cklac3qjffvi93i723k-pre-commit-config.json

93
default.nix Normal file
View File

@ -0,0 +1,93 @@
/* Copyright :
- Maurice Debray <maurice.debray@dgnum.eu> 2023
- 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.
*/
let
sources = import ./npins;
pkgs = import sources.nixpkgs { };
pre-commit-check = (import sources.pre-commit-hooks).run {
src = ./.;
hooks = {
# Nix Hooks
statix.enable = true;
deadnix.enable = true;
rfc101 = {
enable = true;
name = "RFC-101 formatting";
entry = "${pkgs.lib.getExe pkgs.nixfmt-rfc-style}";
files = "\\.nix$";
};
# Misc Hooks
commitizen.enable = true;
};
};
in
{
shells = {
default = pkgs.mkShell {
name = "dgnum-infra";
packages =
(
with pkgs;
[
npins
colmena
nixos-generators
]
++ (builtins.map (p: callPackage p { }) [ (sources.disko + "/package.nix") ])
)
++ (import ./scripts { inherit pkgs; });
shellHook = ''
${pre-commit-check.shellHook}
'';
preferLocalBuild = true;
};
pre-commit = pkgs.mkShell {
name = "pre-commit-shell";
shellHook = ''
${pre-commit-check.shellHook}
'';
};
};
}

View File

@ -1,4 +1,5 @@
{ config, pkgs, ... }: {
{ config, pkgs, ... }:
{
imports = [ ./secrets ];
services = {
@ -8,8 +9,7 @@
listenAddress = "127.0.0.1";
settings = {
ALLOWED_HOSTS = [ "netbox.dgnum.sinavir.fr" ];
REMOTE_AUTH_BACKEND =
"social_core.backends.open_id_connect.OpenIdConnectAuth";
REMOTE_AUTH_BACKEND = "social_core.backends.open_id_connect.OpenIdConnectAuth";
};
extraConfig = ''
@ -27,12 +27,8 @@
enableACME = true;
forceSSL = true;
locations."/".proxyPass =
"http://${config.services.netbox.listenAddress}:${
builtins.toString config.services.netbox.port
}";
locations."/static/".alias =
"${config.services.netbox.dataDir}/static/";
locations."/".proxyPass = "http://${config.services.netbox.listenAddress}:${builtins.toString config.services.netbox.port}";
locations."/static/".alias = "${config.services.netbox.dataDir}/static/";
};
};
@ -50,5 +46,8 @@
};
users.users.nginx.extraGroups = [ "netbox" ];
networking.firewall.allowedTCPPorts = [ 443 80 ];
networking.firewall.allowedTCPPorts = [
443
80
];
}

View File

@ -6,10 +6,15 @@ let
inherit ((import ../../../meta).members) groups;
publicKeys = lib.splitString "\n"
(builtins.readFile (./maurice.keys)) # maurice servers' keys
publicKeys =
lib.splitString "\n" (builtins.readFile (./maurice.keys)) # maurice servers' keys
++ nix-lib.getAllKeys (groups.netbox ++ groups.root);
in {
"netbox.age" = { inherit publicKeys; };
"netbox_env.age" = { inherit publicKeys; };
in
{
"netbox.age" = {
inherit publicKeys;
};
"netbox_env.age" = {
inherit publicKeys;
};
}

View File

@ -6,32 +6,34 @@ let
patch = import sources.nix-patches { patchFile = ./patches; };
mkNode = node:
{ name, nodes, pkgs, ... }: {
# Import the base configuration for each node
imports = builtins.map (lib.mkRel ./machines/${node}) [
"_configuration.nix"
"_hardware-configuration.nix"
];
mkNode = node: _: {
# Import the base configuration for each node
imports = builtins.map (lib.mkRel ./machines/${node}) [
"_configuration.nix"
"_hardware-configuration.nix"
];
# Include default secrets
age-secrets.sources = [ ./machines/${node}/secrets ];
# Include default secrets
age-secrets.sources = [ ./machines/${node}/secrets ];
# Deployment config is specified in meta.nodes.${node}.deployment
inherit (metadata.nodes.${node}) deployment;
# Deployment config is specified in meta.nodes.${node}.deployment
inherit (metadata.nodes.${node}) deployment;
# Set NIX_PATH to the patched version of nixpkgs
nix.nixPath = [ "nixpkgs=${mkNixpkgs node}" ];
nix.optimise.automatic = true;
# Set NIX_PATH to the patched version of nixpkgs
nix.nixPath = [ "nixpkgs=${mkNixpkgs node}" ];
nix.optimise.automatic = true;
# Allow unfree packages
nixpkgs.config.allowUnfree = true;
# Allow unfree packages
nixpkgs.config.allowUnfree = true;
# Use the stateVersion declared in the metadata
system = { inherit (metadata.nodes.${node}) stateVersion; };
# Use the stateVersion declared in the metadata
system = {
inherit (metadata.nodes.${node}) stateVersion;
};
};
mkNixpkgs = node:
mkNixpkgs =
node:
patch.mkNixpkgsSrc rec {
src = sources.${version};
version = "nixos-${metadata.nodes.${node}.nixpkgs}";
@ -42,9 +44,12 @@ let
###
# Function to create arguments based on the node
#
mkArgs = node:
let lib' = (mkNixpkgs' node).lib;
in {
mkArgs =
node:
let
lib' = (mkNixpkgs' node).lib;
in
{
lib = import sources.nix-lib {
lib = lib';
keysRoot = ./keys;
@ -52,8 +57,8 @@ let
};
nodes = builtins.attrNames metadata.nodes;
in {
in
{
meta = {
nodeNixpkgs = lib.mapSingleFuse mkNixpkgs' nodes;
@ -65,8 +70,9 @@ in {
nodeSpecialArgs = lib.mapSingleFuse mkArgs nodes;
};
defaults = { pkgs, ... }: {
defaults = _: {
# Import the default modules
imports = [ ./modules ];
};
} // (lib.mapSingleFuse mkNode nodes)
}
// (lib.mapSingleFuse mkNode nodes)

View File

@ -34,5 +34,6 @@ in
};
users.users.root.openssh.authorizedKeys.keyFiles =
builtins.map (m: dgn-lib.mkRel ../keys "${m}.keys") dgn-members;
builtins.map (m: dgn-lib.mkRel ../keys "${m}.keys")
dgn-members;
}

View File

@ -2,4 +2,7 @@ let
inherit (import ../npins) nixpkgs;
in
(import nixpkgs { }).srcOnly { name = "nixpkgs-for-iso"; src = nixpkgs; }
(import nixpkgs { }).srcOnly {
name = "nixpkgs-for-iso";
src = nixpkgs;
}

View File

@ -3,20 +3,24 @@ _:
let
sources = import ../npins;
nix-lib = (import sources.nix-lib {
inherit ((import sources.nixpkgs { })) lib;
nix-lib =
(import sources.nix-lib {
inherit ((import sources.nixpkgs { })) lib;
keysRoot = ../keys;
}).extra;
in nix-lib // (with nix-lib; {
keysRoot = ../keys;
}).extra;
in
nix-lib
// (with nix-lib; {
# Get publickeys associated to a node
getNodeKeys = node:
getNodeKeys =
node:
let
meta = import ../meta;
names =
builtins.foldl' (names: group: names ++ meta.members.groups.${group})
(meta.nodes.${node}.admins ++ [ "/machines/${node}" ])
(meta.nodes.${node}.adminGroups ++ [ "root" ]);
in getAllKeys names;
(meta.nodes.${node}.admins ++ [ "/machines/${node}" ])
(meta.nodes.${node}.adminGroups ++ [ "root" ]);
in
getAllKeys names;
})

View File

@ -29,6 +29,5 @@
fsType = "vfat";
};
swapDevices =
[{ device = "/dev/disk/by-uuid/30547280-00e9-4ee1-8a07-d116590d9fbf"; }];
swapDevices = [ { device = "/dev/disk/by-uuid/30547280-00e9-4ee1-8a07-d116590d9fbf"; } ];
}

View File

@ -1,7 +1,9 @@
{ config, ... }:
let host = "demarches.dgnum.eu";
in {
let
host = "demarches.dgnum.eu";
in
{
imports = [ ./module.nix ];
services.demarches-simplifiees = {
@ -62,5 +64,7 @@ in {
};
};
age-secrets.matches."^ds_fr-.*$" = { owner = "ds-fr"; };
age-secrets.matches."^ds_fr-.*$" = {
owner = "ds-fr";
};
}

View File

@ -31,15 +31,26 @@
# The fact that you are presently reading this means that you have had
# knowledge of the CeCILL license and that you accept its terms.
{ config, lib, pkgs, ... }:
{
config,
lib,
pkgs,
...
}:
let
inherit (lib)
mdDoc mkDefault mkEnableOption mkIf mkOption
mdDoc
mkDefault
mkEnableOption
mkIf
mkOption
optional optionalString
optional
optionalString
types;
types
;
cfg = config.services.demarches-simplifiees;
@ -64,16 +75,14 @@ let
$SUDO ${cfg.package}/bin/$BIN "$@"
'';
in {
in
{
options.services.demarches-simplifiees = {
enable = mkEnableOption "demarches-simplifiees.";
package = mkOption {
type = types.package;
default = pkgs.callPackage ./package {
inherit (cfg) initialDeploymentDate dataDir logDir;
};
default = pkgs.callPackage ./package { inherit (cfg) initialDeploymentDate dataDir logDir; };
};
user = mkOption {
@ -127,15 +136,17 @@ in {
description = "Demarches Simplifiees setup";
wantedBy = [ "multi-user.target" ];
path = [ pkgs.bash ds-fr ];
path = [
pkgs.bash
ds-fr
];
after = [ "postgresql.service" ];
serviceConfig = {
Type = "oneshot";
User = cfg.user;
Group = cfg.group;
EnvironmentFile = [ env ]
++ (optional (cfg.secretFile != null) cfg.secretFile);
EnvironmentFile = [ env ] ++ (optional (cfg.secretFile != null) cfg.secretFile);
StateDirectory = mkIf (cfg.dataDir == "/var/lib/ds-fr") "ds-fr";
LogsDirectory = mkIf (cfg.logDir == "/var/log/ds-fr") "ds-fr";
};
@ -155,14 +166,19 @@ in {
ds-fr-work = {
description = "Demarches Simplifiees work service";
wantedBy = [ "multi-user.target" "ds-fr.service" ];
after = [ "network.target" "ds-fr-setup.service" ];
wantedBy = [
"multi-user.target"
"ds-fr.service"
];
after = [
"network.target"
"ds-fr-setup.service"
];
requires = [ "ds-fr-setup.service" ];
serviceConfig = {
ExecStart = "${ds-fr}/bin/ds-fr rails jobs:work";
EnvironmentFile = [ env ]
++ (optional (cfg.secretFile != null) cfg.secretFile);
EnvironmentFile = [ env ] ++ (optional (cfg.secretFile != null) cfg.secretFile);
User = cfg.user;
Group = cfg.group;
StateDirectory = mkIf (cfg.dataDir == "/var/lib/ds-fr") "ds-fr";
@ -174,15 +190,17 @@ in {
description = "Demarches Simplifiees web service";
wantedBy = [ "multi-user.target" ];
after = [ "network.target" "ds-fr-setup.service" ];
after = [
"network.target"
"ds-fr-setup.service"
];
requires = [ "ds-fr-setup.service" ];
path = [ pkgs.imagemagick ];
serviceConfig = {
ExecStart = "${ds-fr}/bin/ds-fr rails server";
Environment = [ "RAILS_QUEUE_ADAPTER=delayed_job" ];
EnvironmentFile = [ env ]
++ (optional (cfg.secretFile != null) cfg.secretFile);
EnvironmentFile = [ env ] ++ (optional (cfg.secretFile != null) cfg.secretFile);
User = cfg.user;
Group = cfg.group;
StateDirectory = mkIf (cfg.dataDir == "/var/lib/ds-fr") "ds-fr";
@ -192,171 +210,173 @@ in {
};
services = {
demarches-simplifiees.settings = (builtins.mapAttrs (_: mkDefault) {
RAILS_ENV = "production";
RAILS_ROOT = builtins.toString cfg.package;
demarches-simplifiees.settings =
(builtins.mapAttrs (_: mkDefault) {
RAILS_ENV = "production";
RAILS_ROOT = builtins.toString cfg.package;
# Application host name
#
# Examples:
# * For local development: localhost:3000
# * For preproduction: staging.ds.example.org
# * For production: ds.example.org
APP_HOST = "localhost:3000";
# Application host name
#
# Examples:
# * For local development: localhost:3000
# * For preproduction: staging.ds.example.org
# * For production: ds.example.org
APP_HOST = "localhost:3000";
# Rails key for signing sensitive data
# See https://guides.rubyonrails.org/security.html
#
# For production you MUST generate a new key, and keep it secret.
# Secrets must be long and random. Use bin/rails secret to get new unique secrets.
# Rails key for signing sensitive data
# See https://guides.rubyonrails.org/security.html
#
# For production you MUST generate a new key, and keep it secret.
# Secrets must be long and random. Use bin/rails secret to get new unique secrets.
# Secret key for One-Time-Password codes, used for 2-factors authentication
# OTP_SECRET_KEY = "";
# Secret key for One-Time-Password codes, used for 2-factors authentication
# OTP_SECRET_KEY = "";
# Protect access to the instance with a static login/password (useful for staging environments)
BASIC_AUTH_ENABLED = "disabled";
BASIC_AUTH_USERNAME = "";
BASIC_AUTH_PASSWORD = "";
# Protect access to the instance with a static login/password (useful for staging environments)
BASIC_AUTH_ENABLED = "disabled";
BASIC_AUTH_USERNAME = "";
BASIC_AUTH_PASSWORD = "";
# ActiveStorage service to use for attached files.
# Possible values:
# - "local": store files on the local filesystem
# - "amazon": store files remotely on an S3 storage service
# - "openstack": store files remotely on an OpenStack storage service
#
# (See config/storage.yml for the configuration of each service.)
ACTIVE_STORAGE_SERVICE = "local";
# ActiveStorage service to use for attached files.
# Possible values:
# - "local": store files on the local filesystem
# - "amazon": store files remotely on an S3 storage service
# - "openstack": store files remotely on an OpenStack storage service
#
# (See config/storage.yml for the configuration of each service.)
ACTIVE_STORAGE_SERVICE = "local";
# Configuration for the OpenStack storage service (if enabled)
FOG_OPENSTACK_API_KEY = "";
FOG_OPENSTACK_USERNAME = "";
FOG_OPENSTACK_URL = "";
FOG_OPENSTACK_REGION = "";
DS_PROXY_URL = "";
# Configuration for the OpenStack storage service (if enabled)
FOG_OPENSTACK_API_KEY = "";
FOG_OPENSTACK_USERNAME = "";
FOG_OPENSTACK_URL = "";
FOG_OPENSTACK_REGION = "";
DS_PROXY_URL = "";
# SAML
SAML_IDP_ENABLED = "disabled";
# SAML
SAML_IDP_ENABLED = "disabled";
# External service: authentication through France Connect
FC_PARTICULIER_ID = "";
FC_PARTICULIER_SECRET = "";
FC_PARTICULIER_BASE_URL = "";
# External service: authentication through France Connect
FC_PARTICULIER_ID = "";
FC_PARTICULIER_SECRET = "";
FC_PARTICULIER_BASE_URL = "";
# External service: authentication through Agent Connect
AGENT_CONNECT_ID = "";
AGENT_CONNECT_SECRET = "";
AGENT_CONNECT_BASE_URL = "";
AGENT_CONNECT_JWKS = "";
AGENT_CONNECT_REDIRECT = "";
# External service: authentication through Agent Connect
AGENT_CONNECT_ID = "";
AGENT_CONNECT_SECRET = "";
AGENT_CONNECT_BASE_URL = "";
AGENT_CONNECT_JWKS = "";
AGENT_CONNECT_REDIRECT = "";
# External service: integration with HelpScout (optional)
HELPSCOUT_MAILBOX_ID = "";
HELPSCOUT_CLIENT_ID = "";
HELPSCOUT_CLIENT_SECRET = "";
HELPSCOUT_WEBHOOK_SECRET = "";
# External service: integration with HelpScout (optional)
HELPSCOUT_MAILBOX_ID = "";
HELPSCOUT_CLIENT_ID = "";
HELPSCOUT_CLIENT_SECRET = "";
HELPSCOUT_WEBHOOK_SECRET = "";
# External service: external supervision
SENTRY_ENABLED = "disabled";
SENTRY_CURRENT_ENV = "development";
SENTRY_DSN_RAILS = "";
SENTRY_DSN_JS = "";
# External service: external supervision
SENTRY_ENABLED = "disabled";
SENTRY_CURRENT_ENV = "development";
SENTRY_DSN_RAILS = "";
SENTRY_DSN_JS = "";
# External service: Matomo web analytics
MATOMO_ENABLED = "disabled";
MATOMO_COOKIE_DOMAIN = "*.www.demarches-simplifiees.fr";
MATOMO_DOMAIN = "*.www.demarches-simplifiees.fr";
MATOMO_ID = "";
MATOMO_HOST = "matomo.example.org";
# External service: Matomo web analytics
MATOMO_ENABLED = "disabled";
MATOMO_COOKIE_DOMAIN = "*.www.demarches-simplifiees.fr";
MATOMO_DOMAIN = "*.www.demarches-simplifiees.fr";
MATOMO_ID = "";
MATOMO_HOST = "matomo.example.org";
# Default SMTP Provider: Mailjet
MAILJET_API_KEY = "";
MAILJET_SECRET_KEY = "";
# Default SMTP Provider: Mailjet
MAILJET_API_KEY = "";
MAILJET_SECRET_KEY = "";
# Alternate SMTP Provider: SendInBlue/DoList
SENDINBLUE_CLIENT_KEY = "";
SENDINBLUE_SMTP_KEY = "";
SENDINBLUE_USER_NAME = "";
# SENDINBLUE_LOGIN_URL="https://app.sendinblue.com/account/saml/login/truc"
# Alternate SMTP Provider: SendInBlue/DoList
SENDINBLUE_CLIENT_KEY = "";
SENDINBLUE_SMTP_KEY = "";
SENDINBLUE_USER_NAME = "";
# SENDINBLUE_LOGIN_URL="https://app.sendinblue.com/account/saml/login/truc"
# Alternate SMTP Provider: Mailtrap (mail catcher for staging environments)
# When enabled, all emails will be sent using this provider
MAILTRAP_ENABLED = "disabled";
MAILTRAP_USERNAME = "";
MAILTRAP_PASSWORD = "";
# Alternate SMTP Provider: Mailtrap (mail catcher for staging environments)
# When enabled, all emails will be sent using this provider
MAILTRAP_ENABLED = "disabled";
MAILTRAP_USERNAME = "";
MAILTRAP_PASSWORD = "";
# Alternative SMTP Provider: Mailcatcher (Catches mail and serves it through a dream.)
# When enabled, all emails will be sent using this provider
MAILCATCHER_ENABLED = "disabled";
MAILCATCHER_HOST = "";
MAILCATCHER_PORT = "";
# Alternative SMTP Provider: Mailcatcher (Catches mail and serves it through a dream.)
# When enabled, all emails will be sent using this provider
MAILCATCHER_ENABLED = "disabled";
MAILCATCHER_HOST = "";
MAILCATCHER_PORT = "";
# External service: live chat for admins (specific to démarches-simplifiées.fr)
CRISP_ENABLED = "disabled";
CRISP_CLIENT_KEY = "";
# External service: live chat for admins (specific to démarches-simplifiées.fr)
CRISP_ENABLED = "disabled";
CRISP_CLIENT_KEY = "";
# API Entreprise credentials
# https://api.gouv.fr/api/api-entreprise.html
API_ENTREPRISE_KEY = "";
# API Entreprise credentials
# https://api.gouv.fr/api/api-entreprise.html
API_ENTREPRISE_KEY = "";
# External service: CRM for following admin accounts pipeline (specific to démarches-simplifiées.fr)
PIPEDRIVE_KEY = "";
# External service: CRM for following admin accounts pipeline (specific to démarches-simplifiées.fr)
PIPEDRIVE_KEY = "";
# Networks bypassing the email login token that verifies new devices, and rack-attack throttling
TRUSTED_NETWORKS = "";
# Networks bypassing the email login token that verifies new devices, and rack-attack throttling
TRUSTED_NETWORKS = "";
# External service: mesuring performance of the Rails app (specific to démarches-simplifiées.fr)
SKYLIGHT_AUTHENTICATION_KEY = "";
# "sXaot-fKhBlkI8qaSirQyuZbrpv5sVFoOturQ0pFEh0";
# External service: mesuring performance of the Rails app (specific to démarches-simplifiées.fr)
SKYLIGHT_AUTHENTICATION_KEY = "";
# "sXaot-fKhBlkI8qaSirQyuZbrpv5sVFoOturQ0pFEh0";
# Enable or disable Lograge logs
LOGRAGE_ENABLED = "disabled";
# Enable or disable Lograge logs
LOGRAGE_ENABLED = "disabled";
# Logs source for Lograge
#
# Examples:
# * For local development: tps_local
# * For preproduction: tps_staging
# * For production: tps_prod
LOGRAGE_SOURCE = "tps_prod";
# Logs source for Lograge
#
# Examples:
# * For local development: tps_local
# * For preproduction: tps_staging
# * For production: tps_prod
LOGRAGE_SOURCE = "tps_prod";
# External service: timestamping a daily archive of dossiers status changes
UNIVERSIGN_API_URL = "https://ws.universign.eu/tsa/post/";
UNIVERSIGN_USERPWD = "";
# External service: timestamping a daily archive of dossiers status changes
UNIVERSIGN_API_URL = "https://ws.universign.eu/tsa/post/";
UNIVERSIGN_USERPWD = "";
# External service: API Geo / Adresse
API_ADRESSE_URL = "https://api-adresse.data.gouv.fr";
API_GEO_URL = "https://geo.api.gouv.fr";
# External service: API Geo / Adresse
API_ADRESSE_URL = "https://api-adresse.data.gouv.fr";
API_GEO_URL = "https://geo.api.gouv.fr";
# External service: API Education
API_EDUCATION_URL = "https://data.education.gouv.fr/api/records/1.0";
# External service: API Education
API_EDUCATION_URL = "https://data.education.gouv.fr/api/records/1.0";
# Encryption key for sensitive columns in the database
ENCRYPTION_SERVICE_SALT = "";
# Encryption key for sensitive columns in the database
ENCRYPTION_SERVICE_SALT = "";
# ActiveRecord encryption keys. Generate them with bin/rails db:encryption:init (you can omit deterministic_key)
AR_ENCRYPTION_PRIMARY_KEY = "";
AR_ENCRYPTION_KEY_DERIVATION_SALT = "";
# ActiveRecord encryption keys. Generate them with bin/rails db:encryption:init (you can omit deterministic_key)
AR_ENCRYPTION_PRIMARY_KEY = "";
AR_ENCRYPTION_KEY_DERIVATION_SALT = "";
# Salt for invisible_captcha session data.
# Must be the same value for all app instances behind a load-balancer.
INVISIBLE_CAPTCHA_SECRET = "kikooloool";
# Salt for invisible_captcha session data.
# Must be the same value for all app instances behind a load-balancer.
INVISIBLE_CAPTCHA_SECRET = "kikooloool";
# Clamav antivirus usage
CLAMAV_ENABLED = "disabled";
# Clamav antivirus usage
CLAMAV_ENABLED = "disabled";
# Siret number used for API Entreprise, by default we use SIRET from dinum
API_ENTREPRISE_DEFAULT_SIRET = "put_your_own_siret";
}) // {
# Database credentials
DB_DATABASE = "ds-fr";
DB_USERNAME = cfg.user;
DB_PASSWORD = "";
DB_HOST = "/run/postgresql";
DB_POOL = "";
# Siret number used for API Entreprise, by default we use SIRET from dinum
API_ENTREPRISE_DEFAULT_SIRET = "put_your_own_siret";
})
// {
# Database credentials
DB_DATABASE = "ds-fr";
DB_USERNAME = cfg.user;
DB_PASSWORD = "";
DB_HOST = "/run/postgresql";
DB_POOL = "";
# Log on stdout
RAILS_LOG_TO_STDOUT = true;
};
# Log on stdout
RAILS_LOG_TO_STDOUT = true;
};
postgresql = {
enable = true;
@ -368,8 +388,7 @@ in {
ensureDBOwnership = true;
};
extraPlugins = with config.services.postgresql.package.pkgs;
[ postgis ];
extraPlugins = with config.services.postgresql.package.pkgs; [ postgis ];
};
nginx = {
@ -381,7 +400,9 @@ in {
root = "${cfg.package}/public/";
locations."/".tryFiles = "$uri @proxy";
locations."@proxy" = { proxyPass = "http://127.0.0.1:3000"; };
locations."@proxy" = {
proxyPass = "http://127.0.0.1:3000";
};
};
};
};

View File

@ -1,6 +1,18 @@
{ lib, stdenv, fetchFromGitHub, git, fetchYarnDeps, yarn, fixup_yarn_lock, imagemagick
, nodejs, ruby_3_2, bundlerEnv, logDir ? "/var/log/ds-fr"
, dataDir ? "/var/lib/ds-fr", initialDeploymentDate ? "17941030" }:
{
lib,
stdenv,
fetchFromGitHub,
git,
fetchYarnDeps,
yarn,
fixup_yarn_lock,
nodejs,
ruby_3_2,
bundlerEnv,
logDir ? "/var/log/ds-fr",
dataDir ? "/var/lib/ds-fr",
initialDeploymentDate ? "17941030",
}:
let
pname = "ds-fr";
@ -43,7 +55,12 @@ let
};
buildInputs = [ rubyEnv ];
nativeBuildInputs = [ fixup_yarn_lock nodejs yarn rubyEnv.wrappedRuby ];
nativeBuildInputs = [
fixup_yarn_lock
nodejs
yarn
rubyEnv.wrappedRuby
];
RAILS_ENV = "production";
NODE_ENV = "dev";
@ -53,8 +70,9 @@ let
./patches/build.patch
];
postPatch = builtins.concatStringsSep "\n"
(builtins.map (p: "${git}/bin/git apply -p1 < ${p}") dgn-patches);
postPatch = builtins.concatStringsSep "\n" (
builtins.map (p: "${git}/bin/git apply -p1 < ${p}") dgn-patches
);
OTP_SECRET_KEY = "precompile_placeholder";
SECRET_KEY_BASE = "precompile_placeholder";
@ -82,8 +100,8 @@ let
};
dgn-patches = import ./dgnum.nix { };
in stdenv.mkDerivation {
in
stdenv.mkDerivation {
name = "demarches-simplifiees.fr-${version}";
inherit src;
@ -98,8 +116,9 @@ in stdenv.mkDerivation {
./patches/secrets-fc.patch
];
postPatch = builtins.concatStringsSep "\n"
(builtins.map (p: "${git}/bin/git apply -p1 < ${p}") dgn-patches);
postPatch = builtins.concatStringsSep "\n" (
builtins.map (p: "${git}/bin/git apply -p1 < ${p}") dgn-patches
);
buildPhase = ''
rm -rf public
@ -132,8 +151,7 @@ in stdenv.mkDerivation {
meta = with lib; {
description = "Dématérialiser et simplifier les démarches administratives";
homepage =
"https://github.com/demarches-simplifiees/demarches-simplifiees.fr";
homepage = "https://github.com/demarches-simplifiees/demarches-simplifiees.fr";
license = licenses.agpl3Only;
maintainers = with maintainers; [ thubrecht ];
};

View File

@ -1,6 +1,5 @@
_:
builtins.map (id:
builtins.fetchurl
"https://git.dgnum.eu/DGNum/demarches-normaliennes/commit/${id}.patch")
[ "0b9b32483a700ad3060b3d4ef723d5f40c290c62" ]
builtins.map
(id: builtins.fetchurl "https://git.dgnum.eu/DGNum/demarches-normaliennes/commit/${id}.patch")
[ "0b9b32483a700ad3060b3d4ef723d5f40c290c62" ]

View File

@ -1,5 +1,5 @@
{
version = "2024-01-31-02";
src-hash = "sha256-4ATsSXbjkIMGn5yuyYiI+N+C2R/MSzecMLs5hWCCAM4=";
deps-hash = "sha256-UR5K6DQMvmpWWTH8O9/zJ3Nd+Kkl7xofktFdmBB9z6M=";
version = "2024-01-31-02";
src-hash = "sha256-4ATsSXbjkIMGn5yuyYiI+N+C2R/MSzecMLs5hWCCAM4=";
deps-hash = "sha256-UR5K6DQMvmpWWTH8O9/zJ3Nd+Kkl7xofktFdmBB9z6M=";
}

File diff suppressed because it is too large Load Diff

View File

@ -3,7 +3,8 @@
let
host = "pads.dgnum.eu";
port = 3007;
in {
in
{
services = {
hedgedoc = {
enable = true;
@ -43,13 +44,17 @@ in {
ensureDatabases = [ "hedgedoc" ];
ensureUsers = [{
name = "hedgedoc";
ensureDBOwnership = true;
}];
ensureUsers = [
{
name = "hedgedoc";
ensureDBOwnership = true;
}
];
};
};
systemd.services.hedgedoc.serviceConfig.StateDirectory =
lib.mkForce [ "hedgedoc" "hedgedoc/uploads" ];
systemd.services.hedgedoc.serviceConfig.StateDirectory = lib.mkForce [
"hedgedoc"
"hedgedoc/uploads"
];
}

View File

@ -40,22 +40,23 @@
};
authTokenFile = config.age.secrets."radius-auth_token_file".path;
privateKeyPasswordFile =
config.age.secrets."radius-private_key_password_file".path;
privateKeyPasswordFile = config.age.secrets."radius-private_key_password_file".path;
certs = builtins.listToAttrs (builtins.map (name:
lib.nameValuePair name
config.age.secrets."radius-${name}_pem_file".path) [
certs = builtins.listToAttrs (
builtins.map (name: lib.nameValuePair name config.age.secrets."radius-${name}_pem_file".path) [
"ca"
"cert"
"dh"
"key"
]);
]
);
radiusClients = { };
};
age-secrets.matches."^radius-.*$" = { owner = "radius"; };
age-secrets.matches."^radius-.*$" = {
owner = "radius";
};
networking.firewall.allowedTCPPorts = [ 1812 ];
networking.firewall.allowedUDPPorts = [ 1812 ];

View File

@ -1,17 +1,27 @@
{ config, lib, pkgs, ... }:
{
config,
lib,
pkgs,
...
}:
let
inherit (lib) mkEnableOption mkIf mkOption types;
inherit (lib)
mkEnableOption
mkIf
mkOption
types
;
settingsFormat = pkgs.formats.toml { };
py-pkgs = import ./packages/python { inherit pkgs; };
pykanidm =
pkgs.callPackage ./packages/pykanidm.nix { inherit (py-pkgs) pydantic; };
pykanidm = pkgs.callPackage ./packages/pykanidm.nix { inherit (py-pkgs) pydantic; };
rlm_python = pkgs.callPackage ./packages/rlm_python.nix { inherit pykanidm; };
cfg = config.services.k-radius;
in {
in
{
options.services.k-radius = {
enable = mkEnableOption "a freeradius service linked to kanidm.";
@ -19,17 +29,17 @@ in {
freeradius = mkOption {
type = types.package;
default = pkgs.freeradius.overrideAttrs (old: {
buildInputs = (old.buildInputs or [ ])
++ [ (pkgs.python3.withPackages (ps: [ ps.kanidm ])) ];
});
default = pkgs.freeradius.overrideAttrs (
old: {
buildInputs = (old.buildInputs or [ ]) ++ [ (pkgs.python3.withPackages (ps: [ ps.kanidm ])) ];
}
);
};
configDir = mkOption {
type = types.path;
default = "/var/lib/radius/raddb";
description =
"The path of the freeradius server configuration directory.";
description = "The path of the freeradius server configuration directory.";
};
authTokenFile = mkOption {
@ -38,12 +48,14 @@ in {
};
radiusClients = mkOption {
type = types.attrsOf (types.submodule {
options = {
secret = mkOption { type = types.path; };
ipaddr = mkOption { type = types.str; };
};
});
type = types.attrsOf (
types.submodule {
options = {
secret = mkOption { type = types.path; };
ipaddr = mkOption { type = types.str; };
};
}
);
default = { };
description = "A mapping of clients and their authentication tokens.";
};
@ -55,8 +67,7 @@ in {
};
dh = mkOption {
type = types.str;
description =
"The output of `openssl dhparam -in ca.pem -out dh.pem 2048`.";
description = "The output of `openssl dhparam -in ca.pem -out dh.pem 2048`.";
};
cert = mkOption {
type = types.str;
@ -113,26 +124,32 @@ in {
# write the clients configuration
rm ${cfg.configDir}/clients.conf && touch ${cfg.configDir}/clients.conf
${builtins.concatStringsSep "\n" (builtins.attrValues (builtins.mapAttrs
(name:
{ secret, ipaddr }: ''
cat <<EOF >> ${cfg.configDir}/client.conf
client ${name} {
ipaddr = ${ipaddr}
secret = $(cat "${secret}")
proto = *
}
EOF
'') cfg.radiusClients))}
${builtins.concatStringsSep "\n" (
builtins.attrValues (
builtins.mapAttrs
(
name:
{ secret, ipaddr }:
''
cat <<EOF >> ${cfg.configDir}/client.conf
client ${name} {
ipaddr = ${ipaddr}
secret = $(cat "${secret}")
proto = *
}
EOF
''
)
cfg.radiusClients
)
)}
# Copy the kanidm configuration
cat <<EOF > /var/lib/radius/kanidm.toml
auth_token = "$(cat "${cfg.authTokenFile}")"
EOF
cat ${
settingsFormat.generate "kanidm.toml" cfg.settings
} >> /var/lib/radius/kanidm.toml
cat ${settingsFormat.generate "kanidm.toml" cfg.settings} >> /var/lib/radius/kanidm.toml
chmod u+w /var/lib/radius/kanidm.toml
# Copy the certificates to the correct directory
@ -154,11 +171,13 @@ in {
# ${pkgs.freeradius}/bin/radiusd -C -d ${cfg.configDir} -l stdout
'';
path = [ pkgs.openssl pkgs.gnused ];
path = [
pkgs.openssl
pkgs.gnused
];
serviceConfig = {
ExecStart =
"${cfg.freeradius}/bin/radiusd -f -d ${cfg.configDir} -l stdout";
ExecStart = "${cfg.freeradius}/bin/radiusd -f -d ${cfg.configDir} -l stdout";
ExecReload = [
"${cfg.freeradius}/bin/radiusd -C -d ${cfg.configDir} -l stdout"
"${pkgs.coreutils}/bin/kill -HUP $MAINPID"

View File

@ -1,25 +1,38 @@
{ lib, fetchFromGitHub, python3, pydantic }:
{
lib,
fetchFromGitHub,
python3,
pydantic,
}:
let
pname = "kanidm";
version = "0.0.3";
in python3.pkgs.buildPythonPackage {
in
python3.pkgs.buildPythonPackage {
inherit pname version;
format = "pyproject";
disabled = python3.pythonOlder "3.8";
src = (fetchFromGitHub {
owner = pname;
repo = pname;
# Latest 1.1.0-rc.15 tip
rev = "a5ca8018e3a636dbb0a79b3fd869db059d92979d";
hash = "sha256-PFGoeGn7a/lVR6rOmOKA3ydAoo3/+9RlkwBAKS22Psg=";
}) + "/pykanidm";
src =
(fetchFromGitHub {
owner = pname;
repo = pname;
# Latest 1.1.0-rc.15 tip
rev = "a5ca8018e3a636dbb0a79b3fd869db059d92979d";
hash = "sha256-PFGoeGn7a/lVR6rOmOKA3ydAoo3/+9RlkwBAKS22Psg=";
})
+ "/pykanidm";
nativeBuildInputs = with python3.pkgs; [ poetry-core ];
propagatedBuildInputs = with python3.pkgs; [ aiohttp pydantic toml (authlib.overridePythonAttrs (_: { doCheck = false; })) ];
propagatedBuildInputs = with python3.pkgs; [
aiohttp
pydantic
toml
(authlib.overridePythonAttrs (_: { doCheck = false; }))
];
doCheck = false;
@ -29,6 +42,9 @@ in python3.pkgs.buildPythonPackage {
description = "Kanidm client library";
homepage = "https://github.com/kanidm/kanidm/tree/master/pykanidm";
license = licenses.mpl20;
maintainers = with maintainers; [ arianvp hexa ];
maintainers = with maintainers; [
arianvp
hexa
];
};
}

View File

@ -5,8 +5,16 @@ let
callPackage = lib.callPackageWith (pkgs // pkgs.python3.pkgs // self);
self = builtins.listToAttrs (builtins.map (name: {
inherit name;
value = callPackage (./. + "/${name}.nix") { };
}) [ "pydantic" "pydantic-core" ]);
in self
self = builtins.listToAttrs (
builtins.map
(name: {
inherit name;
value = callPackage (./. + "/${name}.nix") { };
})
[
"pydantic"
"pydantic-core"
]
);
in
self

View File

@ -1,17 +1,18 @@
{ stdenv
, lib
, buildPythonPackage
, fetchFromGitHub
, cargo
, rustPlatform
, rustc
, libiconv
, typing-extensions
, pytestCheckHook
, hypothesis
, pytest-timeout
, pytest-mock
, dirty-equals
{
stdenv,
lib,
buildPythonPackage,
fetchFromGitHub,
cargo,
rustPlatform,
rustc,
libiconv,
typing-extensions,
pytestCheckHook,
hypothesis,
pytest-timeout,
pytest-mock,
dirty-equals,
}:
let
@ -27,9 +28,7 @@ let
hash = "sha256-UguZpA3KEutOgIavjx8Ie//0qJq+4FTZNQTwb/ZIgb8=";
};
patches = [
./01-remove-benchmark-flags.patch
];
patches = [ ./01-remove-benchmark-flags.patch ];
cargoDeps = rustPlatform.fetchCargoTarball {
inherit src;
@ -45,13 +44,9 @@ let
typing-extensions
];
buildInputs = lib.optionals stdenv.isDarwin [
libiconv
];
buildInputs = lib.optionals stdenv.isDarwin [ libiconv ];
propagatedBuildInputs = [
typing-extensions
];
propagatedBuildInputs = [ typing-extensions ];
pythonImportsCheck = [ "pydantic_core" ];
@ -85,4 +80,5 @@ let
maintainers = with maintainers; [ blaggacao ];
};
};
in pydantic-core
in
pydantic-core

View File

@ -1,27 +1,28 @@
{ lib
, buildPythonPackage
, fetchFromGitHub
, pythonOlder
{
lib,
buildPythonPackage,
fetchFromGitHub,
pythonOlder,
# build-system
, hatchling
, hatch-fancy-pypi-readme
# build-system
hatchling,
hatch-fancy-pypi-readme,
# native dependencies
, libxcrypt
# native dependencies
libxcrypt,
# dependencies
, annotated-types
, pydantic-core
, typing-extensions
# dependencies
annotated-types,
pydantic-core,
typing-extensions,
# tests
, cloudpickle
, email-validator
, dirty-equals
, faker
, pytestCheckHook
, pytest-mock
# tests
cloudpickle,
email-validator,
dirty-equals,
faker,
pytestCheckHook,
pytest-mock,
}:
buildPythonPackage rec {
@ -38,9 +39,7 @@ buildPythonPackage rec {
hash = "sha256-D0gYcyrKVVDhBgV9sCVTkGq/kFmIoT9l0i5bRM1qxzM=";
};
buildInputs = lib.optionals (pythonOlder "3.9") [
libxcrypt
];
buildInputs = lib.optionals (pythonOlder "3.9") [ libxcrypt ];
nativeBuildInputs = [
hatch-fancy-pypi-readme
@ -54,9 +53,7 @@ buildPythonPackage rec {
];
passthru.optional-dependencies = {
email = [
email-validator
];
email = [ email-validator ];
};
nativeCheckInputs = [
@ -93,4 +90,3 @@ buildPythonPackage rec {
maintainers = with maintainers; [ wd15 ];
};
}

View File

@ -1,8 +1,14 @@
{ stdenv, fetchFromGitHub, python3, pykanidm }:
{
stdenv,
fetchFromGitHub,
python3,
pykanidm,
}:
let pythonPath = with python3.pkgs; makePythonPath [ pykanidm ];
in stdenv.mkDerivation rec {
let
pythonPath = with python3.pkgs; makePythonPath [ pykanidm ];
in
stdenv.mkDerivation rec {
pname = "rlm_python";
version = "1.1.0-rc.15";
@ -25,9 +31,15 @@ in stdenv.mkDerivation rec {
cp -R rlm_python/{mods-available,sites-available} $out/etc/raddb/
'';
phases = [ "unpackPhase" "patchPhase" "installPhase" ];
phases = [
"unpackPhase"
"patchPhase"
"installPhase"
];
passthru = { inherit pythonPath; };
passthru = {
inherit pythonPath;
};
preferLocalBuild = true;
}

View File

@ -5,8 +5,16 @@ let
cert = config.security.acme.certs.${domain};
allowedSubDomains = [ "cloud" "git" "videos" "social" "demarches" "netbird" ];
in {
allowedSubDomains = [
"cloud"
"git"
"videos"
"social"
"demarches"
"netbird"
];
in
{
services.kanidm = {
enableServer = true;

View File

@ -7,4 +7,3 @@ lib.setDefault { inherit publicKeys; } [
"kanidm-password_admin"
"kanidm-password_idm_admin"
]

View File

@ -1,7 +1,9 @@
{ config, ... }:
let host = "social.dgnum.eu";
in {
let
host = "social.dgnum.eu";
in
{
services.mastodon = {
enable = true;
@ -9,7 +11,6 @@ in {
smtp = {
# TODO: smtp setup
fromAddress = "social@services.dgnum.eu";
};
streamingProcesses = 4;
@ -38,5 +39,7 @@ in {
extraEnvFiles = [ config.age.secrets."mastodon-extra_env_file".path ];
};
age-secrets.matches."^mastodon-.*$" = { owner = "mastodon"; };
age-secrets.matches."^mastodon-.*$" = {
owner = "mastodon";
};
}

View File

@ -3,7 +3,8 @@
let
host = "cloud.dgnum.eu";
nextcloud-occ = "${config.services.nextcloud.occ}/bin/nextcloud-occ";
in {
in
{
services.nextcloud = {
enable = true;
hostName = host;
@ -102,8 +103,7 @@ in {
image = "collabora/code";
imageFile = pkgs.dockerTools.pullImage {
imageName = "collabora/code";
imageDigest =
"sha256:a8cce07c949aa59cea0a7f1f220266a1a6d886c717c3b5005782baf6f384d645";
imageDigest = "sha256:a8cce07c949aa59cea0a7f1f220266a1a6d886c717c3b5005782baf6f384d645";
sha256 = "sha256-lN6skv62x+x7G7SNOUyZ8W6S/uScrkqE1nbBwwSEWXQ=";
};
ports = [ "9980:9980" ];
@ -111,7 +111,12 @@ in {
domain = "cloud.dgnum.eu";
extra_params = "--o:ssl.enable=false --o:ssl.termination=true --o:remote_font_config.url=https://cloud.dgnum.eu/apps/richdocuments/settings/fonts.json";
};
extraOptions = [ "--cap-add" "MKNOD" "--cap-add" "SYS_ADMIN" ];
extraOptions = [
"--cap-add"
"MKNOD"
"--cap-add"
"SYS_ADMIN"
];
};
};
@ -180,7 +185,9 @@ in {
description = "Generate preview for nextcloud media.";
script = "${nextcloud-occ} preview:pre-generate -vvv";
startAt = "*-*-* 01:00:00 UTC";
serviceConfig = { Restart = "on-failure"; };
serviceConfig = {
Restart = "on-failure";
};
};
nextcloud-cron.path = [ pkgs.perl ];
@ -188,9 +195,13 @@ in {
environment.systemPackages = [ pkgs.ffmpeg_6-headless ];
networking.hosts = { "129.199.146.148" = [ "s3.dgnum.eu" ]; };
networking.hosts = {
"129.199.146.148" = [ "s3.dgnum.eu" ];
};
age-secrets.matches."^nextcloud-.*$" = { owner = "nextcloud"; };
age-secrets.matches."^nextcloud-.*$" = {
owner = "nextcloud";
};
system.activationScripts = {
restart-nextcloud.text = ''

View File

@ -1,7 +1,9 @@
{ config, ... }:
let host = "docs.dgnum.eu";
in {
let
host = "docs.dgnum.eu";
in
{
services.outline = {
enable = true;
@ -27,8 +29,7 @@ in {
userinfoUrl = "https://sso.dgnum.eu/oauth2/openid/outline_dgn/userinfo";
displayName = "DGNum SSO";
clientSecretFile =
config.age.secrets."outline-oidc_client_secret_file".path;
clientSecretFile = config.age.secrets."outline-oidc_client_secret_file".path;
};
defaultLanguage = "fr_FR";
@ -51,5 +52,7 @@ in {
};
};
age-secrets.matches."^outline-.*$" = { owner = "outline"; };
age-secrets.matches."^outline-.*$" = {
owner = "outline";
};
}

View File

@ -1,9 +1,10 @@
{ pkgs, ... }:
let
host = "rstudio.dgnum.eu";
# host = "rstudio.dgnum.eu";
port = 19000;
in {
in
{
services.rstudio-server = {
enable = true;
rserverExtraConfig = ''
@ -11,14 +12,17 @@ in {
'';
package = pkgs.rstudioServerWrapper.override {
packages = with pkgs.rPackages; [ ggplot2 rmarkdown dplyr ];
packages = with pkgs.rPackages; [
ggplot2
rmarkdown
dplyr
];
};
};
users.users.ruser = {
isNormalUser = true;
hashedPassword =
"$6$pTXXVh8NfE.M8VPc$q0fFh3Y7Y0DauLCcZLgJzFciq1wkjoHmO61XpOrZLH3a1M32ZzOMbjx2XMm2QxrUncbx6hGerY/lD8rQ8InS4.";
hashedPassword = "$6$pTXXVh8NfE.M8VPc$q0fFh3Y7Y0DauLCcZLgJzFciq1wkjoHmO61XpOrZLH3a1M32ZzOMbjx2XMm2QxrUncbx6hGerY/lD8rQ8InS4.";
};
dgn-access-control.users.ruser = [ "jemagius" ];

View File

@ -1,7 +1,9 @@
{ config, ... }:
let host = "saml-idp.dgnum.eu";
in {
let
host = "saml-idp.dgnum.eu";
in
{
imports = [ ./module.nix ];
@ -20,8 +22,7 @@ in {
config = {
endpoints.single_sign_on_service = {
"urn:oasis:names:tc:SAML:2.0:bindings:HTTP-POST" = "sso/post";
"urn:oasis:names:tc:SAML:2.0:bindings:HTTP-Redirect" =
"sso/redirect";
"urn:oasis:names:tc:SAML:2.0:bindings:HTTP-Redirect" = "sso/redirect";
};
entityid_endpoint = true;
enable_metadata_reload = false;
@ -32,11 +33,13 @@ in {
url = "https://dgnum.eu";
};
contact_person = [{
contact_type = "technical";
email_address = "mailto:tom.hubrecht@dgnum.eu";
given_name = "Tom Hubrecht";
}];
contact_person = [
{
contact_type = "technical";
email_address = "mailto:tom.hubrecht@dgnum.eu";
given_name = "Tom Hubrecht";
}
];
key_file = "/var/lib/satosa/ssl/key.pem";
cert_file = "/var/lib/satosa/ssl/cert.pem";
@ -50,10 +53,12 @@ in {
endpoints.single_sign_on_service = [ ];
name = "DGNum proxy IdP";
ui_info = {
display_name = [{
lang = "fr";
text = "Service de connexion DGNum";
}];
display_name = [
{
lang = "fr";
text = "Service de connexion DGNum";
}
];
};
name_id_format = [
"urn:oasis:names:tc:SAML:2.0:nameid-format:persistent"
@ -63,9 +68,10 @@ in {
default = {
attribute_restrictions = null;
fail_on_missing_requested = false;
lifetime = { minutes = 15; };
name_form =
"urn:oasis:names:tc:SAML:2.0:attrname-format:uri";
lifetime = {
minutes = 15;
};
name_form = "urn:oasis:names:tc:SAML:2.0:attrname-format:uri";
encrypt_assertion = false;
encrypted_advice_attributes = false;
};
@ -121,12 +127,15 @@ in {
module = "satosa.backends.openid_connect.OpenIDConnectBackend";
name = "kanidm";
config = {
provider_metadata.issuer =
"https://sso.dgnum.eu/oauth2/openid/satosa_dgn/";
provider_metadata.issuer = "https://sso.dgnum.eu/oauth2/openid/satosa_dgn/";
client = {
auth_req_params = {
response_type = "code";
scope = [ "openid" "profile" "email" ];
scope = [
"openid"
"profile"
"email"
];
};
client_metadata = {
client_id = "satosa_dgn";
@ -144,5 +153,7 @@ in {
forceSSL = true;
};
age-secrets.matches."^satosa-.*$" = { owner = "satosa"; };
age-secrets.matches."^satosa-.*$" = {
owner = "satosa";
};
}

View File

@ -1,7 +1,18 @@
{ config, lib, pkgs, ... }:
{
config,
lib,
pkgs,
...
}:
let
inherit (lib) mkDefault mkEnableOption mkIf mkOption types;
inherit (lib)
mkDefault
mkEnableOption
mkIf
mkOption
types
;
yamlFormat = pkgs.formats.yaml { };
@ -9,12 +20,17 @@ let
cfg = config.services.satosa;
mkYamlFiles = files:
builtins.attrValues
(builtins.mapAttrs (name: yamlFormat.generate "${name}.yaml") files);
mkYamlFiles =
files: builtins.attrValues (builtins.mapAttrs (name: yamlFormat.generate "${name}.yaml") files);
pyEnv = cfg.package.python.withPackages (ps: [ cfg.package ps.gunicorn ]);
in {
pyEnv = cfg.package.python.withPackages (
ps: [
cfg.package
ps.gunicorn
]
);
in
{
options.services.satosa = {
enable = mkEnableOption "SATOSA, a SAML and OIDC proxy.";
@ -88,8 +104,7 @@ in {
MICRO_SERVICES = mkYamlFiles cfg.microServices;
LOGGING = {
version = 1;
formatters.simple.format =
"[%(asctime)s] [%(levelname)s] [%(name)s.%(funcName)s] %(message)s";
formatters.simple.format = "[%(asctime)s] [%(levelname)s] [%(name)s.%(funcName)s] %(message)s";
handlers.stdout = {
class = "logging.StreamHandler";
stream = "ext://sys.stdout";
@ -171,7 +186,9 @@ in {
TimeoutStopSec = "5";
EnvironmentFile = lib.optional (cfg.envFile != null) cfg.envFile;
};
environment = { SATOSA_CONFIG = configFile; };
environment = {
SATOSA_CONFIG = configFile;
};
};
};
@ -179,8 +196,7 @@ in {
enable = true;
virtualHosts.${cfg.host} = {
locations."/".proxyPass =
"http://127.0.0.1:${builtins.toString cfg.port}";
locations."/".proxyPass = "http://127.0.0.1:${builtins.toString cfg.port}";
};
};

View File

@ -1,6 +1,7 @@
{ lib
, python3
, fetchPypi
{
lib,
python3,
fetchPypi,
}:
python3.pkgs.buildPythonPackage rec {

View File

@ -13,5 +13,5 @@ let
pydantic = callPackage ./pydantic.nix { };
pydantic-core = callPackage ./pydantic-core.nix { };
};
in self.satosa
in
self.satosa

View File

@ -1,7 +1,8 @@
{ lib
, python3
, fetchPypi
, pydantic-settings
{
lib,
python3,
fetchPypi,
pydantic-settings,
}:
python3.pkgs.buildPythonPackage rec {

View File

@ -1,9 +1,10 @@
{ lib
, python3
, fetchPypi
, cargo
, rustPlatform
, rustc
{
lib,
python3,
fetchPypi,
cargo,
rustPlatform,
rustc,
}:
python3.pkgs.buildPythonPackage rec {
@ -31,9 +32,7 @@ python3.pkgs.buildPythonPackage rec {
rustc
];
propagatedBuildInputs = with python3.pkgs; [
typing-extensions
];
propagatedBuildInputs = with python3.pkgs; [ typing-extensions ];
pythonImportsCheck = [ "pydantic_core" ];

View File

@ -1,7 +1,8 @@
{ lib
, python3
, fetchPypi
, pydantic
{
lib,
python3,
fetchPypi,
pydantic,
}:
python3.pkgs.buildPythonPackage rec {
@ -15,9 +16,7 @@ python3.pkgs.buildPythonPackage rec {
hash = "sha256-li3DZySVqtaulqQ5D6x+WTWR4URiXlES01n49n+3WUU=";
};
nativeBuildInputs = [
python3.pkgs.hatchling
];
nativeBuildInputs = [ python3.pkgs.hatchling ];
propagatedBuildInputs = with python3.pkgs; [
pydantic

View File

@ -1,7 +1,8 @@
{ lib
, python3
, fetchPypi
, pydantic-core
{
lib,
python3,
fetchPypi,
pydantic-core,
}:
python3.pkgs.buildPythonPackage rec {
@ -26,9 +27,7 @@ python3.pkgs.buildPythonPackage rec {
];
passthru.optional-dependencies = with python3.pkgs; {
email = [
email-validator
];
email = [ email-validator ];
};
pythonImportsCheck = [ "pydantic" ];

View File

@ -1,7 +1,8 @@
{ lib
, python3
, fetchPypi
, oic
{
lib,
python3,
fetchPypi,
oic,
}:
python3.pkgs.buildPythonPackage rec {

View File

@ -1,8 +1,9 @@
{ lib
, python3
, fetchPypi
, cookies-samesite-compat
, pyop
{
lib,
python3,
fetchPypi,
cookies-samesite-compat,
pyop,
}:
python3.pkgs.buildPythonPackage rec {
@ -36,15 +37,9 @@ python3.pkgs.buildPythonPackage rec {
];
passthru.optional-dependencies = with python3.pkgs; {
ldap = [
ldap3
];
pyop_mongo = [
pyop
];
pyop_redis = [
pyop
];
ldap = [ ldap3 ];
pyop_mongo = [ pyop ];
pyop_redis = [ pyop ];
};
passthru.python = python3;

View File

@ -1,8 +1,9 @@
{ config, ... }:
let host = "pass.dgnum.eu";
in {
let
host = "pass.dgnum.eu";
in
{
services.vaultwarden = {
enable = true;
@ -62,10 +63,12 @@ in {
ensureDatabases = [ "vaultwarden" ];
ensureUsers = [{
name = "vaultwarden";
ensureDBOwnership = true;
}];
ensureUsers = [
{
name = "vaultwarden";
ensureDBOwnership = true;
}
];
};
};
}

View File

@ -5,7 +5,8 @@ let
port = 3005;
websocketPort = 6902;
in {
in
{
services.zammad = {
enable = true;
@ -38,10 +39,9 @@ in {
proxyWebsockets = true;
};
"~ ^/(assets/|robots.txt|humans.txt|favicon.ico|apple-touch-icon.png)".extraConfig =
''
expires max;
'';
"~ ^/(assets/|robots.txt|humans.txt|favicon.ico|apple-touch-icon.png)".extraConfig = ''
expires max;
'';
};
extraConfig = ''
@ -51,5 +51,7 @@ in {
};
};
age-secrets.matches."^zammad-.*$" = { owner = "zammad"; };
age-secrets.matches."^zammad-.*$" = {
owner = "zammad";
};
}

View File

@ -29,6 +29,5 @@
fsType = "vfat";
};
swapDevices =
[{ device = "/dev/disk/by-uuid/65a6f6e4-e996-4718-a4d0-cd0c78dcb15b"; }];
swapDevices = [ { device = "/dev/disk/by-uuid/65a6f6e4-e996-4718-a4d0-cd0c78dcb15b"; } ];
}

View File

@ -1,8 +1,14 @@
{ config, pkgs, sources, ... }:
{
config,
pkgs,
sources,
...
}:
let host = "cachix.dgnum.eu";
in {
let
host = "cachix.dgnum.eu";
in
{
services = {
atticd = {
enable = true;
@ -68,10 +74,12 @@ in {
ensureDatabases = [ "atticd" ];
ensureUsers = [{
name = "atticd";
ensureDBOwnership = true;
}];
ensureUsers = [
{
name = "atticd";
ensureDBOwnership = true;
}
];
};
};
}

View File

@ -3,18 +3,29 @@
let
url = "https://git.dgnum.eu";
mkRunner = { labels, name, token }: {
enable = true;
mkRunner =
{
labels,
name,
token,
}:
{
enable = true;
inherit name labels token url;
inherit
name
labels
token
url
;
settings.container = {
network = "host";
options = "--cpus=4";
settings.container = {
network = "host";
options = "--cpus=4";
};
};
};
in {
in
{
services.forgejo-nix-runners = {
enable = true;
@ -23,7 +34,11 @@ in {
storePath = "/data/slow/nix";
tokenFile = config.age.secrets."forgejo_runners-token_file".path;
dependencies = [ pkgs.colmena pkgs.npins pkgs.tea ];
dependencies = [
pkgs.colmena
pkgs.npins
pkgs.tea
];
containerOptions = [ "--cpus=4" ];

View File

@ -3,7 +3,8 @@
let
port = 3000;
host = "git.dgnum.eu";
in {
in
{
services = {
forgejo = {
enable = true;
@ -19,7 +20,9 @@ in {
};
settings = {
DEFAULT = { APP_NAME = "Forge git de la DGNum"; };
DEFAULT = {
APP_NAME = "Forge git de la DGNum";
};
server = {
ROOT_URL = "https://${host}/";
@ -62,7 +65,9 @@ in {
virtualHosts.${host} = {
enableACME = true;
forceSSL = true;
locations."/" = { proxyPass = "http://127.0.0.1:${toString port}"; };
locations."/" = {
proxyPass = "http://127.0.0.1:${toString port}";
};
};
};
};
@ -77,5 +82,7 @@ in {
users.groups.git = { };
age-secrets.matches."^forgejo-.*$" = { owner = "git"; };
age-secrets.matches."^forgejo-.*$" = {
owner = "git";
};
}

View File

@ -8,20 +8,22 @@ let
metadata_dir = "/data/fast/garage/meta";
buckets = [ "peertube-videos-dgnum" ];
in {
in
{
services.garage = {
enable = true;
package = pkgs.garage_0_9.overrideAttrs (old: {
patches = (old.patches or [ ]) ++ [
# Allow 0 as a part number marker
(pkgs.fetchpatch {
url = "https://git.deuxfleurs.fr/Deuxfleurs/garage/pulls/670.patch";
hash = "sha256-28ctLl1qscMRj2JEVnmhuLyK1Avub8QeyfQFxAK0y08=";
})
];
});
package = pkgs.garage_0_9.overrideAttrs (
old: {
patches = (old.patches or [ ]) ++ [
# Allow 0 as a part number marker
(pkgs.fetchpatch {
url = "https://git.deuxfleurs.fr/Deuxfleurs/garage/pulls/670.patch";
hash = "sha256-28ctLl1qscMRj2JEVnmhuLyK1Avub8QeyfQFxAK0y08=";
})
];
}
);
settings = {
inherit data_dir metadata_dir;
@ -56,7 +58,10 @@ in {
systemd.services.garage.serviceConfig = {
User = "garage";
ReadWriteDirectories = [ data_dir metadata_dir ];
ReadWriteDirectories = [
data_dir
metadata_dir
];
};
users.users.garage = {

View File

@ -1,8 +1,24 @@
{ config, lib, pkgs, ... }:
{
config,
lib,
pkgs,
...
}:
let
inherit (lib)
filterAttrs literalExpression maintainers mkDefault mkEnableOption mkIf
mkMerge mkOption optionalAttrs optionalString optionals types;
filterAttrs
literalExpression
maintainers
mkDefault
mkEnableOption
mkIf
mkMerge
mkOption
optionalAttrs
optionalString
optionals
types
;
inherit ((import ./package { inherit pkgs; })) dashboard;
@ -13,92 +29,100 @@ let
settingsFormat = pkgs.formats.keyValue { };
managementFormat = pkgs.formats.json { };
settingsFile = settingsFormat.generate "setup.env" (builtins.mapAttrs (_: val:
if builtins.isList val then
''"${builtins.concatStringsSep " " val}"''
else
val) settings);
settingsFile = settingsFormat.generate "setup.env" (
builtins.mapAttrs
(_: val: if builtins.isList val then ''"${builtins.concatStringsSep " " val}"'' else val)
settings
);
managementFile = managementFormat.generate "config.json" cfg.managementConfig;
settings = rec {
TURN_DOMAIN = cfg.settings.NETBIRD_DOMAIN;
TURN_PORT = 3478;
TURN_USER = "netbird";
TURN_MIN_PORT = 49152;
TURN_MAX_PORT = 65535;
TURN_PASSWORD =
if cfg.secretFiles.TURN_PASSWORD != null then "$TURN_PASSWORD" else null;
TURN_SECRET =
if cfg.secretFiles.TURN_SECRET != null then "$TURN_SECRET" else "secret";
settings =
rec {
TURN_DOMAIN = cfg.settings.NETBIRD_DOMAIN;
TURN_PORT = 3478;
TURN_USER = "netbird";
TURN_MIN_PORT = 49152;
TURN_MAX_PORT = 65535;
TURN_PASSWORD = if cfg.secretFiles.TURN_PASSWORD != null then "$TURN_PASSWORD" else null;
TURN_SECRET = if cfg.secretFiles.TURN_SECRET != null then "$TURN_SECRET" else "secret";
STUN_USERNAME = "";
STUN_PASSWORD =
if cfg.secretFiles.STUN_PASSWORD != null then "$STUN_PASSWORD" else null;
STUN_USERNAME = "";
STUN_PASSWORD = if cfg.secretFiles.STUN_PASSWORD != null then "$STUN_PASSWORD" else null;
NETBIRD_DASHBOARD_ENDPOINT = "https://${cfg.settings.NETBIRD_DOMAIN}:443";
NETBIRD_MGMT_API_ENDPOINT = "https://${cfg.settings.NETBIRD_DOMAIN}:${
builtins.toString
cfg.settings.NETBIRD_MGMT_API_PORT or NETBIRD_MGMT_API_PORT
NETBIRD_DASHBOARD_ENDPOINT = "https://${cfg.settings.NETBIRD_DOMAIN}:443";
NETBIRD_MGMT_API_ENDPOINT = "https://${cfg.settings.NETBIRD_DOMAIN}:${
builtins.toString cfg.settings.NETBIRD_MGMT_API_PORT or NETBIRD_MGMT_API_PORT
}";
NETBIRD_SIGNAL_ENDPOINT = "https://${cfg.settings.NETBIRD_DOMAIN}:${
builtins.toString
cfg.settings.NETBIRD_SIGNAL_PORT or NETBIRD_SIGNAL_PORT
NETBIRD_SIGNAL_ENDPOINT = "https://${cfg.settings.NETBIRD_DOMAIN}:${
builtins.toString cfg.settings.NETBIRD_SIGNAL_PORT or NETBIRD_SIGNAL_PORT
}";
NETBIRD_SIGNAL_PROTOCOL = "https";
NETBIRD_SIGNAL_PORT = 443;
NETBIRD_SIGNAL_PROTOCOL = "https";
NETBIRD_SIGNAL_PORT = 443;
NETBIRD_AUTH_USER_ID_CLAIM = "sub";
NETBIRD_AUTH_CLIENT_SECRET =
if cfg.secretFiles.AUTH_CLIENT_SECRET != null then
"$AUTH_CLIENT_SECRET"
else
"";
NETBIRD_AUTH_SUPPORTED_SCOPES =
[ "openid" "profile" "email" "offline_access" "api" ];
NETBIRD_AUTH_USER_ID_CLAIM = "sub";
NETBIRD_AUTH_CLIENT_SECRET =
if cfg.secretFiles.AUTH_CLIENT_SECRET != null then "$AUTH_CLIENT_SECRET" else "";
NETBIRD_AUTH_SUPPORTED_SCOPES = [
"openid"
"profile"
"email"
"offline_access"
"api"
];
NETBIRD_AUTH_REDIRECT_URI = "";
NETBIRD_AUTH_SILENT_REDIRECT_URI = "";
NETBIRD_AUTH_REDIRECT_URI = "";
NETBIRD_AUTH_SILENT_REDIRECT_URI = "";
NETBIRD_AUTH_DEVICE_AUTH_PROVIDER = "none";
NETBIRD_AUTH_DEVICE_AUTH_CLIENT_ID = cfg.settings.NETBIRD_AUTH_CLIENT_ID;
NETBIRD_AUTH_DEVICE_AUTH_AUDIENCE = cfg.settings.NETBIRD_AUTH_AUDIENCE;
NETBIRD_AUTH_DEVICE_AUTH_SCOPE =
[ "openid" "profile" "email" "offline_access" "api" ];
NETBIRD_AUTH_DEVICE_AUTH_USE_ID_TOKEN = false;
NETBIRD_AUTH_DEVICE_AUTH_PROVIDER = "none";
NETBIRD_AUTH_DEVICE_AUTH_CLIENT_ID = cfg.settings.NETBIRD_AUTH_CLIENT_ID;
NETBIRD_AUTH_DEVICE_AUTH_AUDIENCE = cfg.settings.NETBIRD_AUTH_AUDIENCE;
NETBIRD_AUTH_DEVICE_AUTH_SCOPE = [
"openid"
"profile"
"email"
"offline_access"
"api"
];
NETBIRD_AUTH_DEVICE_AUTH_USE_ID_TOKEN = false;
NETBIRD_MGMT_API_PORT = 443;
NETBIRD_MGMT_API_PORT = 443;
NETBIRD_MGMT_IDP = "none";
NETBIRD_IDP_MGMT_CLIENT_ID = cfg.settings.NETBIRD_AUTH_CLIENT_ID;
NETBIRD_IDP_MGMT_CLIENT_SECRET =
if cfg.secretFiles.IDP_MGMT_CLIENT_SECRET != null then
"$IDP_MGMT_CLIENT_SECRET"
else
cfg.settings.NETBIRD_AUTH_CLIENT_SECRET;
NETBIRD_IDP_MGMT_GRANT_TYPE = "client_credentials";
NETBIRD_MGMT_IDP = "none";
NETBIRD_IDP_MGMT_CLIENT_ID = cfg.settings.NETBIRD_AUTH_CLIENT_ID;
NETBIRD_IDP_MGMT_CLIENT_SECRET =
if cfg.secretFiles.IDP_MGMT_CLIENT_SECRET != null then
"$IDP_MGMT_CLIENT_SECRET"
else
cfg.settings.NETBIRD_AUTH_CLIENT_SECRET;
NETBIRD_IDP_MGMT_GRANT_TYPE = "client_credentials";
NETBIRD_TOKEN_SOURCE = "accessToken";
NETBIRD_DRAG_QUERY_PARAMS = false;
NETBIRD_TOKEN_SOURCE = "accessToken";
NETBIRD_DRAG_QUERY_PARAMS = false;
NETBIRD_USE_AUTH0 = false;
NETBIRD_USE_AUTH0 = false;
NETBIRD_AUTH_DEVICE_AUTH_ENDPOINT = "";
NETBIRD_AUTH_DEVICE_AUTH_ENDPOINT = "";
NETBIRD_AUTH_PKCE_REDIRECT_URL_PORTS = [ "53000" ];
NETBIRD_AUTH_PKCE_REDIRECT_URLS = builtins.map (p: "http://localhost:${p}")
cfg.settings.NETBIRD_AUTH_PKCE_REDIRECT_URL_PORTS or NETBIRD_AUTH_PKCE_REDIRECT_URL_PORTS;
} // (optionalAttrs cfg.setupAutoOidc {
NETBIRD_AUTH_PKCE_AUTHORIZATION_ENDPOINT =
"$NETBIRD_AUTH_PKCE_AUTHORIZATION_ENDPOINT";
NETBIRD_AUTH_DEVICE_AUTH_ENDPOINT = "$NETBIRD_AUTH_DEVICE_AUTH_ENDPOINT";
NETBIRD_AUTH_TOKEN_ENDPOINT = "$NETBIRD_AUTH_TOKEN_ENDPOINT";
NETBIRD_AUTH_JWT_CERTS = "$NETBIRD_AUTH_JWT_CERTS";
NETBIRD_AUTH_AUTHORITY = "$NETBIRD_AUTH_AUTHORITY";
}) // cfg.settings;
in {
meta = { maintainers = with maintainers; [ thubrecht ]; };
NETBIRD_AUTH_PKCE_REDIRECT_URL_PORTS = [ "53000" ];
NETBIRD_AUTH_PKCE_REDIRECT_URLS =
builtins.map (p: "http://localhost:${p}")
cfg.settings.NETBIRD_AUTH_PKCE_REDIRECT_URL_PORTS or NETBIRD_AUTH_PKCE_REDIRECT_URL_PORTS;
}
// (optionalAttrs cfg.setupAutoOidc {
NETBIRD_AUTH_PKCE_AUTHORIZATION_ENDPOINT = "$NETBIRD_AUTH_PKCE_AUTHORIZATION_ENDPOINT";
NETBIRD_AUTH_DEVICE_AUTH_ENDPOINT = "$NETBIRD_AUTH_DEVICE_AUTH_ENDPOINT";
NETBIRD_AUTH_TOKEN_ENDPOINT = "$NETBIRD_AUTH_TOKEN_ENDPOINT";
NETBIRD_AUTH_JWT_CERTS = "$NETBIRD_AUTH_JWT_CERTS";
NETBIRD_AUTH_AUTHORITY = "$NETBIRD_AUTH_AUTHORITY";
})
// cfg.settings;
in
{
meta = {
maintainers = with maintainers; [ thubrecht ];
};
options.services.netbird-server = {
enable = mkEnableOption (lib.mdDoc "netbird management service.");
@ -111,8 +135,19 @@ in {
};
settings = mkOption {
type = with types;
attrsOf (nullOr (oneOf [ (listOf str) bool int float str ]));
type =
with types;
attrsOf (
nullOr (
oneOf [
(listOf str)
bool
int
float
str
]
)
);
defaultText = lib.literalExpression ''
{
TURN_DOMAIN = cfg.settings.NETBIRD_DOMAIN;
@ -195,15 +230,19 @@ in {
};
logLevel = mkOption {
type = types.enum [ "ERROR" "WARN" "INFO" "DEBUG" ];
type = types.enum [
"ERROR"
"WARN"
"INFO"
"DEBUG"
];
default = "INFO";
description = lib.mdDoc "Log level of the netbird services.";
};
enableDeviceAuthorizationFlow =
mkEnableOption "device authorization flow for netbird." // {
default = true;
};
enableDeviceAuthorizationFlow = mkEnableOption "device authorization flow for netbird." // {
default = true;
};
enableNginx = mkEnableOption "NGINX reverse-proxy for the netbird server.";
@ -232,8 +271,7 @@ in {
disableAnonymousMetrics = mkOption {
type = types.bool;
default = true;
description =
lib.mdDoc "Disables push of anonymous usage metrics to NetBird.";
description = lib.mdDoc "Disables push of anonymous usage metrics to NetBird.";
};
disableSingleAccountMode = mkOption {
@ -250,38 +288,32 @@ in {
TURN_PASSWORD = mkOption {
type = with types; nullOr path;
default = null;
description =
lib.mdDoc "Path to a file containing the secret TURN_PASSWORD.";
description = lib.mdDoc "Path to a file containing the secret TURN_PASSWORD.";
};
TURN_SECRET = mkOption {
type = with types; nullOr path;
default = null;
description =
lib.mdDoc "Path to a file containing the secret TURN_SECRET.";
description = lib.mdDoc "Path to a file containing the secret TURN_SECRET.";
};
STUN_PASSWORD = mkOption {
type = with types; nullOr path;
default = null;
description =
lib.mdDoc "Path to a file containing the secret STUN_PASSWORD.";
description = lib.mdDoc "Path to a file containing the secret STUN_PASSWORD.";
};
AUTH_CLIENT_SECRET = mkOption {
type = with types; nullOr path;
default = null;
description = lib.mdDoc
"Path to a file containing the secret NETBIRD_AUTH_CLIENT_SECRET.";
description = lib.mdDoc "Path to a file containing the secret NETBIRD_AUTH_CLIENT_SECRET.";
};
IDP_MGMT_CLIENT_SECRET = mkOption {
type = with types; nullOr path;
default = cfg.secretFiles.AUTH_CLIENT_SECRET;
defaultText =
lib.literalExpression "cfg.secretFiles.AUTH_CLIENT_SECRET;";
description = lib.mdDoc
"Path to a file containing the secret NETBIRD_IDP_MGMT_CLIENT_SECRET.";
defaultText = lib.literalExpression "cfg.secretFiles.AUTH_CLIENT_SECRET;";
description = lib.mdDoc "Path to a file containing the secret NETBIRD_IDP_MGMT_CLIENT_SECRET.";
};
};
};
@ -289,19 +321,23 @@ in {
config = mkMerge [
(mkIf cfg.enable {
services.netbird-server.managementConfig = with settings; {
Stuns = mkDefault [{
Proto = "udp";
URI = "stun:${TURN_DOMAIN}:${builtins.toString TURN_PORT}";
Username = STUN_USERNAME;
Password = STUN_PASSWORD;
}];
TURNConfig = {
Turns = [{
Stuns = mkDefault [
{
Proto = "udp";
URI = "turn:${TURN_DOMAIN}:${builtins.toString TURN_PORT}";
Username = TURN_USER;
Password = TURN_PASSWORD;
}];
URI = "stun:${TURN_DOMAIN}:${builtins.toString TURN_PORT}";
Username = STUN_USERNAME;
Password = STUN_PASSWORD;
}
];
TURNConfig = {
Turns = [
{
Proto = "udp";
URI = "turn:${TURN_DOMAIN}:${builtins.toString TURN_PORT}";
Username = TURN_USER;
Password = TURN_PASSWORD;
}
];
CredentialsTTL = "12h";
Secret = TURN_SECRET;
TimeBasedCredentials = false;
@ -340,8 +376,7 @@ in {
ClientID = NETBIRD_AUTH_DEVICE_AUTH_CLIENT_ID;
TokenEndpoint = NETBIRD_AUTH_TOKEN_ENDPOINT;
DeviceAuthEndpoint = NETBIRD_AUTH_DEVICE_AUTH_ENDPOINT;
Scope =
builtins.concatStringsSep " " NETBIRD_AUTH_DEVICE_AUTH_SCOPE;
Scope = builtins.concatStringsSep " " NETBIRD_AUTH_DEVICE_AUTH_SCOPE;
UseIDToken = NETBIRD_AUTH_DEVICE_AUTH_USE_ID_TOKEN;
};
};
@ -377,13 +412,10 @@ in {
grpc_socket_keepalive on;
'';
"/api".proxyPass =
"http://localhost:${builtins.toString cfg.ports.management}";
"/api".proxyPass = "http://localhost:${builtins.toString cfg.ports.management}";
"/management.ManagementService/".extraConfig = ''
grpc_pass grpc://localhost:${
builtins.toString cfg.ports.management
};
grpc_pass grpc://localhost:${builtins.toString cfg.ports.management};
grpc_read_timeout 1d;
grpc_send_timeout 1d;
grpc_socket_keepalive on;
@ -411,59 +443,81 @@ in {
StartLimitBurst = 10;
};
path = (with pkgs; [ coreutils findutils gettext gnused ])
++ (optionals cfg.setupAutoOidc (with pkgs; [ curl jq ]));
path =
(with pkgs; [
coreutils
findutils
gettext
gnused
])
++ (optionals cfg.setupAutoOidc (
with pkgs;
[
curl
jq
]
));
script = ''
cp ${managementFile} ${stateDir}/management.json.copy
'' + (optionalString cfg.setupAutoOidc ''
mv ${stateDir}/management.json.copy ${stateDir}/management.json
echo "loading OpenID configuration from $NETBIRD_AUTH_OIDC_CONFIGURATION_ENDPOINT to the openid-configuration.json file"
curl "$NETBIRD_AUTH_OIDC_CONFIGURATION_ENDPOINT" -q -o ${stateDir}/openid-configuration.json
script =
''
cp ${managementFile} ${stateDir}/management.json.copy
''
+ (optionalString cfg.setupAutoOidc ''
mv ${stateDir}/management.json.copy ${stateDir}/management.json
echo "loading OpenID configuration from $NETBIRD_AUTH_OIDC_CONFIGURATION_ENDPOINT to the openid-configuration.json file"
curl "$NETBIRD_AUTH_OIDC_CONFIGURATION_ENDPOINT" -q -o ${stateDir}/openid-configuration.json
export NETBIRD_AUTH_AUTHORITY=$(jq -r '.issuer' ${stateDir}/openid-configuration.json)
export NETBIRD_AUTH_JWT_CERTS=$(jq -r '.jwks_uri' ${stateDir}/openid-configuration.json)
export NETBIRD_AUTH_TOKEN_ENDPOINT=$(jq -r '.token_endpoint' ${stateDir}/openid-configuration.json)
export NETBIRD_AUTH_DEVICE_AUTH_ENDPOINT=$(jq -r '.device_authorization_endpoint' ${stateDir}/openid-configuration.json)
export NETBIRD_AUTH_PKCE_AUTHORIZATION_ENDPOINT=$(jq -r '.authorization_endpoint' ${stateDir}/openid-configuration.json)
export NETBIRD_AUTH_AUTHORITY=$(jq -r '.issuer' ${stateDir}/openid-configuration.json)
export NETBIRD_AUTH_JWT_CERTS=$(jq -r '.jwks_uri' ${stateDir}/openid-configuration.json)
export NETBIRD_AUTH_TOKEN_ENDPOINT=$(jq -r '.token_endpoint' ${stateDir}/openid-configuration.json)
export NETBIRD_AUTH_DEVICE_AUTH_ENDPOINT=$(jq -r '.device_authorization_endpoint' ${stateDir}/openid-configuration.json)
export NETBIRD_AUTH_PKCE_AUTHORIZATION_ENDPOINT=$(jq -r '.authorization_endpoint' ${stateDir}/openid-configuration.json)
envsubst '$NETBIRD_AUTH_AUTHORITY $NETBIRD_AUTH_JWT_CERTS $NETBIRD_AUTH_TOKEN_ENDPOINT $NETBIRD_AUTH_DEVICE_AUTH_ENDPOINT $NETBIRD_AUTH_PKCE_AUTHORIZATION_ENDPOINT' < ${stateDir}/management.json > ${stateDir}/management.json.copy
'') + ''
# Update secrets in management.json
${builtins.concatStringsSep "\n" (builtins.attrValues
(builtins.mapAttrs (name: path: "export ${name}=$(cat ${path})")
(filterAttrs (_: p: p != null) cfg.secretFiles)))}
envsubst '$NETBIRD_AUTH_AUTHORITY $NETBIRD_AUTH_JWT_CERTS $NETBIRD_AUTH_TOKEN_ENDPOINT $NETBIRD_AUTH_DEVICE_AUTH_ENDPOINT $NETBIRD_AUTH_PKCE_AUTHORIZATION_ENDPOINT' < ${stateDir}/management.json > ${stateDir}/management.json.copy
'')
+ ''
# Update secrets in management.json
${builtins.concatStringsSep "\n" (
builtins.attrValues (
builtins.mapAttrs (name: path: "export ${name}=$(cat ${path})") (
filterAttrs (_: p: p != null) cfg.secretFiles
)
)
)}
envsubst '$TURN_PASSWORD $TURN_SECRET $STUN_PASSWORD $AUTH_CLIENT_SECRET $IDP_MGMT_CLIENT_SECRET' < ${stateDir}/management.json.copy > ${stateDir}/management.json
envsubst '$TURN_PASSWORD $TURN_SECRET $STUN_PASSWORD $AUTH_CLIENT_SECRET $IDP_MGMT_CLIENT_SECRET' < ${stateDir}/management.json.copy > ${stateDir}/management.json
rm -rf ${stateDir}/web-ui
mkdir -p ${stateDir}/web-ui
cp -R ${dashboard}/* ${stateDir}/web-ui
rm -rf ${stateDir}/web-ui
mkdir -p ${stateDir}/web-ui
cp -R ${dashboard}/* ${stateDir}/web-ui
export AUTH_AUTHORITY="$NETBIRD_AUTH_AUTHORITY"
export AUTH_CLIENT_ID="$NETBIRD_AUTH_CLIENT_ID"
${optionalString (cfg.secretFiles.AUTH_CLIENT_SECRET == null)
''export AUTH_CLIENT_SECRET="$NETBIRD_AUTH_CLIENT_SECRET"''}
export AUTH_AUDIENCE="$NETBIRD_AUTH_AUDIENCE"
export AUTH_REDIRECT_URI="$NETBIRD_AUTH_REDIRECT_URI"
export AUTH_SILENT_REDIRECT_URI="$NETBIRD_AUTH_SILENT_REDIRECT_URI"
export USE_AUTH0="$NETBIRD_USE_AUTH0"
export AUTH_SUPPORTED_SCOPES=$(echo $NETBIRD_AUTH_SUPPORTED_SCOPES | sed -E 's/"//g')
export AUTH_AUTHORITY="$NETBIRD_AUTH_AUTHORITY"
export AUTH_CLIENT_ID="$NETBIRD_AUTH_CLIENT_ID"
${optionalString (cfg.secretFiles.AUTH_CLIENT_SECRET == null)
''export AUTH_CLIENT_SECRET="$NETBIRD_AUTH_CLIENT_SECRET"''}
export AUTH_AUDIENCE="$NETBIRD_AUTH_AUDIENCE"
export AUTH_REDIRECT_URI="$NETBIRD_AUTH_REDIRECT_URI"
export AUTH_SILENT_REDIRECT_URI="$NETBIRD_AUTH_SILENT_REDIRECT_URI"
export USE_AUTH0="$NETBIRD_USE_AUTH0"
export AUTH_SUPPORTED_SCOPES=$(echo $NETBIRD_AUTH_SUPPORTED_SCOPES | sed -E 's/"//g')
export NETBIRD_MGMT_API_ENDPOINT=$(echo $NETBIRD_MGMT_API_ENDPOINT | sed -E 's/(:80|:443)$//')
export NETBIRD_MGMT_API_ENDPOINT=$(echo $NETBIRD_MGMT_API_ENDPOINT | sed -E 's/(:80|:443)$//')
MAIN_JS=$(find ${stateDir}/web-ui/static/js/main.*js)
OIDC_TRUSTED_DOMAINS=${stateDir}/web-ui/OidcTrustedDomains.js
mv "$MAIN_JS" "$MAIN_JS".copy
envsubst '$USE_AUTH0 $AUTH_AUTHORITY $AUTH_CLIENT_ID $AUTH_CLIENT_SECRET $AUTH_SUPPORTED_SCOPES $AUTH_AUDIENCE $NETBIRD_MGMT_API_ENDPOINT $NETBIRD_MGMT_GRPC_API_ENDPOINT $NETBIRD_HOTJAR_TRACK_ID $AUTH_REDIRECT_URI $AUTH_SILENT_REDIRECT_URI $NETBIRD_TOKEN_SOURCE $NETBIRD_DRAG_QUERY_PARAMS' < "$MAIN_JS".copy > "$MAIN_JS"
envsubst '$NETBIRD_MGMT_API_ENDPOINT' < "$OIDC_TRUSTED_DOMAINS".tmpl > "$OIDC_TRUSTED_DOMAINS"
'';
MAIN_JS=$(find ${stateDir}/web-ui/static/js/main.*js)
OIDC_TRUSTED_DOMAINS=${stateDir}/web-ui/OidcTrustedDomains.js
mv "$MAIN_JS" "$MAIN_JS".copy
envsubst '$USE_AUTH0 $AUTH_AUTHORITY $AUTH_CLIENT_ID $AUTH_CLIENT_SECRET $AUTH_SUPPORTED_SCOPES $AUTH_AUDIENCE $NETBIRD_MGMT_API_ENDPOINT $NETBIRD_MGMT_GRPC_API_ENDPOINT $NETBIRD_HOTJAR_TRACK_ID $AUTH_REDIRECT_URI $AUTH_SILENT_REDIRECT_URI $NETBIRD_TOKEN_SOURCE $NETBIRD_DRAG_QUERY_PARAMS' < "$MAIN_JS".copy > "$MAIN_JS"
envsubst '$NETBIRD_MGMT_API_ENDPOINT' < "$OIDC_TRUSTED_DOMAINS".tmpl > "$OIDC_TRUSTED_DOMAINS"
'';
};
netbird-signal = {
after = [ "network.target" ];
wantedBy = [ "netbird-management.service" ];
restartTriggers = [ settingsFile managementFile ];
restartTriggers = [
settingsFile
managementFile
];
serviceConfig = {
ExecStart = ''
@ -487,24 +541,27 @@ in {
netbird-management = {
description = "The management server for Netbird, a wireguard VPN";
documentation = [ "https://netbird.io/docs/" ];
after = [ "network.target" "netbird-setup.service" ];
after = [
"network.target"
"netbird-setup.service"
];
wantedBy = [ "multi-user.target" ];
wants = [ "netbird-signal.service" "netbird-setup.service" ];
restartTriggers = [ settingsFile managementFile ];
wants = [
"netbird-signal.service"
"netbird-setup.service"
];
restartTriggers = [
settingsFile
managementFile
];
serviceConfig = {
ExecStart = ''
${cfg.package}/bin/netbird-mgmt management \
--config ${stateDir}/management.json \
--datadir ${stateDir}/data \
${
optionalString cfg.management.disableAnonymousMetrics
"--disable-anonymous-metrics"
} \
${
optionalString cfg.management.disableSingleAccountMode
"--disable-single-account-mode"
} \
${optionalString cfg.management.disableAnonymousMetrics "--disable-anonymous-metrics"} \
${optionalString cfg.management.disableSingleAccountMode "--disable-single-account-mode"} \
--dns-domain ${cfg.management.dnsDomain} \
--single-account-mode-domain ${cfg.management.singleAccountModeDomain} \
--idp-sign-key-refresh-enabled \
@ -514,7 +571,10 @@ in {
'';
Restart = "always";
RuntimeDirectory = "netbird-mgmt";
StateDirectory = [ "netbird-mgmt" "netbird-mgmt/data" ];
StateDirectory = [
"netbird-mgmt"
"netbird-mgmt/data"
];
WorkingDirectory = stateDir;
};
unitConfig = {
@ -549,18 +609,25 @@ in {
5349
5350
];
allowedTCPPorts = with settings; [ TURN_PORT (TURN_PORT + 1) ];
allowedUDPPortRanges = [{
from = settings.TURN_MIN_PORT;
to = settings.TURN_MAX_PORT;
}];
allowedTCPPorts = with settings; [
TURN_PORT
(TURN_PORT + 1)
];
allowedUDPPortRanges = [
{
from = settings.TURN_MIN_PORT;
to = settings.TURN_MAX_PORT;
}
];
};
})
(mkIf (cfg.enableNginx && cfg.enableCoturn) {
services.coturn =
let cert = config.security.acme.certs.${settings.TURN_DOMAIN};
in {
let
cert = config.security.acme.certs.${settings.TURN_DOMAIN};
in
{
cert = "${cert.directory}/fullchain.pem";
pkey = "${cert.directory}/key.pem";
};
@ -570,8 +637,7 @@ in {
# share certs with coturn and restart on renewal
security.acme.certs.${settings.TURN_DOMAIN} = {
group = "turnserver";
postRun =
"systemctl reload nginx.service; systemctl restart coturn.service";
postRun = "systemctl reload nginx.service; systemctl restart coturn.service";
};
})
];

View File

@ -1,4 +1,8 @@
{ lib, buildNpmPackage, fetchFromGitHub }:
{
lib,
buildNpmPackage,
fetchFromGitHub,
}:
buildNpmPackage rec {
pname = "netbird-dashboard";

View File

@ -1,4 +1,6 @@
{ pkgs ? import <nixpkgs> {} }:
{
pkgs ? import <nixpkgs> { },
}:
{
dashboard = pkgs.callPackage ./dashboard.nix { };

View File

@ -1,7 +1,9 @@
{ config, ... }:
let host = "videos.dgnum.eu";
in {
let
host = "videos.dgnum.eu";
in
{
services.peertube = {
enable = true;
@ -53,8 +55,7 @@ in {
database.createLocally = true;
smtp.passwordFile = config.age.secrets."peertube-smtp_password_file".path;
serviceEnvironmentFile =
config.age.secrets."peertube-service_environment_file".path;
serviceEnvironmentFile = config.age.secrets."peertube-service_environment_file".path;
secrets.secretsFile = config.age.secrets."peertube-secrets_file".path;
};
@ -63,5 +64,7 @@ in {
forceSSL = true;
};
age-secrets.matches."^peertube-.*$" = { owner = "peertube"; };
age-secrets.matches."^peertube-.*$" = {
owner = "peertube";
};
}

View File

@ -1,8 +1,8 @@
let
lib = import ../../../lib { };
publicKeys = lib.getNodeKeys "storage01";
in lib.setDefault { inherit publicKeys; } [
in
lib.setDefault { inherit publicKeys; } [
"atticd-credentials_file"
"forgejo-database_password_file"
"forgejo_runners-token_file"

View File

@ -11,8 +11,10 @@ lib.extra.mkConfig {
];
extraConfig = {
dgn-fail2ban.jails =
lib.extra.enableAttrs' "enabled" [ "sshd-bruteforce" "sshd-timeout" ];
dgn-fail2ban.jails = lib.extra.enableAttrs' "enabled" [
"sshd-bruteforce"
"sshd-timeout"
];
services.netbird.enable = true;

View File

@ -8,8 +8,14 @@
boot = {
initrd = {
availableKernelModules =
[ "xhci_pci" "megaraid_sas" "ehci_pci" "ahci" "usb_storage" "sd_mod" ];
availableKernelModules = [
"xhci_pci"
"megaraid_sas"
"ehci_pci"
"ahci"
"usb_storage"
"sd_mod"
];
kernelModules = [ ];
};
@ -30,6 +36,5 @@
};
};
swapDevices =
[{ device = "/dev/disk/by-uuid/954ecb9c-ccd1-4e98-9eb6-3514bd3c01d1"; }];
swapDevices = [ { device = "/dev/disk/by-uuid/954ecb9c-ccd1-4e98-9eb6-3514bd3c01d1"; } ];
}

View File

@ -1,6 +1,5 @@
let
lib = import ../../../lib { };
publicKeys = lib.getNodeKeys "vault01";
in lib.setDefault { inherit publicKeys; } [
]
in
lib.setDefault { inherit publicKeys; } [ ]

View File

@ -6,7 +6,12 @@
{
imports = [
(modulesPath + "/profiles/qemu-guest.nix")
(let sources = import ../../npins; in sources.disko + "/module.nix")
(
let
sources = import ../../npins;
in
sources.disko + "/module.nix"
)
./disko.nix
];
}

View File

@ -3,31 +3,31 @@ let
cfg = config.services.castopod;
fpm = config.services.phpfpm.pools.castopod;
in
{
{
services.nginx = {
resolver.addresses = [ "127.0.0.53" ];
virtualHosts."${cfg.localDomain}" = {
resolver.addresses = [ "127.0.0.53" ];
virtualHosts."${cfg.localDomain}" = {
locations."@force_get" = {
extraConfig = lib.mkForce ''
recursive_error_pages on;
proxy_method GET;
proxy_pass https://podcasts.dgnum.eu/$request_uri;
'';
};
locations."@force_get" = {
extraConfig = lib.mkForce ''
recursive_error_pages on;
proxy_method GET;
proxy_pass https://podcasts.dgnum.eu/$request_uri;
'';
};
locations."~ \.php$" = {
extraConfig = lib.mkForce ''
error_page 550 = @force_get;
if ($request_method = HEAD) { return 550; }
fastcgi_intercept_errors on;
fastcgi_index index.php;
fastcgi_pass unix:${fpm.socket};
try_files $uri =404;
fastcgi_read_timeout 3600;
fastcgi_send_timeout 3600;
'';
};
locations."~ .php$" = {
extraConfig = lib.mkForce ''
error_page 550 = @force_get;
if ($request_method = HEAD) { return 550; }
fastcgi_intercept_errors on;
fastcgi_index index.php;
fastcgi_pass unix:${fpm.socket};
try_files $uri =404;
fastcgi_read_timeout 3600;
fastcgi_send_timeout 3600;
'';
};
};
}
};
}

View File

@ -1,38 +1,41 @@
{ config, pkgs, ...}:
{ config, pkgs, ... }:
let
host = "podcasts.dgnum.eu";
in
{
imports = [
./castopod-head-proxy.nix
];
services.castopod = {
enable = true;
localDomain = host;
environmentFile = config.age.secrets.castopod-environment_file.path;
maxUploadSize = 512;
settings = {
"email.fromEmail"="noreply@infra.dgnum.eu";
"email.SMTPHost"="kurisu.lahfa.xyz";
"email.SMTPUser"="web-services@infra.dgnum.eu";
"email.SMTPPort"="587";
imports = [ ./castopod-head-proxy.nix ];
"media.fileManager"="s3";
"media.s3.endpoint"="https://s3.dgnum.eu/";
"media.s3.region"="garage";
"media.s3.bucket"="castopod-dgnum";
"media.s3.pathStyleEndpoint"=true;
services = {
castopod = {
enable = true;
localDomain = host;
environmentFile = config.age.secrets.castopod-environment_file.path;
maxUploadSize = 512;
settings = {
"email.fromEmail" = "noreply@infra.dgnum.eu";
"email.SMTPHost" = "kurisu.lahfa.xyz";
"email.SMTPUser" = "web-services@infra.dgnum.eu";
"email.SMTPPort" = "587";
"restapi.enabled"=true;
"restapi.basicAuthUsername"="castopod";
"restapi.basicAuth"=true;
"media.fileManager" = "s3";
"media.s3.endpoint" = "https://s3.dgnum.eu/";
"media.s3.region" = "garage";
"media.s3.bucket" = "castopod-dgnum";
"media.s3.pathStyleEndpoint" = true;
"restapi.enabled" = true;
"restapi.basicAuthUsername" = "castopod";
"restapi.basicAuth" = true;
};
database.createLocally = true;
configureNginx = true;
};
mysql.package = pkgs.mariadb;
nginx.virtualHosts.${host} = {
forceSSL = true;
enableACME = true;
};
database.createLocally = true;
configureNginx = true;
};
services.mysql.package = pkgs.mariadb;
services.nginx.virtualHosts.${host} = {
forceSSL = true;
enableACME = true;
};
}

View File

@ -56,7 +56,10 @@ in
mountpoint = "/var/log";
};
"/nix" = {
mountOptions = [ "noatime" "compress=zstd" ];
mountOptions = [
"noatime"
"compress=zstd"
];
mountpoint = "/nix";
};
};

View File

@ -1,5 +1,4 @@
{ ... }:
{
_: {
services.dolibarr = {
enable = true;
domain = "erp.dgnum.eu";

View File

@ -1,4 +1,9 @@
{ sources, pkgs, lib, ... }:
{
sources,
pkgs,
lib,
...
}:
let
host = "cal.dgnum.eu";
@ -26,7 +31,8 @@ let
calendars = metis2linkal sources.metis;
};
};
in {
in
{
imports = [ ./module.nix ];
dgn-linkal = {

View File

@ -7,18 +7,10 @@ let
inherit (import source { inherit pkgs; }) providers;
# helper function to map 2-level deep attribute-sets
mapDeepAttrs = mapFct:
lib.concatMapAttrs (name: value:
lib.mapAttrs' (name': value':
mapFct name name' value'
) value
);
toLinkal = upstream: identifier:
lib.nameValuePair
"${providers.${upstream}}${identifier}"
;
mapDeepAttrs =
mapFct:
lib.concatMapAttrs (name: value: lib.mapAttrs' (name': value': mapFct name name' value') value);
toLinkal = upstream: identifier: lib.nameValuePair "${providers.${upstream}}${identifier}";
in
mapDeepAttrs toLinkal calendars
mapDeepAttrs toLinkal calendars

View File

@ -1,14 +1,28 @@
{ config, lib, pkgs, sources, ... }:
{
config,
lib,
pkgs,
sources,
...
}:
let
inherit (lib) mapAttrs' mkEnableOption mkIf mkOption nameValuePair types;
inherit (lib)
mapAttrs'
mkEnableOption
mkIf
mkOption
nameValuePair
types
;
package = import sources.linkal { inherit pkgs; };
cfg = config.dgn-linkal;
jsonFormat = pkgs.formats.json { };
in {
in
{
options.dgn-linkal = {
enable = mkEnableOption "the linkal server.";
@ -20,32 +34,40 @@ in {
domain = mkOption { type = types.str; };
calendarGroups = mkOption {
type = let inherit (types) attrsOf port submodule;
in attrsOf (submodule {
options = {
port = mkOption { type = port; };
calendars = mkOption { inherit (jsonFormat) type; };
};
});
type =
let
inherit (types) attrsOf port submodule;
in
attrsOf (
submodule {
options = {
port = mkOption { type = port; };
calendars = mkOption { inherit (jsonFormat) type; };
};
}
);
default = { };
};
};
config = mkIf cfg.enable {
systemd.services = mapAttrs' (name:
{ port, calendars }:
nameValuePair "linkal-${name}" {
description = "Linkal - ${name}";
wantedBy = [ "multi-user.target" ];
serviceConfig = {
Type = "simple";
ExecStart = "${cfg.package}/bin/linkal --port ${
builtins.toString port
} --calendar-file ${
jsonFormat.generate "linkal-${name}.json" { inherit calendars; }
}";
};
}) cfg.calendarGroups;
systemd.services =
mapAttrs'
(
name:
{ port, calendars }:
nameValuePair "linkal-${name}" {
description = "Linkal - ${name}";
wantedBy = [ "multi-user.target" ];
serviceConfig = {
Type = "simple";
ExecStart = "${cfg.package}/bin/linkal --port ${builtins.toString port} --calendar-file ${
jsonFormat.generate "linkal-${name}.json" { inherit calendars; }
}";
};
}
)
cfg.calendarGroups;
# Configure bind for DNS certificate validation on *.cal.dgnum.eu.
# services.bind = {
@ -85,16 +107,20 @@ in {
services.nginx = {
enable = true;
virtualHosts = mapAttrs' (name:
{ port, ... }:
nameValuePair "${name}.${cfg.domain}" {
enableACME = true;
# acmeRoot = null; # Use DNS-01 validation
forceSSL = true;
virtualHosts =
mapAttrs'
(
name:
{ port, ... }:
nameValuePair "${name}.${cfg.domain}" {
enableACME = true;
# acmeRoot = null; # Use DNS-01 validation
forceSSL = true;
locations."/".proxyPass =
"http://127.0.0.1:${builtins.toString port}/";
}) cfg.calendarGroups;
locations."/".proxyPass = "http://127.0.0.1:${builtins.toString port}/";
}
)
cfg.calendarGroups;
};
};
}

View File

@ -6,5 +6,7 @@
configPath = config.age.secrets."matterbridge-config_file".path;
};
age-secrets.matches."^matterbridge-.*$" = { owner = "matterbridge"; };
age-secrets.matches."^matterbridge-.*$" = {
owner = "matterbridge";
};
}

View File

@ -1,24 +1,35 @@
{ lib, pkgs, sources, ... }:
{
lib,
pkgs,
sources,
...
}:
let
metis = import sources.metis { inherit pkgs; };
inherit (metis) providers;
in {
in
{
services.nginx.virtualHosts."calendrier.dgnum.eu" = {
enableACME = true;
forceSSL = true;
root = metis.production;
locations = lib.mapAttrs' (name: value:
lib.nameValuePair "/cal/${name}/" {
extraConfig = ''
proxy_set_header X-Forwarded-Host $host;
proxy_set_header X-Forwarded-Server $host;
proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;
proxy_pass ${value};
'';
}) providers;
locations =
lib.mapAttrs'
(
name: value:
lib.nameValuePair "/cal/${name}/" {
extraConfig = ''
proxy_set_header X-Forwarded-Host $host;
proxy_set_header X-Forwarded-Server $host;
proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;
proxy_pass ${value};
'';
}
)
providers;
extraConfig = ''
rewrite ^/calendrier(.*)$ $1 permanent;

View File

@ -1,8 +1,9 @@
{ config, ... }:
let host = "push.dgnum.eu";
in {
let
host = "push.dgnum.eu";
in
{
services.ntfy-sh = {
enable = true;
@ -26,6 +27,7 @@ in {
};
};
systemd.services.ntfy-sh.serviceConfig.EnvironmentFile =
[ config.age.secrets."ntfy_sh-environment_file".path ];
systemd.services.ntfy-sh.serviceConfig.EnvironmentFile = [
config.age.secrets."ntfy_sh-environment_file".path
];
}

View File

@ -3,15 +3,19 @@ _:
let
retired_host = "retired.dgnum.eu";
mkRetired = hosts:
builtins.listToAttrs (builtins.map (name: {
inherit name;
value.to = retired_host;
}) hosts);
mkRetired =
hosts:
builtins.listToAttrs (
builtins.map
(name: {
inherit name;
value.to = retired_host;
})
hosts
);
mkSub = domain: builtins.map (s: "${s}.${domain}");
mkSubs = attrs:
builtins.concatLists (builtins.attrValues (builtins.mapAttrs mkSub attrs));
mkSubs = attrs: builtins.concatLists (builtins.attrValues (builtins.mapAttrs mkSub attrs));
redirections = {
"calendrier.eleves.ens.fr".to = "calendrier.dgnum.eu";
@ -23,9 +27,15 @@ let
} // (mkRetired retired);
retired = mkSubs {
"ens.fr" = [ "alevins" "www.climatenavigator" ];
"ens.fr" = [
"alevins"
"www.climatenavigator"
];
"ens.wtf" = [ "photos" ];
"rz.ens.wtf" = [ "s3" "cdn" ];
"rz.ens.wtf" = [
"s3"
"cdn"
];
"beta.rz.ens.wtf" = [
"todo"
"minecraft"
@ -39,14 +49,25 @@ let
"rstudio"
];
};
in {
services.nginx.virtualHosts = {
${retired_host}.default = true;
} // (builtins.mapAttrs (host:
{ to, ssl ? true }: {
globalRedirect = to;
enableACME = ssl;
forceSSL = ssl;
}) redirections);
in
{
services.nginx.virtualHosts =
{
${retired_host}.default = true;
}
// (builtins.mapAttrs
(
_:
{
to,
ssl ? true,
}:
{
globalRedirect = to;
enableACME = ssl;
forceSSL = ssl;
}
)
redirections
);
}

View File

@ -1,7 +1,8 @@
let
lib = import ../../../lib { };
publicKeys = lib.getNodeKeys "web01";
in lib.setDefault { inherit publicKeys; } [
in
lib.setDefault { inherit publicKeys; } [
"acme-certs_secret"
"matterbridge-config_file"
"named-bind_dnskeys_conf"

View File

@ -1,20 +1,34 @@
# Generated by npins. Do not modify; will be overwritten regularly
let
data = builtins.fromJSON (builtins.readFile ./sources.json);
version = data.version;
inherit (data) version;
mkSource = spec:
assert spec ? type; let
mkSource =
spec:
assert spec ? type;
let
path =
if spec.type == "Git" then mkGitSource spec
else if spec.type == "GitRelease" then mkGitSource spec
else if spec.type == "PyPi" then mkPyPiSource spec
else if spec.type == "Channel" then mkChannelSource spec
else builtins.throw "Unknown source type ${spec.type}";
if spec.type == "Git" then
mkGitSource spec
else if spec.type == "GitRelease" then
mkGitSource spec
else if spec.type == "PyPi" then
mkPyPiSource spec
else if spec.type == "Channel" then
mkChannelSource spec
else
builtins.throw "Unknown source type ${spec.type}";
in
spec // { outPath = path; };
mkGitSource = { repository, revision, url ? null, hash, ... }:
mkGitSource =
{
repository,
revision,
url ? null,
hash,
...
}:
assert repository ? type;
# At the moment, either it is a plain git repository (which has an url), or it is a GitHub/GitLab repository
# In the latter case, there we will always be an url to the tarball
@ -23,19 +37,23 @@ let
inherit url;
sha256 = hash; # FIXME: check nix version & use SRI hashes
})
else assert repository.type == "Git"; builtins.fetchGit {
url = repository.url;
rev = revision;
# hash = hash;
};
else
assert repository.type == "Git";
builtins.fetchGit {
inherit (repository) url;
rev = revision;
# hash = hash;
};
mkPyPiSource = { url, hash, ... }:
mkPyPiSource =
{ url, hash, ... }:
builtins.fetchurl {
inherit url;
sha256 = hash;
};
mkChannelSource = { url, hash, ... }:
mkChannelSource =
{ url, hash, ... }:
builtins.fetchTarball {
inherit url;
sha256 = hash;

View File

@ -1,7 +1,9 @@
{ pkgs, sources, ... }:
let wp4nix = pkgs.callPackage sources.wp4nix { };
in {
let
wp4nix = pkgs.callPackage sources.wp4nix { };
in
{
imports = [ ./module.nix ];
services.wp-containers = {
@ -9,26 +11,38 @@ in {
sites = {
"lavoixduntexte.normalesup.eu" = {
themes = { inherit (wp4nix.themes) avant; };
themes = {
inherit (wp4nix.themes) avant;
};
plugins = { inherit (wp4nix.plugins) wordpress-importer; };
plugins = {
inherit (wp4nix.plugins) wordpress-importer;
};
languages = [ pkgs.wordpressPackages.languages.fr_FR ];
};
"bds.wp.dgnum.eu" = {
plugins = { inherit (wp4nix.plugins) user-role-editor; };
plugins = {
inherit (wp4nix.plugins) user-role-editor;
};
languages = [ pkgs.wordpressPackages.languages.fr_FR ];
themes = { inherit (wp4nix.themes) gateway twentytwentythree; };
themes = {
inherit (wp4nix.themes) gateway twentytwentythree;
};
};
"bda.wp.dgnum.eu" = {
plugins = { inherit (wp4nix.plugins) user-role-editor; };
plugins = {
inherit (wp4nix.plugins) user-role-editor;
};
languages = [ pkgs.wordpressPackages.languages.fr_FR ];
};
"cineclub.wp.dgnum.eu" = {
plugins = { inherit (wp4nix.plugins) user-role-editor; };
plugins = {
inherit (wp4nix.plugins) user-role-editor;
};
languages = [ pkgs.wordpressPackages.languages.fr_FR ];
};
};

View File

@ -1,4 +1,9 @@
{ config, lib, pkgs, ... }:
{
config,
lib,
pkgs,
...
}:
let
inherit (lib) mkEnableOption mkIf mkOption;
@ -13,41 +18,52 @@ let
mkHost = mkIp "10.31.41";
mkLocal = mkIp "10.0.0";
mkConfig = { name, value, i }: {
services.wordpress = {
webserver = "nginx";
sites.${name} = value;
mkConfig =
{
name,
value,
i,
}:
{
services.wordpress = {
webserver = "nginx";
sites.${name} = value;
};
services.nginx.virtualHosts.${name} = {
onlySSL = true;
sslCertificate = "${certs.${name}.directory}/fullchain.pem";
sslCertificateKey = "${certs.${name}.directory}/key.pem";
sslTrustedCertificate = "${certs.${name}.directory}/chain.pem";
};
networking = {
hostName = mkName name;
hosts.${mkLocal i} = [ name ];
firewall.allowedTCPPorts = [ 443 ];
};
environment.systemPackages = [
pkgs.wp-cli
pkgs.neovim
];
system.stateVersion = "23.11";
};
services.nginx.virtualHosts.${name} = {
onlySSL = true;
sslCertificate = "${certs.${name}.directory}/fullchain.pem";
sslCertificateKey = "${certs.${name}.directory}/key.pem";
sslTrustedCertificate = "${certs.${name}.directory}/chain.pem";
};
networking = {
hostName = mkName name;
hosts.${mkLocal i} = [ name ];
firewall.allowedTCPPorts = [ 443 ];
};
environment.systemPackages = [ pkgs.wp-cli pkgs.neovim ];
system.stateVersion = "23.11";
};
mkContainer = i: site: {
name = mkName site.name;
value = {
privateNetwork = true;
forwardPorts = [{
containerPort = 443;
hostPort = cfg.basePort + i;
}];
forwardPorts = [
{
containerPort = 443;
hostPort = cfg.basePort + i;
}
];
bindMounts.certs = {
hostPath = certs.${site.name}.directory;
@ -69,13 +85,13 @@ let
enableACME = true;
forceSSL = true;
locations."/".proxyPass =
"https://${mkHost i}:${builtins.toString (cfg.basePort + i)}";
locations."/".proxyPass = "https://${mkHost i}:${builtins.toString (cfg.basePort + i)}";
};
};
siteList = lib.attrsToList cfg.sites;
in {
in
{
options.services.wp-containers = {
enable = mkEnableOption "wordpress sites in containers";
@ -93,7 +109,6 @@ in {
config = mkIf cfg.enable {
containers = builtins.listToAttrs (lib.imap1 mkContainer siteList);
services.nginx.virtualHosts =
builtins.listToAttrs (lib.imap1 mkVhost siteList);
services.nginx.virtualHosts = builtins.listToAttrs (lib.imap1 mkVhost siteList);
};
}

View File

@ -11,8 +11,10 @@ lib.extra.mkConfig {
];
extraConfig = {
dgn-fail2ban.jails =
lib.extra.enableAttrs' "enabled" [ "sshd-bruteforce" "sshd-timeout" ];
dgn-fail2ban.jails = lib.extra.enableAttrs' "enabled" [
"sshd-bruteforce"
"sshd-timeout"
];
services.netbird.enable = true;
};

View File

@ -8,8 +8,14 @@
boot = {
initrd = {
availableKernelModules =
[ "ata_piix" "uhci_hcd" "ehci_pci" "virtio_pci" "sr_mod" "virtio_blk" ];
availableKernelModules = [
"ata_piix"
"uhci_hcd"
"ehci_pci"
"virtio_pci"
"sr_mod"
"virtio_blk"
];
kernelModules = [ ];
};
@ -30,6 +36,5 @@
};
};
swapDevices =
[{ device = "/dev/disk/by-uuid/d64ae21e-693c-4c77-b62c-97d5e2a960cb"; }];
swapDevices = [ { device = "/dev/disk/by-uuid/d64ae21e-693c-4c77-b62c-97d5e2a960cb"; } ];
}

View File

@ -1,6 +1,5 @@
let
lib = import ../../../lib { };
publicKeys = lib.getNodeKeys "web02";
in lib.setDefault { inherit publicKeys; } [
]
in
lib.setDefault { inherit publicKeys; } [ ]

View File

@ -8,9 +8,7 @@
];
# Jourdan
par02 = [
"vault01"
];
par02 = [ "vault01" ];
# VMs du SPI/NPS/Whatever
dmi01 = [

View File

@ -26,15 +26,25 @@ let
groups = {
# members of this group are root on all nodes
root = [ "thubrecht" "raito" "mdebray" ];
root = [
"thubrecht"
"raito"
"mdebray"
];
# members of this group will have root access on the installation isos
iso = [ "thubrecht" "mdebray" "raito" ];
iso = [
"thubrecht"
"mdebray"
"raito"
];
# members of this group can access netbox's secret
netbox = [];
netbox = [ ];
bureau = [ "gdd" ];
};
in { inherit groups members; }
in
{
inherit groups members;
}

View File

@ -1,27 +1,47 @@
let
mkDefaultInterface = _: attrs: { ipv4 = [ ]; ipv6 = [ ]; gateways = [ ]; } // attrs;
mkDefaultInterface =
_: attrs:
{
ipv4 = [ ];
ipv6 = [ ];
gateways = [ ];
}
// attrs;
mkBase = config: config // { interfaces = builtins.mapAttrs mkDefaultInterface (config.interfaces or { }); };
mkBase =
config: config // { interfaces = builtins.mapAttrs mkDefaultInterface (config.interfaces or { }); };
getAddresses = version: interface: builtins.map (builtins.getAttr "address") interface.${version};
filterIPv4 = ip: builtins.substring 0 7 ip != "192.168";
filterIPv6 = _: true;
mkNet = _: value:
let base = mkBase value; in
base // {
mkNet =
_: value:
let
base = mkBase value;
in
base
// {
addresses =
let
_addresses = builtins.foldl'
({ ipv4, ipv6 }: net: {
ipv4 = ipv4 ++ getAddresses "ipv4" net;
ipv6 = ipv6 ++ getAddresses "ipv6" net;
})
{ ipv4 = [ ]; ipv6 = [ ]; }
(builtins.attrValues base.interfaces);
_addresses =
builtins.foldl'
(
{ ipv4, ipv6 }:
net: {
ipv4 = ipv4 ++ getAddresses "ipv4" net;
ipv6 = ipv6 ++ getAddresses "ipv6" net;
}
)
{
ipv4 = [ ];
ipv6 = [ ];
}
(builtins.attrValues base.interfaces);
in
_addresses // rec {
_addresses
// rec {
publicV4 = builtins.filter filterIPv4 _addresses.ipv4;
publicV6 = builtins.filter filterIPv6 _addresses.ipv6;
public = publicV4 ++ publicV6;
@ -34,8 +54,14 @@ builtins.mapAttrs mkNet {
interfaces = {
eno1 = {
ipv4 = [
{ address = "129.199.146.147"; prefixLength = 24; }
{ address = "192.168.1.147"; prefixLength = 24; }
{
address = "129.199.146.147";
prefixLength = 24;
}
{
address = "192.168.1.147";
prefixLength = 24;
}
];
gateways = [ "129.199.146.254" ];
@ -49,8 +75,14 @@ builtins.mapAttrs mkNet {
interfaces = {
eno1 = {
ipv4 = [
{ address = "129.199.146.148"; prefixLength = 24; }
{ address = "192.168.1.148"; prefixLength = 24; }
{
address = "129.199.146.148";
prefixLength = 24;
}
{
address = "192.168.1.148";
prefixLength = 24;
}
];
gateways = [ "129.199.146.254" ];
@ -64,7 +96,10 @@ builtins.mapAttrs mkNet {
interfaces = {
enp130s0f0 = {
ipv4 = [
{ address = "129.199.210.85"; prefixLength = 24; }
{
address = "129.199.210.85";
prefixLength = 24;
}
];
gateways = [ "129.199.210.254" ];
@ -77,7 +112,12 @@ builtins.mapAttrs mkNet {
web01 = {
interfaces = {
ens3 = {
ipv4 = [{ address = "129.199.129.53"; prefixLength = 24; }];
ipv4 = [
{
address = "129.199.129.53";
prefixLength = 24;
}
];
gateways = [ "129.199.129.1" ];
};
@ -89,7 +129,12 @@ builtins.mapAttrs mkNet {
web02 = {
interfaces = {
ens3 = {
ipv4 = [{ address = "129.199.129.235"; prefixLength = 24; }];
ipv4 = [
{
address = "129.199.129.235";
prefixLength = 24;
}
];
gateways = [ "129.199.129.1" ];
};

View File

@ -11,14 +11,17 @@
# }
let
mkNode = _: attrs: {
adminGroups = [ ];
admins = [ ];
mkNode =
_: attrs:
{
adminGroups = [ ];
admins = [ ];
deployment = { };
deployment = { };
nixpkgs = "23.11";
} // attrs;
nixpkgs = "23.11";
}
// attrs;
in
builtins.mapAttrs mkNode {

View File

@ -35,22 +35,25 @@
{ lib, sources, ... }:
{
imports = (lib.extra.mkImports ./. [
"dgn-access-control"
"dgn-acme"
"dgn-console"
"dgn-fail2ban"
"dgn-hardware"
"dgn-network"
"dgn-ssh"
"dgn-web"
"dgn-vm-variant"
]) ++ [
"${sources.agenix}/modules/age.nix"
"${sources.attic}/nixos/atticd.nix"
] ++ ((import sources.nix-modules { inherit lib; }).importModules [
"age-secrets"
"services/crabfit"
"services/forgejo-nix-runners"
]);
imports =
(lib.extra.mkImports ./. [
"dgn-access-control"
"dgn-acme"
"dgn-console"
"dgn-fail2ban"
"dgn-hardware"
"dgn-network"
"dgn-ssh"
"dgn-web"
"dgn-vm-variant"
])
++ [
"${sources.agenix}/modules/age.nix"
"${sources.attic}/nixos/atticd.nix"
]
++ ((import sources.nix-modules { inherit lib; }).importModules [
"age-secrets"
"services/crabfit"
"services/forgejo-nix-runners"
]);
}

View File

@ -31,7 +31,13 @@
# pris connaissance de la licence CeCILL, et que vous en avez accepté les
# termes.
{ config, lib, meta, name, ... }:
{
config,
lib,
meta,
name,
...
}:
let
inherit (lib)
@ -40,10 +46,13 @@ let
mkIf
mkOption
types;
types
;
nodeMeta = meta.nodes.${name};
admins = meta.members.groups.root ++ nodeMeta.admins
admins =
meta.members.groups.root
++ nodeMeta.admins
++ (builtins.concatMap (g: meta.members.groups.${g}) nodeMeta.adminGroups);
cfg = config.dgn-access-control;
@ -51,7 +60,9 @@ in
{
options.dgn-access-control = {
enable = mkEnableOption "DGNum access control." // { default = true; };
enable = mkEnableOption "DGNum access control." // {
default = true;
};
users = mkOption {
type = with types; attrsOf (listOf str);
@ -72,8 +83,8 @@ in
# Admins have root access to the node
dgn-access-control.users.root = mkDefault admins;
users.users = builtins.mapAttrs
(u: members: { openssh.authorizedKeys.keys = lib.extra.getAllKeys members; })
cfg.users;
users.users =
builtins.mapAttrs (_: members: { openssh.authorizedKeys.keys = lib.extra.getAllKeys members; })
cfg.users;
};
}

View File

@ -34,15 +34,15 @@
{ config, lib, ... }:
let
inherit (lib)
mkEnableOption
mkIf;
inherit (lib) mkEnableOption mkIf;
cfg = config.dgn-acme;
in
{
options.dgn-acme.enable = mkEnableOption "ACME settings." // { default = true; };
options.dgn-acme.enable = mkEnableOption "ACME settings." // {
default = true;
};
config = mkIf cfg.enable {
security.acme = {

View File

@ -1,13 +1,20 @@
{ config, lib, pkgs, ... }:
{
config,
lib,
pkgs,
...
}:
let
inherit (lib) mkEnableOption mkOption mkIf;
cfg = config.dgn-console;
in {
in
{
options.dgn-console = {
enable = mkEnableOption "DGNum console setup." // { default = true; };
enable = mkEnableOption "DGNum console setup." // {
default = true;
};
pg-upgrade-to = mkOption {
type = lib.types.package;
@ -18,7 +25,9 @@ in {
config = mkIf cfg.enable {
time.timeZone = "Europe/Paris";
console = { keyMap = "fr"; };
console = {
keyMap = "fr";
};
environment.variables.EDITOR = "nvim";
@ -26,7 +35,7 @@ in {
# services.nscd.enableNsncd = false;
nixpkgs.overlays = [
(final: prev: {
(_: _: {
nsncd = pkgs.rustPlatform.buildRustPackage {
pname = "nsncd";
version = "unstable-2023-10-26";
@ -70,29 +79,36 @@ in {
hardware.enableRedistributableFirmware = true;
environment.systemPackages = (with pkgs; [ neovim wget kitty.terminfo ])
++ lib.optional (config.services.postgresql.enable
&& config.services.postgresql.package != cfg.pg-upgrade-to)
(pkgs.writeScriptBin "upgrade-pg-cluster" ''
set -eux
# XXX it's perhaps advisable to stop all services that depend on postgresql
systemctl stop postgresql
environment.systemPackages =
(with pkgs; [
neovim
wget
kitty.terminfo
])
++ lib.optional
(config.services.postgresql.enable && config.services.postgresql.package != cfg.pg-upgrade-to)
(
pkgs.writeScriptBin "upgrade-pg-cluster" ''
set -eux
# XXX it's perhaps advisable to stop all services that depend on postgresql
systemctl stop postgresql
export NEWDATA="/var/lib/postgresql/${cfg.pg-upgrade-to.psqlSchema}"
export NEWDATA="/var/lib/postgresql/${cfg.pg-upgrade-to.psqlSchema}"
export NEWBIN="${cfg.pg-upgrade-to}/bin"
export NEWBIN="${cfg.pg-upgrade-to}/bin"
export OLDDATA="${config.services.postgresql.dataDir}"
export OLDBIN="${config.services.postgresql.package}/bin"
export OLDDATA="${config.services.postgresql.dataDir}"
export OLDBIN="${config.services.postgresql.package}/bin"
install -d -m 0700 -o postgres -g postgres "$NEWDATA"
cd "$NEWDATA"
sudo -u postgres $NEWBIN/initdb -D "$NEWDATA"
install -d -m 0700 -o postgres -g postgres "$NEWDATA"
cd "$NEWDATA"
sudo -u postgres $NEWBIN/initdb -D "$NEWDATA"
sudo -u postgres $NEWBIN/pg_upgrade \
--old-datadir "$OLDDATA" --new-datadir "$NEWDATA" \
--old-bindir $OLDBIN --new-bindir $NEWBIN \
"$@"
'');
sudo -u postgres $NEWBIN/pg_upgrade \
--old-datadir "$OLDDATA" --new-datadir "$NEWDATA" \
--old-bindir $OLDBIN --new-bindir $NEWBIN \
"$@"
''
);
};
}

View File

@ -1,10 +1,19 @@
{ config, lib, pkgs, ... }:
{
config,
lib,
pkgs,
...
}:
let
inherit (lib)
mkDefault mkEnableOption mkIf mkOption
mkDefault
mkEnableOption
mkIf
mkOption
types;
types
;
cfg = config.dgn-fail2ban;
@ -22,8 +31,7 @@ let
};
filter = mkOption {
type =
types.nullOr (types.submodule { freeformType = configFormat.type; });
type = types.nullOr (types.submodule { freeformType = configFormat.type; });
description = "Content of the filter used for this jail.";
};
@ -36,8 +44,8 @@ let
};
};
};
in {
in
{
options.dgn-fail2ban = {
enable = mkEnableOption "fail2ban service.";
@ -50,9 +58,9 @@ in {
};
config = mkIf cfg.enable {
dgn-fail2ban.jails =
builtins.mapAttrs (_: j: j // { enabled = mkDefault false; })
(import ./jails.nix { });
dgn-fail2ban.jails = builtins.mapAttrs (_: j: j // { enabled = mkDefault false; }) (
import ./jails.nix { }
);
services.fail2ban = {
enable = true;

View File

@ -33,8 +33,7 @@
_: {
nginx-spam = {
filter.Definition.failregex = ''
^<HOST>.*GET.*(matrix/server|\.php|admin|wp\-).* HTTP/\d.\d\" 404.*$'';
filter.Definition.failregex = ''^<HOST>.*GET.*(matrix/server|\.php|admin|wp\-).* HTTP/\d.\d\" 404.*$'';
settings = {
logpath = "/var/log/nginx/access.log";

View File

@ -1,11 +1,16 @@
{ config, lib, pkgs, ... }:
{
config,
lib,
pkgs,
...
}:
let
inherit (lib) mkEnableOption mkIf mkMerge;
cfg = config.dgn-hardware;
in {
in
{
options.dgn-hardware = {
enable = mkEnableOption "default hardware configuration." // {
default = true;
@ -19,45 +24,56 @@ in {
useBcachefs = mkEnableOption "bcachefs configuration";
};
config = mkIf cfg.enable (mkMerge [
{
hardware.enableRedistributableFirmware = true;
hardware.cpu.intel.updateMicrocode = true;
config = mkIf cfg.enable (
mkMerge [
{
hardware.enableRedistributableFirmware = true;
hardware.cpu.intel.updateMicrocode = true;
nixpkgs.hostPlatform = lib.mkDefault "x86_64-linux";
nixpkgs.hostPlatform = lib.mkDefault "x86_64-linux";
boot = {
initrd.availableKernelModules =
[ "ata_piix" "uhci_hcd" "ehci_pci" "virtio_pci" "ahci" "virtio_blk" ];
kernelModules = [ "kvm-intel" ];
kernelParams = [
"cgroup_enable=cpu"
"cgroup_enable=cpuset"
"cgroup_enable=memory"
"cgroup_memory=1"
];
};
}
(mkIf cfg.useSystemd {
boot.loader = {
systemd-boot.enable = true;
efi.canTouchEfiVariables = true;
};
})
(mkIf cfg.useBcachefs { boot.supportedFilesystems = [ "bcachefs" ]; })
(mkIf cfg.useZfs {
boot = {
supportedFilesystems = [ "zfs" ];
zfs = {
forceImportRoot = false;
extraPools = [ "fast01" "work01" ];
package = pkgs.zfs_2_1;
boot = {
initrd.availableKernelModules = [
"ata_piix"
"uhci_hcd"
"ehci_pci"
"virtio_pci"
"ahci"
"virtio_blk"
];
kernelModules = [ "kvm-intel" ];
kernelParams = [
"cgroup_enable=cpu"
"cgroup_enable=cpuset"
"cgroup_enable=memory"
"cgroup_memory=1"
];
};
};
})
]);
}
(mkIf cfg.useSystemd {
boot.loader = {
systemd-boot.enable = true;
efi.canTouchEfiVariables = true;
};
})
(mkIf cfg.useBcachefs { boot.supportedFilesystems = [ "bcachefs" ]; })
(mkIf cfg.useZfs {
boot = {
supportedFilesystems = [ "zfs" ];
zfs = {
forceImportRoot = false;
extraPools = [
"fast01"
"work01"
];
package = pkgs.zfs_2_1;
};
};
})
]
);
}

View File

@ -1,12 +1,22 @@
{ config, lib, meta, name, ... }:
{
config,
lib,
meta,
name,
...
}:
let
inherit (lib) mapAttrs' mkEnableOption mkIf optionalAttrs;
inherit (lib)
mapAttrs'
mkEnableOption
mkIf
optionalAttrs
;
net = meta.network.${name};
mkAddress = { address, prefixLength, ... }:
"${address}/${builtins.toString prefixLength}";
mkAddress = { address, prefixLength, ... }: "${address}/${builtins.toString prefixLength}";
mkRoute = gateway: {
routeConfig = {
Gateway = gateway;
@ -38,12 +48,11 @@ let
};
cfg = config.dgn-network;
in {
options.dgn-network.enable =
mkEnableOption "automatic network configuration based on metadata" // {
default = true;
};
in
{
options.dgn-network.enable = mkEnableOption "automatic network configuration based on metadata" // {
default = true;
};
config = mkIf cfg.enable {
networking = {

View File

@ -1,14 +1,14 @@
{ config, lib, ... }:
let
inherit (lib)
mkEnableOption
mkIf;
inherit (lib) mkEnableOption mkIf;
cfg = config.dgn-vmVariant;
in
{
options.dgn-vmVariant.enable = mkEnableOption "ACME settings." // { default = true; };
options.dgn-vmVariant.enable = mkEnableOption "ACME settings." // {
default = true;
};
config = mkIf cfg.enable {
virtualisation.vmVariant = {
@ -16,4 +16,3 @@ in
};
};
}

View File

@ -4,7 +4,8 @@ let
inherit (lib) mkEnableOption mkIf;
cfg = config.dgn-web;
in {
in
{
options.dgn-web = {
enable = mkEnableOption "sane defaults for web services.";
};
@ -21,6 +22,9 @@ in {
recommendedZstdSettings = true;
};
networking.firewall.allowedTCPPorts = [ 80 443 ];
networking.firewall.allowedTCPPorts = [
80
443
];
};
}

View File

@ -1,20 +1,34 @@
# Generated by npins. Do not modify; will be overwritten regularly
let
data = builtins.fromJSON (builtins.readFile ./sources.json);
version = data.version;
inherit (data) version;
mkSource = spec:
assert spec ? type; let
mkSource =
spec:
assert spec ? type;
let
path =
if spec.type == "Git" then mkGitSource spec
else if spec.type == "GitRelease" then mkGitSource spec
else if spec.type == "PyPi" then mkPyPiSource spec
else if spec.type == "Channel" then mkChannelSource spec
else builtins.throw "Unknown source type ${spec.type}";
if spec.type == "Git" then
mkGitSource spec
else if spec.type == "GitRelease" then
mkGitSource spec
else if spec.type == "PyPi" then
mkPyPiSource spec
else if spec.type == "Channel" then
mkChannelSource spec
else
builtins.throw "Unknown source type ${spec.type}";
in
spec // { outPath = path; };
mkGitSource = { repository, revision, url ? null, hash, ... }:
mkGitSource =
{
repository,
revision,
url ? null,
hash,
...
}:
assert repository ? type;
# At the moment, either it is a plain git repository (which has an url), or it is a GitHub/GitLab repository
# In the latter case, there we will always be an url to the tarball
@ -23,19 +37,23 @@ let
inherit url;
sha256 = hash; # FIXME: check nix version & use SRI hashes
})
else assert repository.type == "Git"; builtins.fetchGit {
url = repository.url;
rev = revision;
# hash = hash;
};
else
assert repository.type == "Git";
builtins.fetchGit {
inherit (repository) url;
rev = revision;
# hash = hash;
};
mkPyPiSource = { url, hash, ... }:
mkPyPiSource =
{ url, hash, ... }:
builtins.fetchurl {
inherit url;
sha256 = hash;
};
mkChannelSource = { url, hash, ... }:
mkChannelSource =
{ url, hash, ... }:
builtins.fetchTarball {
inherit url;
sha256 = hash;

View File

@ -118,6 +118,18 @@
"url": "https://releases.nixos.org/nixpkgs/nixpkgs-24.05pre578430.5ad9903c1612/nixexprs.tar.xz",
"hash": "1zg01pxmaf56gqxdf59mj1aanlvkpw5b3gmsx4mawxi6m1f2l6c6"
},
"pre-commit-hooks": {
"type": "Git",
"repository": {
"type": "GitHub",
"owner": "cachix",
"repo": "pre-commit-hooks.nix"
},
"branch": "master",
"revision": "7c54e08a689b53c8a1e5d70169f2ec9e2a68ffaf",
"url": "https://github.com/cachix/pre-commit-hooks.nix/archive/7c54e08a689b53c8a1e5d70169f2ec9e2a68ffaf.tar.gz",
"hash": "0gj03fzsqcybzr4shj7x62l0xc34w20zhphd2jg7sd2rxaw42x23"
},
"wp4nix": {
"type": "Git",
"repository": {
@ -132,4 +144,4 @@
}
},
"version": 3
}
}

View File

@ -8,19 +8,25 @@ let
coreutils
nvd
git
jq;
jq
;
};
mkShellScript = name: (pkgs.substituteAll ({
inherit name;
src = ./. + "/${name}.sh";
dir = "/bin/";
isExecutable = true;
mkShellScript =
name:
(pkgs.substituteAll (
{
inherit name;
src = ./. + "/${name}.sh";
dir = "/bin/";
isExecutable = true;
checkPhase = ''
${pkgs.stdenv.shellDryRun} "$target"
'';
} // substitutions));
checkPhase = ''
${pkgs.stdenv.shellDryRun} "$target"
'';
}
// substitutions
));
scripts = [
"check-deployment"

View File

@ -1,52 +1 @@
/*
Copyright :
- Maurice Debray <maurice.debray@dgnum.eu> 2023
- 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.
*/
let
sources = import ./npins;
pkgs = import sources.nixpkgs { };
in
pkgs.mkShell {
packages = (with pkgs; [
npins
colmena
nixos-generators
] ++ (builtins.map (p: callPackage p { }) [
(sources.disko + "/package.nix")
])) ++ (import ./scripts { inherit pkgs; });
preferLocalBuild = true;
}
(import ./.).shells.default