Merge branch 'factorisation' into 'main'

Factorisation en un module crans

See merge request nounous/nixos!14
merge-requests/21/merge
lzebulon 2025-06-22 19:59:13 +02:00
commit 89ae1f5475
60 changed files with 1035 additions and 890 deletions

View File

@ -34,7 +34,10 @@
flake = with nixpkgs.lib; { flake = with nixpkgs.lib; {
nixosConfigurations = nixosConfigurations =
let let
baseModules = [ agenix.nixosModules.default ]; baseModules = [
./modules
agenix.nixosModules.default
];
in in
{ {
apprentix = nixosSystem { apprentix = nixosSystem {
@ -71,22 +74,17 @@
specialArgs = inputs; specialArgs = inputs;
modules = [ ./hosts/vm/two ] ++ baseModules; modules = [ ./hosts/vm/two ] ++ baseModules;
}; };
vaultwarden = nixosSystem { vaultwarden = nixosSystem {
specialArgs = inputs; specialArgs = inputs;
modules = [ ./hosts/vm/vaultwarden ] ++ baseModules; modules = [ ./hosts/vm/vaultwarden ] ++ baseModules;
};
}; };
};
}; };
perSystem = perSystem =
{ config, pkgs, ... }: { config, pkgs, ... }:
{ {
treefmt = {
projectRootFile = "flake.nix";
programs.nixpkgs-fmt.enable = true;
};
devShells = { devShells = {
default = pkgs.callPackage ./devshells/default.nix { inherit (inputs) agenix; }; default = pkgs.callPackage ./devshells/default.nix { inherit (inputs) agenix; };
}; };

View File

@ -4,10 +4,7 @@
imports = [ imports = [
./hardware-configuration.nix ./hardware-configuration.nix
./networking.nix ./networking.nix
./nginx.nix
../../../modules
../../../modules/services/nginx.nix
../../../modules/services/restic.nix
]; ];
networking.hostId = "bbdd1133"; networking.hostId = "bbdd1133";
@ -39,5 +36,19 @@
restic restic
]; ];
crans = {
enable = true;
networking.adm.enable = false;
resticClient.enable = false;
services = {
resticServer = {
enable = true;
port = 4242;
};
};
};
system.stateVersion = "24.05"; system.stateVersion = "24.05";
} }

View File

@ -0,0 +1,15 @@
{ config, ... }:
{
services.nginx = {
enable = true;
virtualHosts = {
"${config.networking.hostName}.adm.crans.org" = {
locations."/" = {
proxyPass = "http://${config.services.restic.server.listenAddress}";
};
};
};
};
}

View File

@ -2,14 +2,30 @@
Voici la liste des machines virtuelles sur NixOS ainsi que leur utilisation (par ordre alphabétique). Voici la liste des machines virtuelles sur NixOS ainsi que leur utilisation (par ordre alphabétique).
## apprentix
Machine des apprenti⋅e⋅s sous NixOS. Toustes les apprenti⋅e⋅s ont le droit de sudo (les home-nounous ne sont donc pas montés).
## jitsi
Serveur jitsi (vidéoconférence), accessible à <https://jitsi.crans.org>.
## livre
Serveur stirling (manipulation de PDF), accessible à <https://pdf.crans.org>.
## neo ## neo
Serveur Matrix (encore non déployé). Serveur Matrix, bridge IRC <-> Matrix et interface admin pour synapse, accessible à <https://matrix.crans.org/admin>.
## redite ## redite
Serveur libreddit, accessible à https://redite.crans.org. Serveur redlib (client WEB alternatif pour Reddit), accessible à <https://redite.crans.org>.
## two ## two
Serveur NixOS de test. Vous pouvez vous en servir comme base pour la configuration d'une nouvelle machine. Serveur NixOS de test. Vous pouvez vous en servir comme base pour la configuration d'une nouvelle machine.
## vaultwarden
Serveur vaultwarden (gestionnaire de mots de passe), accessible à <https://vaultwarden.crans.org>.

View File

@ -1,17 +1,29 @@
{ config, lib, ... }: { ... }:
{ {
imports = [ imports = [
./hardware-configuration.nix ./hardware-configuration.nix
./networking.nix
../../../modules
]; ];
boot.loader.grub.devices = [ "/dev/sda" ]; boot.loader.grub.devices = [ "/dev/sda" ];
networking.hostName = "apprentix"; networking.hostName = "apprentix";
crans = {
enable = true;
networking = {
id = "50";
srvNat.enable = true;
};
resticClient.when = "01:23";
homeNounou.enable = false;
users.root.passwordFile = ../../../secrets/apprentix/root.age;
};
security.sudo.extraRules = [ security.sudo.extraRules = [
{ {
groups = [ "_user" ]; groups = [ "_user" ];
@ -19,15 +31,5 @@
} }
]; ];
age.secrets = {
root-passwd-hash.file = ../../../secrets/apprentix/root.age;
};
users.users.root = {
hashedPasswordFile = config.age.secrets.root-passwd-hash.path;
};
crans.home_nounou.enable = false;
system.stateVersion = "24.11"; system.stateVersion = "24.11";
} }

View File

@ -1,65 +0,0 @@
{ ... }:
{
networking = {
interfaces = {
ens18 = {
ipv4 = {
addresses = [
{
address = "172.16.10.150";
prefixLength = 24;
}
];
};
ipv6 = {
addresses = [
{
address = "fd00::10:0:ff:fe01:5010";
prefixLength = 64;
}
];
};
};
ens19 = {
ipv4 = {
addresses = [
{
address = "172.16.3.150";
prefixLength = 24;
}
];
routes = [
{
address = "0.0.0.0";
via = "172.16.3.99";
prefixLength = 0;
}
];
};
ipv6 = {
addresses = [
{
address = "2a0c:700:3::ff:fe01:5003";
prefixLength = 64;
}
];
routes = [
{
address = "::";
via = "2a0c:700:3::ff:fe00:9903";
prefixLength = 0;
}
];
};
};
};
};
}

View File

@ -3,15 +3,29 @@
{ {
imports = [ imports = [
./hardware-configuration.nix ./hardware-configuration.nix
./networking.nix ./jitsi.nix
../../../modules
../../../modules/services/jitsi.nix
../../../modules/services/acme.nix
]; ];
networking.hostName = "jitsi"; networking.hostName = "jitsi";
boot.loader.grub.devices = [ "/dev/vda" ]; boot.loader.grub.devices = [ "/dev/vda" ];
crans = {
enable = true;
networking = {
id = "63";
srv = {
enable = true;
ipv4 = "185.230.79.15";
};
};
resticClient.when = "02:34";
services = {
acme.enable = true;
};
};
system.stateVersion = "24.11"; system.stateVersion = "24.11";
} }

View File

