Compare commits

..

71 commits

Author SHA1 Message Date
Rouven Seifert df66ad3870 forgejo: initial runner configuration 2024-06-03 12:13:52 +02:00
Rouven Seifert 05152b6db4
web: init crimecampus 2024-05-25 15:36:33 +02:00
Rouven Seifert 6a8559fb33
nix: flake update 2024-05-25 15:35:35 +02:00
quitte 66519d8196 decisions: set network mode host 2024-05-19 11:41:38 +02:00
quitte 1c8fe9ec66 directus: undo network port mapping: for host db access network mode host required 2024-05-19 11:38:58 +02:00
quitte 68138c0a31 podman: add dive and podman-tui 2024-05-19 11:34:46 +02:00
quitte c7f3120c9d kanboard: update 2024-05-19 11:29:25 +02:00
quitte 616b3c64f7 ese directus: use port mapping insted of network mode=host 2024-05-19 11:25:15 +02:00
quitte bb697f3a50 decisions: use port mapping insted of network mode=host 2024-05-19 11:25:03 +02:00
quitte b34c53ddf8 podman: conf in extra file 2024-05-19 11:21:30 +02:00
quitte c8afe48290 use podman and kanboard with podman 2024-05-19 11:16:49 +02:00
quitte 16f8ec19f9 firewall: allow ldaps from podman 2024-05-19 11:15:58 +02:00
quitte 7f00d6746a disable struktur-bot 2024-05-19 11:15:07 +02:00
Jonas Gaffke 0c19d4e565
sops: fix kanboard conf 2024-05-19 11:14:27 +02:00
Jonas Gaffke fa964bf950
sops: add kanboard conf 2024-05-18 10:28:15 +02:00
Rouven Seifert 727f5464ae
keycloak: explain things 2024-05-14 18:59:43 +02:00
Rouven Seifert f5f4bf1b24
keycloak: use from unstable 2024-05-14 18:57:23 +02:00
Rouven Seifert b70c5b14b3
nix: flake update 2024-05-14 18:35:01 +02:00
Rouven Seifert 763a71c93f
initrd-ssh: fix shell 2024-05-14 14:08:21 +02:00
Rouven Seifert 071c0aa464
ldap: fix dex line 2024-05-13 15:50:34 +02:00
Rouven Seifert c595af81e7
nix: flake update 2024-05-08 16:12:10 +02:00
Rouven Seifert 077138401e
dex: deconfigure 2024-05-08 15:37:19 +02:00
Rouven Seifert cb828a2188
decision: move to keycloak 2024-05-08 14:10:46 +02:00
Rouven Seifert 7b7e8858cf
secrets: cleanup 2024-05-08 14:08:05 +02:00
Rouven Seifert f40e47f871
mediawiki: fix account migration 2024-05-08 12:29:07 +02:00
Rouven Seifert 7c87808bc1
mediawiki: update secret 2024-05-08 11:54:11 +02:00
Rouven Seifert 8ea250e387
mediawiki: enable keycloak 2024-05-08 11:47:07 +02:00
Rouven Seifert a339235b33
postgres: add more databases to the backup 2024-05-08 11:41:47 +02:00
Rouven Seifert 02535cca08
grafana: configure oidc 2024-05-08 00:09:40 +02:00
Rouven Seifert 5384918ce6
directus: fix sso 2024-05-07 11:57:15 +02:00
Rouven Seifert 6abc1e75b9
directus: configure openid connect 2024-05-07 11:10:59 +02:00
Rouven Seifert 395ca48ac0
padlist: remove dex configuration 2024-05-06 23:51:28 +02:00
Rouven Seifert 6a2bcecb5e
ifsr.de: add sso redirect 2024-05-06 22:59:48 +02:00
Rouven Seifert a832b8d2a5
keycloak: fix things 2024-05-06 17:05:22 +02:00
Rouven Seifert 2c4be79f32 Merge pull request 'keycloak: init' (#92) from keycloak into main
Reviewed-on: #92
2024-05-06 16:57:53 +02:00
Rouven Seifert 5294cd68f8
keycloak: init 2024-05-06 11:24:21 +02:00
Rouven Seifert 4fa9a2fe7d
treewide: cleanup with deadnix 2024-05-06 11:21:12 +02:00
Rouven Seifert 5930da6bdf
ssh: fix type 2024-05-06 11:13:49 +02:00
Rouven Seifert 81ac3b4c0d
ssh: disable password login 2024-05-06 11:12:19 +02:00
Jonas Gaffke 7630dc4494
decisions: use newer image 2024-05-06 11:08:41 +02:00
Jonas Gaffke 993a554396
sops: decisions env 2024-05-05 09:40:31 +02:00
Rouven Seifert bdc6185fce
grafana: fix root_url 2024-05-02 19:33:50 +02:00
Rouven Seifert 197956ea90
prometheus: patch the postfix exporter to catch rspamd rejects 2024-05-02 11:23:13 +02:00
quitte 1f4e9a620b trying to get postfix running 2024-05-02 10:48:26 +02:00
quitte ab5df354ff Merge branch 'monitoring' of ifsr.de:wurzel/fruitbasket into monitoring 2024-04-30 14:23:46 +02:00
Joachim Stramke cf7ff37367 adding postfix to monitoring 2024-04-30 14:22:50 +02:00
quitte f0c73a1763 Merge branch 'monitoring' of ifsr.de:wurzel/fruitbasket into monitoring 2024-04-29 17:10:37 +02:00
quitte d92eff80ce fixing postgres warning 2024-04-29 17:10:35 +02:00
Joachim Stramke d1147621e1 changing scrape intervall 2024-04-29 17:09:37 +02:00
Joachim Stramke 3f47b32983 add first node 2024-04-29 15:12:52 +02:00
quitte 7526b9273b making grafana work 2024-04-29 15:09:56 +02:00
quitte 795e3db47f Merge branch 'main' into monitoring
merging master in monitoring
2024-04-29 14:30:23 +02:00
Rouven Seifert 126cff2263
quitte: pin kernel to 6.6.27
6.6.28 broke the network driver
2024-04-29 14:26:49 +02:00
tenksom 9327314ec9 create grafana and prometheus setup 2024-04-29 14:21:58 +02:00
Rouven Seifert d03f4c6fb1
initrd: try loading network modules in stage 1 2024-04-26 22:40:30 +02:00
Rouven Seifert ebe977672a
mailman: restrict registration to tud nets 2024-04-26 22:40:18 +02:00
Rouven Seifert 579ad274d5
nix: flake update 2024-04-26 09:47:36 +02:00
Rouven Seifert 15299bcb99
nix: flake update 2024-04-26 09:40:21 +02:00
Rouven Seifert d5ab09207a
core: set zsh as default shell for the root user 2024-04-16 21:44:48 +02:00
Rouven Seifert 375674b1b4
nginx: fix the http3 wordpress fix 2024-04-16 20:51:16 +02:00
Rouven Seifert 6cd1ba6aa5
Revert "nix: update course-management"
This reverts commit f24793bbb6.
2024-04-16 20:38:07 +02:00
Rouven Seifert 08893439e7
http3: attempt a fix for wordpress sites 2024-04-16 20:36:44 +02:00
Rouven Seifert 0d4283f109
Revert "nginx: disable http3 to prevent wordpress error"
This reverts commit 8606e89c03.
2024-04-16 20:32:29 +02:00
Rouven Seifert ceca1b3798
tomate: remove fail2ban
- Not really needed any more
2024-04-16 20:21:16 +02:00
Rouven Seifert 3a47c43741
tomate: use zsh as default shell 2024-04-16 18:50:51 +02:00
Rouven Seifert f24793bbb6
nix: update course-management 2024-04-16 13:58:32 +02:00
Rouven Seifert 5b95918c29
tomate: configure ifsr-apb network 2024-04-16 10:58:35 +02:00
Rouven Seifert 83db5399d7
quitte: format hardware config 2024-04-14 11:40:00 +02:00
Rouven Seifert 4b173581dc
mount boot drives with the nofail option
One drive failure shouldn't block the entire boot
2024-04-14 11:39:11 +02:00
Rouven Seifert be638b274d
systemd-boot: copy the entire bootloader to the second disc on every switch 2024-04-14 11:35:47 +02:00
Rouven Seifert c534e2a8e1
nix-serve: use nix-serve-ng 2024-04-12 11:21:52 +02:00
33 changed files with 393 additions and 183 deletions

View file

@ -9,11 +9,11 @@
"poetry2nix": "poetry2nix" "poetry2nix": "poetry2nix"
}, },
"locked": { "locked": {
"lastModified": 1710843969, "lastModified": 1714117615,
"narHash": "sha256-Ilu7j7tihFI0jtnsQS+7H0SZX4C61NZHaV/7fJ39t/E=", "narHash": "sha256-Ilu7j7tihFI0jtnsQS+7H0SZX4C61NZHaV/7fJ39t/E=",
"owner": "fsr", "owner": "fsr",
"repo": "course-management", "repo": "course-management",
"rev": "07b173b4ea458e5a08b3aa9ec677153c08657c98", "rev": "9e5ab11788b926a9a26d2aaa0e0958c3c5865cc9",
"type": "github" "type": "github"
}, },
"original": { "original": {
@ -145,11 +145,11 @@
] ]
}, },
"locked": { "locked": {
"lastModified": 1711854532, "lastModified": 1716170277,
"narHash": "sha256-JPStavwlT7TfxxiXHk6Q7sbNxtnXAIjXQJMLO0KB6M0=", "narHash": "sha256-fCAiox/TuzWGVaAz16PxrR4Jtf9lN5dwWL2W74DS0yI=",
"owner": "nix-community", "owner": "nix-community",
"repo": "nix-index-database", "repo": "nix-index-database",
"rev": "2844b5f3ad3b478468151bd101370b9d8ef8a3a7", "rev": "e0638db3db43b582512a7de8c0f8363a162842b9",
"type": "github" "type": "github"
}, },
"original": { "original": {
@ -160,11 +160,11 @@
}, },
"nixpkgs": { "nixpkgs": {
"locked": { "locked": {
"lastModified": 1712168706, "lastModified": 1716361217,
"narHash": "sha256-XP24tOobf6GGElMd0ux90FEBalUtw6NkBSVh/RlA6ik=", "narHash": "sha256-mzZDr00WUiUXVm1ujBVv6A0qRd8okaITyUp4ezYRgc4=",
"owner": "nixos", "owner": "nixos",
"repo": "nixpkgs", "repo": "nixpkgs",
"rev": "1487bdea619e4a7a53a4590c475deabb5a9d1bfb", "rev": "46397778ef1f73414b03ed553a3368f0e7e33c2f",
"type": "github" "type": "github"
}, },
"original": { "original": {
@ -176,11 +176,11 @@
}, },
"nixpkgs-stable": { "nixpkgs-stable": {
"locked": { "locked": {
"lastModified": 1711819797, "lastModified": 1716061101,
"narHash": "sha256-tNeB6emxj74Y6ctwmsjtMlzUMn458sBmwnD35U5KIM4=", "narHash": "sha256-H0eCta7ahEgloGIwE/ihkyGstOGu+kQwAiHvwVoXaA0=",
"owner": "NixOS", "owner": "NixOS",
"repo": "nixpkgs", "repo": "nixpkgs",
"rev": "2b4e3ca0091049c6fbb4908c66b05b77eaef9f0c", "rev": "e7cc61784ddf51c81487637b3031a6dd2d6673a2",
"type": "github" "type": "github"
}, },
"original": { "original": {
@ -192,11 +192,11 @@
}, },
"nixpkgs-unstable": { "nixpkgs-unstable": {
"locked": { "locked": {
"lastModified": 1712163089, "lastModified": 1716509168,
"narHash": "sha256-Um+8kTIrC19vD4/lUCN9/cU9kcOsD1O1m+axJqQPyMM=", "narHash": "sha256-4zSIhSRRIoEBwjbPm3YiGtbd8HDWzFxJjw5DYSDy1n8=",
"owner": "nixos", "owner": "nixos",
"repo": "nixpkgs", "repo": "nixpkgs",
"rev": "fd281bd6b7d3e32ddfa399853946f782553163b5", "rev": "bfb7a882678e518398ce9a31a881538679f6f092",
"type": "github" "type": "github"
}, },
"original": { "original": {
@ -286,11 +286,11 @@
"nixpkgs-stable": "nixpkgs-stable" "nixpkgs-stable": "nixpkgs-stable"
}, },
"locked": { "locked": {
"lastModified": 1711855048, "lastModified": 1716400300,
"narHash": "sha256-HxegAPnQJSC4cbEbF4Iq3YTlFHZKLiNTk8147EbLdGg=", "narHash": "sha256-0lMkIk9h3AzOHs1dCL9RXvvN4PM8VBKb+cyGsqOKa4c=",
"owner": "Mic92", "owner": "Mic92",
"repo": "sops-nix", "repo": "sops-nix",
"rev": "99b1e37f9fc0960d064a7862eb7adfb92e64fa10", "rev": "b549832718b8946e875c016a4785d204fcfc2e53",
"type": "github" "type": "github"
}, },
"original": { "original": {
@ -386,11 +386,11 @@
"nixpkgs": "nixpkgs_2" "nixpkgs": "nixpkgs_2"
}, },
"locked": { "locked": {
"lastModified": 1709622318, "lastModified": 1713958148,
"narHash": "sha256-bTscF0366xtoIXgH7Zq+Mn0mpX3w4h/2xKpHiYMyLNc=", "narHash": "sha256-8PDNi/dgoI2kyM7uSiU4eoLBqUKoA+3TXuz+VWmuCOc=",
"owner": "nix-community", "owner": "nix-community",
"repo": "nixos-vscode-server", "repo": "nixos-vscode-server",
"rev": "d0ed9b8cf1f0a71f110df9119489ab047e0726bd", "rev": "fc900c16efc6a5ed972fb6be87df018bcf3035bc",
"type": "github" "type": "github"
}, },
"original": { "original": {

View file

@ -83,12 +83,14 @@
./modules/hedgedoc.nix ./modules/hedgedoc.nix
./modules/padlist.nix ./modules/padlist.nix
./modules/nextcloud.nix ./modules/nextcloud.nix
./modules/keycloak.nix
./modules/monitoring.nix
./modules/vaultwarden.nix ./modules/vaultwarden.nix
./modules/forgejo ./modules/forgejo
./modules/kanboard.nix ./modules/kanboard.nix
./modules/zammad.nix ./modules/zammad.nix
./modules/decisions.nix ./modules/decisions.nix
./modules/struktur-bot.nix # ./modules/struktur-bot.nix
{ {
nixpkgs.overlays = [ self.overlays.default ]; nixpkgs.overlays = [ self.overlays.default ];
sops.defaultSopsFile = ./secrets/quitte.yaml; sops.defaultSopsFile = ./secrets/quitte.yaml;
@ -106,7 +108,6 @@
./hosts/tomate/configuration.nix ./hosts/tomate/configuration.nix
./modules/core/base.nix ./modules/core/base.nix
./modules/core/zsh.nix ./modules/core/zsh.nix
./modules/core/fail2ban.nix
./modules/core/sssd.nix ./modules/core/sssd.nix
{ {
sops.defaultSopsFile = ./secrets/tomate.yaml; sops.defaultSopsFile = ./secrets/tomate.yaml;

View file

@ -1,4 +1,4 @@
{ config, ... }: { pkgs, ... }:
{ {
imports = imports =
@ -7,11 +7,27 @@
./network.nix ./network.nix
]; ];
boot.loader.systemd-boot.enable = true; boot.loader.systemd-boot = {
enable = true;
extraInstallCommands = ''
${pkgs.coreutils}/bin/cp -r /boot/* /boot2
'';
};
# boot.kernelParams = [ "video=VGA-1:1024x768@30" ]; # boot.kernelParams = [ "video=VGA-1:1024x768@30" ];
boot.loader.efi.canTouchEfiVariables = true; boot.loader.efi.canTouchEfiVariables = true;
boot.supportedFilesystems = [ "zfs" ]; boot.supportedFilesystems = [ "zfs" ];
boot.kernelPackages = config.boot.zfs.package.latestCompatibleLinuxPackages; # boot.kernelPackages = config.boot.zfs.package.latestCompatibleLinuxPackages;
# Pin Kernel Version as 6.6.28 has a broken networking driver
boot.kernelPackages = pkgs.linuxPackagesFor (pkgs.linux_6_6.override {
argsOverride = rec {
src = pkgs.fetchurl {
url = "mirror://kernel/linux/kernel/v6.x/linux-${version}.tar.xz";
sha256 = "sha256-Y55QBg48jyPtAXyxDP6sxrqI/1WDgSu3aFm0zGoSgpE=";
};
version = "6.6.27";
modDirVersion = "6.6.27";
};
});
services.zfs = { services.zfs = {
trim.enable = true; trim.enable = true;
@ -37,9 +53,6 @@
value = "10000"; value = "10000";
} }
]; ];
# Enable the OpenSSH daemon.
services.openssh.enable = true;
services.openssh.settings.PermitRootLogin = "yes";
systemd = { systemd = {
services.nix-daemon.serviceConfig = { services.nix-daemon.serviceConfig = {

View file

@ -10,41 +10,41 @@
boot.kernelModules = [ "kvm-amd" ]; boot.kernelModules = [ "kvm-amd" ];
boot.extraModulePackages = [ ]; boot.extraModulePackages = [ ];
fileSystems."/" = fileSystems."/" = {
{ device = "rpool/nixos/root";
device = "rpool/nixos/root"; fsType = "zfs";
fsType = "zfs"; };
};
fileSystems."/home" = fileSystems."/home" = {
{ device = "rpool/nixos/home";
device = "rpool/nixos/home"; fsType = "zfs";
fsType = "zfs"; };
};
fileSystems."/nix" = fileSystems."/nix" = {
{ device = "rpool/nixos/nixnew";
device = "rpool/nixos/nixnew"; fsType = "zfs";
fsType = "zfs"; };
};
fileSystems."/var/lib" = fileSystems."/var/lib" = {
{ device = "rpool/nixos/var/lib";
device = "rpool/nixos/var/lib"; fsType = "zfs";
fsType = "zfs"; };
};
fileSystems."/var/log" = fileSystems."/var/log" = {
{ device = "rpool/nixos/var/log";
device = "rpool/nixos/var/log"; fsType = "zfs";
fsType = "zfs"; };
};
fileSystems."/boot" = fileSystems."/boot" = {
{ device = "/dev/disk/by-uuid/3278-8D00";
device = "/dev/disk/by-uuid/3278-8D00"; fsType = "vfat";
fsType = "vfat"; options = [ "nofail" ];
}; };
fileSystems."/boot2" = {
device = "/dev/disk/by-uuid/3366-F71E";
fsType = "vfat";
options = [ "nofail" ];
};
swapDevices = [ ]; swapDevices = [ ];
nixpkgs.hostPlatform = lib.mkDefault "x86_64-linux"; nixpkgs.hostPlatform = lib.mkDefault "x86_64-linux";

View file

@ -8,6 +8,7 @@
imports = imports =
[ [
# Include the results of the hardware scan. # Include the results of the hardware scan.
./network.nix
./hardware-configuration.nix ./hardware-configuration.nix
]; ];
@ -15,8 +16,6 @@
boot.loader.systemd-boot.enable = true; boot.loader.systemd-boot.enable = true;
boot.loader.efi.canTouchEfiVariables = true; boot.loader.efi.canTouchEfiVariables = true;
networking.hostName = "tomate"; # Define your hostname.
networking.nftables.enable = true;
nix = { nix = {
settings = { settings = {
@ -29,9 +28,6 @@
}; };
}; };
# Enable networking
networking.networkmanager.enable = true;
# Set your time zone. # Set your time zone.
time.timeZone = "Europe/Berlin"; time.timeZone = "Europe/Berlin";

40
hosts/tomate/network.nix Normal file
View file

@ -0,0 +1,40 @@
{ config, ... }:
{
sops.secrets.ifsr-apb-auth = { };
networking = {
domain = "ifsr.de";
hostName = "tomate";
useNetworkd = true;
nftables.enable = true;
# Radius authentification
supplicant."enp3s0" = {
driver = "wired";
configFile.path = config.sops.secrets.ifsr-apb-auth.path;
};
};
services.resolved = {
enable = true;
fallbackDns = [ "9.9.9.9" ];
};
systemd.network = {
enable = true;
networks."10-wired-default" = {
matchConfig.Name = "enp3s0";
address = [ "141.30.86.196/26" ];
routes = [
{
routeConfig.Gateway = "141.30.86.193";
}
];
networkConfig = {
DNS = "141.30.1.1";
LLDP = true;
EmitLLDP = "nearest-bridge";
};
};
};
}

View file

@ -29,7 +29,13 @@
}; };
# Enable the OpenSSH daemon. # Enable the OpenSSH daemon.
services.openssh.enable = true; services.openssh = {
enable = true;
settings = {
PermitRootLogin = "yes";
PasswordAuthentication = false;
};
};
programs.mosh.enable = true; programs.mosh.enable = true;
# vs code server # vs code server

View file

@ -7,6 +7,7 @@
./initrd-ssh.nix ./initrd-ssh.nix
./mysql.nix ./mysql.nix
./nginx.nix ./nginx.nix
./podman.nix
./postgres.nix ./postgres.nix
./sssd.nix ./sssd.nix
./zsh.nix ./zsh.nix

View file

@ -6,13 +6,14 @@
{ config, ... }: { config, ... }:
{ {
boot.initrd = { boot.initrd = {
availableKernelModules = [ "mlx5_core" ];
systemd = { systemd = {
enable = true; enable = true;
network = { network = {
enable = true; enable = true;
networks."10-wired-default" = config.systemd.network.networks."10-wired-default"; networks."10-wired-default" = config.systemd.network.networks."10-wired-default";
}; };
users.root.shell = "/bin/zfs load-key rpool/nixos"; users.root.shell = "/bin/systemd-tty-ask-password-agent";
}; };
network = { network = {
enable = true; enable = true;

View file

@ -7,10 +7,14 @@
({ name, ... }: { ({ name, ... }: {
enableACME = true; enableACME = true;
forceSSL = true; forceSSL = true;
# enable http3 for all hosts
quic = true;
http3 = true;
# split up nginx access logs per vhost # split up nginx access logs per vhost
extraConfig = '' extraConfig = ''
access_log /var/log/nginx/${name}_access.log; access_log /var/log/nginx/${name}_access.log;
error_log /var/log/nginx/${name}_error.log; error_log /var/log/nginx/${name}_error.log;
add_header Alt-Svc 'h3=":443"; ma=86400';
''; '';
}) })
); );
@ -22,6 +26,7 @@
networking.firewall.allowedUDPPorts = [ 443 ]; networking.firewall.allowedUDPPorts = [ 443 ];
services.nginx = { services.nginx = {
enable = true; enable = true;
package = pkgs.nginxQuic;
additionalModules = [ pkgs.nginxModules.pam ]; additionalModules = [ pkgs.nginxModules.pam ];
recommendedProxySettings = true; recommendedProxySettings = true;
recommendedGzipSettings = true; recommendedGzipSettings = true;

26
modules/core/podman.nix Normal file
View file

@ -0,0 +1,26 @@
{ config, pkgs, ... }:
{
# From: https://nixos.wiki/wiki/Podman
virtualisation.containers.enable = true;
virtualisation = {
podman = {
enable = true;
# Create a `docker` alias for podman, to use it as a drop-in replacement
dockerCompat = true;
# Required for containers under podman-compose to be able to talk to each other.
defaultNetwork.settings.dns_enabled = true;
};
};
virtualisation.oci-containers.backend = "podman";
# Useful otherdevelopment tools
environment.systemPackages = with pkgs; [
dive # look into docker image layers
podman-tui # status of containers in the terminal
#docker-compose # start group of containers for dev
#podman-compose # start group of containers for dev
];
}

View file

@ -8,7 +8,9 @@
"directus_ese" "directus_ese"
"course-management" "course-management"
"git" "git"
"grafana"
"hedgedoc" "hedgedoc"
"keycloak"
"matrix-synapse" "matrix-synapse"
"mautrix-telegram" "mautrix-telegram"
"mediawiki" "mediawiki"

View file

@ -1,5 +1,6 @@
{ lib, pkgs, ... }: { lib, pkgs, ... }:
{ {
users.users.root.shell = pkgs.zsh;
programs.command-not-found.enable = false; programs.command-not-found.enable = false;
programs.nix-index-database.comma.enable = true; programs.nix-index-database.comma.enable = true;
environment.systemPackages = with pkgs; [ environment.systemPackages = with pkgs; [

View file

@ -6,14 +6,14 @@ in
sops.secrets."decisions_env" = { }; sops.secrets."decisions_env" = { };
virtualisation.oci-containers = { virtualisation.oci-containers = {
containers.decisions = { containers.decisions = {
image = "decisions"; image = "ghcr.io/fsr/decisions";
volumes = [ volumes = [
"/var/lib/nextcloud/data/root/files/FSR/protokolle:/protokolle:ro" "/var/lib/nextcloud/data/root/files/FSR/protokolle:/protokolle:ro"
]; ];
extraOptions = [ "--network=host" ];
environmentFiles = [ environmentFiles = [
config.sops.secrets."decisions_env".path config.sops.secrets."decisions_env".path
]; ];
extraOptions = [ "--network=host" ];
}; };
}; };
@ -25,11 +25,6 @@ in
}; };
}; };
services.portunus.dex.oidcClients = [{
id = "decisions";
callbackURL = "https://decisions.ifsr.de/auth";
}];
systemd.timers."decisions-to-db" = { systemd.timers."decisions-to-db" = {
wantedBy = [ "timers.target" ]; wantedBy = [ "timers.target" ];
timerConfig = { timerConfig = {

View file

@ -1,65 +1,33 @@
{ pkgs, config, lib, ... }: { config, pkgs, ... }:
let let
domain = "kanboard.${config.networking.domain}"; domain = "kanboard.${config.networking.domain}";
domain_short = "kb.${config.networking.domain}"; domain_short = "kb.${config.networking.domain}";
user = "kanboard";
group = "kanboard";
in in
{ {
users.users.${user} = { sops.secrets."kanboard_env" = { };
group = group;
isSystemUser = true; virtualisation.oci-containers = {
}; containers.kanboard = {
users.groups.${group} = { }; image = "ghcr.io/kanboard/kanboard:v1.2.36";
volumes = [
services.phpfpm.pools.kanboard = { "kanboard_data:/var/www/app/data"
user = "kanboard"; "kanboard_plugins:/var/www/app/plugins"
group = "kanboard"; ];
settings = { ports = [ "127.0.0.1:8045:80" ];
"listen.owner" = config.services.nginx.user; environmentFiles = [
"pm" = "dynamic"; config.sops.secrets."kanboard_env".path
"pm.max_children" = 32; ];
"pm.max_requests" = 500;
"pm.start_servers" = 2;
"pm.min_spare_servers" = 2;
"pm.max_spare_servers" = 5;
"php_admin_value[error_log]" = "stderr";
"php_admin_flag[log_errors]" = true;
"catch_workers_output" = true;
}; };
phpEnv."PATH" = lib.makeBinPath [ pkgs.php ];
}; };
services.nginx.enable = true;
services.nginx = { services.nginx = {
virtualHosts."${domain_short}" = { virtualHosts."${domain_short}" = {
locations."/".return = "301 $scheme://${domain}$request_uri"; locations."/".return = "301 $scheme://${domain}$request_uri";
}; };
virtualHosts."${domain}" = { virtualHosts."${domain}" = {
root = "/srv/web/kanboard"; locations."/" = {
extraConfig = '' proxyPass = "http://127.0.0.1:8045";
index index.html index.php;
'';
locations = {
"/" = {
tryFiles = "$uri $uri/ =404";
};
"~ \.php$" = {
extraConfig = ''
try_files $uri =404;
fastcgi_pass unix:${config.services.phpfpm.pools.kanboard.socket};
fastcgi_split_path_info ^(.+\.php)(/.+)$;
fastcgi_index index.php;
include ${pkgs.nginx}/conf/fastcgi_params;
include ${pkgs.nginx}/conf/fastcgi.conf;
fastcgi_param SCRIPT_FILENAME $document_root/$fastcgi_script_name;
'';
};
"/data".return = "403";
}; };
}; };
}; };

34
modules/keycloak.nix Normal file
View file

@ -0,0 +1,34 @@
{ config, nixpkgs-unstable, ... }:
let
domain = "sso.${config.networking.domain}";
in
{
sops.secrets."keycloak/db" = { };
services.keycloak = {
enable = true;
# we use unstable as the release in stable is insecure
package = nixpkgs-unstable.legacyPackages.x86_64-linux.keycloak;
settings = {
http-port = 8086;
https-port = 19000;
hostname = domain;
proxy = "edge";
};
# The module requires a password for the DB and works best with its own DB config
# Does an automatic Postgresql configuration
database = {
passwordFile = config.sops.secrets."keycloak/db".path;
};
initialAdminPassword = "plschangeme";
};
services.nginx.virtualHosts."${domain}" = {
locations."/" = {
proxyPass = "http://127.0.0.1:${toString config.services.keycloak.settings.http-port}";
extraConfig = ''
proxy_buffer_size 128k;
proxy_buffers 4 256k;
proxy_busy_buffers_size 256k;
'';
};
};
}

View file

@ -1,4 +1,4 @@
{ config, lib, pkgs, nixpkgs-unstable, system, ... }: { config, pkgs, nixpkgs-unstable, system, ... }:
let let
domain = "auth.${config.networking.domain}"; domain = "auth.${config.networking.domain}";
seedSettings = { seedSettings = {
@ -55,7 +55,6 @@ in
sops.secrets = { sops.secrets = {
"portunus/admin-password".owner = config.services.portunus.user; "portunus/admin-password".owner = config.services.portunus.user;
"portunus/search-password".owner = config.services.portunus.user; "portunus/search-password".owner = config.services.portunus.user;
"dex/environment".owner = config.systemd.services.dex.serviceConfig.User;
}; };
services.portunus = { services.portunus = {
@ -72,8 +71,6 @@ in
inherit domain seedSettings; inherit domain seedSettings;
port = 8681; port = 8681;
dex.enable = true;
ldap = { ldap = {
suffix = "dc=ifsr,dc=de"; suffix = "dc=ifsr,dc=de";
searchUserName = "search"; searchUserName = "search";
@ -84,30 +81,6 @@ in
}; };
}; };
services.dex.settings = {
oauth2.skipApprovalScreen = true;
frontend = {
issuer = "iFSR Schliboleth";
logoURL = "https://wiki.ifsr.de/images/3/3b/LogoiFSR.png";
theme = "dark";
};
};
systemd.services.dex.serviceConfig = {
DynamicUser = lib.mkForce false;
EnvironmentFile = config.sops.secrets."dex/environment".path;
StateDirectory = "dex";
User = "dex";
};
users = {
users.dex = {
group = "dex";
isSystemUser = true;
};
groups.dex = { };
};
security.pam.services.sshd.makeHomeDir = true; security.pam.services.sshd.makeHomeDir = true;
services.nginx = { services.nginx = {
@ -115,13 +88,12 @@ in
virtualHosts."${config.services.portunus.domain}" = { virtualHosts."${config.services.portunus.domain}" = {
locations = { locations = {
"/".proxyPass = "http://localhost:${toString config.services.portunus.port}"; "/".proxyPass = "http://localhost:${toString config.services.portunus.port}";
"/dex".proxyPass = "http://localhost:${toString config.services.portunus.dex.port}";
}; };
}; };
}; };
networking.firewall = { networking.firewall = {
extraInputRules = '' extraInputRules = ''
ip saddr { 141.30.86.192/26, 141.76.100.128/25 } tcp dport 636 accept comment "Allow ldaps access from office nets" ip saddr { 141.30.86.192/26, 141.76.100.128/25, 141.30.30.169, 10.88.0.1/16 } tcp dport 636 accept comment "Allow ldaps access from office nets and podman"
''; '';
}; };
} }

View file

@ -66,6 +66,14 @@
ensureDatabases = [ "mailman" "mailman-web" ]; ensureDatabases = [ "mailman" "mailman-web" ];
}; };
services.nginx.virtualHosts."lists.${config.networking.domain}" = { services.nginx.virtualHosts."lists.${config.networking.domain}" = {
locations."/accounts/signup" = {
extraConfig = ''
allow 141.30.0.0/16;
allow 141.76.0.0/16;
deny all;
uwsgi_pass unix:/run/mailman-web.socket;
'';
};
locations."/robots.txt" = { locations."/robots.txt" = {
extraConfig = '' extraConfig = ''
add_header Content-Type text/plain; add_header Content-Type text/plain;

98
modules/monitoring.nix Normal file
View file

@ -0,0 +1,98 @@
{ config, ... }:
let
domain = "monitoring.${config.networking.domain}";
in
{
sops.secrets."grafana/oidc_secret" = {
owner = "grafana";
};
# grafana configuration
services.grafana = {
enable = true;
settings = {
server = {
inherit domain;
http_addr = "127.0.0.1";
http_port = 2342;
root_url = "https://monitoring.ifsr.de";
};
database = {
type = "postgres";
user = "grafana";
host = "/run/postgresql";
};
"auth.generic_oauth" = {
enabled = true;
name = "iFSR";
allow_sign_up = true;
client_id = "grafana";
client_secret = "$__file{${config.sops.secrets."grafana/oidc_secret".path}}";
scopes = "openid email profile offline_access roles";
email_attribute_path = "email";
login_attribute_path = "username";
name_attribute_path = "full_name";
auth_url = "https://sso.ifsr.de/realms/internal/protocol/openid-connect/auth";
token_url = "https://sso.ifsr.de/realms/internal/protocol/openid-connect/token";
api_url = "https://sso.ifsr.de/realms/internal/protocol/openid-connect/userinfo";
role_attribute_path = "contains(roles[*], 'admin') && 'Admin' || contains(roles[*], 'editor') && 'Editor' || 'Viewer'";
};
};
};
services.postgresql = {
enable = true;
ensureUsers = [
{
name = "grafana";
ensureDBOwnership = true;
}
];
ensureDatabases = [ "grafana" ];
};
services.prometheus = {
enable = true;
port = 9001;
exporters = {
node = {
enable = true;
enabledCollectors = [ "systemd" ];
port = 9002;
};
postfix = {
enable = true;
port = 9003;
};
};
scrapeConfigs = [
{
job_name = "node";
static_configs = [{
targets = [ "127.0.0.1:${toString config.services.prometheus.exporters.node.port}" ];
}];
scrape_interval = "15s";
}
{
job_name = "postfix";
static_configs = [{
targets = [ "127.0.0.1:${toString config.services.prometheus.exporters.postfix.port}" ];
}];
# scrape_interval = "60s";
}
];
};
# nginx reverse proxy
services.nginx.virtualHosts.${domain} = {
locations."/" = {
proxyPass = "http://localhost:${toString config.services.grafana.settings.server.http_port}";
proxyWebsockets = true;
};
};
}

View file

@ -1,4 +1,4 @@
{ config, ... }: { config, pkgs, ... }:
let let
domain = "cache.${config.networking.domain}"; domain = "cache.${config.networking.domain}";
in in
@ -6,6 +6,7 @@ in
sops.secrets."nix-serve/key" = { }; sops.secrets."nix-serve/key" = { };
services.nix-serve = { services.nix-serve = {
enable = true; enable = true;
package = pkgs.nix-serve-ng;
secretKeyFile = config.sops.secrets."nix-serve/key".path; secretKeyFile = config.sops.secrets."nix-serve/key".path;
port = 5002; port = 5002;
}; };

View file

@ -46,10 +46,4 @@ in
}; };
}; };
}; };
services.portunus.dex.oidcClients = [{
id = "padlist";
callbackURL = "https://list.pad.ifsr.de/callback.php";
}];
} }

View file

@ -1,7 +1,7 @@
{ config, pkgs, ... }: { config, pkgs, ... }:
{ {
sops.secrets."strukturbot_env" = { }; sops.secrets."strukturbot_env" = { };
virtualisation.docker.daemon.settings.dns = [ "141.30.1.1" "141.76.14.1" ]; # virtualisation.docker.daemon.settings.dns = [ "141.30.1.1" "141.76.14.1" ];
virtualisation.oci-containers = { virtualisation.oci-containers = {
containers.struktur-bot = { containers.struktur-bot = {
image = "struktur-bot"; image = "struktur-bot";

View file

@ -0,0 +1,7 @@
{ config, pkgs, ... }:
let
domain = "cc.${config.networking.domain}";
in
{
services.nginx.virtualHosts."${domain}".root = "/srv/web/regex";
}

View file

@ -1,6 +1,7 @@
{ ... }: { ... }:
{ {
imports = [ imports = [
./crimecampus.nix
./ifsrde.nix ./ifsrde.nix
./ese.nix ./ese.nix
./infoscreen.nix ./infoscreen.nix

View file

@ -7,14 +7,12 @@ in
sops.secrets."directus_env" = { }; sops.secrets."directus_env" = { };
environment.systemPackages = [ pkgs.nodejs_21 ]; environment.systemPackages = [ pkgs.nodejs_21 ];
virtualisation.oci-containers = { virtualisation.oci-containers = {
backend = "docker";
containers.directus-ese = { containers.directus-ese = {
image = "directus/directus:latest"; image = "directus/directus:latest";
volumes = [ volumes = [
"/srv/web/directus-ese/uploads:/directus/uploads" "/srv/web/directus-ese/uploads:/directus/uploads"
"/srv/web/directus-ese/database:/directus/database" "/srv/web/directus-ese/database:/directus/database"
]; ];
ports = [ "127.0.0.1:8055:8055" ];
extraOptions = [ "--network=host" ]; extraOptions = [ "--network=host" ];
environment = { environment = {
"DB_CLIENT" = "pg"; "DB_CLIENT" = "pg";
@ -22,6 +20,14 @@ in
"DB_PORT" = "5432"; "DB_PORT" = "5432";
"DB_DATABASE" = "directus_ese"; "DB_DATABASE" = "directus_ese";
"DB_USER" = "directus_ese"; "DB_USER" = "directus_ese";
"PUBLIC_URL" = "https://directus-ese.ifsr.de";
"AUTH_PROVIDERS"="keycloak";
"AUTH_KEYCLOAK_DRIVER" = "openid";
"AUTH_KEYCLOAK_CLIENT_ID" = "directus-ese";
"AUTH_KEYCLOAK_ISSUER_URL" = "https://sso.ifsr.de/realms/internal/.well-known/openid-configuration";
"AUTH_KEYCLOAK_IDENTIFIER_KEY" = "email";
"AUTH_KEYCLOAK_ALLOW_PUBLIC_REGISTRATION"="true";
"AUTH_KEYCLOAK_DEFAULT_ROLE_ID"="a6b7a1b6-a6fa-442c-87fd-e37c2a16424b";
}; };
environmentFiles = [ environmentFiles = [
config.sops.secrets."directus_env".path config.sops.secrets."directus_env".path

View file

@ -58,6 +58,7 @@ in
include ${pkgs.nginx}/conf/fastcgi_params; include ${pkgs.nginx}/conf/fastcgi_params;
include ${pkgs.nginx}/conf/fastcgi.conf; include ${pkgs.nginx}/conf/fastcgi.conf;
fastcgi_param SCRIPT_FILENAME $document_root/$fastcgi_script_name; fastcgi_param SCRIPT_FILENAME $document_root/$fastcgi_script_name;
fastcgi_param HTTP_HOST $host;
''; '';
}; };
"~ \.log$".return = "403"; "~ \.log$".return = "403";

View file

@ -60,6 +60,7 @@ in
"~ ^/cmd(/?[^\\n|\\r]*)$".return = "301 https://pad.ifsr.de$1"; "~ ^/cmd(/?[^\\n|\\r]*)$".return = "301 https://pad.ifsr.de$1";
"/bbb".return = "301 https://bbb.tu-dresden.de/b/fsr-58o-tmf-yy6"; "/bbb".return = "301 https://bbb.tu-dresden.de/b/fsr-58o-tmf-yy6";
"/kpp".return = "301 https://kpp.ifsr.de"; "/kpp".return = "301 https://kpp.ifsr.de";
"/sso".return = "301 https://sso.ifsr.de/realms/internal/account";
# security # security
"~* /(\.git|cache|bin|logs|backup|tests)/.*$".return = "403"; "~* /(\.git|cache|bin|logs|backup|tests)/.*$".return = "403";
# deny running scripts inside core system folders # deny running scripts inside core system folders
@ -72,9 +73,4 @@ in
}; };
}; };
}; };
services.portunus.dex.oidcClients = [{
id = "grav";
callbackURL = "https://ifsr.de/admin/task:callback.oauth2";
}];
} }

View file

@ -55,6 +55,7 @@ in
include ${pkgs.nginx}/conf/fastcgi_params; include ${pkgs.nginx}/conf/fastcgi_params;
include ${pkgs.nginx}/conf/fastcgi.conf; include ${pkgs.nginx}/conf/fastcgi.conf;
fastcgi_param SCRIPT_FILENAME $document_root/$fastcgi_script_name; fastcgi_param SCRIPT_FILENAME $document_root/$fastcgi_script_name;
fastcgi_param HTTP_HOST $host;
''; '';
}; };
"~ \.log$".return = "403"; "~ \.log$".return = "403";

View file

@ -63,11 +63,12 @@ in
# Auth # Auth
# https://www.mediawiki.org/wiki/Extension:PluggableAuth # https://www.mediawiki.org/wiki/Extension:PluggableAuth
# https://www.mediawiki.org/wiki/Extension:OpenID_Connect # https://www.mediawiki.org/wiki/Extension:OpenID_Connect
$wgOpenIDConnect_MigrateUsersByEmail = true;
$wgPluggableAuth_EnableLocalLogin = true; $wgPluggableAuth_EnableLocalLogin = true;
$wgPluggableAuth_Config["iFSR Login"] = [ $wgPluggableAuth_Config["iFSR Login"] = [
"plugin" => "OpenIDConnect", "plugin" => "OpenIDConnect",
"data" => [ "data" => [
"providerURL" => "${config.services.portunus.domain}/dex", "providerURL" => "https://sso.ifsr.de/realms/internal",
"clientID" => "wiki", "clientID" => "wiki",
"clientsecret" => file_get_contents('${config.sops.secrets."mediawiki/oidc_secret".path}'), "clientsecret" => file_get_contents('${config.sops.secrets."mediawiki/oidc_secret".path}'),
], ],
@ -94,11 +95,6 @@ in
}; };
}; };
portunus.dex.oidcClients = [{
id = "wiki";
callbackURL = "https://${domain}/Spezial:PluggableAuthLogin";
}];
nginx = { nginx = {
recommendedProxySettings = true; recommendedProxySettings = true;
virtualHosts.${domain} = { virtualHosts.${domain} = {

View file

@ -1,6 +1,7 @@
_final: prev: _final: prev:
let let
inherit (prev) fetchurl; inherit (prev) fetchurl;
inherit (prev) fetchFromGitHub;
in in
{ {
# AGDSN is running an outdated version that we have to comply to # AGDSN is running an outdated version that we have to comply to
@ -11,5 +12,17 @@ in
sha256 = "sha256-3w+FJezbo4DnS1N8pxrfO3WWWT8CGJtZqw6//IXMyN4="; sha256 = "sha256-3w+FJezbo4DnS1N8pxrfO3WWWT8CGJtZqw6//IXMyN4=";
}; };
})); }));
# (hopefully) fix systemd journal reading
prometheus-postfix-exporter = prev.prometheus-postfix-exporter.overrideAttrs (_old: {
patches = [
./prometheus-postfix-exporter/0001-cleanup-also-catch-milter-reject.patch
];
src = fetchFromGitHub {
owner = "adangel";
repo = "postfix_exporter";
rev = "414ac12ee63415eede46cb3084d755a6da6fba23";
hash = "sha256-m1kVaO3N7XC1vtnxXX9kMiEFPmZuoopRUYgA7gQzP8w=";
};
});
} }

View file

@ -0,0 +1,25 @@
From f4c5dd5628c873981b2d6d6b8f3bbf036b9fd724 Mon Sep 17 00:00:00 2001
From: Rouven Seifert <rouven.seifert@ifsr.de>
Date: Thu, 2 May 2024 11:20:27 +0200
Subject: [PATCH] cleanup: also catch milter-reject
---
postfix_exporter.go | 2 ++
1 file changed, 2 insertions(+)
diff --git a/postfix_exporter.go b/postfix_exporter.go
index f20d99c..676d767 100644
--- a/postfix_exporter.go
+++ b/postfix_exporter.go
@@ -335,6 +335,8 @@ func (e *PostfixExporter) CollectFromLogLine(line string) {
e.cleanupProcesses.Inc()
} else if strings.Contains(remainder, ": reject: ") {
e.cleanupRejects.Inc()
+ } else if strings.Contains(remainder, ": milter-reject: ") {
+ e.cleanupRejects.Inc()
} else {
e.addToUnsupportedLine(line, subprocess, level)
}
--
2.44.0

File diff suppressed because one or more lines are too long

View file

@ -4,6 +4,7 @@ print:
smtp-password: ENC[AES256_GCM,data:XoaLiEpqAdKapeS9YoBfh2w7HFuTCV9rHIciH+qUbhHcdsgVpnPMsSlC,iv:WxfP5d2K9soJPoRPuS6O6PbNvo4TBQjPGiV0e+a501Q=,tag:ZsTdR+b/oYFAYz/MN73PFg==,type:str] smtp-password: ENC[AES256_GCM,data:XoaLiEpqAdKapeS9YoBfh2w7HFuTCV9rHIciH+qUbhHcdsgVpnPMsSlC,iv:WxfP5d2K9soJPoRPuS6O6PbNvo4TBQjPGiV0e+a501Q=,tag:ZsTdR+b/oYFAYz/MN73PFg==,type:str]
sssd: sssd:
env: ENC[AES256_GCM,data:9IbU7uaElmemQHVUvsM88hcyNl3WFehgQeLZPtUxt2Sd0IECm8qNkQhWJ4kuvoBnQsdsUrFm/0QuW7AfDFOeE7FxMxg0,iv:dyzsYHlqClWbfzsoJ36iYjaXWpidB1ZqHXI7RP7js2Y=,tag:97FMOeVwAEy8Ka79uZKC8Q==,type:str] env: ENC[AES256_GCM,data:9IbU7uaElmemQHVUvsM88hcyNl3WFehgQeLZPtUxt2Sd0IECm8qNkQhWJ4kuvoBnQsdsUrFm/0QuW7AfDFOeE7FxMxg0,iv:dyzsYHlqClWbfzsoJ36iYjaXWpidB1ZqHXI7RP7js2Y=,tag:97FMOeVwAEy8Ka79uZKC8Q==,type:str]
ifsr-apb-auth: ENC[AES256_GCM,data:hxJOvRbgjB//YU3wy04P7yrQbV0Ggoi18wQxwy4hHgbXizTHbmlfiZ/MstITrZQ6qEPVBEW41/iGU3DO2Cg2ofpWvFU5Gr8FM1AC9DKq8SppLGqzel1mEejPfrh4RbQUMe0zZlc/YfhCah5sM0oPnBQNg8bPpveEO+5/bRq5S24jkkv7w6/AAS8tGvjALVf/g95jsCrQO2MYg9jCCEkdhORU0bowGD8cjTr6wnPkNhwzn5tiKoPn6eH6TFBkqNC+Q/5E+os10i9F1c3z/sv8Snrcl7V5higqrQekhEvGRDmax/4lE8Yb3AoxC/2M4/+9x+OPi0JUkkhC6rghETXpmYkuaD7E8+eEtLeSbiJPlPijq2HTtbtsHcSoMUdoGO8644TVe/jDxaEe54p9OWEFjRRpONijQKsfH3wENlUXmqDQDLfMSpoANxIHMh+RmRzktGIvTgvs6rlKXsWp7/gggFVxdM/5QPbE3pUvGr+JPWz4,iv:6c1HxYGrItPwKzAnQ0zUvO3TSejVZ/aWF9zs99ufzl4=,tag:fELOskceJWKmkm74MCsfoA==,type:str]
sops: sops:
kms: [] kms: []
gcp_kms: [] gcp_kms: []
@ -19,8 +20,8 @@ sops:
TXVrMHZCNU5zOG5hVnNkdEoxcTZqWXMKA9eG1zM6HeLAAOpIo8Z5+5KD4Z5P3rdc TXVrMHZCNU5zOG5hVnNkdEoxcTZqWXMKA9eG1zM6HeLAAOpIo8Z5+5KD4Z5P3rdc
kE8sUXHD3d8SMmSKcTYe6gGVzFuw0xxnMb/AmjAQosvDFTQsWy1sTw== kE8sUXHD3d8SMmSKcTYe6gGVzFuw0xxnMb/AmjAQosvDFTQsWy1sTw==
-----END AGE ENCRYPTED FILE----- -----END AGE ENCRYPTED FILE-----
lastmodified: "2024-01-29T13:36:12Z" lastmodified: "2024-04-16T08:58:21Z"
mac: ENC[AES256_GCM,data:CnoH4KmYy72E0L+X7SHYXrFH6z0KhRhfYXmIO8HnPlkYnwKXDeAYezv4kL3ItZG+8pnmbFdoyHxxVMT6rWtV//x16YPMI0zhwIEBs67ZxM+gzeei4fniktolydKmlXUgbtWw3/y3OtxzAn9Dne2LPz7CwN/imGOTgrWFYGWRhtU=,iv:gcurHYWPSijYRlt9FoutrGInWDOfSkjrNqwU6jxiHDk=,tag:qWhpQ9vLuuihOzJeOGYEog==,type:str] mac: ENC[AES256_GCM,data:2aOOVZK7kshJFBWphvW/BqRUXht4p80Q15nGJNA1EbjT05f3tYdrr8QuM5Xd1vJO07rgmokWv4XwbzodRIwqidEXD5xuJ1v+kHC/jJnO3yrBKY7kVMHkia2Wq00bcN/iwdW6G6AP5D4HQbmFNo+rLHyjIVwPvtu9jutKpz12NH0=,iv:YCBX2gSEmiUa6HrHi0VEcRGWDJrXGajD8ZbOZcppFnM=,tag:FK2E4hukl8oL5aZNTCQESA==,type:str]
pgp: pgp:
- created_at: "2024-02-29T15:23:28Z" - created_at: "2024-02-29T15:23:28Z"
enc: |- enc: |-