diff --git a/flake.nix b/flake.nix index e4d64c4..c212442 100644 --- a/flake.nix +++ b/flake.nix @@ -34,7 +34,10 @@ flake = with nixpkgs.lib; { nixosConfigurations = let - baseModules = [ agenix.nixosModules.default ]; + baseModules = [ + ./modules + agenix.nixosModules.default + ]; in { apprentix = nixosSystem { @@ -71,22 +74,17 @@ specialArgs = inputs; modules = [ ./hosts/vm/two ] ++ baseModules; }; - - vaultwarden = nixosSystem { - specialArgs = inputs; - modules = [ ./hosts/vm/vaultwarden ] ++ baseModules; + + vaultwarden = nixosSystem { + specialArgs = inputs; + modules = [ ./hosts/vm/vaultwarden ] ++ baseModules; + }; }; - }; }; perSystem = { config, pkgs, ... }: { - treefmt = { - projectRootFile = "flake.nix"; - programs.nixpkgs-fmt.enable = true; - }; - devShells = { default = pkgs.callPackage ./devshells/default.nix { inherit (inputs) agenix; }; }; diff --git a/hosts/physiques/thot/default.nix b/hosts/physiques/thot/default.nix index ed4cee3..ba780fa 100644 --- a/hosts/physiques/thot/default.nix +++ b/hosts/physiques/thot/default.nix @@ -4,10 +4,7 @@ imports = [ ./hardware-configuration.nix ./networking.nix - - ../../../modules - ../../../modules/services/nginx.nix - ../../../modules/services/restic.nix + ./nginx.nix ]; networking.hostId = "bbdd1133"; @@ -39,5 +36,19 @@ restic ]; + crans = { + enable = true; + + networking.adm.enable = false; + resticClient.enable = false; + + services = { + resticServer = { + enable = true; + port = 4242; + }; + }; + }; + system.stateVersion = "24.05"; } diff --git a/hosts/physiques/thot/nginx.nix b/hosts/physiques/thot/nginx.nix new file mode 100644 index 0000000..aa721d0 --- /dev/null +++ b/hosts/physiques/thot/nginx.nix @@ -0,0 +1,15 @@ +{ config, ... }: + +{ + services.nginx = { + enable = true; + + virtualHosts = { + "${config.networking.hostName}.adm.crans.org" = { + locations."/" = { + proxyPass = "http://${config.services.restic.server.listenAddress}"; + }; + }; + }; + }; +} diff --git a/hosts/vm/README.md b/hosts/vm/README.md index 58279f3..1e4607b 100644 --- a/hosts/vm/README.md +++ b/hosts/vm/README.md @@ -2,14 +2,30 @@ 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 à . + +## livre + +Serveur stirling (manipulation de PDF), accessible à . + ## neo -Serveur Matrix (encore non déployé). +Serveur Matrix, bridge IRC <-> Matrix et interface admin pour synapse, accessible à . ## redite -Serveur libreddit, accessible à https://redite.crans.org. +Serveur redlib (client WEB alternatif pour Reddit), accessible à . ## two -Serveur NixOS de test. Vous pouvez vous en servir comme base pour la configuration d'une nouvelle machine. \ No newline at end of file +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 à . diff --git a/hosts/vm/apprentix/default.nix b/hosts/vm/apprentix/default.nix index 945f8e0..81e5c14 100644 --- a/hosts/vm/apprentix/default.nix +++ b/hosts/vm/apprentix/default.nix @@ -1,17 +1,29 @@ -{ config, lib, ... }: +{ ... }: { imports = [ ./hardware-configuration.nix - ./networking.nix - - ../../../modules ]; boot.loader.grub.devices = [ "/dev/sda" ]; 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 = [ { 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"; } diff --git a/hosts/vm/apprentix/networking.nix b/hosts/vm/apprentix/networking.nix deleted file mode 100644 index 548d59a..0000000 --- a/hosts/vm/apprentix/networking.nix +++ /dev/null @@ -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; - } - ]; - }; - - }; - }; - }; -} diff --git a/hosts/vm/jitsi/default.nix b/hosts/vm/jitsi/default.nix index 51e86f3..f04f286 100644 --- a/hosts/vm/jitsi/default.nix +++ b/hosts/vm/jitsi/default.nix @@ -3,15 +3,29 @@ { imports = [ ./hardware-configuration.nix - ./networking.nix - - ../../../modules - ../../../modules/services/jitsi.nix - ../../../modules/services/acme.nix + ./jitsi.nix ]; networking.hostName = "jitsi"; 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"; } diff --git a/hosts/vm/jitsi/hardware-configuration.nix b/hosts/vm/jitsi/hardware-configuration.nix index 8bc6d1b..15779d2 100644 --- a/hosts/vm/jitsi/hardware-configuration.nix +++ b/hosts/vm/jitsi/hardware-configuration.nix @@ -1,22 +1,34 @@ # Do not modify this file! It was generated by ‘nixos-generate-config’ # and may be overwritten by future invocations. Please make changes # to /etc/nixos/configuration.nix instead. -{ config, lib, pkgs, modulesPath, ... }: +{ + config, + lib, + pkgs, + modulesPath, + ... +}: { - imports = - [ (modulesPath + "/profiles/qemu-guest.nix") - ]; + imports = [ + (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.kernelModules = [ ]; boot.extraModulePackages = [ ]; - fileSystems."/" = - { device = "/dev/disk/by-uuid/66101184-15ad-4859-addf-95040bac1145"; - fsType = "ext4"; - }; + fileSystems."/" = { + device = "/dev/disk/by-uuid/66101184-15ad-4859-addf-95040bac1145"; + fsType = "ext4"; + }; swapDevices = [ ]; diff --git a/hosts/vm/jitsi/jitsi.nix b/hosts/vm/jitsi/jitsi.nix new file mode 100644 index 0000000..71f46a1 --- /dev/null +++ b/hosts/vm/jitsi/jitsi.nix @@ -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" + ]; +} diff --git a/hosts/vm/jitsi/networking.nix b/hosts/vm/jitsi/networking.nix deleted file mode 100644 index 4a18bf0..0000000 --- a/hosts/vm/jitsi/networking.nix +++ /dev/null @@ -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; - }]; - }; - - }; - }; - }; -} diff --git a/hosts/vm/livre/default.nix b/hosts/vm/livre/default.nix index 19e40b1..042d63c 100644 --- a/hosts/vm/livre/default.nix +++ b/hosts/vm/livre/default.nix @@ -1,24 +1,23 @@ -{ config, ... }: +{ ... }: { imports = [ ./hardware-configuration.nix - ./networking.nix - - ../../../modules - ../../../modules/services/nginx.nix - ../../../modules/services/stirling.nix + ./stirling.nix ]; networking.hostName = "livre"; boot.loader.grub.devices = [ "/dev/sda" ]; - services.nginx.virtualHosts = { - "pdf.crans.org" = { - locations."/" = { - proxyPass = "http://localhost:${toString config.services.stirling-pdf.environment.SERVER_PORT}"; - }; + crans = { + enable = true; + + networking = { + id = "40"; + srvNat.enable = true; }; + + resticClient.when = "03:45"; }; system.stateVersion = "24.11"; diff --git a/hosts/vm/livre/hardware-configuration.nix b/hosts/vm/livre/hardware-configuration.nix index 66ff281..04493d3 100644 --- a/hosts/vm/livre/hardware-configuration.nix +++ b/hosts/vm/livre/hardware-configuration.nix @@ -1,22 +1,35 @@ # Do not modify this file! It was generated by ‘nixos-generate-config’ # and may be overwritten by future invocations. Please make changes # to /etc/nixos/configuration.nix instead. -{ config, lib, pkgs, modulesPath, ... }: +{ + config, + lib, + pkgs, + modulesPath, + ... +}: { - imports = - [ (modulesPath + "/profiles/qemu-guest.nix") - ]; + imports = [ + (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.kernelModules = [ ]; boot.extraModulePackages = [ ]; - fileSystems."/" = - { device = "/dev/disk/by-uuid/9fed1492-e7b2-4ec2-a5f4-8825bf8e89a0"; - fsType = "ext4"; - }; + fileSystems."/" = { + device = "/dev/disk/by-uuid/9fed1492-e7b2-4ec2-a5f4-8825bf8e89a0"; + fsType = "ext4"; + }; swapDevices = [ ]; @@ -30,4 +43,3 @@ nixpkgs.hostPlatform = lib.mkDefault "x86_64-linux"; } - diff --git a/hosts/vm/livre/networking.nix b/hosts/vm/livre/networking.nix deleted file mode 100644 index ae7302c..0000000 --- a/hosts/vm/livre/networking.nix +++ /dev/null @@ -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; - }]; - }; - - }; - }; - }; -} diff --git a/modules/services/stirling.nix b/hosts/vm/livre/stirling.nix similarity index 50% rename from modules/services/stirling.nix rename to hosts/vm/livre/stirling.nix index fe958e5..a18fe97 100644 --- a/modules/services/stirling.nix +++ b/hosts/vm/livre/stirling.nix @@ -10,4 +10,16 @@ SYSTEM_DEFAULTLOCALE = "fr-FR"; }; }; + + services.nginx = { + enable = true; + + virtualHosts = { + "pdf.crans.org" = { + locations."/" = { + proxyPass = "http://localhost:${toString config.services.stirling-pdf.environment.SERVER_PORT}"; + }; + }; + }; + }; } diff --git a/hosts/vm/neo/default.nix b/hosts/vm/neo/default.nix index 5b51a68..f845f57 100644 --- a/hosts/vm/neo/default.nix +++ b/hosts/vm/neo/default.nix @@ -3,16 +3,33 @@ { imports = [ ./hardware-configuration.nix - ./networking.nix - - ../../../modules - ../../../modules/services/matrix.nix - ../../../modules/services/synapse-admin.nix + ./matrix.nix + ./matrix-appservice-irc.nix + ./synapse-admin.nix ]; boot.loader.grub.devices = [ "/dev/sda" ]; 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"; } diff --git a/modules/services/matrix-appservice-irc.nix b/hosts/vm/neo/matrix-appservice-irc.nix similarity index 99% rename from modules/services/matrix-appservice-irc.nix rename to hosts/vm/neo/matrix-appservice-irc.nix index 6352c7c..0540c42 100644 --- a/modules/services/matrix-appservice-irc.nix +++ b/hosts/vm/neo/matrix-appservice-irc.nix @@ -1,7 +1,8 @@ -{ config -, pkgs -, lib -, ... +{ + config, + pkgs, + lib, + ... }: let diff --git a/modules/services/matrix.nix b/hosts/vm/neo/matrix.nix similarity index 92% rename from modules/services/matrix.nix rename to hosts/vm/neo/matrix.nix index f360537..5345f8e 100644 --- a/modules/services/matrix.nix +++ b/hosts/vm/neo/matrix.nix @@ -1,35 +1,28 @@ { config, ... }: { - imports = [ - ./acme.nix - ./coturn.nix - ./matrix-appservice-irc.nix - ./nginx.nix - ]; - age.secrets = { ldap_synapse_password = { - file = ../../secrets/neo/ldap_synapse_password.age; + file = ../../../secrets/neo/ldap_synapse_password.age; owner = "matrix-synapse"; }; database_extra_config = { - file = ../../secrets/neo/database_extra_config.age; + file = ../../../secrets/neo/database_extra_config.age; owner = "matrix-synapse"; }; note_oidc_extra_config = { - file = ../../secrets/neo/note_oidc_extra_config.age; + file = ../../../secrets/neo/note_oidc_extra_config.age; owner = "matrix-synapse"; }; appservice_irc_db_env = { - file = ../../secrets/neo/appservice_irc_db_env.age; + file = ../../../secrets/neo/appservice_irc_db_env.age; }; coturn_auth_secret = { - file = ../../secrets/neo/coturn_auth_secret.age; + file = ../../../secrets/neo/coturn_auth_secret.age; owner = "turnserver"; }; }; diff --git a/hosts/vm/neo/networking.nix b/hosts/vm/neo/networking.nix deleted file mode 100644 index 363ead7..0000000 --- a/hosts/vm/neo/networking.nix +++ /dev/null @@ -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; - }; - }; -} diff --git a/hosts/vm/neo/synapse-admin.nix b/hosts/vm/neo/synapse-admin.nix new file mode 100644 index 0000000..193b29b --- /dev/null +++ b/hosts/vm/neo/synapse-admin.nix @@ -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/; + ''; + }; + }; + }; +} diff --git a/hosts/vm/redite/default.nix b/hosts/vm/redite/default.nix index 4921d62..f4cf49f 100644 --- a/hosts/vm/redite/default.nix +++ b/hosts/vm/redite/default.nix @@ -3,14 +3,22 @@ { imports = [ ./hardware-configuration.nix - ./networking.nix - - ../../../modules - ../../../modules/services/libreddit.nix + ./redlib.nix ]; networking.hostName = "redite"; boot.loader.grub.devices = [ "/dev/sda" ]; + crans = { + enable = true; + + networking = { + id = "39"; + srvNat.enable = true; + }; + + resticClient.when = "06:18"; + }; + system.stateVersion = "23.11"; } diff --git a/hosts/vm/redite/networking.nix b/hosts/vm/redite/networking.nix deleted file mode 100644 index 8ec9ca3..0000000 --- a/hosts/vm/redite/networking.nix +++ /dev/null @@ -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; - } - ]; - }; - - }; - }; - }; -} diff --git a/modules/services/libreddit.nix b/hosts/vm/redite/redlib.nix similarity index 75% rename from modules/services/libreddit.nix rename to hosts/vm/redite/redlib.nix index 35157b7..e569cf6 100644 --- a/modules/services/libreddit.nix +++ b/hosts/vm/redite/redlib.nix @@ -1,7 +1,7 @@ { ... }: { - services.libreddit = { + services.redlib = { openFirewall = true; port = 80; enable = true; diff --git a/hosts/vm/two/default.nix b/hosts/vm/two/default.nix index a2f6c54..b280e43 100644 --- a/hosts/vm/two/default.nix +++ b/hosts/vm/two/default.nix @@ -3,13 +3,24 @@ { imports = [ ./hardware-configuration.nix - ./networking.nix - - ../../../modules ]; networking.hostName = "two"; 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"; } diff --git a/hosts/vm/two/networking.nix b/hosts/vm/two/networking.nix deleted file mode 100644 index 1840458..0000000 --- a/hosts/vm/two/networking.nix +++ /dev/null @@ -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; - } - ]; - }; - - }; - }; - }; -} diff --git a/hosts/vm/vaultwarden/default.nix b/hosts/vm/vaultwarden/default.nix index 18e2c6e..26cfe43 100644 --- a/hosts/vm/vaultwarden/default.nix +++ b/hosts/vm/vaultwarden/default.nix @@ -3,14 +3,22 @@ { imports = [ ./hardware-configuration.nix - ./networking.nix - - ../../../modules - ../../../modules/services/vaultwarden.nix + ./vaultwarden.nix ]; networking.hostName = "vaultwarden"; boot.loader.grub.devices = [ "/dev/sda" ]; + crans = { + enable = true; + + networking = { + id = "59"; + srvNat.enable = true; + }; + + resticClient.when = "04:44"; + }; + system.stateVersion = "24.05"; } diff --git a/hosts/vm/vaultwarden/hardware-configuration.nix b/hosts/vm/vaultwarden/hardware-configuration.nix index 9b113d6..3854e59 100644 --- a/hosts/vm/vaultwarden/hardware-configuration.nix +++ b/hosts/vm/vaultwarden/hardware-configuration.nix @@ -1,22 +1,35 @@ # Do not modify this file! It was generated by ‘nixos-generate-config’ # and may be overwritten by future invocations. Please make changes # to /etc/nixos/configuration.nix instead. -{ config, lib, pkgs, modulesPath, ... }: +{ + config, + lib, + pkgs, + modulesPath, + ... +}: { - imports = - [ (modulesPath + "/profiles/qemu-guest.nix") - ]; + imports = [ + (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.kernelModules = [ ]; boot.extraModulePackages = [ ]; - fileSystems."/" = - { device = "/dev/disk/by-uuid/c97aeccd-b88a-407e-a08d-f821a3f34936"; - fsType = "ext4"; - }; + fileSystems."/" = { + device = "/dev/disk/by-uuid/c97aeccd-b88a-407e-a08d-f821a3f34936"; + fsType = "ext4"; + }; swapDevices = [ ]; diff --git a/hosts/vm/vaultwarden/networking.nix b/hosts/vm/vaultwarden/networking.nix deleted file mode 100644 index 5e870b4..0000000 --- a/hosts/vm/vaultwarden/networking.nix +++ /dev/null @@ -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; - }]; - }; - - }; - }; - }; -} diff --git a/modules/services/vaultwarden.nix b/hosts/vm/vaultwarden/vaultwarden.nix similarity index 64% rename from modules/services/vaultwarden.nix rename to hosts/vm/vaultwarden/vaultwarden.nix index 4cb76a3..a8bf1fa 100644 --- a/modules/services/vaultwarden.nix +++ b/hosts/vm/vaultwarden/vaultwarden.nix @@ -1,13 +1,9 @@ { config, lib, ... }: { - imports = [ - ./nginx.nix - ]; - age.secrets = { - env = { - file = ../../secrets/vaultwarden/env.age; + vaultwarden-env = { + file = ../../../secrets/vaultwarden/env.age; }; }; @@ -15,12 +11,13 @@ enable = true; dbBackend = "postgresql"; - environmentFile = config.age.secrets.env.path; + environmentFile = config.age.secrets.vaultwarden-env.path; config = { ROCKET_PORT = 8222; SENDMAIL_COMMAND = "${config.security.wrapperDir}/sendmail"; }; }; + users.users.vaultwarden.extraGroups = [ "nullmailer" ]; systemd.services.vaultwarden = { @@ -37,10 +34,14 @@ }; }; - services.nginx.virtualHosts."vaultwarden.crans.org" = { - locations."/" = { - proxyPass = "http://localhost:${toString config.services.vaultwarden.config.ROCKET_PORT}"; - proxyWebsockets = true; + services.nginx = { + enable = true; + + virtualHosts."vaultwarden.crans.org" = { + locations."/" = { + proxyPass = "http://localhost:${toString config.services.vaultwarden.config.ROCKET_PORT}"; + proxyWebsockets = true; + }; }; }; } diff --git a/modules/README.md b/modules/README.md index fb791c0..9d49acf 100644 --- a/modules/README.md +++ b/modules/README.md @@ -12,4 +12,4 @@ Le dossier [`crans`](crans) contient tous les services/programmes communs à tou ## 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. diff --git a/modules/crans/README.md b/modules/crans/README.md index cc78b77..fd9a209 100644 --- a/modules/crans/README.md +++ b/modules/crans/README.md @@ -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. +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` -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` @@ -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. +## `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` -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` 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` -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). diff --git a/modules/crans/default.nix b/modules/crans/default.nix index a86b3ca..cac4a63 100644 --- a/modules/crans/default.nix +++ b/modules/crans/default.nix @@ -1,5 +1,10 @@ -{ pkgs, ... }: +{ lib, config, ... }: +let + cfg = config.crans; + + inherit (lib) mkEnableOption mkIf; +in { imports = [ ./age.nix @@ -10,32 +15,28 @@ ./restic_client.nix ./monitoring.nix ./nullmailer.nix + ./packages.nix + ./ssh.nix ./users.nix + ./virtualisation.nix ]; - services.qemuGuest.enable = true; - boot.kernelParams = [ "console=ttyS0,115200" ]; - - services.openssh = { - enable = true; + options.crans = { + enable = mkEnableOption "Configuration commune à toutes les machines du Crans"; }; - nixpkgs.config.allowUnfree = true; - - # Enable some utility programs. - 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 - fd - helix - nfs-utils - ripgrep - shelldap - ]; + config = mkIf cfg.enable { + crans = { + homeNounou.enable = lib.mkDefault true; + monitoring.enable = true; + networking = { + enable = true; + adm.enable = lib.mkDefault true; + }; + resticClient.enable = lib.mkDefault true; + users = { + ldap.enable = true; + }; + }; + }; } diff --git a/modules/crans/home.nix b/modules/crans/home.nix index 0ae6c23..e95fbed 100644 --- a/modules/crans/home.nix +++ b/modules/crans/home.nix @@ -1,24 +1,17 @@ -{ - pkgs, - lib, - config, - ... -}: +{ lib, config, ... }: let - cfg = config.crans.home_nounou; + cfg = config.crans.homeNounou; + + inherit (lib) mkEnableOption mkIf; in { - options.crans.home_nounou = { - enable = lib.mkOption { - type = lib.types.bool; - default = true; - description = "Monter les home nounous"; - }; + options.crans.homeNounou = { + enable = mkEnableOption "Monter /home_nounou."; }; - config = lib.mkIf cfg.enable { + config = mkIf cfg.enable { fileSystems.home_nounou = { mountPoint = "/home_nounou"; device = "172.16.10.1:/pool/home"; diff --git a/modules/crans/monitoring.nix b/modules/crans/monitoring.nix index bea4865..18862cf 100644 --- a/modules/crans/monitoring.nix +++ b/modules/crans/monitoring.nix @@ -1,17 +1,44 @@ -{ config, ... }: -{ - services.prometheus.exporters = { - node = { - enable = true; - port = 9100; +{ config, lib, ... }: - 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 = { - enable = config.services.nginx.enable; - port = 9117; - scrapeUri = "http://[::1]:6424/stub_status"; + enable = mkOption { + type = types.bool; + 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"; + }; }; }; } diff --git a/modules/crans/networking.nix b/modules/crans/networking.nix index 1e3644b..a376fb2 100644 --- a/modules/crans/networking.nix +++ b/modules/crans/networking.nix @@ -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. - networking = { - useDHCP = false; - firewall.enable = lib.mkDefault false; - nameservers = [ "172.16.10.128" ]; + options.crans.networking = { + enable = mkEnableOption "Configuration réseaux commune à toutes les machines du Crans."; + + id = mkOption { + 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 + { } + ); }; } diff --git a/modules/crans/packages.nix b/modules/crans/packages.nix new file mode 100644 index 0000000..1f2d4cd --- /dev/null +++ b/modules/crans/packages.nix @@ -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 + ]; +} diff --git a/modules/crans/restic_client.nix b/modules/crans/restic_client.nix index d99c252..b0b3228 100644 --- a/modules/crans/restic_client.nix +++ b/modules/crans/restic_client.nix @@ -1,36 +1,73 @@ -{ config, ... }: +{ config, lib, ... }: + +let + cfg = config.crans.resticClient; + + inherit (lib) + mkEnableOption + mkIf + mkOption + types + ; +in { - age.secrets = { - restic-base-env.file = ../../secrets/restic/client_env.age; - restic-base-repo.file = ../../secrets/restic/${config.networking.hostName}/base-repo.age; - restic-base-password.file = ../../secrets/restic/${config.networking.hostName}/base-password.age; + options.crans.resticClient = { + enable = mkEnableOption "Configuration générale pour le client restic."; + + 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//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 = { - base = { - exclude = [ - "/var/cache" - "/var/lib/lxcfs" - ]; - initialize = true; - passwordFile = config.age.secrets.restic-base-password.path; - repositoryFile = config.age.secrets.restic-base-repo.path; - environmentFile = config.age.secrets.restic-base-env.path; - paths = [ - "/etc" - "/var" - ]; - timerConfig = { - OnCalendar = "00:00"; - RandomizedDelaySec = "6h"; + config = mkIf cfg.enable { + age.secrets = { + restic-base-env.file = ../../secrets/restic/client_env.age; + restic-base-repo.file = ../../secrets/restic/${config.networking.hostName}/base-repo.age; + restic-base-password.file = ../../secrets/restic/${config.networking.hostName}/base-password.age; + }; + + services.restic.backups = { + base = { + initialize = true; + passwordFile = config.age.secrets.restic-base-password.path; + repositoryFile = config.age.secrets.restic-base-repo.path; + environmentFile = config.age.secrets.restic-base-env.path; + paths = [ + "/etc" + "/var" + ] ++ 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" - ]; }; }; } diff --git a/modules/crans/ssh.nix b/modules/crans/ssh.nix new file mode 100644 index 0000000..3bea073 --- /dev/null +++ b/modules/crans/ssh.nix @@ -0,0 +1,11 @@ +{ ... }: + +{ + services.openssh = { + enable = true; + + settings = { + PermitRootLogin = "yes"; + }; + }; +} diff --git a/modules/crans/users.nix b/modules/crans/users.nix index 1425d94..68e27e4 100644 --- a/modules/crans/users.nix +++ b/modules/crans/users.nix @@ -1,50 +1,75 @@ { config, lib, ... }: -{ - users = { - mutableUsers = false; +let + cfg = config.crans.users; + inherit (lib) + mkEnableOption + mkOption + types + ; +in + +{ + options.crans.users = { ldap = { - enable = true; - 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 - ''; + enable = mkEnableOption "Authentification par le LDAP adm."; + }; + + root = { + passwordFile = mkOption { + type = types.path; + default = ../../secrets/common/root.age; + example = ../../secrets/apprentix/root.age; + description = "Fichier chiffré par age contenant le mot de passe root."; }; }; }; - 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" ]; - } - ]; - }; + config = { + age.secrets.root-passwd-hash = { + file = cfg.root.passwordFile; + }; - age.secrets.root-passwd-hash = { - file = lib.mkDefault ../../secrets/common/root.age; - }; + users = { + mutableUsers = false; - users.users.root = { - hashedPasswordFile = lib.mkDefault config.age.secrets.root-passwd-hash.path; - }; + users.root = { + 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" ]; + } + ]; + }; + }; } diff --git a/modules/crans/virtualisation.nix b/modules/crans/virtualisation.nix new file mode 100644 index 0000000..7018e4a --- /dev/null +++ b/modules/crans/virtualisation.nix @@ -0,0 +1,6 @@ +{ ... }: + +{ + services.qemuGuest.enable = true; + boot.kernelParams = [ "console=ttyS0,115200" ]; +} diff --git a/modules/default.nix b/modules/default.nix index 1515e9b..6a72322 100644 --- a/modules/default.nix +++ b/modules/default.nix @@ -3,10 +3,25 @@ { imports = [ ./crans + ./services ]; - nix.settings.experimental-features = [ - "flakes" - "nix-command" - ]; + nix = { + settings = { + experimental-features = [ + "flakes" + "nix-command" + ]; + auto-optimise-store = true; + }; + }; + + nixpkgs.config = { + allowUnfree = true; + }; + + boot.tmp = { + useTmpfs = true; + cleanOnBoot = true; + }; } diff --git a/modules/services/acme.nix b/modules/services/acme.nix index 236ddb0..1b90021 100644 --- a/modules/services/acme.nix +++ b/modules/services/acme.nix @@ -1,24 +1,36 @@ -{ config, ... }: +{ config, lib, ... }: + +let + cfg = config.crans.services.acme; + + inherit (lib) mkEnableOption mkIf; +in { - age.secrets = { - acme-env.file = ../../secrets/acme/env.age; + options.crans.services.acme = { + enable = mkEnableOption "Activer les certificats ACME via let's encrypt."; }; - security.acme = { - acceptTerms = true; - - defaults = { - email = "root@crans.org"; - dnsPropagationCheck = false; + config = mkIf cfg.enable { + age.secrets = { + acme-env.file = ../../secrets/acme/env.age; }; - 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; + security.acme = { + acceptTerms = true; + + defaults = { + email = "root@crans.org"; + 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; + }; }; }; } diff --git a/modules/services/coturn.nix b/modules/services/coturn.nix index 8382c11..e1bc36e 100644 --- a/modules/services/coturn.nix +++ b/modules/services/coturn.nix @@ -1,59 +1,100 @@ -{ config, ... }: +{ config, lib, ... }: + +let + cfg = config.crans.services.coturn; + + inherit (lib) + mkEnableOption + mkOption + mkIf + types + ; +in { - services.coturn = { - enable = true; - no-cli = true; - no-tcp-relay = true; - min-port = 49000; - max-port = 50000; - use-auth-secret = true; - static-auth-secret-file = config.age.secrets.coturn_auth_secret.path; - realm = "crans.org"; - cert = "/var/lib/acme/crans.org/full.pem"; - pkey = "/var/lib/acme/crans.org/key.pem"; - 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 - ''; + options.crans.services.coturn = { + enable = mkEnableOption "Coturn, un serveur TURN open-source."; + + secretFile = mkOption { + type = types.path; + default = config.age.secrets.coturn_auth_secret.path; + description = "Fichier contenant le secret de configuration du serveur."; + }; + + fqdn = mkOption { + type = types.str; + default = "crans.org"; + description = "Domaine pour lequel le serveur coturn est configuré."; + }; + + certFile = mkOption { + type = types.path; + default = "/var/lib/acme/${cfg.fqdn}/full.pem"; + description = "Fichier contenant le certificat associé au FQDN."; + }; + + keyFile = mkOption { + type = types.path; + default = "/var/lib/acme/${cfg.fqdn}/key.pem"; + description = "Fichier contenant la clef associé au FQDN."; + }; }; - networking.firewall = { - allowedTCPPorts = [ - 3478 - 5349 - ]; - allowedUDPPorts = [ - 3478 - 5349 - ]; - allowedUDPPortRanges = [ - { - from = config.services.coturn.min-port; - to = config.services.coturn.max-port; - } - ]; + config = mkIf cfg.enable { + services.coturn = { + enable = true; + no-cli = true; + no-tcp-relay = true; + min-port = 49000; + max-port = 50000; + use-auth-secret = true; + static-auth-secret-file = cfg.secretFile; + realm = cfg.fqdn; + cert = cfg.certFile; + pkey = cfg.keyFile; + 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; + } + ]; + }; }; } diff --git a/modules/services/default.nix b/modules/services/default.nix new file mode 100644 index 0000000..9c1cafb --- /dev/null +++ b/modules/services/default.nix @@ -0,0 +1,10 @@ +{ ... }: + +{ + imports = [ + ./acme.nix + ./coturn.nix + ./nginx.nix + ./restic.nix + ]; +} diff --git a/modules/services/jitsi.nix b/modules/services/jitsi.nix deleted file mode 100644 index 1356890..0000000 --- a/modules/services/jitsi.nix +++ /dev/null @@ -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; - }; - -} diff --git a/modules/services/nginx.nix b/modules/services/nginx.nix index e05c89a..b15423d 100644 --- a/modules/services/nginx.nix +++ b/modules/services/nginx.nix @@ -1,9 +1,7 @@ -{ ... }: +{ lib, config, ... }: { - services.nginx = { - enable = true; - + services.nginx = lib.mkIf config.services.nginx.enable { recommendedProxySettings = true; recommendedOptimisation = true; diff --git a/modules/services/restic.nix b/modules/services/restic.nix index 9f0d302..5e6c8dd 100644 --- a/modules/services/restic.nix +++ b/modules/services/restic.nix @@ -1,19 +1,42 @@ -{ config, ... }: +{ config, lib, ... }: + +let + cfg = config.crans.services.resticServer; + + inherit (lib) + mkEnableOption + mkIf + mkOption + types + ; +in { - services.restic.server = { - enable = true; + options.crans.services.resticServer = { + enable = mkEnableOption "Serveur de backups restic."; - dataDir = "/backups"; - listenAddress = "localhost:4242"; - privateRepos = true; + dataDir = mkOption { + type = types.path; + 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.networking.hostName}.adm.crans.org" = { - locations."/" = { - proxyPass = "http://${config.services.restic.server.listenAddress}"; - }; + config = mkIf cfg.enable { + services.restic.server = { + enable = true; + + dataDir = cfg.dataDir; + listenAddress = "localhost:${toString cfg.port}"; + privateRepos = true; }; }; } diff --git a/modules/services/synapse-admin.nix b/modules/services/synapse-admin.nix deleted file mode 100644 index 9e2f298..0000000 --- a/modules/services/synapse-admin.nix +++ /dev/null @@ -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/; - ''; - }; - }; -} diff --git a/secrets.nix b/secrets.nix index b2665f4..7957792 100644 --- a/secrets.nix +++ b/secrets.nix @@ -1,4 +1,11 @@ let + inherit (import { }) lib; + inherit (lib) + attrsets + filesystem + lists + path + ; # Nounous aeltheos_0 = "age1yubikey1qvn7t9hplvnr2w8nsfezfqudz8gq3v8sq99dkdpzmm4a74rng5qgz4v6wzt"; @@ -21,80 +28,52 @@ let # 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 = { - inherit - apprentix - cephiroth - jitsi - livre - neo - redite - thot - two - vaultwarden - ; + 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"; }; - hostnames = [ - "apprentix" - "cephiroth" - "jitsi" - "livre" - "neo" - "redite" - "thot" - "two" - "vaultwarden" - ]; + hostnames = attrsets.mapAttrsToList (host: _: host) hosts; # Groupes - all = [ - apprentix - cephiroth - jitsi - livre - neo - thot - two - vaultwarden - ]; + all = attrsets.mapAttrsToList (_: key: key) hosts; acme = [ - jitsi - neo + hosts.jitsi + hosts.neo ]; - # Secrets - - commonSecrets = [ "restic/client_env" ]; - - acmeSecrets = [ "acme/env" ]; - # Fonctions utilitaires - remove = el: list: builtins.filter (x: el != x) list; + listFilesRelative = dir: map (p: path.removePrefix ./. p) (filesystem.listFilesRecursive dir); genAttrs = paths: groups: - builtins.foldl' ( - acc: secret: acc // { "secrets/${secret}.age".publicKeys = groups ++ nounous; } - ) { } paths; + builtins.foldl' (acc: secret: acc // { "${secret}".publicKeys = groups ++ nounous; }) { } paths; + + # Secrets + + commonSecrets = (listFilesRelative ./secrets/common) ++ [ + "./secrets/restic/client_env" + ]; + + acmeSecrets = listFilesRelative ./secrets/acme; 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) +# Secrets pour restic // builtins.foldl' ( acc: name: acc @@ -104,19 +83,23 @@ in in genAttrs [ - "restic/${name}/base-repo" - "restic/${name}/base-password" + "./secrets/restic/${name}/base-repo" + "./secrets/restic/${name}/base-password" ] [ key ] ) -) { } (remove "thot" hostnames) -// builtins.mapAttrs (name: value: { publicKeys = value.publicKeys ++ nounous; }) { - "secrets/apprentix/root.age".publicKeys = [ apprentix ]; - "secrets/common/root.age".publicKeys = remove apprentix all; - "secrets/neo/appservice_irc_db_env.age".publicKeys = [ neo ]; - "secrets/neo/coturn_auth_secret.age".publicKeys = [ neo ]; - "secrets/neo/database_extra_config.age".publicKeys = [ neo ]; - "secrets/neo/note_oidc_extra_config.age".publicKeys = [ neo ]; - "secrets/neo/ldap_synapse_password.age".publicKeys = [ neo ]; - "secrets/vaultwarden/env.age".publicKeys = [ vaultwarden ]; -} +) { } (lists.remove "thot" hostnames) +// attrsets.foldlAttrs ( + outacc: host: key: + let + secrets = listFilesRelative (path.append ./secrets host); + in + outacc + // builtins.foldl' ( + acc: secret: + acc + // { + "${secret}".publicKeys = [ key ] ++ nounous; + } + ) { } secrets +) { } hosts diff --git a/secrets/acme/.gitkeep b/secrets/acme/.gitkeep new file mode 100644 index 0000000..e69de29 diff --git a/secrets/apprentix/.gitkeep b/secrets/apprentix/.gitkeep new file mode 100644 index 0000000..e69de29 diff --git a/secrets/cephiroth/.gitkeep b/secrets/cephiroth/.gitkeep new file mode 100644 index 0000000..e69de29 diff --git a/secrets/common/.gitkeep b/secrets/common/.gitkeep new file mode 100644 index 0000000..e69de29 diff --git a/secrets/jitsi/.gitkeep b/secrets/jitsi/.gitkeep new file mode 100644 index 0000000..e69de29 diff --git a/secrets/livre/.gitkeep b/secrets/livre/.gitkeep new file mode 100644 index 0000000..e69de29 diff --git a/secrets/neo/.gitkeep b/secrets/neo/.gitkeep new file mode 100644 index 0000000..e69de29 diff --git a/secrets/redite/.gitkeep b/secrets/redite/.gitkeep new file mode 100644 index 0000000..e69de29 diff --git a/secrets/restic/.gitkeep b/secrets/restic/.gitkeep new file mode 100644 index 0000000..e69de29 diff --git a/secrets/thot/.gitkeep b/secrets/thot/.gitkeep new file mode 100644 index 0000000..e69de29 diff --git a/secrets/two/.gitkeep b/secrets/two/.gitkeep new file mode 100644 index 0000000..e69de29 diff --git a/secrets/vaultwarden/.gitkeep b/secrets/vaultwarden/.gitkeep new file mode 100644 index 0000000..e69de29