@ -1,22 +1,34 @@
# Do not modify this file! It was generated by nixos-generate-config # Do not modify this file! It was generated by nixos-generate-config
# and may be overwritten by future invocations. Please make changes # and may be overwritten by future invocations. Please make changes
# to /etc/nixos/configuration.nix instead. # to /etc/nixos/configuration.nix instead.
{ config, lib, pkgs, modulesPath, ... }: {
config,
lib,
pkgs,
modulesPath,
...
}:
{ {
imports = imports = [
[ (modulesPath + "/profiles/qemu-guest.nix") (modulesPath + "/profiles/qemu-guest.nix")
]; ];
boot.initrd.availableKernelModules = [ "ata_piix" "uhci_hcd" "virtio_pci" "sr_mod" "virtio_blk" ]; boot.initrd.availableKernelModules = [
"ata_piix"
"uhci_hcd"
"virtio_pci"
"sr_mod"
"virtio_blk"
];
boot.initrd.kernelModules = [ ]; boot.initrd.kernelModules = [ ];
boot.kernelModules = [ ]; boot.kernelModules = [ ];
boot.extraModulePackages = [ ]; boot.extraModulePackages = [ ];
fileSystems."/" = fileSystems."/" = {
{ device = "/dev/disk/by-uuid/66101184-15ad-4859-addf-95040bac1145"; device = "/dev/disk/by-uuid/66101184-15ad-4859-addf-95040bac1145";
fsType = "ext4"; fsType = "ext4";
}; };
swapDevices = [ ]; swapDevices = [ ];

View File

@ -0,0 +1,26 @@
{ ... }:
{
services.jitsi-meet = {
enable = true;
hostName = "jitsi.crans.org";
config = {
liveStreaming.enabled = true;
};
};
services.jitsi-videobridge = {
enable = true;
openFirewall = true;
};
services.prometheus.exporters.jitsi = {
enable = true;
port = 9700;
};
nixpkgs.config.permittedInsecurePackages = [
"jitsi-meet-1.0.8043"
];
}

View File

@ -1,53 +0,0 @@
{ ... }:
{
networking = {
interfaces = {
ens18 = {
ipv4 = {
addresses = [{
address = "172.16.10.163";
prefixLength = 24;
}];
};
ipv6 = {
addresses = [{
address = "fd00::10:0:ff:fe01:6310";
prefixLength = 64;
}];
};
};
ens19 = {
ipv4 = {
addresses = [{
address = "185.230.79.15";
prefixLength = 26;
}];
routes = [{
address = "0.0.0.0";
via = "185.230.79.62";
prefixLength = 0;
}];
};
ipv6 = {
addresses = [{
address = "2a0c:700:2::ff:fe01:6302";
prefixLength = 64;
}];
routes = [{
address = "::";
via = "2a0c:700:2::ff:fe00:9902";
prefixLength = 0;
}];
};
};
};
};
}

View File

@ -1,24 +1,23 @@
{ config, ... }: { ... }:
{ {
imports = [ imports = [
./hardware-configuration.nix ./hardware-configuration.nix
./networking.nix ./stirling.nix
../../../modules
../../../modules/services/nginx.nix
../../../modules/services/stirling.nix
]; ];
networking.hostName = "livre"; networking.hostName = "livre";
boot.loader.grub.devices = [ "/dev/sda" ]; boot.loader.grub.devices = [ "/dev/sda" ];
services.nginx.virtualHosts = { crans = {
"pdf.crans.org" = { enable = true;
locations."/" = {
proxyPass = "http://localhost:${toString config.services.stirling-pdf.environment.SERVER_PORT}"; networking = {
}; id = "40";
srvNat.enable = true;
}; };
resticClient.when = "03:45";
}; };
system.stateVersion = "24.11"; system.stateVersion = "24.11";

View File

@ -1,22 +1,35 @@
# Do not modify this file! It was generated by nixos-generate-config # Do not modify this file! It was generated by nixos-generate-config
# and may be overwritten by future invocations. Please make changes # and may be overwritten by future invocations. Please make changes
# to /etc/nixos/configuration.nix instead. # to /etc/nixos/configuration.nix instead.
{ config, lib, pkgs, modulesPath, ... }: {
config,
lib,
pkgs,
modulesPath,
...
}:
{ {
imports = imports = [
[ (modulesPath + "/profiles/qemu-guest.nix") (modulesPath + "/profiles/qemu-guest.nix")
]; ];
boot.initrd.availableKernelModules = [ "ata_piix" "uhci_hcd" "virtio_pci" "virtio_scsi" "sd_mod" "sr_mod" ]; boot.initrd.availableKernelModules = [
"ata_piix"
"uhci_hcd"
"virtio_pci"
"virtio_scsi"
"sd_mod"
"sr_mod"
];
boot.initrd.kernelModules = [ ]; boot.initrd.kernelModules = [ ];
boot.kernelModules = [ ]; boot.kernelModules = [ ];
boot.extraModulePackages = [ ]; boot.extraModulePackages = [ ];
fileSystems."/" = fileSystems."/" = {
{ device = "/dev/disk/by-uuid/9fed1492-e7b2-4ec2-a5f4-8825bf8e89a0"; device = "/dev/disk/by-uuid/9fed1492-e7b2-4ec2-a5f4-8825bf8e89a0";
fsType = "ext4"; fsType = "ext4";
}; };
swapDevices = [ ]; swapDevices = [ ];
@ -30,4 +43,3 @@
nixpkgs.hostPlatform = lib.mkDefault "x86_64-linux"; nixpkgs.hostPlatform = lib.mkDefault "x86_64-linux";
} }

View File

@ -1,53 +0,0 @@
{ ... }:
{
networking = {
interfaces = {
ens18 = {
ipv4 = {
addresses = [{
address = "172.16.10.140";
prefixLength = 24;
}];
};
ipv6 = {
addresses = [{
address = "fd00::10:0:ff:fe01:4010";
prefixLength = 64;
}];
};
};
ens19 = {
ipv4 = {
addresses = [{
address = "172.16.3.140";
prefixLength = 24;
}];
routes = [{
address = "0.0.0.0";
via = "172.16.3.99";
prefixLength = 0;
}];
};
ipv6 = {
addresses = [{
address = "2a0c:700:3::ff:fe01:4003";
prefixLength = 64;
}];
routes = [{
address = "::";
via = "2a0c:700:3::ff:fe00:9903";
prefixLength = 0;
}];
};
};
};
};
}

View File

@ -10,4 +10,16 @@
SYSTEM_DEFAULTLOCALE = "fr-FR"; SYSTEM_DEFAULTLOCALE = "fr-FR";
}; };
}; };
services.nginx = {
enable = true;
virtualHosts = {
"pdf.crans.org" = {
locations."/" = {
proxyPass = "http://localhost:${toString config.services.stirling-pdf.environment.SERVER_PORT}";
};
};
};
};
} }

View File

@ -3,16 +3,33 @@
{ {
imports = [ imports = [
./hardware-configuration.nix ./hardware-configuration.nix
./networking.nix ./matrix.nix
./matrix-appservice-irc.nix
../../../modules ./synapse-admin.nix
../../../modules/services/matrix.nix
../../../modules/services/synapse-admin.nix
]; ];
boot.loader.grub.devices = [ "/dev/sda" ]; boot.loader.grub.devices = [ "/dev/sda" ];
networking.hostName = "neo"; networking.hostName = "neo";
crans = {
enable = true;
networking = {
id = "41";
srv = {
enable = true;
ipv4 = "185.230.79.5";
};
};
resticClient.when = "04:56";
services = {
acme.enable = true;
coturn.enable = true;
};
};
system.stateVersion = "24.11"; system.stateVersion = "24.11";
} }

View File

@ -1,7 +1,8 @@
{ config {
, pkgs config,
, lib pkgs,
, ... lib,
...
}: }:
let let

View File

@ -1,35 +1,28 @@
{ config, ... }: { config, ... }:
{ {
imports = [
./acme.nix
./coturn.nix
./matrix-appservice-irc.nix
./nginx.nix
];
age.secrets = { age.secrets = {
ldap_synapse_password = { ldap_synapse_password = {
file = ../../secrets/neo/ldap_synapse_password.age; file = ../../../secrets/neo/ldap_synapse_password.age;
owner = "matrix-synapse"; owner = "matrix-synapse";
}; };
database_extra_config = { database_extra_config = {
file = ../../secrets/neo/database_extra_config.age; file = ../../../secrets/neo/database_extra_config.age;
owner = "matrix-synapse"; owner = "matrix-synapse";
}; };
note_oidc_extra_config = { note_oidc_extra_config = {
file = ../../secrets/neo/note_oidc_extra_config.age; file = ../../../secrets/neo/note_oidc_extra_config.age;
owner = "matrix-synapse"; owner = "matrix-synapse";
}; };
appservice_irc_db_env = { appservice_irc_db_env = {
file = ../../secrets/neo/appservice_irc_db_env.age; file = ../../../secrets/neo/appservice_irc_db_env.age;
}; };
coturn_auth_secret = { coturn_auth_secret = {
file = ../../secrets/neo/coturn_auth_secret.age; file = ../../../secrets/neo/coturn_auth_secret.age;
owner = "turnserver"; owner = "turnserver";
}; };
}; };

View File

@ -1,62 +0,0 @@
{ ... }:
{
networking = {
interfaces = {
ens18 = {
ipv4 = {
addresses = [
{
address = "172.16.10.141";
prefixLength = 24;
}
];
};
ipv6 = {
addresses = [
{
address = "fd00::10:0:ff:fe01:4110";
prefixLength = 64;
}
];
};
};
ens19 = {
ipv4 = {
addresses = [
{
address = "185.230.79.5";
prefixLength = 26;
}
];
routes = [
{
address = "0.0.0.0";
via = "185.230.79.62";
prefixLength = 0;
}
];
};
ipv6 = {
addresses = [
{
address = "2a0c:700:2::ff:fe01:4102";
prefixLength = 64;
}
];
routes = [{
address = "::";
via = "2a0c:700:2::ff:fe00:9902";
prefixLength = 0;
}];
};
};
};
firewall = {
enable = true;
};
};
}

View File

@ -0,0 +1,29 @@
{ pkgs, ... }:
let
synapse-admin_over = pkgs.synapse-admin-etkecc.overrideAttrs (_: {
yarnBuildFlags = "--base=/admin";
});
synapse-admin = synapse-admin_over.withConfig {
restrictBaseUrl = [
"https://matrix.crans.org"
];
asManagedUsers = [
"^@ircbot:crans\\.org$"
];
};
in
{
services.nginx = {
enable = true;
virtualHosts = {
"matrix.crans.org" = {
locations."/admin/".alias = synapse-admin + "/";
locations."=/admin".extraConfig = ''
return 301 /admin/;
'';
};
};
};
}

View File

@ -3,14 +3,22 @@
{ {
imports = [ imports = [
./hardware-configuration.nix ./hardware-configuration.nix
./networking.nix ./redlib.nix
../../../modules
../../../modules/services/libreddit.nix
]; ];
networking.hostName = "redite"; networking.hostName = "redite";
boot.loader.grub.devices = [ "/dev/sda" ]; boot.loader.grub.devices = [ "/dev/sda" ];
crans = {
enable = true;
networking = {
id = "39";
srvNat.enable = true;
};
resticClient.when = "06:18";
};
system.stateVersion = "23.11"; system.stateVersion = "23.11";
} }

View File

@ -1,65 +0,0 @@
{ ... }:
{
networking = {
interfaces = {
ens18 = {
ipv4 = {
addresses = [
{
address = "172.16.10.139";
prefixLength = 24;
}
];
};
ipv6 = {
addresses = [
{
address = "fd00::10:0:ff:fe01:3910";
prefixLength = 64;
}
];
};
};
ens19 = {
ipv4 = {
addresses = [
{
address = "172.16.3.139";
prefixLength = 24;
}
];
routes = [
{
address = "0.0.0.0";
via = "172.16.3.99";
prefixLength = 0;
}
];
};
ipv6 = {
addresses = [
{
address = "2a0c:700:3::ff:fe01:3903";
prefixLength = 64;
}
];
routes = [
{
address = "::";
via = "2a0c:700:3::ff:fe00:9903";
prefixLength = 0;
}
];
};
};
};
};
}

View File

@ -1,7 +1,7 @@
{ ... }: { ... }:
{ {
services.libreddit = { services.redlib = {
openFirewall = true; openFirewall = true;
port = 80; port = 80;
enable = true; enable = true;

View File

@ -3,13 +3,24 @@
{ {
imports = [ imports = [
./hardware-configuration.nix ./hardware-configuration.nix
./networking.nix
../../../modules
]; ];
networking.hostName = "two"; networking.hostName = "two";
boot.loader.grub.devices = [ "/dev/sda" ]; boot.loader.grub.devices = [ "/dev/sda" ];
crans = {
enable = true;
networking = {
id = "35";
srvNat = {
enable = true;
interface = "ens19";
};
};
resticClient.when = "07:29";
};
system.stateVersion = "23.11"; system.stateVersion = "23.11";
} }

View File

@ -1,65 +0,0 @@
{ ... }:
{
networking = {
interfaces = {
ens18 = {
ipv4 = {
addresses = [
{
address = "172.16.10.135";
prefixLength = 24;
}
];
};
ipv6 = {
addresses = [
{
address = "fd00::10:0:ff:fe01:3510";
prefixLength = 64;
}
];
};
};
ens19 = {
ipv4 = {
addresses = [
{
address = "172.16.3.135";
prefixLength = 24;
}
];
routes = [
{
address = "0.0.0.0";
via = "172.16.3.99";
prefixLength = 0;
}
];
};
ipv6 = {
addresses = [
{
address = "2a0c:700:3::ff:fe01:3503";
prefixLength = 64;
}
];
routes = [
{
address = "::";
via = "2a0c:700:3::ff:fe00:9903";
prefixLength = 0;
}
];
};
};
};
};
}

View File

@ -3,14 +3,22 @@
{ {
imports = [ imports = [
./hardware-configuration.nix ./hardware-configuration.nix
./networking.nix ./vaultwarden.nix
../../../modules
../../../modules/services/vaultwarden.nix
]; ];
networking.hostName = "vaultwarden"; networking.hostName = "vaultwarden";
boot.loader.grub.devices = [ "/dev/sda" ]; boot.loader.grub.devices = [ "/dev/sda" ];
crans = {
enable = true;
networking = {
id = "59";
srvNat.enable = true;
};
resticClient.when = "04:44";
};
system.stateVersion = "24.05"; system.stateVersion = "24.05";
} }

View File

@ -1,22 +1,35 @@
# Do not modify this file! It was generated by nixos-generate-config # Do not modify this file! It was generated by nixos-generate-config
# and may be overwritten by future invocations. Please make changes # and may be overwritten by future invocations. Please make changes
# to /etc/nixos/configuration.nix instead. # to /etc/nixos/configuration.nix instead.
{ config, lib, pkgs, modulesPath, ... }: {
config,
lib,
pkgs,
modulesPath,
...
}:
{ {
imports = imports = [
[ (modulesPath + "/profiles/qemu-guest.nix") (modulesPath + "/profiles/qemu-guest.nix")
]; ];
boot.initrd.availableKernelModules = [ "ata_piix" "uhci_hcd" "virtio_pci" "virtio_scsi" "sd_mod" "sr_mod" ]; boot.initrd.availableKernelModules = [
"ata_piix"
"uhci_hcd"
"virtio_pci"
"virtio_scsi"
"sd_mod"
"sr_mod"
];
boot.initrd.kernelModules = [ ]; boot.initrd.kernelModules = [ ];
boot.kernelModules = [ ]; boot.kernelModules = [ ];
boot.extraModulePackages = [ ]; boot.extraModulePackages = [ ];
fileSystems."/" = fileSystems."/" = {
{ device = "/dev/disk/by-uuid/c97aeccd-b88a-407e-a08d-f821a3f34936"; device = "/dev/disk/by-uuid/c97aeccd-b88a-407e-a08d-f821a3f34936";
fsType = "ext4"; fsType = "ext4";
}; };
swapDevices = [ ]; swapDevices = [ ];

View File

@ -1,53 +0,0 @@
{ ... }:
{
networking = {
interfaces = {
ens18 = {
ipv4 = {
addresses = [{
address = "172.16.10.159";
prefixLength = 24;
}];
};
ipv6 = {
addresses = [{
address = "fd00::10:0:ff:fe01:5910";
prefixLength = 64;
}];
};
};
ens19 = {
ipv4 = {
addresses = [{
address = "172.16.3.159";
prefixLength = 24;
}];
routes = [{
address = "0.0.0.0";
via = "172.16.3.99";
prefixLength = 0;
}];
};
ipv6 = {
addresses = [{
address = "2a0c:700:3::ff:fe01:5903";
prefixLength = 64;
}];
routes = [{
address = "::";
via = "2a0c:700:3::ff:fe00:9903";
prefixLength = 0;
}];
};
};
};
};
}

View File

@ -1,13 +1,9 @@
{ config, lib, ... }: { config, lib, ... }:
{ {
imports = [
./nginx.nix
];
age.secrets = { age.secrets = {
env = { vaultwarden-env = {
file = ../../secrets/vaultwarden/env.age; file = ../../../secrets/vaultwarden/env.age;
}; };
}; };
@ -15,12 +11,13 @@
enable = true; enable = true;
dbBackend = "postgresql"; dbBackend = "postgresql";
environmentFile = config.age.secrets.env.path; environmentFile = config.age.secrets.vaultwarden-env.path;
config = { config = {
ROCKET_PORT = 8222; ROCKET_PORT = 8222;
SENDMAIL_COMMAND = "${config.security.wrapperDir}/sendmail"; SENDMAIL_COMMAND = "${config.security.wrapperDir}/sendmail";
}; };
}; };
users.users.vaultwarden.extraGroups = [ "nullmailer" ]; users.users.vaultwarden.extraGroups = [ "nullmailer" ];
systemd.services.vaultwarden = { systemd.services.vaultwarden = {
@ -37,10 +34,14 @@
}; };
}; };
services.nginx.virtualHosts."vaultwarden.crans.org" = { services.nginx = {
locations."/" = { enable = true;
proxyPass = "http://localhost:${toString config.services.vaultwarden.config.ROCKET_PORT}";
proxyWebsockets = true; virtualHosts."vaultwarden.crans.org" = {
locations."/" = {
proxyPass = "http://localhost:${toString config.services.vaultwarden.config.ROCKET_PORT}";
proxyWebsockets = true;
};
}; };
}; };
} }

View File

@ -12,4 +12,4 @@ Le dossier [`crans`](crans) contient tous les services/programmes communs à tou
## Services ## Services
Le dossier [`services`](services) contient tous les services/programmes utilisés par un nombre restreint de machines. On peut y déclarer deux types de configurations : les configurations directement inscrites car seront toujours utilisées de la même façon, et les configurations mettant en place un système d'options et de configuration générée pour avoir plus de granularités. Cette seconde utilisation est plus complexe à mettre en place et nécessite une meilleure compréhension de `nix`. Le dossier [`services`](services) contient tous les services/programmes utilisés par un nombre restreint de machines. On y déclare les configurations mettant en place un système d'options et de configuration générée pour avoir plus de granularités.

View File

@ -2,9 +2,15 @@
Ce dossier contient tous les modules commun à la majorité des machines virtuelles du Crans. On y retrouve par exemple les utilisateurices, les `home_nounou`, etc. Ce dossier contient tous les modules commun à la majorité des machines virtuelles du Crans. On y retrouve par exemple les utilisateurices, les `home_nounou`, etc.
Ces modules sont présentés sous forme d'option (si besoin), afin de pouvoir contrôler la présence ou l'absence de certains services.
## `default.nix` ## `default.nix`
Le fichier [`default.nix`](default.nix), comme tous les autres du même nom, importe tous les autres fichiers du dossier. De plus, il déclare des programmes utiles à avoir en permanence, tels que `ssh`, `git`, `nvim`, ... Le fichier [`default.nix`](default.nix), comme tous les autres du même nom, importe tous les autres fichiers du dossier. De plus, il déclare des programmes utiles à avoir en permanence, tels que `ssh`, `git`, `nvim`, ... et importe les options par défaut qui sont utile pour la majorité des machines.
## `age.nix`
Le fichier [`age.nix`](age.nix) contient la configuration commune d'agenix (voir [`../../secrets/README.md`](../../secrets/README.md)).
## `home.nix` ## `home.nix`
@ -14,18 +20,38 @@ Le fichier [`home.nix`](home.nix) monte les `home_nounou` par NFS à partir de `
Le fichier [`locale.nix`](locale.nix) déclare simplement les locales à utiliser. Le fichier [`locale.nix`](locale.nix) déclare simplement les locales à utiliser.
## `monitoring.nix`
Le fichier [`monitoring.nix`] déploie une instance prometheus avec un exporteur node contactable sur le port `9100` par défaut, ainsi qu'un exporteur nginx (si pertinent) sur le port `9117`.
## `networking.nix` ## `networking.nix`
Le fichier [`networking.nix`](networking.nix) a moins d'utilité que ce à quoi on pourrait s'attendre : comme chaque machine possède sa propre configuration réseau, les seules choses communes à déclarer sont : la non-utilisation de DHCP, la non-utilisation d'un pare-feu par défault ainsi que l'ajout d'un serveur DNS. Le fichier [`networking.nix`](networking.nix) contient toute la configuration réseau des machines : l'option `crans.networking.id` permet de configurer la majorité du réseau automatiquement (il faut alors déployer interface par interface).
## `ntp.nix` ## `ntp.nix`
Le fichier [`ntp.nix`](ntp.nix) active simplement le NTP (Network Time Protocol) en ajoutant le serveur `ntp.adm.crans.org` comme serveur de temps. Le fichier [`ntp.nix`](ntp.nix) active simplement le NTP (Network Time Protocol) en ajoutant le serveur `ntp.adm.crans.org` comme serveur de temps.
## `sops.nix` ## `nullmailer.nix`
Le fichier [`sops.nix`](sops.nix) déclare l'utilisation de `sops` dans la configuration (voir [ce `README.md`](../../secrets/README.md) pour plus de détails) et importe la clef publique SSH de la machine pour pouvoir l'utiliser dans la gestion des secrets. Le fichier [`nullmailer.nix`](nullmailer.nix) déploie un client SMTP sur chaque serveur afin de pouvoir envoyer des mails en le nom du Crans.
## `packages.nix`
Le fichier [`packages.nix`](packages.nix) contient la liste des programmes installés par défaut sur les machines du Crans.
## `restic_client.nix`
Le fichier [`restic_client`](restic_client.nix) permet de configurer un client restic sur chaque machine pour faire des backups et les envoyer sur le serveur thot.
## `ssh.nix`
Le fichier [`ssh.nix`](ssh.nix) contient la configuration SSH pour toutes les machines.
## `users.nix` ## `users.nix`
Le fichier [`users.nix`](users.nix) configure les `_users` à partir du LDAP d'administration, et configure les droits pour que les `_nounou` aient les accès `sudo`. Il configure également le user `root` en lui donnant son mot de passe haché à travers un fichier `sops`. Le fichier [`users.nix`](users.nix) configure les `_users` à partir du LDAP d'administration, et configure les droits pour que les `_nounou` aient les accès `sudo`. Il configure également le user `root` en lui donnant son mot de passe haché à travers un fichier `age`.
## `virtualisation.nix`
Le fichier [`virtualisation.nix`](virtualisation.nix) contient des paramètres utiles pour la virtualisation (pour les VM en priorité donc).

View File

@ -1,5 +1,10 @@
{ pkgs, ... }: { lib, config, ... }:
let
cfg = config.crans;
inherit (lib) mkEnableOption mkIf;
in
{ {
imports = [ imports = [
./age.nix ./age.nix
@ -10,32 +15,28 @@
./restic_client.nix ./restic_client.nix
./monitoring.nix ./monitoring.nix
./nullmailer.nix ./nullmailer.nix
./packages.nix
./ssh.nix
./users.nix ./users.nix
./virtualisation.nix
]; ];
services.qemuGuest.enable = true; options.crans = {
boot.kernelParams = [ "console=ttyS0,115200" ]; enable = mkEnableOption "Configuration commune à toutes les machines du Crans";
services.openssh = {
enable = true;
}; };
nixpkgs.config.allowUnfree = true; config = mkIf cfg.enable {
crans = {
# Enable some utility programs. homeNounou.enable = lib.mkDefault true;
programs.git.enable = true; monitoring.enable = true;
programs.htop.enable = true; networking = {
programs.neovim.enable = true; enable = true;
programs.screen.enable = true; adm.enable = lib.mkDefault true;
programs.tmux.enable = true; };
programs.vim.enable = true; resticClient.enable = lib.mkDefault true;
users = {
environment.systemPackages = with pkgs; [ ldap.enable = true;
bat };
fd };
helix };
nfs-utils
ripgrep
shelldap
];
} }

View File

@ -1,24 +1,17 @@
{ { lib, config, ... }:
pkgs,
lib,
config,
...
}:
let let
cfg = config.crans.home_nounou; cfg = config.crans.homeNounou;
inherit (lib) mkEnableOption mkIf;
in in
{ {
options.crans.home_nounou = { options.crans.homeNounou = {
enable = lib.mkOption { enable = mkEnableOption "Monter /home_nounou.";
type = lib.types.bool;
default = true;
description = "Monter les home nounous";
};
}; };
config = lib.mkIf cfg.enable { config = mkIf cfg.enable {
fileSystems.home_nounou = { fileSystems.home_nounou = {
mountPoint = "/home_nounou"; mountPoint = "/home_nounou";
device = "172.16.10.1:/pool/home"; device = "172.16.10.1:/pool/home";

View File

@ -1,17 +1,44 @@
{ config, ... }: { config, lib, ... }:
{
services.prometheus.exporters = {
node = {
enable = true;
port = 9100;
openFirewall = true; let
}; cfg = config.crans.monitoring;
inherit (lib)
mkEnableOption
mkIf
mkOption
types
;
in
{
options.crans.monitoring = {
enable = mkEnableOption "Monitoring prometheus de la machine.";
nginx = { nginx = {
enable = config.services.nginx.enable; enable = mkOption {
port = 9117; type = types.bool;
scrapeUri = "http://[::1]:6424/stub_status"; default = config.services.nginx.enable;
example = true;
description = "Monitoring de Nginx par prometheus.";
};
};
};
config = mkIf cfg.enable {
services.prometheus.exporters = {
node = {
enable = true;
port = 9100;
openFirewall = true;
};
nginx = {
enable = cfg.nginx.enable;
port = 9117;
scrapeUri = "http://[::1]:6424/stub_status";
};
}; };
}; };
} }

View File

@ -1,10 +1,216 @@
{ lib, ... }: { lib, config, ... }:
let
cfg = config.crans.networking;
inherit (lib)
mkEnableOption
mkIf
mkOption
types
;
in
{ {
# Les interfaces ne sont pas déclarées ici : elles sont propres à chaque VM. options.crans.networking = {
networking = { enable = mkEnableOption "Configuration réseaux commune à toutes les machines du Crans.";
useDHCP = false;
firewall.enable = lib.mkDefault false; id = mkOption {
nameservers = [ "172.16.10.128" ]; type = types.str;
example = "35";
description = "Le numéro de la VM dans Proxmox (sans le `1` devant).";
};
adm = {
enable = mkEnableOption "Configuration du VLAN adm.";
interface = mkOption {
type = types.str;
default = "ens18";
example = "ens20";
description = "Nom de l'interface réseau sur laquelle est située le VLAN adm.";
};
};
srv = {
enable = mkEnableOption "Configuration du VLAN srv.";
interface = mkOption {
type = types.str;
default = "ens18";
example = "ens19";
description = "Nom de l'interface réseau sur laquelle est située le VLAN srv.";
};
ipv4 = mkOption {
type = types.str;
example = "185.230.79.1";
description = "Adresse IPv4 de la machine.";
};
};
srvNat = {
enable = mkEnableOption "Configuration du VLAN srv-nat.";
interface = mkOption {
type = types.str;
default = "ens19";
example = "ens20";
description = "Nom de l'interface réseau sur laquelle est située le VLAN srv-nat.";
};
};
san = {
enable = mkEnableOption "Configuration du VLAN san.";
interface = mkOption {
type = types.str;
example = "ens19";
description = "Nom de l'interface réseau sur laquelle est située le VLAN san.";
};
};
};
config = mkIf cfg.enable {
networking =
{
useDHCP = false;
firewall.enable = lib.mkDefault false;
nameservers = [ "172.16.10.128" ];
}
//
# Configuration du VLAN adm
(
if cfg.adm.enable then
{
interfaces."${cfg.adm.interface}" = {
ipv4.addresses = [
{
address = "172.16.10.1${cfg.id}";
prefixLength = 24;
}
];
ipv6.addresses = [
{
address = "fd00::10:0:ff:fe01:${cfg.id}10";
prefixLength = 64;
}
];
};
}
else
{ }
)
//
# Configuration du VLAN srv
(
if cfg.srv.enable then
{
firewall.enable = true;
interfaces."${cfg.srv.interface}" = {
ipv4 = {
addresses = [
{
address = cfg.srv.ipv4;
prefixLength = 26;
}
];
routes = [
{
address = "0.0.0.0";
via = "185.230.79.62";
prefixLength = 0;
}
];
};
ipv6 = {
addresses = [
{
address = "2a0c:700:2::ff::fe01:${cfg.id}02";
prefixLength = 64;
}
];
routes = [
{
address = "::";
via = "2a0c:700:2::ff:fe00:9902";
prefixLength = 0;
}
];
};
};
}
else
{ }
)
//
# Configuration du VLAN srv-nat
(
if cfg.srvNat.enable then
{
interfaces."${cfg.srvNat.interface}" = {
ipv4 = {
addresses = [
{
address = "172.16.3.1${cfg.id}";
prefixLength = 24;
}
];
routes = [
{
address = "0.0.0.0";
via = "172.16.3.99";
prefixLength = 0;
}
];
};
ipv6 = {
addresses = [
{
address = "2a0c:700:3::ff:fe01:${cfg.id}03";
prefixLength = 64;
}
];
routes = [
{
address = "::";
via = "2a0c:700:3::ff:fe00:9903";
prefixLength = 0;
}
];
};
};
}
else
{ }
)
//
# Configuration du VLAN san
(
if cfg.san.enable then
{
interfaces."${cfg.san.interface}" = {
ipv4.addresses = [
{
address = "172.16.4.1${cfg.id}";
prefixLength = 24;
}
];
ipv6.addresses = [
{
address = "fd00::4:0:ff:fe01:${cfg.id}04";
prefixLength = 64;
}
];
};
}
else
{ }
);
}; };
} }

View File

@ -0,0 +1,21 @@
{ pkgs, ... }:
{
programs.git.enable = true;
programs.htop.enable = true;
programs.neovim.enable = true;
programs.screen.enable = true;
programs.tmux.enable = true;
programs.vim.enable = true;
environment.systemPackages = with pkgs; [
bat
coreutils-full
fd
helix
inetutils
nfs-utils
ripgrep
shelldap
];
}

View File

@ -1,36 +1,73 @@
{ config, ... }: { config, lib, ... }:
let
cfg = config.crans.resticClient;
inherit (lib)
mkEnableOption
mkIf
mkOption
types
;
in
{ {
age.secrets = { options.crans.resticClient = {
restic-base-env.file = ../../secrets/restic/client_env.age; enable = mkEnableOption "Configuration générale pour le client restic.";
restic-base-repo.file = ../../secrets/restic/${config.networking.hostName}/base-repo.age;
restic-base-password.file = ../../secrets/restic/${config.networking.hostName}/base-password.age; additionalPaths = mkOption {
type = types.listOf types.path;
default = [ ];
example = [ "/backup" ];
description = "Chemins à backuper en plus de ceux par défaut.";
};
additionalExcludes = mkOption {
type = types.listOf types.path;
default = [ ];
example = [ "/var/lib/<service>/cache" ];
description = "Chemins à exclure des backups en plus de ceux par défaut.";
};
when = mkOption {
type = types.str;
example = "05:42";
description = "À quelle heure faire les backups.";
};
}; };
services.restic.backups = { config = mkIf cfg.enable {
base = { age.secrets = {
exclude = [ restic-base-env.file = ../../secrets/restic/client_env.age;
"/var/cache" restic-base-repo.file = ../../secrets/restic/${config.networking.hostName}/base-repo.age;
"/var/lib/lxcfs" restic-base-password.file = ../../secrets/restic/${config.networking.hostName}/base-password.age;
]; };
initialize = true;
passwordFile = config.age.secrets.restic-base-password.path; services.restic.backups = {
repositoryFile = config.age.secrets.restic-base-repo.path; base = {
environmentFile = config.age.secrets.restic-base-env.path; initialize = true;
paths = [ passwordFile = config.age.secrets.restic-base-password.path;
"/etc" repositoryFile = config.age.secrets.restic-base-repo.path;
"/var" environmentFile = config.age.secrets.restic-base-env.path;
]; paths = [
timerConfig = { "/etc"
OnCalendar = "00:00"; "/var"
RandomizedDelaySec = "6h"; ] ++ cfg.additionalPaths;
exclude = [
"/var/cache"
"/var/lib/lxcfs"
] ++ cfg.additionalExcludes;
timerConfig = {
OnCalendar = cfg.when;
RandomizedDelaySec = "6h";
};
pruneOpts = [
"--keep-daily 2"
"--keep-weekly 2"
"--keep-monthly 2"
"--keep-yearly 1"
];
}; };
pruneOpts = [
"--keep-daily 2"
"--keep-weekly 2"
"--keep-monthly 2"
"--keep-yearly 1"
];
}; };
}; };
} }

View File

@ -0,0 +1,11 @@
{ ... }:
{
services.openssh = {
enable = true;
settings = {
PermitRootLogin = "yes";
};
};
}

View File

@ -1,50 +1,75 @@
{ config, lib, ... }: { config, lib, ... }:
{ let
users = { cfg = config.crans.users;
mutableUsers = false;
inherit (lib)
mkEnableOption
mkOption
types
;
in
{
options.crans.users = {
ldap = { ldap = {
enable = true; enable = mkEnableOption "Authentification par le LDAP adm.";
base = "dc=crans,dc=org"; };
server = "ldaps://ldap-adm.adm.crans.org/";
daemon = { root = {
enable = true; passwordFile = mkOption {
extraConfig = '' type = types.path;
ldap_version 3 default = ../../secrets/common/root.age;
tls_reqcert allow example = ../../secrets/apprentix/root.age;
map passwd loginShell /run/current-system/sw/bin/bash description = "Fichier chiffré par age contenant le mot de passe root.";
'';
}; };
}; };
}; };
security.sudo = { config = {
enable = true; age.secrets.root-passwd-hash = {
extraConfig = '' file = cfg.root.passwordFile;
Defaults passprompt_override };
Defaults passprompt="[sudo] mot de passe pour %p sur %h: "
'';
extraRules = [
{
groups = [ "_user" ];
runAs = "root:ALL";
commands = [ "NOPASSWD:/usr/bin/qm list" ];
}
{
groups = [ "_nounou" ];
commands = [ "ALL" ];
}
];
};
age.secrets.root-passwd-hash = { users = {
file = lib.mkDefault ../../secrets/common/root.age; mutableUsers = false;
};
users.users.root = { users.root = {
hashedPasswordFile = lib.mkDefault config.age.secrets.root-passwd-hash.path; hashedPasswordFile = config.age.secrets.root-passwd-hash.path;
}; };
services.openssh.settings.PermitRootLogin = "yes"; ldap = {
enable = cfg.ldap.enable;
base = "dc=crans,dc=org";
server = "ldaps://ldap-adm.adm.crans.org/";
daemon = {
enable = true;
extraConfig = ''
ldap_version 3
tls_reqcert allow
map passwd loginShell /run/current-system/sw/bin/bash
'';
};
};
};
security.sudo = {
enable = true;
extraConfig = ''
Defaults passprompt_override
Defaults passprompt="[sudo] mot de passe pour %p sur %h: "
'';
extraRules = [
{
groups = [ "_user" ];
runAs = "root:ALL";
commands = [ "NOPASSWD:/usr/bin/qm list" ];
}
{
groups = [ "_nounou" ];
commands = [ "ALL" ];
}
];
};
};
} }

View File

@ -0,0 +1,6 @@
{ ... }:
{
services.qemuGuest.enable = true;
boot.kernelParams = [ "console=ttyS0,115200" ];
}

View File

@ -3,10 +3,25 @@
{ {
imports = [ imports = [
./crans ./crans
./services
]; ];
nix.settings.experimental-features = [ nix = {
"flakes" settings = {
"nix-command" experimental-features = [
]; "flakes"
"nix-command"
];
auto-optimise-store = true;
};
};
nixpkgs.config = {
allowUnfree = true;
};
boot.tmp = {
useTmpfs = true;
cleanOnBoot = true;
};
} }

View File

@ -1,24 +1,36 @@
{ config, ... }: { config, lib, ... }:
let
cfg = config.crans.services.acme;
inherit (lib) mkEnableOption mkIf;
in
{ {
age.secrets = { options.crans.services.acme = {
acme-env.file = ../../secrets/acme/env.age; enable = mkEnableOption "Activer les certificats ACME via let's encrypt.";
}; };
security.acme = { config = mkIf cfg.enable {
acceptTerms = true; age.secrets = {
acme-env.file = ../../secrets/acme/env.age;
defaults = {
email = "root@crans.org";
dnsPropagationCheck = false;
}; };
certs."crans.org" = { security.acme = {
domain = "*.crans.org"; acceptTerms = true;
dnsProvider = "rfc2136";
# Contient le serveur à contacter avec le protocole defaults = {
# et le mot de passe email = "root@crans.org";
environmentFile = config.age.secrets.acme-env.path; dnsPropagationCheck = false;
};
certs."crans.org" = {
domain = "*.crans.org";
dnsProvider = "rfc2136";
# Contient le serveur à contacter avec le protocole
# et le mot de passe
environmentFile = config.age.secrets.acme-env.path;
};
}; };
}; };
} }

View File

@ -1,59 +1,100 @@
{ config, ... }: { config, lib, ... }:
let
cfg = config.crans.services.coturn;
inherit (lib)
mkEnableOption
mkOption
mkIf
types
;
in
{ {
services.coturn = { options.crans.services.coturn = {
enable = true; enable = mkEnableOption "Coturn, un serveur TURN open-source.";
no-cli = true;
no-tcp-relay = true; secretFile = mkOption {
min-port = 49000; type = types.path;
max-port = 50000; default = config.age.secrets.coturn_auth_secret.path;
use-auth-secret = true; description = "Fichier contenant le secret de configuration du serveur.";
static-auth-secret-file = config.age.secrets.coturn_auth_secret.path; };
realm = "crans.org";
cert = "/var/lib/acme/crans.org/full.pem"; fqdn = mkOption {
pkey = "/var/lib/acme/crans.org/key.pem"; type = types.str;
extraConfig = '' default = "crans.org";
verbose description = "Domaine pour lequel le serveur coturn est configuré.";
no-multicast-peers };
denied-peer-ip=0.0.0.0-0.255.255.255
denied-peer-ip=10.0.0.0-10.255.255.255 certFile = mkOption {
denied-peer-ip=100.64.0.0-100.127.255.255 type = types.path;
denied-peer-ip=127.0.0.0-127.255.255.255 default = "/var/lib/acme/${cfg.fqdn}/full.pem";
denied-peer-ip=169.254.0.0-169.254.255.255 description = "Fichier contenant le certificat associé au FQDN.";
denied-peer-ip=172.16.0.0-172.31.255.255 };
denied-peer-ip=192.0.0.0-192.0.0.255
denied-peer-ip=192.0.2.0-192.0.2.255 keyFile = mkOption {
denied-peer-ip=192.88.99.0-192.88.99.255 type = types.path;
denied-peer-ip=192.168.0.0-192.168.255.255 default = "/var/lib/acme/${cfg.fqdn}/key.pem";
denied-peer-ip=198.18.0.0-198.19.255.255 description = "Fichier contenant la clef associé au FQDN.";
denied-peer-ip=198.51.100.0-198.51.100.255 };
denied-peer-ip=203.0.113.0-203.0.113.255
denied-peer-ip=240.0.0.0-255.255.255.255
denied-peer-ip=::1
denied-peer-ip=64:ff9b::-64:ff9b::ffff:ffff
denied-peer-ip=::ffff:0.0.0.0-::ffff:255.255.255.255
denied-peer-ip=100::-100::ffff:ffff:ffff:ffff
denied-peer-ip=2001::-2001:1ff:ffff:ffff:ffff:ffff:ffff:ffff
denied-peer-ip=2002::-2002:ffff:ffff:ffff:ffff:ffff:ffff:ffff
denied-peer-ip=fc00::-fdff:ffff:ffff:ffff:ffff:ffff:ffff:ffff
denied-peer-ip=fe80::-febf:ffff:ffff:ffff:ffff:ffff:ffff:ffff
'';
}; };
networking.firewall = { config = mkIf cfg.enable {
allowedTCPPorts = [ services.coturn = {
3478 enable = true;
5349 no-cli = true;
]; no-tcp-relay = true;
allowedUDPPorts = [ min-port = 49000;
3478 max-port = 50000;
5349 use-auth-secret = true;
]; static-auth-secret-file = cfg.secretFile;
allowedUDPPortRanges = [ realm = cfg.fqdn;
{ cert = cfg.certFile;
from = config.services.coturn.min-port; pkey = cfg.keyFile;
to = config.services.coturn.max-port; extraConfig = ''
} verbose
]; no-multicast-peers
denied-peer-ip=0.0.0.0-0.255.255.255
denied-peer-ip=10.0.0.0-10.255.255.255
denied-peer-ip=100.64.0.0-100.127.255.255
denied-peer-ip=127.0.0.0-127.255.255.255
denied-peer-ip=169.254.0.0-169.254.255.255
denied-peer-ip=172.16.0.0-172.31.255.255
denied-peer-ip=192.0.0.0-192.0.0.255
denied-peer-ip=192.0.2.0-192.0.2.255
denied-peer-ip=192.88.99.0-192.88.99.255
denied-peer-ip=192.168.0.0-192.168.255.255
denied-peer-ip=198.18.0.0-198.19.255.255
denied-peer-ip=198.51.100.0-198.51.100.255
denied-peer-ip=203.0.113.0-203.0.113.255
denied-peer-ip=240.0.0.0-255.255.255.255
denied-peer-ip=::1
denied-peer-ip=64:ff9b::-64:ff9b::ffff:ffff
denied-peer-ip=::ffff:0.0.0.0-::ffff:255.255.255.255
denied-peer-ip=100::-100::ffff:ffff:ffff:ffff
denied-peer-ip=2001::-2001:1ff:ffff:ffff:ffff:ffff:ffff:ffff
denied-peer-ip=2002::-2002:ffff:ffff:ffff:ffff:ffff:ffff:ffff
denied-peer-ip=fc00::-fdff:ffff:ffff:ffff:ffff:ffff:ffff:ffff
denied-peer-ip=fe80::-febf:ffff:ffff:ffff:ffff:ffff:ffff:ffff
'';
};
networking.firewall = {
allowedTCPPorts = [
3478
5349
];
allowedUDPPorts = [
3478
5349
];
allowedUDPPortRanges = [
{
from = config.services.coturn.min-port;
to = config.services.coturn.max-port;
}
];
};
}; };
} }

View File

@ -0,0 +1,10 @@
{ ... }:
{
imports = [
./acme.nix
./coturn.nix
./nginx.nix
./restic.nix
];
}

View File

@ -1,44 +0,0 @@
{ ... }:
{
# il y a une faille de secu mais c'est pas exploitable
# libolm : https://github.com/NixOS/nixpkgs/pull/334638#issuecomment-2289025802
nixpkgs.config.permittedInsecurePackages = [
"jitsi-meet-1.0.8043"
];
services.jitsi-meet = {
enable = true;
hostName = "jitsi.crans.org";
config = {
# vient de l'ancienne config liveStreamingEnable = true
liveStreaming.enabled = true;
};
};
services.jitsi-videobridge = {
enable = true;
#xmppConfigs."localhost" = {
# port = 5347;
#};
openFirewall = true;
};
services.jicofo = {
enable = true;
config = {
xmpp = {
trusted-domains = [ "recoder.jitsi.crans.org" ];
};
};
};
services.prometheus.exporters.jitsi = {
enable = true;
};
}

View File

@ -1,9 +1,7 @@
{ ... }: { lib, config, ... }:
{ {
services.nginx = { services.nginx = lib.mkIf config.services.nginx.enable {
enable = true;
recommendedProxySettings = true; recommendedProxySettings = true;
recommendedOptimisation = true; recommendedOptimisation = true;

View File

@ -1,19 +1,42 @@
{ config, ... }: { config, lib, ... }:
let
cfg = config.crans.services.resticServer;
inherit (lib)
mkEnableOption
mkIf
mkOption
types
;
in
{ {
services.restic.server = { options.crans.services.resticServer = {
enable = true; enable = mkEnableOption "Serveur de backups restic.";
dataDir = "/backups"; dataDir = mkOption {
listenAddress = "localhost:4242"; type = types.path;
privateRepos = true; default = "/backups";
example = "/var/backups";
description = "Dossier dans lequel les backups seront effectuées.";
};
port = mkOption {
type = types.int;
default = 8080;
example = 4242;
description = "Port sur lequel le serveur restic écoute.";
};
}; };
services.nginx.virtualHosts = { config = mkIf cfg.enable {
"${config.networking.hostName}.adm.crans.org" = { services.restic.server = {
locations."/" = { enable = true;
proxyPass = "http://${config.services.restic.server.listenAddress}";
}; dataDir = cfg.dataDir;
listenAddress = "localhost:${toString cfg.port}";
privateRepos = true;
}; };
}; };
} }

View File

@ -1,28 +0,0 @@
{ pkgs, ... }:
let
synapse-admin_over = pkgs.synapse-admin-etkecc.overrideAttrs (_: { yarnBuildFlags = "--base=/admin"; });
synapse-admin = synapse-admin_over
.withConfig {
restrictBaseUrl = [
"https://matrix.crans.org"
];
asManagedUsers = [
"^@ircbot:crans\\.org$"
];
};
in
{
imports = [
./nginx.nix
];
services.nginx.virtualHosts = {
"matrix.crans.org" = {
locations."/admin/".alias = synapse-admin + "/";
locations."=/admin".extraConfig = ''
return 301 /admin/;
'';
};
};
}

View File

@ -1,4 +1,11 @@
let let
inherit (import <nixpkgs> { }) lib;
inherit (lib)
attrsets
filesystem
lists
path
;
# Nounous # Nounous
aeltheos_0 = "age1yubikey1qvn7t9hplvnr2w8nsfezfqudz8gq3v8sq99dkdpzmm4a74rng5qgz4v6wzt"; aeltheos_0 = "age1yubikey1qvn7t9hplvnr2w8nsfezfqudz8gq3v8sq99dkdpzmm4a74rng5qgz4v6wzt";
@ -21,80 +28,52 @@ let
# Machines # Machines
apprentix = "ssh-ed25519 AAAAC3NzaC1lZDI1NTE5AAAAIDCJV6jqQWEYuwi+OJ9r/4TbBN/cK9NvYWNiJhpFzcc7 root@apprentix";
cephiroth = "ssh-ed25519 AAAAC3NzaC1lZDI1NTE5AAAAIOsBGkhiu6l3jeo15cQHMu3dPyL025zXPV2ZH02EDYEt root@nixos";
jitsi = "ssh-ed25519 AAAAC3NzaC1lZDI1NTE5AAAAIB6jVMIZ5y2oXX9HOkw7r5UUjw95MlFaFuu7FnEC0Q8z root@jitsi";
livre = "ssh-ed25519 AAAAC3NzaC1lZDI1NTE5AAAAIEVfKNokHG6ig32hhQxTep+fKFmKahlDClPrX/dP4/gb root@livre";
neo = "ssh-ed25519 AAAAC3NzaC1lZDI1NTE5AAAAIMGfSvxqC2PJYRrxJaivVDujwlwCZ6AwH8hOSA9ktZ1V root@neo";
redite = "ssh-ed25519 AAAAC3NzaC1lZDI1NTE5AAAAIOwfVmR3NjZf6qkDlTSiyo39Up5nSNUVW7jYDWXrY8Xr root@redite";
thot = "ssh-ed25519 AAAAC3NzaC1lZDI1NTE5AAAAIFKNg1b8ft1L55+joXQ/7Dt2QTOdkea8opTEnq4xrhPU root@thot";
two = "ssh-ed25519 AAAAC3NzaC1lZDI1NTE5AAAAIPpaGf8A+XWXBdNrs69RiC0qPbjPHdtkl31OjxrktmF6 root@nixos";
vaultwarden = "ssh-ed25519 AAAAC3NzaC1lZDI1NTE5AAAAICn6vfDlsZVU6TEWg9vTgq9+Fp3irHjytBTky7A4ErRM root@vaultwarden";
hosts = { hosts = {
inherit apprentix = "ssh-ed25519 AAAAC3NzaC1lZDI1NTE5AAAAIDCJV6jqQWEYuwi+OJ9r/4TbBN/cK9NvYWNiJhpFzcc7 root@apprentix";
apprentix cephiroth = "ssh-ed25519 AAAAC3NzaC1lZDI1NTE5AAAAIOsBGkhiu6l3jeo15cQHMu3dPyL025zXPV2ZH02EDYEt root@nixos";
cephiroth jitsi = "ssh-ed25519 AAAAC3NzaC1lZDI1NTE5AAAAIB6jVMIZ5y2oXX9HOkw7r5UUjw95MlFaFuu7FnEC0Q8z root@jitsi";
jitsi livre = "ssh-ed25519 AAAAC3NzaC1lZDI1NTE5AAAAIEVfKNokHG6ig32hhQxTep+fKFmKahlDClPrX/dP4/gb root@livre";
livre neo = "ssh-ed25519 AAAAC3NzaC1lZDI1NTE5AAAAIMGfSvxqC2PJYRrxJaivVDujwlwCZ6AwH8hOSA9ktZ1V root@neo";
neo redite = "ssh-ed25519 AAAAC3NzaC1lZDI1NTE5AAAAIOwfVmR3NjZf6qkDlTSiyo39Up5nSNUVW7jYDWXrY8Xr root@redite";
redite thot = "ssh-ed25519 AAAAC3NzaC1lZDI1NTE5AAAAIFKNg1b8ft1L55+joXQ/7Dt2QTOdkea8opTEnq4xrhPU root@thot";
thot two = "ssh-ed25519 AAAAC3NzaC1lZDI1NTE5AAAAIPpaGf8A+XWXBdNrs69RiC0qPbjPHdtkl31OjxrktmF6 root@nixos";
two vaultwarden = "ssh-ed25519 AAAAC3NzaC1lZDI1NTE5AAAAICn6vfDlsZVU6TEWg9vTgq9+Fp3irHjytBTky7A4ErRM root@vaultwarden";
vaultwarden
;
}; };
hostnames = [ hostnames = attrsets.mapAttrsToList (host: _: host) hosts;
"apprentix"
"cephiroth"
"jitsi"
"livre"
"neo"
"redite"
"thot"
"two"
"vaultwarden"
];
# Groupes # Groupes
all = [ all = attrsets.mapAttrsToList (_: key: key) hosts;
apprentix
cephiroth
jitsi
livre
neo
thot
two
vaultwarden
];
acme = [ acme = [
jitsi hosts.jitsi
neo hosts.neo
]; ];
# Secrets
commonSecrets = [ "restic/client_env" ];
acmeSecrets = [ "acme/env" ];
# Fonctions utilitaires # Fonctions utilitaires
remove = el: list: builtins.filter (x: el != x) list; listFilesRelative = dir: map (p: path.removePrefix ./. p) (filesystem.listFilesRecursive dir);
genAttrs = genAttrs =
paths: groups: paths: groups:
builtins.foldl' ( builtins.foldl' (acc: secret: acc // { "${secret}".publicKeys = groups ++ nounous; }) { } paths;
acc: secret: acc // { "secrets/${secret}.age".publicKeys = groups ++ nounous; }
) { } paths; # Secrets
commonSecrets = (listFilesRelative ./secrets/common) ++ [
"./secrets/restic/client_env"
];
acmeSecrets = listFilesRelative ./secrets/acme;
in in
(genAttrs commonSecrets (remove apprentix all)) # Secrets communs à toutes les machines (sauf apprentix)
(genAttrs commonSecrets (lists.remove hosts.apprentix all))
# Secrets pour ACME
// (genAttrs acmeSecrets acme) // (genAttrs acmeSecrets acme)
# Secrets pour restic
// builtins.foldl' ( // builtins.foldl' (
acc: name: acc: name:
acc acc
@ -104,19 +83,23 @@ in
in in
genAttrs genAttrs
[ [
"restic/${name}/base-repo" "./secrets/restic/${name}/base-repo"
"restic/${name}/base-password" "./secrets/restic/${name}/base-password"
] ]
[ key ] [ key ]
) )
) { } (remove "thot" hostnames) ) { } (lists.remove "thot" hostnames)
// builtins.mapAttrs (name: value: { publicKeys = value.publicKeys ++ nounous; }) { // attrsets.foldlAttrs (
"secrets/apprentix/root.age".publicKeys = [ apprentix ]; outacc: host: key:
"secrets/common/root.age".publicKeys = remove apprentix all; let
"secrets/neo/appservice_irc_db_env.age".publicKeys = [ neo ]; secrets = listFilesRelative (path.append ./secrets host);
"secrets/neo/coturn_auth_secret.age".publicKeys = [ neo ]; in
"secrets/neo/database_extra_config.age".publicKeys = [ neo ]; outacc
"secrets/neo/note_oidc_extra_config.age".publicKeys = [ neo ]; // builtins.foldl' (
"secrets/neo/ldap_synapse_password.age".publicKeys = [ neo ]; acc: secret:
"secrets/vaultwarden/env.age".publicKeys = [ vaultwarden ]; acc
} // {
"${secret}".publicKeys = [ key ] ++ nounous;
}
) { } secrets
) { } hosts

View File

View File

View File

View File

View File

View File

View File

View File

View File

View File

View File

View File