Compare commits

..

3 Commits

Author SHA1 Message Date
Eirik Witterso 60e1bbfd08 WIP: Add bluemap
Co-authored-by: Daniel Olsen <daniel.olsen99@gmail.com>
2024-06-09 07:33:43 +02:00
Oystein Kristoffer Tveit ceaa67fc19
WIP: fix loki 2024-06-08 20:58:25 +02:00
Oystein Kristoffer Tveit 375e0f1486
treewide: fix issues for 24.05 upgrade 2024-06-08 20:58:10 +02:00
116 changed files with 1198 additions and 6429 deletions

View File

@ -1,10 +0,0 @@
root = true
[*]
end_of_line = lf
insert_final_newline = true
trim_trailing_whitespace = true
[*.nix]
indent_style = space
indent_size = 2

1
.envrc
View File

@ -1 +0,0 @@
use flake

View File

@ -1 +0,0 @@
e00008da1afe0d760badd34bbeddff36bb08c475

2
.gitignore vendored
View File

@ -1,4 +1,2 @@
result*
/configuration.nix
/.direnv/
*.qcow2

View File

@ -4,15 +4,13 @@ keys:
- &user_felixalb age1mrnldl334l2nszuta6ywvewng0fswv2dz9l5g4qcwe3nj4yxf92qjskdx6
- &user_oysteikt F7D37890228A907440E1FD4846B9228E814A2AAC
- &user_eirikwit age1ju7rd26llahz3g8tz7cy5ld52swj8gsmg0flrmrxngc0nj0avq3ssh0sn5
- &user_pederbs_sopp age1hmpdk4h69wxpwqk9tkud39f66hprhehxtzhgw97r6dvr7v0mx5jscsuhkn
- &user_pederbs_nord age1wrssr4z4g6vl3fd3qme5cewchmmhm0j2xe6wf2meu4r6ycn37anse98mfs
- &user_pederbs_bjarte age1zhxul786an743u0fascv4wtc5xduu7qfy803lfs539yzhgmlq5ds2lznt5
# Hosts
- &host_jokum age1gp8ye4g2mmw3may5xg0zsy7mm04glfz3788mmdx9cvcsdxs9hg0s0cc9kt
- &host_ildkule age1x28hmzvuv6f2n66c0jtqcca3h9rput8d7j5uek6jcpx8n9egd52sqpejq0
- &host_bekkalokk age12nj59tguy9wg882updc2vjdusx5srnxmjyfaqve4zx6jnnsaw3qsyjq6zd
- &host_bicep age1sl43gc9cw939z5tgha2lpwf0xxxgcnlw7w4xem4sqgmt2pt264vq0dmwx2
- &host_buskerud age1tmn5qahlyf0e579e4camckdyxrexjzffv54hdzdnrw7lzqs7kyqq0f2fr3
creation_rules:
# Global secrets
@ -23,9 +21,6 @@ creation_rules:
- *user_danio
- *user_felixalb
- *user_eirikwit
- *user_pederbs_sopp
- *user_pederbs_nord
- *user_pederbs_bjarte
pgp:
- *user_oysteikt
@ -37,9 +32,6 @@ creation_rules:
- *host_bekkalokk
- *user_danio
- *user_felixalb
- *user_pederbs_sopp
- *user_pederbs_nord
- *user_pederbs_bjarte
pgp:
- *user_oysteikt
@ -49,9 +41,6 @@ creation_rules:
- *host_jokum
- *user_danio
- *user_felixalb
- *user_pederbs_sopp
- *user_pederbs_nord
- *user_pederbs_bjarte
pgp:
- *user_oysteikt
@ -61,9 +50,6 @@ creation_rules:
- *host_ildkule
- *user_danio
- *user_felixalb
- *user_pederbs_sopp
- *user_pederbs_nord
- *user_pederbs_bjarte
pgp:
- *user_oysteikt
@ -73,8 +59,12 @@ creation_rules:
- *host_bicep
- *user_danio
- *user_felixalb
- *user_pederbs_sopp
- *user_pederbs_nord
- *user_pederbs_bjarte
pgp:
- *user_oysteikt
- path_regex: secrets/buskerud/[^/]+\.yaml$
key_groups:
- age:
- *host_buskerud
- *user_danio
- *user_eirikwit

View File

@ -26,14 +26,10 @@ Det er sikkert lurt å lage en PR først om du ikke er vandt til nix enda.
Innen 24h skal alle systemene hente ned den nye konfigurasjonen og deploye den.
Du kan tvinge en maskin til å oppdatere seg før dette ved å kjøre:
`nixos-rebuild switch --update-input nixpkgs --update-input nixpkgs-unstable --no-write-lock-file --refresh --upgrade --flake git+https://git.pvv.ntnu.no/Drift/pvv-nixos-config.git`
`nixos-rebuild switch --update-input nixpkgs --update-input nixpkgs-unstable --no-write-lock-file --refresh --flake git+https://git.pvv.ntnu.no/Drift/pvv-nixos-config.git --upgrade`
som root på maskinen.
Hvis du ikke har lyst til å oppdatere alle pakkene (og kanskje måtte vente en stund!) kan du kjøre
`nixos-rebuild switch --override-input nixpkgs nixpkgs --override-input nixpkgs-unstable nixpkgs-unstable --flake git+https://git.pvv.ntnu.no/Drift/pvv-nixos-config.git`
## Seksjonen for hemmeligheter
For at hemmeligheter ikke skal deles med hele verden i git - eller å være world

133
base.nix Normal file
View File

@ -0,0 +1,133 @@
{ config, lib, pkgs, inputs, values, ... }:
{
imports = [
./users
./modules/snakeoil-certs.nix
];
networking.domain = "pvv.ntnu.no";
networking.useDHCP = false;
# networking.search = [ "pvv.ntnu.no" "pvv.org" ];
# networking.nameservers = lib.mkDefault [ "129.241.0.200" "129.241.0.201" ];
# networking.tempAddresses = lib.mkDefault "disabled";
# networking.defaultGateway = values.hosts.gateway;
systemd.network.enable = true;
services.resolved = {
enable = lib.mkDefault true;
dnssec = "false"; # Supposdly this keeps breaking and the default is to allow downgrades anyways...
};
time.timeZone = "Europe/Oslo";
i18n.defaultLocale = "en_US.UTF-8";
console = {
font = "Lat2-Terminus16";
keyMap = "no";
};
system.autoUpgrade = {
enable = true;
flake = "git+https://git.pvv.ntnu.no/Drift/pvv-nixos-config.git";
flags = [
"--update-input" "nixpkgs"
"--update-input" "nixpkgs-unstable"
"--no-write-lock-file"
];
};
nix.gc.automatic = true;
nix.gc.options = "--delete-older-than 2d";
nix.settings.experimental-features = [ "nix-command" "flakes" ];
/* This makes commandline tools like
** nix run nixpkgs#hello
** and nix-shell -p hello
** use the same channel the system
** was built with
*/
nix.registry = {
nixpkgs.flake = inputs.nixpkgs;
};
nix.nixPath = [ "nixpkgs=${inputs.nixpkgs}" ];
environment.systemPackages = with pkgs; [
file
git
gnupg
htop
nano
ripgrep
rsync
screen
tmux
vim
wget
kitty.terminfo
];
programs.zsh.enable = true;
users.groups."drift".name = "drift";
# Trusted users on the nix builder machines
users.groups."nix-builder-users".name = "nix-builder-users";
services.openssh = {
enable = true;
extraConfig = ''
PubkeyAcceptedAlgorithms=+ssh-rsa
'';
settings.PermitRootLogin = "yes";
};
# nginx return 444 for all nonexistent virtualhosts
systemd.services.nginx.after = [ "generate-snakeoil-certs.service" ];
environment.snakeoil-certs = lib.mkIf config.services.nginx.enable {
"/etc/certs/nginx" = {
owner = "nginx";
group = "nginx";
};
};
services.nginx = {
recommendedTlsSettings = true;
recommendedProxySettings = true;
recommendedOptimisation = true;
recommendedGzipSettings = true;
appendConfig = ''
pcre_jit on;
worker_processes auto;
worker_rlimit_nofile 100000;
'';
eventsConfig = ''
worker_connections 2048;
use epoll;
multi_accept on;
'';
};
systemd.services.nginx.serviceConfig = lib.mkIf config.services.nginx.enable {
LimitNOFILE = 65536;
};
services.nginx.virtualHosts."_" = lib.mkIf config.services.nginx.enable {
sslCertificate = "/etc/certs/nginx.crt";
sslCertificateKey = "/etc/certs/nginx.key";
addSSL = true;
extraConfig = "return 444;";
};
networking.firewall.allowedTCPPorts = lib.mkIf config.services.nginx.enable [ 80 443 ];
security.acme = {
acceptTerms = true;
defaults.email = "drift@pvv.ntnu.no";
};
}

View File

@ -1,60 +0,0 @@
{ pkgs, lib, fp, ... }:
{
imports = [
(fp /users)
(fp /modules/snakeoil-certs.nix)
./networking.nix
./nix.nix
./services/acme.nix
./services/auto-upgrade.nix
./services/irqbalance.nix
./services/logrotate.nix
./services/nginx.nix
./services/openssh.nix
./services/postfix.nix
./services/smartd.nix
./services/thermald.nix
];
boot.tmp.cleanOnBoot = lib.mkDefault true;
time.timeZone = "Europe/Oslo";
i18n.defaultLocale = "en_US.UTF-8";
console = {
font = "Lat2-Terminus16";
keyMap = "no";
};
environment.systemPackages = with pkgs; [
file
git
gnupg
htop
nano
ripgrep
rsync
screen
tmux
vim
wget
kitty.terminfo
];
programs.zsh.enable = true;
security.sudo.execWheelOnly = true;
security.sudo.extraConfig = ''
Defaults lecture = never
'';
users.groups."drift".name = "drift";
# Trusted users on the nix builder machines
users.groups."nix-builder-users".name = "nix-builder-users";
}

View File

@ -1,13 +0,0 @@
{ lib, values, ... }:
{
systemd.network.enable = true;
networking.domain = "pvv.ntnu.no";
networking.useDHCP = false;
# The rest of the networking configuration is usually sourced from /values.nix
services.resolved = {
enable = lib.mkDefault true;
dnssec = "false"; # Supposdly this keeps breaking and the default is to allow downgrades anyways...
};
}

View File

@ -1,34 +0,0 @@
{ inputs, ... }:
{
nix = {
gc = {
automatic = true;
options = "--delete-older-than 2d";
};
settings = {
allow-dirty = true;
auto-optimise-store = true;
builders-use-substitutes = true;
experimental-features = [ "nix-command" "flakes" ];
log-lines = 50;
use-xdg-base-directories = true;
};
/* This makes commandline tools like
** nix run nixpkgs#hello
** and nix-shell -p hello
** use the same channel the system
** was built with
*/
registry = {
"nixpkgs".flake = inputs.nixpkgs;
"nixpkgs-unstable".flake = inputs.nixpkgs-unstable;
"pvv-nix".flake = inputs.self;
};
nixPath = [
"nixpkgs=${inputs.nixpkgs}"
"unstable=${inputs.nixpkgs-unstable}"
];
};
}

View File

@ -1,15 +0,0 @@
{ ... }:
{
security.acme = {
acceptTerms = true;
defaults.email = "drift@pvv.ntnu.no";
};
# Let's not spam LetsEncrypt in `nixos-rebuild build-vm` mode:
virtualisation.vmVariant = {
security.acme.defaults.server = "https://127.0.0.1";
security.acme.preliminarySelfsigned = true;
users.users.root.initialPassword = "root";
};
}

View File

@ -1,26 +0,0 @@
{ inputs, pkgs, lib, ... }:
{
system.autoUpgrade = {
enable = true;
flake = "git+https://git.pvv.ntnu.no/Drift/pvv-nixos-config.git";
flags = [
# --update-input is deprecated since nix 2.22, and removed in lix 2.90
# https://git.lix.systems/lix-project/lix/issues/400
"--refresh"
"--override-input" "nixpkgs" "github:nixos/nixpkgs/nixos-24.05-small"
"--override-input" "nixpkgs-unstable" "github:nixos/nixpkgs/nixos-unstable-small"
"--no-write-lock-file"
];
};
# workaround for https://github.com/NixOS/nix/issues/6895
# via https://git.lix.systems/lix-project/lix/issues/400
environment.etc."current-system-flake-inputs.json".source
= pkgs.writers.writeJSON "flake-inputs.json" (
lib.flip lib.mapAttrs inputs (name: input:
# inputs.*.sourceInfo sans outPath, since writeJSON will otherwise serialize sourceInfo like a derivation
lib.removeAttrs (input.sourceInfo or {}) [ "outPath" ]
// { store-path = input.outPath; } # comment this line if you don't want to retain a store reference to the flake inputs
)
);
}

View File

@ -1,4 +0,0 @@
{ ... }:
{
services.irqbalance.enable = true;
}

View File

@ -1,42 +0,0 @@
{ ... }:
{
# source: https://github.com/logrotate/logrotate/blob/main/examples/logrotate.service
systemd.services.logrotate = {
documentation = [ "man:logrotate(8)" "man:logrotate.conf(5)" ];
unitConfig.RequiresMountsFor = "/var/log";
serviceConfig = {
Nice = 19;
IOSchedulingClass = "best-effort";
IOSchedulingPriority = 7;
ReadWritePaths = [ "/var/log" ];
AmbientCapabilities = [ "" ];
CapabilityBoundingSet = [ "" ];
DeviceAllow = [ "" ];
LockPersonality = true;
MemoryDenyWriteExecute = true;
NoNewPrivileges = true; # disable for third party rotate scripts
PrivateDevices = true;
PrivateNetwork = true; # disable for mail delivery
PrivateTmp = true;
ProtectClock = true;
ProtectControlGroups = true;
ProtectHome = true; # disable for userdir logs
ProtectHostname = true;
ProtectKernelLogs = true;
ProtectKernelModules = true;
ProtectKernelTunables = true;
ProtectProc = "invisible";
ProtectSystem = "full";
RestrictNamespaces = true;
RestrictRealtime = true;
RestrictSUIDSGID = true; # disable for creating setgid directories
SocketBindDeny = [ "any" ];
SystemCallArchitectures = "native";
SystemCallFilter = [
"@system-service"
];
};
};
}

View File

@ -1,44 +0,0 @@
{ config, lib, ... }:
{
# nginx return 444 for all nonexistent virtualhosts
systemd.services.nginx.after = [ "generate-snakeoil-certs.service" ];
environment.snakeoil-certs = lib.mkIf config.services.nginx.enable {
"/etc/certs/nginx" = {
owner = "nginx";
group = "nginx";
};
};
networking.firewall.allowedTCPPorts = lib.mkIf config.services.nginx.enable [ 80 443 ];
services.nginx = {
recommendedTlsSettings = true;
recommendedProxySettings = true;
recommendedOptimisation = true;
recommendedGzipSettings = true;
appendConfig = ''
pcre_jit on;
worker_processes auto;
worker_rlimit_nofile 100000;
'';
eventsConfig = ''
worker_connections 2048;
use epoll;
multi_accept on;
'';
};
systemd.services.nginx.serviceConfig = lib.mkIf config.services.nginx.enable {
LimitNOFILE = 65536;
};
services.nginx.virtualHosts."_" = lib.mkIf config.services.nginx.enable {
sslCertificate = "/etc/certs/nginx.crt";
sslCertificateKey = "/etc/certs/nginx.key";
addSSL = true;
extraConfig = "return 444;";
};
}

View File

@ -1,21 +0,0 @@
{ ... }:
{
services.openssh = {
enable = true;
startWhenNeeded = true;
extraConfig = ''
PubkeyAcceptedAlgorithms=+ssh-rsa
Match Group wheel
PasswordAuthentication no
Match All
'';
settings.PermitRootLogin = "yes";
};
users.users."root".openssh.authorizedKeys.keys = [
"ssh-rsa AAAAB3NzaC1yc2EAAAADAQABAAACAQCqVt4LCe0YIttr9swFxjkjn37ZDY9JxwVC+2gvfSINDJorOCtqPjDOTD2fTS1Gz08QCwpnLWq2kyvRchu6WgriAbSACpbZZBgxRaF/FVh3oiMVFGnNKGnv6/fdo/vZtu8mUVuqtmTrgLYpZdbR4oD3XiBlDKs7Cv5hPqt95lnP6MNFvE8mICCfd1PwhsABd2IQ5laz3u77/RXhNFJL0Kf2/+6gk9awcLuwHrPdvq7c3BxRHbc9UMRQENyjyQPa7aLe+uJBFLKP51I8VBuDpDacuibQx7nMt6N2UJ2KWI0JxRMHuJNq4S5jidR82aOw9gzGbTv30SKNLMqsZ0xj4LtdqCXDiZF6Lr09PsJYsvnBUFWa14HGcThKDtgwQwBryNViYmfv//0h9+RLZiU0ab+NEwSs7Zh5iAD+vhx64QqNX3tR7Le4SWXh8W0eShU9N78qYdSkiC3Ui7htxeqOocXM/P4AwbnHsLELIvkHdvgchCPvl8ygZa4WJTEWv16+ICskJcAKWGuqjvXAFuwjJJmPp9xLW9O0DFfQhMELiGamQR9wK07yYQVr34iah6qZO7cwhSKyEPFrVPIaNtfDhsjED639F7vmktf26SWNJHWfW0wOHILjI6TgqUvy0JDd8W8w0CHlAfz6Fs2l99NNgNF8dB3vBASbxS0hu/y0PVu/xQ== openstack-sleipner"
"ssh-ed25519 AAAAC3NzaC1lZDI1NTE5AAAAICCbgJ0Uwh9VSVhfId7l9i5/jk4CvAK5rbkiab8R+moF root@sleipner"
];
}

View File

@ -1,23 +0,0 @@
{ config, pkgs, lib, ... }:
let
cfg = config.services.postfix;
in
{
services.postfix = {
enable = true;
hostname = "${config.networking.hostName}.pvv.ntnu.no";
domain = "pvv.ntnu.no";
relayHost = "smtp.pvv.ntnu.no";
relayPort = 465;
config = {
smtp_tls_wrappermode = "yes";
smtp_tls_security_level = "encrypt";
};
# Nothing should be delivered to this machine
destination = [ ];
};
}

View File

@ -1,18 +0,0 @@
{ config, pkgs, lib, ... }:
{
services.smartd = {
enable = lib.mkDefault true;
notifications = {
mail = {
enable = true;
sender = "root@pvv.ntnu.no";
recipient = "root@pvv.ntnu.no";
};
wall.enable = false;
};
};
environment.systemPackages = lib.optionals config.services.smartd.enable (with pkgs; [
smartmontools
]);
}

View File

@ -1,8 +0,0 @@
{ config, lib, ... }:
{
# Let's not thermal throttle
services.thermald.enable = lib.mkIf (lib.all (x: x) [
(config.nixpkgs.system == "x86_64-linux")
(!config.boot.isContainer or false)
]) true;
}

View File

@ -7,11 +7,11 @@
]
},
"locked": {
"lastModified": 1731746438,
"narHash": "sha256-f3SSp1axoOk0NAI7oFdRzbxG2XPBSIXC+/DaAXnvS1A=",
"lastModified": 1716431128,
"narHash": "sha256-t3T8HlX3udO6f4ilLcN+j5eC3m2gqsouzSGiriKK6vk=",
"owner": "nix-community",
"repo": "disko",
"rev": "cb64993826fa7a477490be6ccb38ba1fa1e18fa8",
"rev": "7ffc4354dfeb37c8c725ae1465f04a9b45ec8606",
"type": "github"
},
"original": {
@ -20,25 +20,64 @@
"type": "github"
}
},
"greg-ng": {
"fix-python": {
"inputs": {
"flake-utils": "flake-utils",
"nixpkgs": [
"grzegorz",
"nixpkgs"
],
"rust-overlay": "rust-overlay"
]
},
"locked": {
"lastModified": 1730249639,
"narHash": "sha256-G3URSlqCcb+GIvGyki+HHrDM5ZanX/dP9BtppD/SdfI=",
"ref": "refs/heads/main",
"rev": "80e0447bcb79adad4f459ada5610f3eae987b4e3",
"revCount": 34,
"type": "git",
"url": "https://git.pvv.ntnu.no/Projects/greg-ng.git"
"lastModified": 1713887124,
"narHash": "sha256-hGTSm0p9xXUYDgsAAr/ORZICo6T6u33vLfX3tILikaQ=",
"owner": "GuillaumeDesforges",
"repo": "fix-python",
"rev": "f7f4b33e22414071fc1f9cbf68072c413c3a7fdf",
"type": "github"
},
"original": {
"type": "git",
"url": "https://git.pvv.ntnu.no/Projects/greg-ng.git"
"owner": "GuillaumeDesforges",
"repo": "fix-python",
"type": "github"
}
},
"flake-utils": {
"inputs": {
"systems": "systems"
},
"locked": {
"lastModified": 1689068808,
"narHash": "sha256-6ixXo3wt24N/melDWjq70UuHQLxGV8jZvooRanIHXw0=",
"owner": "numtide",
"repo": "flake-utils",
"rev": "919d646de7be200f3bf08cb76ae1f09402b6f9b4",
"type": "github"
},
"original": {
"id": "flake-utils",
"type": "indirect"
}
},
"grzegorz": {
"inputs": {
"fix-python": "fix-python",
"nixpkgs": [
"nixpkgs-unstable"
]
},
"locked": {
"lastModified": 1716065905,
"narHash": "sha256-08uhxBzfakfhl/ooc+gMzDupWKYvTeyQZwuvB1SBS7A=",
"owner": "Programvareverkstedet",
"repo": "grzegorz",
"rev": "0481aef6553ae9aee86e4edb4ca0ed4f2eba2058",
"type": "github"
},
"original": {
"owner": "Programvareverkstedet",
"repo": "grzegorz",
"type": "github"
}
},
"grzegorz-clients": {
@ -48,17 +87,17 @@
]
},
"locked": {
"lastModified": 1726861934,
"narHash": "sha256-lOzPDwktd+pwszUTbpUdQg6iCzInS11fHLfkjmnvJrM=",
"ref": "refs/heads/master",
"rev": "546d921ec46735dbf876e36f4af8df1064d09432",
"revCount": 78,
"type": "git",
"url": "https://git.pvv.ntnu.no/Projects/grzegorz-clients.git"
"lastModified": 1716115695,
"narHash": "sha256-aI65l4x+U5v3i/nfn6N3eW5IZodmf4pyAByE7vTJh8I=",
"owner": "Programvareverkstedet",
"repo": "grzegorz-clients",
"rev": "b9444658fbb39cd1bf1c61ee5a1d5f0641c49abe",
"type": "github"
},
"original": {
"type": "git",
"url": "https://git.pvv.ntnu.no/Projects/grzegorz-clients.git"
"owner": "Programvareverkstedet",
"repo": "grzegorz-clients",
"type": "github"
}
},
"matrix-next": {
@ -68,35 +107,20 @@
]
},
"locked": {
"lastModified": 1727410897,
"narHash": "sha256-tWsyxvf421ieWUJYgjV7m1eTdr2ZkO3vId7vmtvfFpQ=",
"lastModified": 1717234745,
"narHash": "sha256-MFyKRdw4WQD6V3vRGbP6MYbtJhZp712zwzjW6YiOBYM=",
"owner": "dali99",
"repo": "nixos-matrix-modules",
"rev": "ff787d410cba17882cd7b6e2e22cc88d4064193c",
"rev": "d7dc42c9bbb155c5e4aa2f0985d0df75ce978456",
"type": "github"
},
"original": {
"owner": "dali99",
"ref": "v0.6.1",
"ref": "v0.6.0",
"repo": "nixos-matrix-modules",
"type": "github"
}
},
"minecraft-data": {
"locked": {
"lastModified": 1725277886,
"narHash": "sha256-Fw4VbbE3EfypQWSgPDFfvVH47BHeg3ptsO715NlUM8Q=",
"ref": "refs/heads/master",
"rev": "1b4087bd3322a2e2ba84271c8fcc013e6b641a58",
"revCount": 2,
"type": "git",
"url": "https://git.pvv.ntnu.no/Drift/minecraft-data.git"
},
"original": {
"type": "git",
"url": "https://git.pvv.ntnu.no/Drift/minecraft-data.git"
}
},
"nix-gitea-themes": {
"inputs": {
"nixpkgs": [
@ -119,50 +143,48 @@
},
"nixpkgs": {
"locked": {
"lastModified": 1731663789,
"narHash": "sha256-x07g4NcqGP6mQn6AISXJaks9sQYDjZmTMBlKIvajvyc=",
"lastModified": 1716586607,
"narHash": "sha256-PzpeC/xi0+YTGJS5rdbcOqVgIryuWHkimMVXoCIidgA=",
"owner": "NixOS",
"repo": "nixpkgs",
"rev": "035d434d48f4375ac5d3a620954cf5fda7dd7c36",
"rev": "03309929e115bba1339308814f8b6e63f250fedf",
"type": "github"
},
"original": {
"owner": "NixOS",
"id": "nixpkgs",
"ref": "nixos-24.05-small",
"repo": "nixpkgs",
"type": "github"
"type": "indirect"
}
},
"nixpkgs-stable": {
"locked": {
"lastModified": 1730602179,
"narHash": "sha256-efgLzQAWSzJuCLiCaQUCDu4NudNlHdg2NzGLX5GYaEY=",
"lastModified": 1716061101,
"narHash": "sha256-H0eCta7ahEgloGIwE/ihkyGstOGu+kQwAiHvwVoXaA0=",
"owner": "NixOS",
"repo": "nixpkgs",
"rev": "3c2f1c4ca372622cb2f9de8016c9a0b1cbd0f37c",
"rev": "e7cc61784ddf51c81487637b3031a6dd2d6673a2",
"type": "github"
},
"original": {
"owner": "NixOS",
"ref": "release-24.05",
"ref": "release-23.11",
"repo": "nixpkgs",
"type": "github"
}
},
"nixpkgs-unstable": {
"locked": {
"lastModified": 1731745710,
"narHash": "sha256-SVeiClbgqL071JpAspOu0gCkPSAL51kSIRwo4C/pghA=",
"lastModified": 1716660083,
"narHash": "sha256-QO7cdjtDhx72KEw6m0NOtuE5FS4asaRExZ65uFR/q8g=",
"owner": "NixOS",
"repo": "nixpkgs",
"rev": "dfaa4cb76c2d450d8f396bb6b9f43cede3ade129",
"rev": "6de51d98ec2ae46730f11845e221aab9d2470a8a",
"type": "github"
},
"original": {
"owner": "NixOS",
"id": "nixpkgs",
"ref": "nixos-unstable-small",
"repo": "nixpkgs",
"type": "github"
"type": "indirect"
}
},
"pvv-calendar-bot": {
@ -172,11 +194,11 @@
]
},
"locked": {
"lastModified": 1723850344,
"narHash": "sha256-aT37O9l9eclWEnqxASVNBL1dKwDHZUOqdbA4VO9DJvw=",
"lastModified": 1693136143,
"narHash": "sha256-amHprjftc3y/bg8yf4hITCLa+ez5HIi0yGfR7TU6UIc=",
"ref": "refs/heads/main",
"rev": "38b66677ab8c01aee10cd59e745af9ce3ea88092",
"revCount": 19,
"rev": "a32894b305f042d561500f5799226afd1faf5abb",
"revCount": 9,
"type": "git",
"url": "https://git.pvv.ntnu.no/Projects/calendar-bot.git"
},
@ -192,11 +214,11 @@
]
},
"locked": {
"lastModified": 1725212759,
"narHash": "sha256-yZBsefIarFUEhFRj+rCGMp9Zvag3MCafqV/JfGVRVwc=",
"lastModified": 1716150352,
"narHash": "sha256-c13lzYbLmbrcbEdPTYZYtlX2Qsz1W+2sLsIMGShPgwo=",
"ref": "refs/heads/master",
"rev": "e7b66b4bc6a89bab74bac45b87e9434f5165355f",
"revCount": 473,
"rev": "2cab4df4b119e08a1f90ea1c944652cd78b4d478",
"revCount": 459,
"type": "git",
"url": "https://git.pvv.ntnu.no/Projects/nettsiden.git"
},
@ -208,10 +230,9 @@
"root": {
"inputs": {
"disko": "disko",
"greg-ng": "greg-ng",
"grzegorz": "grzegorz",
"grzegorz-clients": "grzegorz-clients",
"matrix-next": "matrix-next",
"minecraft-data": "minecraft-data",
"nix-gitea-themes": "nix-gitea-themes",
"nixpkgs": "nixpkgs",
"nixpkgs-unstable": "nixpkgs-unstable",
@ -220,27 +241,6 @@
"sops-nix": "sops-nix"
}
},
"rust-overlay": {
"inputs": {
"nixpkgs": [
"greg-ng",
"nixpkgs"
]
},
"locked": {
"lastModified": 1729391507,
"narHash": "sha256-as0I9xieJUHf7kiK2a9znDsVZQTFWhM1pLivII43Gi0=",
"owner": "oxalica",
"repo": "rust-overlay",
"rev": "784981a9feeba406de38c1c9a3decf966d853cca",
"type": "github"
},
"original": {
"owner": "oxalica",
"repo": "rust-overlay",
"type": "github"
}
},
"sops-nix": {
"inputs": {
"nixpkgs": [
@ -249,11 +249,11 @@
"nixpkgs-stable": "nixpkgs-stable"
},
"locked": {
"lastModified": 1731748189,
"narHash": "sha256-Zd/Uukvpcu26M6YGhpbsgqm6LUSLz+Q8mDZ5LOEGdiE=",
"lastModified": 1716400300,
"narHash": "sha256-0lMkIk9h3AzOHs1dCL9RXvvN4PM8VBKb+cyGsqOKa4c=",
"owner": "Mic92",
"repo": "sops-nix",
"rev": "d2bd7f433b28db6bc7ae03d5eca43564da0af054",
"rev": "b549832718b8946e875c016a4785d204fcfc2e53",
"type": "github"
},
"original": {
@ -261,6 +261,21 @@
"repo": "sops-nix",
"type": "github"
}
},
"systems": {
"locked": {
"lastModified": 1681028828,
"narHash": "sha256-Vy1rq5AaRuLzOxct8nz4T6wlgyUR7zLU309k9mBC768=",
"owner": "nix-systems",
"repo": "default",
"rev": "da67096a3b9bf56a91d16901293e51ba5b49a27e",
"type": "github"
},
"original": {
"owner": "nix-systems",
"repo": "default",
"type": "github"
}
}
},
"root": "root",

View File

@ -2,8 +2,8 @@
description = "PVV System flake";
inputs = {
nixpkgs.url = "github:NixOS/nixpkgs/nixos-24.05-small"; # remember to also update the url in base/services/auto-upgrade.nix
nixpkgs-unstable.url = "github:NixOS/nixpkgs/nixos-unstable-small";
nixpkgs.url = "nixpkgs/nixos-24.05-small";
nixpkgs-unstable.url = "nixpkgs/nixos-unstable-small";
sops-nix.url = "github:Mic92/sops-nix";
sops-nix.inputs.nixpkgs.follows = "nixpkgs";
@ -17,21 +17,19 @@
pvv-calendar-bot.url = "git+https://git.pvv.ntnu.no/Projects/calendar-bot.git";
pvv-calendar-bot.inputs.nixpkgs.follows = "nixpkgs";
matrix-next.url = "github:dali99/nixos-matrix-modules/v0.6.1";
matrix-next.url = "github:dali99/nixos-matrix-modules/v0.6.0";
matrix-next.inputs.nixpkgs.follows = "nixpkgs";
nix-gitea-themes.url = "git+https://git.pvv.ntnu.no/oysteikt/nix-gitea-themes.git";
nix-gitea-themes.inputs.nixpkgs.follows = "nixpkgs";
greg-ng.url = "git+https://git.pvv.ntnu.no/Projects/greg-ng.git";
greg-ng.inputs.nixpkgs.follows = "nixpkgs";
grzegorz-clients.url = "git+https://git.pvv.ntnu.no/Projects/grzegorz-clients.git";
grzegorz.url = "github:Programvareverkstedet/grzegorz";
grzegorz.inputs.nixpkgs.follows = "nixpkgs-unstable";
grzegorz-clients.url = "github:Programvareverkstedet/grzegorz-clients";
grzegorz-clients.inputs.nixpkgs.follows = "nixpkgs";
minecraft-data.url = "git+https://git.pvv.ntnu.no/Drift/minecraft-data.git";
};
outputs = { self, nixpkgs, nixpkgs-unstable, sops-nix, disko, ... }@inputs:
outputs = { self, nixpkgs, nixpkgs-unstable, pvv-nettsiden, sops-nix, disko, ... }@inputs:
let
nixlib = nixpkgs.lib;
systems = [
@ -39,8 +37,8 @@
"aarch64-linux"
"aarch64-darwin"
];
forAllSystems = f: nixlib.genAttrs systems f;
allMachines = builtins.attrNames self.nixosConfigurations;
forAllSystems = f: nixlib.genAttrs systems (system: f system);
allMachines = nixlib.mapAttrsToList (name: _: name) self.nixosConfigurations;
importantMachines = [
"bekkalokk"
"bicep"
@ -49,17 +47,14 @@
"ildkule"
];
in {
inherit inputs;
nixosConfigurations = let
unstablePkgs = nixpkgs-unstable.legacyPackages.x86_64-linux;
nixosConfig = nixpkgs: name: config: nixpkgs.lib.nixosSystem (nixpkgs.lib.recursiveUpdate
rec {
system = "x86_64-linux";
specialArgs = {
inherit unstablePkgs inputs;
inherit nixpkgs-unstable inputs;
values = import ./values.nix;
fp = path: ./${path};
};
modules = [
@ -95,7 +90,6 @@
heimdal = unstablePkgs.heimdal;
mediawiki-extensions = final.callPackage ./packages/mediawiki-extensions { };
simplesamlphp = final.callPackage ./packages/simplesamlphp { };
bluemap = final.callPackage ./packages/bluemap.nix { };
})
inputs.nix-gitea-themes.overlays.default
inputs.pvv-nettsiden.overlays.default
@ -117,27 +111,17 @@
brzeczyszczykiewicz = stableNixosConfig "brzeczyszczykiewicz" {
modules = [
inputs.grzegorz.nixosModules.grzegorz-kiosk
inputs.grzegorz-clients.nixosModules.grzegorz-webui
inputs.greg-ng.nixosModules.default
];
overlays = [
inputs.greg-ng.overlays.default
];
};
georg = stableNixosConfig "georg" {
modules = [
inputs.grzegorz.nixosModules.grzegorz-kiosk
inputs.grzegorz-clients.nixosModules.grzegorz-webui
inputs.greg-ng.nixosModules.default
];
overlays = [
inputs.greg-ng.overlays.default
];
};
};
nixosModules = {
snakeoil-certs = ./modules/snakeoil-certs.nix;
snappymail = ./modules/snappymail.nix;
buskerud = stableNixosConfig "buskerud" { };
};
devShells = forAllSystems (system: {

View File

@ -1,25 +1,21 @@
{ fp, pkgs, values, ... }:
{ pkgs, values, ... }:
{
imports = [
./hardware-configuration.nix
(fp /base)
(fp /misc/metrics-exporters.nix)
../../base.nix
../../misc/metrics-exporters.nix
./services/bluemap/default.nix
./services/gitea/default.nix
./services/idp-simplesamlphp
./services/kerberos
./services/mediawiki
./services/nginx.nix
./services/phpfpm.nix
./services/vaultwarden.nix
./services/webmail
./services/website
./services/well-known
./services/nginx.nix
./services/gitea/default.nix
./services/kerberos
./services/webmail
./services/mediawiki
./services/idp-simplesamlphp
];
sops.defaultSopsFile = fp /secrets/bekkalokk/bekkalokk.yaml;
sops.defaultSopsFile = ../../secrets/bekkalokk/bekkalokk.yaml;
sops.age.sshKeyPaths = [ "/etc/ssh/ssh_host_ed25519_key" ];
sops.age.keyFile = "/var/lib/sops-nix/key.txt";
sops.age.generateKey = true;
@ -34,8 +30,6 @@
address = with values.hosts.bekkalokk; [ (ipv4 + "/25") (ipv6 + "/64") ];
};
services.btrfs.autoScrub.enable = true;
# Do not change, even during upgrades.
# See https://search.nixos.org/options?show=system.stateVersion
system.stateVersion = "22.11";

View File

@ -1,83 +0,0 @@
{ config, lib, pkgs, inputs, ... }:
let
vanillaSurvival = "/var/lib/bluemap/vanilla_survival_world";
in {
imports = [
./module.nix # From danio, pending upstreaming
];
disabledModules = [ "services/web-servers/bluemap.nix" ];
sops.secrets."bluemap/ssh-key" = { };
sops.secrets."bluemap/ssh-known-hosts" = { };
services.bluemap = {
enable = true;
eula = true;
onCalendar = "*-*-* 05:45:00"; # a little over an hour after auto-upgrade
host = "minecraft.pvv.ntnu.no";
maps = {
"verden" = {
settings = {
world = vanillaSurvival;
sorting = 0;
ambient-light = 0.1;
cave-detection-ocean-floor = -5;
marker-sets = inputs.minecraft-data.map-markers.vanillaSurvival.verden;
};
};
"underverden" = {
settings = {
world = "${vanillaSurvival}/DIM-1";
sorting = 100;
sky-color = "#290000";
void-color = "#150000";
ambient-light = 0.6;
world-sky-light = 0;
remove-caves-below-y = -10000;
cave-detection-ocean-floor = -5;
cave-detection-uses-block-light = true;
max-y = 90;
marker-sets = inputs.minecraft-data.map-markers.vanillaSurvival.underverden;
};
};
"enden" = {
settings = {
world = "${vanillaSurvival}/DIM1";
sorting = 200;
sky-color = "#080010";
void-color = "#080010";
ambient-light = 0.6;
world-sky-light = 0;
remove-caves-below-y = -10000;
cave-detection-ocean-floor = -5;
};
};
};
};
services.nginx.virtualHosts."minecraft.pvv.ntnu.no" = {
enableACME = true;
forceSSL = true;
};
# TODO: render somewhere else lmao
systemd.services."render-bluemap-maps" = {
preStart = ''
mkdir -p /var/lib/bluemap/world
${pkgs.rsync}/bin/rsync \
-e "${pkgs.openssh}/bin/ssh -o UserKnownHostsFile=$CREDENTIALS_DIRECTORY/ssh-known-hosts -i $CREDENTIALS_DIRECTORY/sshkey" \
-avz --no-owner --no-group \
root@innovation.pvv.ntnu.no:/ \
${vanillaSurvival}
'';
serviceConfig = {
LoadCredential = [
"sshkey:${config.sops.secrets."bluemap/ssh-key".path}"
"ssh-known-hosts:${config.sops.secrets."bluemap/ssh-known-hosts".path}"
];
};
};
}

View File

@ -1,343 +0,0 @@
{ config, lib, pkgs, ... }:
let
cfg = config.services.bluemap;
format = pkgs.formats.hocon { };
coreConfig = format.generate "core.conf" cfg.coreSettings;
webappConfig = format.generate "webapp.conf" cfg.webappSettings;
webserverConfig = format.generate "webserver.conf" cfg.webserverSettings;
storageFolder = pkgs.linkFarm "storage"
(lib.attrsets.mapAttrs' (name: value:
lib.nameValuePair "${name}.conf"
(format.generate "${name}.conf" value))
cfg.storage);
mapsFolder = pkgs.linkFarm "maps"
(lib.attrsets.mapAttrs' (name: value:
lib.nameValuePair "${name}.conf"
(format.generate "${name}.conf" value.settings))
cfg.maps);
webappConfigFolder = pkgs.linkFarm "bluemap-config" {
"maps" = mapsFolder;
"storages" = storageFolder;
"core.conf" = coreConfig;
"webapp.conf" = webappConfig;
"webserver.conf" = webserverConfig;
"packs" = cfg.resourcepacks;
"addons" = cfg.resourcepacks; # TODO
};
renderConfigFolder = name: value: pkgs.linkFarm "bluemap-${name}-config" {
"maps" = pkgs.linkFarm "maps" {
"${name}.conf" = (format.generate "${name}.conf" value.settings);
};
"storages" = storageFolder;
"core.conf" = coreConfig;
"webapp.conf" = format.generate "webapp.conf" (cfg.webappSettings // { "update-settings-file" = false; });
"webserver.conf" = webserverConfig;
"packs" = value.resourcepacks;
"addons" = cfg.resourcepacks; # TODO
};
inherit (lib) mkOption;
in {
options.services.bluemap = {
enable = lib.mkEnableOption "bluemap";
eula = mkOption {
type = lib.types.bool;
description = ''
By changing this option to true you confirm that you own a copy of minecraft Java Edition,
and that you agree to minecrafts EULA.
'';
default = false;
};
defaultWorld = mkOption {
type = lib.types.path;
description = ''
The world used by the default map ruleset.
If you configure your own maps you do not need to set this.
'';
example = lib.literalExpression "\${config.services.minecraft.dataDir}/world";
};
enableRender = mkOption {
type = lib.types.bool;
description = "Enable rendering";
default = true;
};
webRoot = mkOption {
type = lib.types.path;
default = "/var/lib/bluemap/web";
description = "The directory for saving and serving the webapp and the maps";
};
enableNginx = mkOption {
type = lib.types.bool;
default = true;
description = "Enable configuring a virtualHost for serving the bluemap webapp";
};
host = mkOption {
type = lib.types.str;
default = "bluemap.${config.networking.domain}";
defaultText = lib.literalExpression "bluemap.\${config.networking.domain}";
description = "Domain to configure nginx for";
};
onCalendar = mkOption {
type = lib.types.str;
description = ''
How often to trigger rendering the map,
in the format of a systemd timer onCalendar configuration.
See {manpage}`systemd.timer(5)`.
'';
default = "*-*-* 03:10:00";
};
coreSettings = mkOption {
type = lib.types.submodule {
freeformType = format.type;
options = {
data = mkOption {
type = lib.types.path;
description = "Folder for where bluemap stores its data";
default = "/var/lib/bluemap";
};
metrics = lib.mkEnableOption "Sending usage metrics containing the version of bluemap in use";
};
};
description = "Settings for the core.conf file, [see upstream docs](https://github.com/BlueMap-Minecraft/BlueMap/blob/master/BlueMapCommon/src/main/resources/de/bluecolored/bluemap/config/core.conf).";
};
webappSettings = mkOption {
type = lib.types.submodule {
freeformType = format.type;
};
default = {
enabled = true;
webroot = cfg.webRoot;
};
defaultText = lib.literalExpression ''
{
enabled = true;
webroot = config.services.bluemap.webRoot;
}
'';
description = "Settings for the webapp.conf file, see [upstream docs](https://github.com/BlueMap-Minecraft/BlueMap/blob/master/BlueMapCommon/src/main/resources/de/bluecolored/bluemap/config/webapp.conf).";
};
webserverSettings = mkOption {
type = lib.types.submodule {
freeformType = format.type;
options = {
enabled = mkOption {
type = lib.types.bool;
description = ''
Enable bluemap's built-in webserver.
Disabled by default in nixos for use of nginx directly.
'';
default = false;
};
};
};
default = { };
description = ''
Settings for the webserver.conf file, usually not required.
[See upstream docs](https://github.com/BlueMap-Minecraft/BlueMap/blob/master/BlueMapCommon/src/main/resources/de/bluecolored/bluemap/config/webserver.conf).
'';
};
maps = mkOption {
type = lib.types.attrsOf (lib.types.submodule {
options = {
resourcepacks = mkOption {
type = lib.types.path;
default = cfg.resourcepacks;
defaultText = lib.literalExpression "config.services.bluemap.resourcepacks";
description = "A set of resourcepacks/mods to extract models from loaded in alphabetical order";
};
settings = mkOption {
type = (lib.types.submodule {
freeformType = format.type;
options = {
world = mkOption {
type = lib.types.path;
description = "Path to world folder containing the dimension to render";
};
};
});
description = ''
Settings for files in `maps/`.
See the default for an example with good options for the different world types.
For valid values [consult upstream docs](https://github.com/BlueMap-Minecraft/BlueMap/blob/master/BlueMapCommon/src/main/resources/de/bluecolored/bluemap/config/maps/map.conf).
'';
};
};
});
default = {
"overworld".settings = {
world = "${cfg.defaultWorld}";
ambient-light = 0.1;
cave-detection-ocean-floor = -5;
};
"nether".settings = {
world = "${cfg.defaultWorld}/DIM-1";
sorting = 100;
sky-color = "#290000";
void-color = "#150000";
ambient-light = 0.6;
world-sky-light = 0;
remove-caves-below-y = -10000;
cave-detection-ocean-floor = -5;
cave-detection-uses-block-light = true;
max-y = 90;
};
"end".settings = {
world = "${cfg.defaultWorld}/DIM1";
sorting = 200;
sky-color = "#080010";
void-color = "#080010";
ambient-light = 0.6;
world-sky-light = 0;
remove-caves-below-y = -10000;
cave-detection-ocean-floor = -5;
};
};
defaultText = lib.literalExpression ''
{
"overworld".settings = {
world = "''${cfg.defaultWorld}";
ambient-light = 0.1;
cave-detection-ocean-floor = -5;
};
"nether".settings = {
world = "''${cfg.defaultWorld}/DIM-1";
sorting = 100;
sky-color = "#290000";
void-color = "#150000";
ambient-light = 0.6;
world-sky-light = 0;
remove-caves-below-y = -10000;
cave-detection-ocean-floor = -5;
cave-detection-uses-block-light = true;
max-y = 90;
};
"end".settings = {
world = "''${cfg.defaultWorld}/DIM1";
sorting = 200;
sky-color = "#080010";
void-color = "#080010";
ambient-light = 0.6;
world-sky-light = 0;
remove-caves-below-y = -10000;
cave-detection-ocean-floor = -5;
};
};
'';
description = ''
map-specific configuration.
These correspond to views in the webapp and are usually
different dimension of a world or different render settings of the same dimension.
If you set anything in this option you must configure all dimensions yourself!
'';
};
storage = mkOption {
type = lib.types.attrsOf (lib.types.submodule {
freeformType = format.type;
options = {
storage-type = mkOption {
type = lib.types.enum [ "FILE" "SQL" ];
description = "Type of storage config";
default = "FILE";
};
};
});
description = ''
Where the rendered map will be stored.
Unless you are doing something advanced you should probably leave this alone and configure webRoot instead.
[See upstream docs](https://github.com/BlueMap-Minecraft/BlueMap/tree/master/BlueMapCommon/src/main/resources/de/bluecolored/bluemap/config/storages)
'';
default = {
"file" = {
root = "${cfg.webRoot}/maps";
};
};
defaultText = lib.literalExpression ''
{
"file" = {
root = "''${config.services.bluemap.webRoot}/maps";
};
}
'';
};
resourcepacks = mkOption {
type = lib.types.path;
default = pkgs.linkFarm "resourcepacks" { };
description = ''
A set of resourcepacks/mods to extract models from loaded in alphabetical order.
Can be overriden on a per-map basis with `services.bluemap.maps.<name>.resourcepacks`.
'';
};
};
config = lib.mkIf cfg.enable {
assertions =
[ { assertion = config.services.bluemap.eula;
message = ''
You have enabled bluemap but have not accepted minecraft's EULA.
You can achieve this through setting `services.bluemap.eula = true`
'';
}
];
services.bluemap.coreSettings.accept-download = cfg.eula;
systemd.services."render-bluemap-maps" = lib.mkIf cfg.enableRender {
serviceConfig = {
Type = "oneshot";
Group = "nginx";
UMask = "026";
};
script = lib.strings.concatStringsSep "\n" ((lib.attrsets.mapAttrsToList
(name: value: "${lib.getExe pkgs.bluemap} -c ${renderConfigFolder name value} -r")
cfg.maps) ++ [ "${lib.getExe pkgs.bluemap} -c ${webappConfigFolder} -gs" ]);
};
systemd.timers."render-bluemap-maps" = lib.mkIf cfg.enableRender {
wantedBy = [ "timers.target" ];
timerConfig = {
OnCalendar = cfg.onCalendar;
Persistent = true;
Unit = "render-bluemap-maps.service";
};
};
services.nginx.virtualHosts = lib.mkIf cfg.enableNginx {
"${cfg.host}" = {
root = config.services.bluemap.webRoot;
locations = {
"~* ^/maps/[^/]*/tiles/".extraConfig = ''
error_page 404 = @empty;
'';
"@empty".return = "204";
};
};
};
};
meta = {
maintainers = with lib.maintainers; [ dandellion h7x4 ];
};
}

View File

@ -15,9 +15,9 @@ let
enable = true;
name = "git-runner-${name}"; url = "https://git.pvv.ntnu.no";
labels = [
"debian-latest:docker://node:18-bullseye"
"ubuntu-latest:docker://node:18-bullseye"
];
"debian-latest:docker://node:18-bullseye"
"ubuntu-latest:docker://node:18-bullseye"
];
tokenFile = config.sops.secrets."gitea/runners/${name}".path;
};
};

View File

@ -1,4 +1,4 @@
{ config, values, fp, pkgs, lib, ... }:
{ config, values, pkgs, ... }:
let
cfg = config.services.gitea;
domain = "git.pvv.ntnu.no";
@ -6,9 +6,7 @@ let
in {
imports = [
./ci.nix
./gpg.nix
./import-users
./web-secret-provider
./import-users.nix
];
sops.secrets = {
@ -24,6 +22,7 @@ in {
services.gitea = {
enable = true;
stateDir = "/data/gitea";
appName = "PVV Git";
database = {
@ -36,7 +35,6 @@ in {
mailerPasswordFile = config.sops.secrets."gitea/email-password".path;
# https://docs.gitea.com/administration/config-cheat-sheet
settings = {
server = {
DOMAIN = domain;
@ -44,8 +42,6 @@ in {
PROTOCOL = "http+unix";
SSH_PORT = sshPort;
START_SSH_SERVER = true;
START_LFS_SERVER = true;
LANDING_PAGE = "explore";
};
mailer = {
ENABLED = true;
@ -54,81 +50,16 @@ in {
SMTP_ADDR = "smtp.pvv.ntnu.no";
SMTP_PORT = 587;
USER = "gitea@pvv.ntnu.no";
SUBJECT_PREFIX = "[pvv-git]";
};
metrics = {
ENABLED = true;
ENABLED_ISSUE_BY_LABEL = true;
ENABLED_ISSUE_BY_REPOSITORY = true;
};
indexer.REPO_INDEXER_ENABLED = true;
service = {
DISABLE_REGISTRATION = true;
ENABLE_NOTIFY_MAIL = true;
AUTO_WATCH_NEW_REPOS = false;
};
admin.DEFAULT_EMAIL_NOTIFICATIONS = "onmention";
service.DISABLE_REGISTRATION = true;
session.COOKIE_SECURE = true;
database.LOG_SQL = false;
repository = {
PREFERRED_LICENSES = lib.concatStringsSep "," [
"AGPL-3.0-only"
"AGPL-3.0-or-later"
"Apache-2.0"
"BSD-3-Clause"
"CC-BY-4.0"
"CC-BY-NC-4.0"
"CC-BY-NC-ND-4.0"
"CC-BY-NC-SA-4.0"
"CC-BY-ND-4.0"
"CC-BY-SA-4.0"
"CC0-1.0"
"GPL-2.0-only"
"GPL-3.0-only"
"GPL-3.0-or-later"
"LGPL-3.0-linking-exception"
"LGPL-3.0-only"
"LGPL-3.0-or-later"
"MIT"
"MPL-2.0"
"Unlicense"
];
DEFAULT_REPO_UNITS = lib.concatStringsSep "," [
"repo.code"
"repo.issues"
"repo.pulls"
"repo.releases"
];
};
picture = {
DISABLE_GRAVATAR = true;
ENABLE_FEDERATED_AVATAR = false;
};
actions.ENABLED = true;
ui = {
REACTIONS = lib.concatStringsSep "," [
"+1"
"-1"
"laugh"
"confused"
"heart"
"hooray"
"rocket"
"eyes"
"100"
"anger"
"astonished"
"no_good"
"ok_hand"
"pensive"
"pizza"
"point_up"
"sob"
"skull"
"upside_down_face"
"shrug"
];
};
"ui.meta".DESCRIPTION = "Bokstavelig talt programvareverkstedet";
};
};
@ -139,20 +70,11 @@ in {
forceSSL = true;
enableACME = true;
kTLS = true;
locations = {
"/" = {
proxyPass = "http://unix:${cfg.settings.server.HTTP_ADDR}";
extraConfig = ''
client_max_body_size 512M;
'';
};
"/metrics" = {
proxyPass = "http://unix:${cfg.settings.server.HTTP_ADDR}";
extraConfig = ''
allow ${values.hosts.ildkule.ipv4}/32;
deny all;
'';
};
locations."/" = {
proxyPass = "http://unix:${cfg.settings.server.HTTP_ADDR}";
extraConfig = ''
client_max_body_size 512M;
'';
};
};
@ -174,18 +96,12 @@ in {
};
script = let
logo-svg = fp /assets/logo_blue_regular.svg;
logo-png = fp /assets/logo_blue_regular.png;
extraLinks = pkgs.writeText "gitea-extra-links.tmpl" ''
<a class="item" href="https://www.pvv.ntnu.no/">PVV</a>
<a class="item" href="https://wiki.pvv.ntnu.no/">Wiki</a>
<a class="item" href="https://git.pvv.ntnu.no/Drift/-/projects/4">Tokyo Drift Issues</a>
'';
logo-svg = ../../../../assets/logo_blue_regular.svg;
logo-png = ../../../../assets/logo_blue_regular.png;
in ''
install -Dm444 ${logo-svg} ${cfg.customDir}/public/assets/img/logo.svg
install -Dm444 ${logo-png} ${cfg.customDir}/public/assets/img/logo.png
install -Dm444 ${./loading.apng} ${cfg.customDir}/public/assets/img/loading.png
install -Dm444 ${extraLinks} ${cfg.customDir}/templates/custom/extra_links.tmpl
install -Dm444 ${logo-svg} ${cfg.customDir}/public/img/logo.svg
install -Dm444 ${logo-png} ${cfg.customDir}/public/img/logo.png
install -Dm444 ${./loading.apng} ${cfg.customDir}/public/img/loading.png
'';
};
}

View File

@ -0,0 +1,94 @@
import requests
import secrets
import os
EMAIL_DOMAIN = os.getenv('EMAIL_DOMAIN')
if EMAIL_DOMAIN is None:
EMAIL_DOMAIN = 'pvv.ntnu.no'
API_TOKEN = os.getenv('API_TOKEN')
if API_TOKEN is None:
raise Exception('API_TOKEN not set')
GITEA_API_URL = os.getenv('GITEA_API_URL')
if GITEA_API_URL is None:
GITEA_API_URL = 'https://git.pvv.ntnu.no/api/v1'
BANNED_SHELLS = [
"/usr/bin/nologin",
"/usr/sbin/nologin",
"/sbin/nologin",
"/bin/false",
"/bin/msgsh",
]
existing_users = {}
# This function should only ever be called when adding users
# from the passwd file
def add_user(username, name):
user = {
"full_name": name,
"username": username,
"login_name": username,
"source_id": 1, # 1 = SMTP
}
if username not in existing_users:
user["password"] = secrets.token_urlsafe(32)
user["must_change_password"] = False
user["visibility"] = "private"
user["email"] = username + '@' + EMAIL_DOMAIN
r = requests.post(GITEA_API_URL + '/admin/users', json=user,
headers={'Authorization': 'token ' + API_TOKEN})
if r.status_code != 201:
print('ERR: Failed to create user ' + username + ': ' + r.text)
return
print('Created user ' + username)
existing_users[username] = user
else:
user["visibility"] = existing_users[username]["visibility"]
r = requests.patch(GITEA_API_URL + f'/admin/users/{username}',
json=user,
headers={'Authorization': 'token ' + API_TOKEN})
if r.status_code != 200:
print('ERR: Failed to update user ' + username + ': ' + r.text)
return
print('Updated user ' + username)
def main():
# Fetch existing users
r = requests.get(GITEA_API_URL + '/admin/users',
headers={'Authorization': 'token ' + API_TOKEN})
if r.status_code != 200:
raise Exception('Failed to get users: ' + r.text)
for user in r.json():
existing_users[user['login']] = user
# Read the file, add each user
with open("/tmp/passwd-import", 'r') as f:
for line in f.readlines():
uid = int(line.split(':')[2])
if uid < 1000:
continue
shell = line.split(':')[-1]
if shell in BANNED_SHELLS:
continue
username = line.split(':')[0]
name = line.split(':')[4].split(',')[0]
add_user(username, name)
if __name__ == '__main__':
main()

View File

@ -1,38 +0,0 @@
{ config, pkgs, lib, ... }:
let
cfg = config.services.gitea;
GNUPGHOME = "${config.users.users.gitea.home}/gnupg";
in
{
sops.secrets."gitea/gpg-signing-key" = {
owner = cfg.user;
inherit (cfg) group;
};
systemd.services.gitea.environment = { inherit GNUPGHOME; };
systemd.tmpfiles.settings."20-gitea-gnugpg".${GNUPGHOME}.d = {
inherit (cfg) user group;
mode = "700";
};
systemd.services.gitea-ensure-gnupg-homedir = {
description = "Import gpg key for gitea";
environment = { inherit GNUPGHOME; };
serviceConfig = {
Type = "oneshot";
User = cfg.user;
PrivateNetwork = true;
};
script = ''
${lib.getExe pkgs.gnupg} --import ${config.sops.secrets."gitea/gpg-signing-key".path}
'';
};
services.gitea.settings."repository.signing" = {
SIGNING_KEY = "0549C43374D2253C";
SIGNING_NAME = "PVV Git";
SIGNING_EMAIL = "gitea@git.pvv.ntnu.no";
INITIAL_COMMIT = "always";
};
}

View File

@ -14,9 +14,6 @@ in
preStart=''${pkgs.rsync}/bin/rsync -e "${pkgs.openssh}/bin/ssh -o UserKnownHostsFile=$CREDENTIALS_DIRECTORY/ssh-known-hosts -i $CREDENTIALS_DIRECTORY/sshkey" -a pvv@smtp.pvv.ntnu.no:/etc/passwd /tmp/passwd-import'';
serviceConfig = {
ExecStart = pkgs.writers.writePython3 "gitea-import-users" {
flakeIgnore = [
"E501" # Line over 80 chars lol
];
libraries = with pkgs.python3Packages; [ requests ];
} (builtins.readFile ./gitea-import-users.py);
LoadCredential=[

View File

@ -1,198 +0,0 @@
import requests
import secrets
import os
EMAIL_DOMAIN = os.getenv('EMAIL_DOMAIN')
if EMAIL_DOMAIN is None:
EMAIL_DOMAIN = 'pvv.ntnu.no'
API_TOKEN = os.getenv('API_TOKEN')
if API_TOKEN is None:
raise Exception('API_TOKEN not set')
GITEA_API_URL = os.getenv('GITEA_API_URL')
if GITEA_API_URL is None:
GITEA_API_URL = 'https://git.pvv.ntnu.no/api/v1'
def gitea_list_all_users() -> dict[str, dict[str, any]] | None:
r = requests.get(
GITEA_API_URL + '/admin/users',
headers={'Authorization': 'token ' + API_TOKEN}
)
if r.status_code != 200:
print('Failed to get users:', r.text)
return None
return {user['login']: user for user in r.json()}
def gitea_create_user(username: str, userdata: dict[str, any]) -> bool:
r = requests.post(
GITEA_API_URL + '/admin/users',
json=userdata,
headers={'Authorization': 'token ' + API_TOKEN},
)
if r.status_code != 201:
print(f'ERR: Failed to create user {username}:', r.text)
return False
return True
def gitea_edit_user(username: str, userdata: dict[str, any]) -> bool:
r = requests.patch(
GITEA_API_URL + f'/admin/users/{username}',
json=userdata,
headers={'Authorization': 'token ' + API_TOKEN},
)
if r.status_code != 200:
print(f'ERR: Failed to update user {username}:', r.text)
return False
return True
def gitea_list_teams_for_organization(org: str) -> dict[str, any] | None:
r = requests.get(
GITEA_API_URL + f'/orgs/{org}/teams',
headers={'Authorization': 'token ' + API_TOKEN},
)
if r.status_code != 200:
print(f"ERR: Failed to list teams for {org}:", r.text)
return None
return {team['name']: team for team in r.json()}
def gitea_add_user_to_organization_team(username: str, team_id: int) -> bool:
r = requests.put(
GITEA_API_URL + f'/teams/{team_id}/members/{username}',
headers={'Authorization': 'token ' + API_TOKEN},
)
if r.status_code != 204:
print(f'ERR: Failed to add user {username} to org team {team_id}:', r.text)
return False
return True
# If a passwd user has one of the following shells,
# it is most likely not a PVV user, but rather a system user.
# Users with these shells should thus be ignored.
BANNED_SHELLS = [
"/usr/bin/nologin",
"/usr/sbin/nologin",
"/sbin/nologin",
"/bin/false",
"/bin/msgsh",
]
# Reads out a passwd-file line for line, and filters out
# real PVV users (as opposed to system users meant for daemons and such)
def passwd_file_parser(passwd_path):
with open(passwd_path, 'r') as f:
for line in f.readlines():
uid = int(line.split(':')[2])
if uid < 1000:
continue
shell = line.split(':')[-1]
if shell in BANNED_SHELLS:
continue
username = line.split(':')[0]
name = line.split(':')[4].split(',')[0]
yield (username, name)
# This function either creates a new user in gitea
# and fills it out with some default information if
# it does not exist, or ensures that the default information
# is correct if the user already exists. All user information
# (including non-default fields) is pulled from gitea and added
# to the `existing_users` dict
def add_or_patch_gitea_user(
username: str,
name: str,
existing_users: dict[str, dict[str, any]],
) -> None:
user = {
"full_name": name,
"username": username,
"login_name": username,
"source_id": 1, # 1 = SMTP
}
if username not in existing_users:
user["password"] = secrets.token_urlsafe(32)
user["must_change_password"] = False
user["visibility"] = "private"
user["email"] = username + '@' + EMAIL_DOMAIN
if not gitea_create_user(username, user):
return
print('Created user', username)
existing_users[username] = user
else:
user["visibility"] = existing_users[username]["visibility"]
if not gitea_edit_user(username, user):
return
print('Updated user', username)
# This function adds a user to a gitea team (part of organization)
# if the user is not already part of said team.
def ensure_gitea_user_is_part_of_team(
username: str,
org: str,
team_name: str,
) -> None:
teams = gitea_list_teams_for_organization(org)
if teams is None:
return
if team_name not in teams:
print(f'ERR: could not find team "{team_name}" in organization "{org}"')
gitea_add_user_to_organization_team(username, teams[team_name]['id'])
print(f'User {username} is now part of {org}/{team_name}')
# List of teams that all users should be part of by default
COMMON_USER_TEAMS = [
("Projects", "Members"),
("Kurs", "Members"),
]
def main():
existing_users = gitea_list_all_users()
if existing_users is None:
exit(1)
for username, name in passwd_file_parser("/tmp/passwd-import"):
print(f"Processing {username}")
add_or_patch_gitea_user(username, name, existing_users)
for org, team_name in COMMON_USER_TEAMS:
ensure_gitea_user_is_part_of_team(username, org, team_name)
print()
if __name__ == '__main__':
main()

View File

@ -1,114 +0,0 @@
{ config, pkgs, lib, ... }:
let
organizations = [
"Drift"
"Projects"
"Kurs"
];
giteaCfg = config.services.gitea;
giteaWebSecretProviderScript = pkgs.writers.writePython3 "gitea-web-secret-provider" {
libraries = with pkgs.python3Packages; [ requests ];
flakeIgnore = [
"E501" # Line over 80 chars lol
"E201" # "whitespace after {"
"E202" # "whitespace after }"
"E251" # unexpected spaces around keyword / parameter equals
"W391" # Newline at end of file
];
makeWrapperArgs = [
"--prefix PATH : ${(lib.makeBinPath [ pkgs.openssh ])}"
];
} (builtins.readFile ./gitea-web-secret-provider.py);
in
{
users.groups."gitea-web" = { };
users.users."gitea-web" = {
group = "gitea-web";
isSystemUser = true;
};
sops.secrets."gitea/web-secret-provider/token" = {
owner = "gitea-web";
group = "gitea-web";
restartUnits = [
"gitea-web-secret-provider@"
] ++ (map (org: "gitea-web-secret-provider@${org}") organizations);
};
systemd.slices.system-giteaweb = {
description = "Gitea web directories";
};
# https://www.freedesktop.org/software/systemd/man/latest/systemd.unit.html#Specifiers
# %i - instance name (after the @)
# %d - secrets directory
systemd.services."gitea-web-secret-provider@" = {
description = "Ensure all repos in %i has an SSH key to push web content";
requires = [ "gitea.service" "network.target" ];
serviceConfig = {
Slice = "system-giteaweb.slice";
Type = "oneshot";
ExecStart = let
args = lib.cli.toGNUCommandLineShell { } {
org = "%i";
token-path = "%d/token";
api-url = "${giteaCfg.settings.server.ROOT_URL}api/v1";
key-dir = "/var/lib/gitea-web/keys/%i";
authorized-keys-path = "/var/lib/gitea-web/authorized_keys.d/%i";
rrsync-script = pkgs.writeShellScript "rrsync-chown" ''
${lib.getExe pkgs.rrsync} -wo "$1"
${pkgs.coreutils}/bin/chown -R gitea-web:gitea-web "$1"
'';
web-dir = "/var/lib/gitea-web/web";
};
in "${giteaWebSecretProviderScript} ${args}";
User = "gitea-web";
Group = "gitea-web";
StateDirectory = "gitea-web";
StateDirectoryMode = "0750";
LoadCredential = [
"token:${config.sops.secrets."gitea/web-secret-provider/token".path}"
];
NoNewPrivileges = true;
PrivateTmp = true;
PrivateDevices = true;
ProtectSystem = true;
ProtectHome = true;
ProtectControlGroups = true;
ProtectKernelModules = true;
ProtectKernelTunables = true;
RestrictAddressFamilies = [ "AF_INET" "AF_INET6" ];
RestrictRealtime = true;
RestrictSUIDSGID = true;
MemoryDenyWriteExecute = true;
LockPersonality = true;
};
};
systemd.timers."gitea-web-secret-provider@" = {
description = "Ensure all repos in %i has an SSH key to push web content";
timerConfig = {
RandomizedDelaySec = "1h";
Persistent = true;
Unit = "gitea-web-secret-provider@%i.service";
OnCalendar = "daily";
};
};
systemd.targets.timers.wants = map (org: "gitea-web-secret-provider@${org}.timer") organizations;
services.openssh.authorizedKeysFiles = map (org: "/var/lib/gitea-web/authorized_keys.d/${org}") organizations;
users.users.nginx.extraGroups = [ "gitea-web" ];
services.nginx.virtualHosts."pages.pvv.ntnu.no" = {
kTLS = true;
forceSSL = true;
enableACME = true;
root = "/var/lib/gitea-web/web";
};
}

View File

@ -1,112 +0,0 @@
import argparse
import hashlib
import os
import requests
import subprocess
from pathlib import Path
def parse_args():
parser = argparse.ArgumentParser(description="Generate SSH keys for Gitea repositories and add them as secrets")
parser.add_argument("--org", required=True, type=str, help="The organization to generate keys for")
parser.add_argument("--token-path", metavar='PATH', required=True, type=Path, help="Path to a file containing the Gitea API token")
parser.add_argument("--api-url", metavar='URL', type=str, help="The URL of the Gitea API", default="https://git.pvv.ntnu.no/api/v1")
parser.add_argument("--key-dir", metavar='PATH', type=Path, help="The directory to store the generated keys in", default="/run/gitea-web-secret-provider")
parser.add_argument("--authorized-keys-path", metavar='PATH', type=Path, help="The path to the resulting authorized_keys file", default="/etc/ssh/authorized_keys.d/gitea-web-secret-provider")
parser.add_argument("--rrsync-script", metavar='PATH', type=Path, help="The path to a rrsync script, taking the destination path as its single argument")
parser.add_argument("--web-dir", metavar='PATH', type=Path, help="The directory to sync the repositories to", default="/var/www")
parser.add_argument("--force", action="store_true", help="Overwrite existing keys")
return parser.parse_args()
def add_secret(args: argparse.Namespace, token: str, repo: str, name: str, secret: str):
result = requests.put(
f"{args.api_url}/repos/{args.org}/{repo}/actions/secrets/{name}",
json = { 'data': secret },
headers = { 'Authorization': 'token ' + token },
)
if result.status_code not in (201, 204):
raise Exception(f"Failed to add secret: {result.json()}")
def get_org_repo_list(args: argparse.Namespace, token: str):
result = requests.get(
f"{args.api_url}/orgs/{args.org}/repos",
headers = { 'Authorization': 'token ' + token },
)
return [repo["name"] for repo in result.json()]
def generate_ssh_key(args: argparse.Namespace, repository: str):
keyname = hashlib.sha256(args.org.encode() + repository.encode()).hexdigest()
key_path = args.key_dir / keyname
if not key_path.is_file() or args.force:
subprocess.run(
[
"ssh-keygen",
*("-t", "ed25519"),
*("-f", key_path),
*("-N", ""),
*("-C", f"{args.org}/{repository}"),
],
check=True,
stdin=subprocess.DEVNULL,
stdout=subprocess.PIPE,
stderr=subprocess.PIPE,
)
print(f"Generated SSH key for `{args.org}/{repository}`")
with open(key_path, "r") as f:
private_key = f.read()
pub_key_path = args.key_dir / (keyname + '.pub')
with open(pub_key_path, "r") as f:
public_key = f.read()
return private_key, public_key
SSH_OPTS = ",".join([
"restrict",
"no-agent-forwarding",
"no-port-forwarding",
"no-pty",
"no-X11-forwarding",
])
def generate_authorized_keys(args: argparse.Namespace, repo_public_keys: list[tuple[str, str]]):
lines = []
for repo, public_key in repo_public_keys:
command = f"{args.rrsync_script} {args.web_dir}/{args.org}/{repo}"
lines.append(f'command="{command}",{SSH_OPTS} {public_key}')
with open(args.authorized_keys_path, "w") as f:
f.writelines(lines)
def main():
args = parse_args()
with open(args.token_path, "r") as f:
token = f.read().strip()
os.makedirs(args.key_dir, 0o700, exist_ok=True)
os.makedirs(args.authorized_keys_path.parent, 0o700, exist_ok=True)
repos = get_org_repo_list(args, token)
print(f'Found {len(repos)} repositories in `{args.org}`')
repo_public_keys = []
for repo in repos:
print(f"Locating key for `{args.org}/{repo}`")
private_key, public_key = generate_ssh_key(args, repo)
add_secret(args, token, repo, "WEB_SYNC_SSH_KEY", private_key)
repo_public_keys.append((repo, public_key))
generate_authorized_keys(args, repo_public_keys)
print(f"Wrote authorized_keys file to `{args.authorized_keys_path}`")
if __name__ == "__main__":
main()

View File

@ -22,78 +22,78 @@ let
# openssl req -newkey rsa:4096 -new -x509 -days 365 -nodes -out idp.crt -keyout idp.pem
"metadata/saml20-idp-hosted.php" = pkgs.writeText "saml20-idp-remote.php" ''
<?php
$metadata['https://idp.pvv.ntnu.no/'] = array(
'host' => '__DEFAULT__',
'privatekey' => '${config.sops.secrets."idp/privatekey".path}',
'certificate' => '${./idp.crt}',
'auth' => 'pwauth',
);
?>
$metadata['https://idp.pvv.ntnu.no/'] = array(
'host' => '__DEFAULT__',
'privatekey' => '${config.sops.secrets."idp/privatekey".path}',
'certificate' => '${./idp.crt}',
'auth' => 'pwauth',
);
?>
'';
"metadata/saml20-sp-remote.php" = pkgs.writeText "saml20-sp-remote.php" ''
<?php
${ lib.pipe config.services.idp.sp-remote-metadata [
(map (url: ''
$metadata['${url}'] = [
'SingleLogoutService' => [
[
'Binding' => 'urn:oasis:names:tc:SAML:2.0:bindings:HTTP-Redirect',
'Location' => '${url}module.php/saml/sp/saml2-logout.php/default-sp',
],
[
'Binding' => 'urn:oasis:names:tc:SAML:2.0:bindings:SOAP',
'Location' => '${url}module.php/saml/sp/saml2-logout.php/default-sp',
],
],
'AssertionConsumerService' => [
[
'Binding' => 'urn:oasis:names:tc:SAML:2.0:bindings:HTTP-POST',
'Location' => '${url}module.php/saml/sp/saml2-acs.php/default-sp',
'index' => 0,
],
[
'Binding' => 'urn:oasis:names:tc:SAML:2.0:bindings:HTTP-Artifact',
'Location' => '${url}module.php/saml/sp/saml2-acs.php/default-sp',
'index' => 1,
],
],
];
''))
(lib.concatStringsSep "\n")
]}
?>
${ lib.pipe config.services.idp.sp-remote-metadata [
(map (url: ''
$metadata['${url}'] = [
'SingleLogoutService' => [
[
'Binding' => 'urn:oasis:names:tc:SAML:2.0:bindings:HTTP-Redirect',
'Location' => '${url}module.php/saml/sp/saml2-logout.php/default-sp',
],
[
'Binding' => 'urn:oasis:names:tc:SAML:2.0:bindings:SOAP',
'Location' => '${url}module.php/saml/sp/saml2-logout.php/default-sp',
],
],
'AssertionConsumerService' => [
[
'Binding' => 'urn:oasis:names:tc:SAML:2.0:bindings:HTTP-POST',
'Location' => '${url}module.php/saml/sp/saml2-acs.php/default-sp',
'index' => 0,
],
[
'Binding' => 'urn:oasis:names:tc:SAML:2.0:bindings:HTTP-Artifact',
'Location' => '${url}module.php/saml/sp/saml2-acs.php/default-sp',
'index' => 1,
],
],
];
''))
(lib.concatStringsSep "\n")
]}
?>
'';
"config/authsources.php" = pkgs.writeText "idp-authsources.php" ''
<?php
$config = array(
'admin' => array(
'core:AdminPassword'
),
'admin' => array(
'core:AdminPassword'
),
'pwauth' => array(
'authpwauth:PwAuth',
'pwauth_bin_path' => '${lib.getExe pwAuthScript}',
'mail_domain' => '@pvv.ntnu.no',
'authpwauth:PwAuth',
'pwauth_bin_path' => '${lib.getExe pwAuthScript}',
'mail_domain' => '@pvv.ntnu.no',
),
);
?>
?>
'';
"config/config.php" = pkgs.runCommandLocal "simplesamlphp-config.php" { } ''
cp ${./config.php} "$out"
substituteInPlace "$out" \
--replace-warn '$SAML_COOKIE_SECURE' 'true' \
--replace-warn '$SAML_COOKIE_SALT' 'file_get_contents("${config.sops.secrets."idp/cookie_salt".path}")' \
--replace-warn '$SAML_ADMIN_NAME' '"Drift"' \
--replace-warn '$SAML_ADMIN_EMAIL' '"drift@pvv.ntnu.no"' \
--replace-warn '$SAML_ADMIN_PASSWORD' 'file_get_contents("${config.sops.secrets."idp/admin_password".path}")' \
--replace-warn '$SAML_TRUSTED_DOMAINS' 'array( "idp.pvv.ntnu.no" )' \
--replace-warn '$SAML_DATABASE_DSN' '"pgsql:host=postgres.pvv.ntnu.no;port=5432;dbname=idp"' \
--replace-warn '$SAML_DATABASE_USERNAME' '"idp"' \
--replace-warn '$SAML_DATABASE_PASSWORD' 'file_get_contents("${config.sops.secrets."idp/postgres_password".path}")' \
--replace-warn '$CACHE_DIRECTORY' '/var/cache/idp'
--replace '$SAML_COOKIE_SECURE' 'true' \
--replace '$SAML_COOKIE_SALT' 'file_get_contents("${config.sops.secrets."idp/cookie_salt".path}")' \
--replace '$SAML_ADMIN_NAME' '"Drift"' \
--replace '$SAML_ADMIN_EMAIL' '"drift@pvv.ntnu.no"' \
--replace '$SAML_ADMIN_PASSWORD' 'file_get_contents("${config.sops.secrets."idp/admin_password".path}")' \
--replace '$SAML_TRUSTED_DOMAINS' 'array( "idp.pvv.ntnu.no" )' \
--replace '$SAML_DATABASE_DSN' '"pgsql:host=postgres.pvv.ntnu.no;port=5432;dbname=idp"' \
--replace '$SAML_DATABASE_USERNAME' '"idp"' \
--replace '$SAML_DATABASE_PASSWORD' 'file_get_contents("${config.sops.secrets."idp/postgres_password".path}")' \
--replace '$CACHE_DIRECTORY' '/var/cache/idp'
'';
"modules/authpwauth/src/Auth/Source/PwAuth.php" = ./authpwauth.php;
@ -108,7 +108,7 @@ in
List of urls point to (simplesamlphp) service profiders, which the idp should trust.
:::{.note}
Make sure the url ends with a `/`
Make sure the url ends with a `/`
:::
'';
};
@ -199,15 +199,9 @@ in
'';
};
"^~ /simplesaml/".extraConfig = ''
rewrite ^/simplesaml/(.*)$ /$1 redirect;
return 404;
'';
"/robots.txt" = {
root = pkgs.writeTextDir "robots.txt" ''
User-agent: *
Disallow: /
'';
};
rewrite ^/simplesaml/(.*)$ /$1 redirect;
return 404;
'';
};
};
};

View File

@ -1,5 +1,18 @@
{ config, pkgs, lib, ... }:
{
#######################
# TODO: remove these once nixos 24.05 gets released
#######################
# imports = [
# ./krb5.nix
# ./pam.nix
# ];
# disabledModules = [
# "config/krb5/default.nix"
# "security/pam.nix"
# ];
#######################
security.krb5 = {
enable = true;
settings = {

View File

@ -1,88 +0,0 @@
{ pkgs, lib, ... }:
# Based on
# - https://web.mit.edu/kerberos/krb5-1.12/doc/admin/conf_files/krb5_conf.html
# - https://manpages.debian.org/unstable/heimdal-docs/krb5.conf.5heimdal.en.html
let
inherit (lib) boolToString concatMapStringsSep concatStringsSep filter
isAttrs isBool isList mapAttrsToList mdDoc mkOption singleton splitString;
inherit (lib.types) attrsOf bool coercedTo either int listOf oneOf path
str submodule;
in
{ }: {
type = let
section = attrsOf relation;
relation = either (attrsOf value) value;
value = either (listOf atom) atom;
atom = oneOf [int str bool];
in submodule {
freeformType = attrsOf section;
options = {
include = mkOption {
default = [ ];
description = mdDoc ''
Files to include in the Kerberos configuration.
'';
type = coercedTo path singleton (listOf path);
};
includedir = mkOption {
default = [ ];
description = mdDoc ''
Directories containing files to include in the Kerberos configuration.
'';
type = coercedTo path singleton (listOf path);
};
module = mkOption {
default = [ ];
description = mdDoc ''
Modules to obtain Kerberos configuration from.
'';
type = coercedTo path singleton (listOf path);
};
};
};
generate = let
indent = str: concatMapStringsSep "\n" (line: " " + line) (splitString "\n" str);
formatToplevel = args @ {
include ? [ ],
includedir ? [ ],
module ? [ ],
...
}: let
sections = removeAttrs args [ "include" "includedir" "module" ];
in concatStringsSep "\n" (filter (x: x != "") [
(concatStringsSep "\n" (mapAttrsToList formatSection sections))
(concatMapStringsSep "\n" (m: "module ${m}") module)
(concatMapStringsSep "\n" (i: "include ${i}") include)
(concatMapStringsSep "\n" (i: "includedir ${i}") includedir)
]);
formatSection = name: section: ''
[${name}]
${indent (concatStringsSep "\n" (mapAttrsToList formatRelation section))}
'';
formatRelation = name: relation:
if isAttrs relation
then ''
${name} = {
${indent (concatStringsSep "\n" (mapAttrsToList formatValue relation))}
}''
else formatValue name relation;
formatValue = name: value:
if isList value
then concatMapStringsSep "\n" (formatAtom name) value
else formatAtom name value;
formatAtom = name: atom: let
v = if isBool atom then boolToString atom else toString atom;
in "${name} = ${v}";
in
name: value: pkgs.writeText name ''
${formatToplevel value}
'';
}

View File

@ -1,90 +0,0 @@
{ config, lib, pkgs, ... }:
let
inherit (lib) mdDoc mkIf mkOption mkPackageOption mkRemovedOptionModule;
inherit (lib.types) bool;
mkRemovedOptionModule' = name: reason: mkRemovedOptionModule ["krb5" name] reason;
mkRemovedOptionModuleCfg = name: mkRemovedOptionModule' name ''
The option `krb5.${name}' has been removed. Use
`security.krb5.settings.${name}' for structured configuration.
'';
cfg = config.security.krb5;
format = import ./krb5-conf-format.nix { inherit pkgs lib; } { };
in {
imports = [
(mkRemovedOptionModuleCfg "libdefaults")
(mkRemovedOptionModuleCfg "realms")
(mkRemovedOptionModuleCfg "domain_realm")
(mkRemovedOptionModuleCfg "capaths")
(mkRemovedOptionModuleCfg "appdefaults")
(mkRemovedOptionModuleCfg "plugins")
(mkRemovedOptionModuleCfg "config")
(mkRemovedOptionModuleCfg "extraConfig")
(mkRemovedOptionModule' "kerberos" ''
The option `krb5.kerberos' has been moved to `security.krb5.package'.
'')
];
options = {
security.krb5 = {
enable = mkOption {
default = false;
description = mdDoc "Enable and configure Kerberos utilities";
type = bool;
};
package = mkPackageOption pkgs "krb5" {
example = "heimdal";
};
settings = mkOption {
default = { };
type = format.type;
description = mdDoc ''
Structured contents of the {file}`krb5.conf` file. See
{manpage}`krb5.conf(5)` for details about configuration.
'';
example = {
include = [ "/run/secrets/secret-krb5.conf" ];
includedir = [ "/run/secrets/secret-krb5.conf.d" ];
libdefaults = {
default_realm = "ATHENA.MIT.EDU";
};
realms = {
"ATHENA.MIT.EDU" = {
admin_server = "athena.mit.edu";
kdc = [
"athena01.mit.edu"
"athena02.mit.edu"
];
};
};
domain_realm = {
"mit.edu" = "ATHENA.MIT.EDU";
};
logging = {
kdc = "SYSLOG:NOTICE";
admin_server = "SYSLOG:NOTICE";
default = "SYSLOG:NOTICE";
};
};
};
};
};
config = mkIf cfg.enable {
environment = {
systemPackages = [ cfg.package ];
etc."krb5.conf".source = format.generate "krb5.conf" cfg.settings;
};
};
meta.maintainers = builtins.attrValues {
inherit (lib.maintainers) dblsaiko h7x4;
};
}

File diff suppressed because it is too large Load Diff

View File

@ -1,4 +1,4 @@
{ pkgs, lib, fp, config, values, pkgs-unstable, ... }: let
{ pkgs, lib, config, values, pkgs-unstable, ... }: let
cfg = config.services.mediawiki;
# "mediawiki"
@ -17,16 +17,16 @@
cp ${./simplesaml-config.php} "$out"
substituteInPlace "$out" \
--replace-warn '$SAML_COOKIE_SECURE' 'true' \
--replace-warn '$SAML_COOKIE_SALT' 'file_get_contents("${config.sops.secrets."mediawiki/simplesamlphp/cookie_salt".path}")' \
--replace-warn '$SAML_ADMIN_NAME' '"Drift"' \
--replace-warn '$SAML_ADMIN_EMAIL' '"drift@pvv.ntnu.no"' \
--replace-warn '$SAML_ADMIN_PASSWORD' 'file_get_contents("${config.sops.secrets."mediawiki/simplesamlphp/admin_password".path}")' \
--replace-warn '$SAML_TRUSTED_DOMAINS' 'array( "wiki.pvv.ntnu.no" )' \
--replace-warn '$SAML_DATABASE_DSN' '"pgsql:host=postgres.pvv.ntnu.no;port=5432;dbname=mediawiki_simplesamlphp"' \
--replace-warn '$SAML_DATABASE_USERNAME' '"mediawiki_simplesamlphp"' \
--replace-warn '$SAML_DATABASE_PASSWORD' 'file_get_contents("${config.sops.secrets."mediawiki/simplesamlphp/postgres_password".path}")' \
--replace-warn '$CACHE_DIRECTORY' '/var/cache/mediawiki/idp'
--replace '$SAML_COOKIE_SECURE' 'true' \
--replace '$SAML_COOKIE_SALT' 'file_get_contents("${config.sops.secrets."mediawiki/simplesamlphp/cookie_salt".path}")' \
--replace '$SAML_ADMIN_NAME' '"Drift"' \
--replace '$SAML_ADMIN_EMAIL' '"drift@pvv.ntnu.no"' \
--replace '$SAML_ADMIN_PASSWORD' 'file_get_contents("${config.sops.secrets."mediawiki/simplesamlphp/admin_password".path}")' \
--replace '$SAML_TRUSTED_DOMAINS' 'array( "wiki.pvv.ntnu.no" )' \
--replace '$SAML_DATABASE_DSN' '"pgsql:host=postgres.pvv.ntnu.no;port=5432;dbname=mediawiki_simplesamlphp"' \
--replace '$SAML_DATABASE_USERNAME' '"mediawiki_simplesamlphp"' \
--replace '$SAML_DATABASE_PASSWORD' 'file_get_contents("${config.sops.secrets."mediawiki/simplesamlphp/postgres_password".path}")' \
--replace '$CACHE_DIRECTORY' '/var/cache/mediawiki/idp'
'';
};
};
@ -86,20 +86,7 @@ in {
};
extensions = {
inherit (pkgs.mediawiki-extensions)
CodeEditor
CodeMirror
DeleteBatch
PluggableAuth
Popups
Scribunto
SimpleSAMLphp
TemplateData
TemplateStyles
UserMerge
VisualEditor
WikiEditor
;
inherit (pkgs.mediawiki-extensions) DeleteBatch UserMerge PluggableAuth SimpleSAMLphp VisualEditor;
};
extraConfig = ''
@ -133,27 +120,13 @@ in {
# Misc
$wgEmergencyContact = "${cfg.passwordSender}";
$wgShowIPinHeader = false;
$wgUseTeX = false;
$wgLocalInterwiki = $wgSitename;
# Fix https://github.com/NixOS/nixpkgs/issues/183097
$wgDBserver = "${toString cfg.database.host}";
$wgAllowCopyUploads = true;
# Misc program paths
$wgFFmpegLocation = '${pkgs.ffmpeg}/bin/ffmpeg';
$wgExiftool = '${pkgs.exiftool}/bin/exiftool';
$wgExiv2Command = '${pkgs.exiv2}/bin/exiv2';
# See https://gist.github.com/sergejmueller/088dce028b6dd120a16e
$wgJpegTran = '${pkgs.mozjpeg}/bin/jpegtran';
$wgGitBin = '${pkgs.git}/bin/git';
# Debugging
$wgShowExceptionDetails = false;
$wgShowIPinHeader = false;
# EXT:{SimpleSAML,PluggableAuth}
# SimpleSAML
$wgSimpleSAMLphp_InstallDir = "${simplesamlphp}/share/php/simplesamlphp/";
$wgPluggableAuth_Config['Log in using SAML'] = [
$wgPluggableAuth_Config['Log in using my SAML'] = [
'plugin' => 'SimpleSAMLphp',
'data' => [
'authSourceId' => 'default-sp',
@ -163,12 +136,8 @@ in {
]
];
# EXT:Scribunto
$wgScribuntoDefaultEngine = 'luastandalone';
$wgScribuntoEngineConf['luastandalone']['luaPath'] = '${pkgs.lua}/bin';
# EXT:WikiEditor
$wgWikiEditorRealtimePreview = true;
# Fix https://github.com/NixOS/nixpkgs/issues/183097
$wgDBserver = "${toString cfg.database.host}";
'';
};
@ -210,8 +179,8 @@ in {
'';
};
"= /PNG/PVV-logo.svg".alias = fp /assets/logo_blue_regular.svg;
"= /PNG/PVV-logo.png".alias = fp /assets/logo_blue_regular.png;
"= /PNG/PVV-logo.svg".alias = ../../../../assets/logo_blue_regular.svg;
"= /PNG/PVV-logo.png".alias = ../../../../assets/logo_blue_regular.png;
"= /favicon.ico".alias = pkgs.runCommandLocal "mediawiki-favicon.ico" {
buildInputs = with pkgs; [ imagemagick ];
} ''
@ -219,7 +188,7 @@ in {
-resize x64 \
-gravity center \
-crop 64x64+0+0 \
${fp /assets/logo_blue_regular.png} \
${../../../../assets/logo_blue_regular.png} \
-flatten \
-colors 256 \
-background transparent \

View File

@ -1,51 +0,0 @@
{ lib, ... }:
let
pools = map (pool: "phpfpm-${pool}") [
"idp"
"mediawiki"
"pvv-nettsiden"
"roundcube"
"snappymail"
];
in
{
# Source: https://www.pierreblazquez.com/2023/06/17/how-to-harden-apache-php-fpm-daemons-using-systemd/
systemd.services = lib.genAttrs pools (_: {
serviceConfig = let
caps = [
"CAP_NET_BIND_SERVICE"
"CAP_SETGID"
"CAP_SETUID"
"CAP_CHOWN"
"CAP_KILL"
"CAP_IPC_LOCK"
"CAP_DAC_OVERRIDE"
];
in {
AmbientCapabilities = caps;
CapabilityBoundingSet = caps;
DeviceAllow = [ "" ];
LockPersonality = true;
MemoryDenyWriteExecute = false;
NoNewPrivileges = true;
PrivateMounts = true;
ProtectClock = true;
ProtectControlGroups = true;
ProtectHome = true;
ProtectHostname = true;
ProtectKernelLogs = true;
ProtectKernelModules = true;
ProtectKernelTunables = true;
RemoveIPC = true;
UMask = "0077";
RestrictNamespaces = "~mnt";
RestrictRealtime = true;
RestrictSUIDSGID = true;
SystemCallArchitectures = "native";
KeyringMode = "private";
SystemCallFilter = [
"@system-service"
];
};
});
}

View File

@ -1,104 +0,0 @@
{ config, pkgs, lib, ... }:
let
cfg = config.services.vaultwarden;
domain = "pw.pvv.ntnu.no";
address = "127.0.1.2";
port = 3011;
wsPort = 3012;
in {
sops.secrets."vaultwarden/environ" = {
owner = "vaultwarden";
group = "vaultwarden";
};
services.vaultwarden = {
enable = true;
dbBackend = "postgresql";
environmentFile = config.sops.secrets."vaultwarden/environ".path;
config = {
domain = "https://${domain}";
rocketAddress = address;
rocketPort = port;
websocketEnabled = true;
websocketAddress = address;
websocketPort = wsPort;
signupsAllowed = true;
signupsVerify = true;
signupsDomainsWhitelist = "pvv.ntnu.no";
smtpFrom = "vaultwarden@pvv.ntnu.no";
smtpFromName = "VaultWarden PVV";
smtpHost = "smtp.pvv.ntnu.no";
smtpUsername = "vaultwarden";
smtpSecurity = "force_tls";
smtpAuthMechanism = "Login";
# Configured in environ:
# databaseUrl = "postgresql://vaultwarden@/vaultwarden";
# smtpPassword = hemli
};
};
services.nginx.virtualHosts."${domain}" = {
forceSSL = true;
enableACME = true;
kTLS = true;
extraConfig = ''
client_max_body_size 128M;
'';
locations."/" = {
proxyPass = "http://${address}:${toString port}";
proxyWebsockets = true;
};
locations."/notifications/hub" = {
proxyPass = "http://${address}:${toString wsPort}";
proxyWebsockets = true;
};
locations."/notifications/hub/negotiate" = {
proxyPass = "http://${address}:${toString port}";
proxyWebsockets = true;
};
};
systemd.services.vaultwarden = lib.mkIf cfg.enable {
serviceConfig = {
AmbientCapabilities = [ "" ];
CapabilityBoundingSet = [ "" ];
DeviceAllow = [ "" ];
LockPersonality = true;
NoNewPrivileges = true;
# MemoryDenyWriteExecute = true;
PrivateMounts = true;
PrivateUsers = true;
ProcSubset = "pid";
ProtectClock = true;
ProtectControlGroups = true;
ProtectHostname = true;
ProtectKernelLogs = true;
ProtectKernelModules = true;
ProtectKernelTunables = true;
ProtectProc = "invisible";
RestrictAddressFamilies = [
"AF_INET"
"AF_INET6"
"AF_UNIX"
];
RemoveIPC = true;
RestrictNamespaces = true;
RestrictRealtime = true;
RestrictSUIDSGID = true;
SystemCallArchitectures = "native";
SystemCallFilter = [
"@system-service"
"~@privileged"
];
UMask = "0007";
};
};
}

View File

@ -6,11 +6,6 @@ let
domain = "webmail.pvv.ntnu.no";
in
{
sops.secrets."roundcube/postgres_password" = {
owner = "nginx";
group = "nginx";
};
services.roundcube = {
enable = true;
@ -25,11 +20,6 @@ in
maxAttachmentSize = 20;
hostName = "roundcubeplaceholder.example.com";
database = {
host = "postgres.pvv.ntnu.no";
passwordFile = config.sops.secrets."roundcube/postgres_password".path;
};
extraConfig = ''
$config['enable_installer'] = false;
$config['default_host'] = "ssl://imap.pvv.ntnu.no";

View File

@ -1,8 +1,8 @@
{ config, lib, fp, pkgs, ... }:
{ config, lib, pkgs, ... }:
let
cfg = config.services.snappymail;
in {
imports = [ (fp /modules/snappymail.nix) ];
imports = [ ../../../../modules/snappymail.nix ];
services.snappymail = {
enable = true;

View File

@ -43,7 +43,7 @@ in {
'idp' => 'https://idp.pvv.ntnu.no/',
),
);
'';
'';
};
};
@ -116,6 +116,16 @@ in {
"/drift".return = "301 https://wiki.pvv.ntnu.no/wiki/Drift";
"/diverse/abuse.php".return = "301 https://wiki.pvv.ntnu.no/wiki/CERT/Abuse";
"/nerds/".return = "301 https://wiki.pvv.ntnu.no/wiki/Nerdepizza";
# Proxy the matrix well-known files
# Host has be set before proxy_pass
# The header must be set so nginx on the other side routes it to the right place
"^~ /.well-known/matrix/" = {
extraConfig = ''
proxy_set_header Host matrix.pvv.ntnu.no;
proxy_pass https://matrix.pvv.ntnu.no/.well-known/matrix/;
'';
};
};
};
}

View File

@ -46,7 +46,7 @@ in {
while IFS= read fname; do
# Skip this file if an up-to-date thumbnail already exists
if [ -f ".thumbnails/$fname.png" ] && \
[ "$(date -R -r "$fname")" == "$(date -R -r ".thumbnails/$fname.png")" ]
[ "$(date -R -r "$fname")" == "$(date -R -r ".thumbnails/$fname.png")" ]
then
continue
fi
@ -54,7 +54,7 @@ in {
echo "Creating thumbnail for $fname"
mkdir -p $(dirname ".thumbnails/$fname")
convert -define jpeg:size=200x200 "$fname" -thumbnail 300 -auto-orient ".thumbnails/$fname.png" ||:
touch -m -d "$(date -R -r "$fname")" ".thumbnails/$fname.png"
touch -m -d "$(date -R -r "$fname")" ".thumbnails/$fname.png"
done <<< "$images"
'';
@ -62,33 +62,6 @@ in {
WorkingDirectory = galleryDir;
User = config.services.pvv-nettsiden.user;
Group = config.services.pvv-nettsiden.group;
AmbientCapabilities = [ "" ];
CapabilityBoundingSet = [ "" ];
DeviceAllow = [ "" ];
LockPersonality = true;
MemoryDenyWriteExecute = true;
NoNewPrivileges = true; # disable for third party rotate scripts
PrivateDevices = true;
PrivateNetwork = true; # disable for mail delivery
PrivateTmp = true;
ProtectClock = true;
ProtectControlGroups = true;
ProtectHome = true; # disable for userdir logs
ProtectHostname = true;
ProtectKernelLogs = true;
ProtectKernelModules = true;
ProtectKernelTunables = true;
ProtectProc = "invisible";
ProtectSystem = "full";
RestrictNamespaces = true;
RestrictRealtime = true;
RestrictSUIDSGID = true; # disable for creating setgid directories
SocketBindDeny = [ "any" ];
SystemCallArchitectures = "native";
SystemCallFilter = [
"@system-service"
];
};
};
}

View File

@ -1,18 +0,0 @@
{ ... }:
{
services.nginx.virtualHosts."www.pvv.ntnu.no".locations = {
"^~ /.well-known/" = {
alias = (toString ./root) + "/";
};
# Proxy the matrix well-known files
# Host has be set before proxy_pass
# The header must be set so nginx on the other side routes it to the right place
"^~ /.well-known/matrix/" = {
extraConfig = ''
proxy_set_header Host matrix.pvv.ntnu.no;
proxy_pass https://matrix.pvv.ntnu.no/.well-known/matrix/;
'';
};
};
}

View File

@ -1,31 +0,0 @@
<?xml version="1.0"?>
<clientConfig version="1.1">
<emailProvider id="pvv.ntnu.no">
<domain>pvv.ntnu.no</domain>
<domain>pvv.org</domain>
<displayName>Programvareverkstedet</displayName>
<incomingServer type="imap">
<hostname>imap.pvv.ntnu.no</hostname>
<port>993</port>
<socketType>SSL</socketType>
<username>%EMAILLOCALPART%</username>
<authentication>password-cleartext</authentication>
</incomingServer>
<outgoingServer type="smtp">
<hostname>smtp.pvv.ntnu.no</hostname>
<port>587</port>
<socketType>STARTTLS</socketType>
<username>%EMAILLOCALPART%</username>
<authentication>password-cleartext</authentication>
<useGlobalPreferredServer>true</useGlobalPreferredServer>
</outgoingServer>
<documentation url="https://www.pvv.ntnu.no/pvv/Drift/Mail/IMAP_POP3">
<descr lang="en">Setup programvareverkstedet email user with IMAP or POP3</descr>
<descr lang="nb">Sett opp programvareverkstedet email bruker med IMAP eller POP3</descr>
</documentation>
</emailProvider>
</clientConfig>

View File

@ -1,12 +0,0 @@
Contact: mailto:drift@pvv.ntnu.no
Contact: mailto:cert@pvv.ntnu.no
# drift@pvv.ntnu.no is read by more people and have a quicker reaction time,
# but cert@pvv.ntnu.no can be used for more severe issues.
Preferred-Languages: no, en
Expires: 2032-12-31T23:59:59.000Z
# This file was last updated 2024-09-14.
# You can find a wikipage for our security policies at:
# https://wiki.pvv.ntnu.no/wiki/CERT

24
hosts/bicep/acmeCert.nix Normal file
View File

@ -0,0 +1,24 @@
{ values, ... }:
{
users.groups.acme.members = [ "nginx" ];
security.acme.certs."postgres.pvv.ntnu.no" = {
group = "acme";
extraDomainNames = [
# "postgres.pvv.org"
"bicep.pvv.ntnu.no"
# "bicep.pvv.org"
# values.hosts.bicep.ipv4
# values.hosts.bicep.ipv6
];
};
services.nginx = {
enable = true;
virtualHosts."postgres.pvv.ntnu.no" = {
forceSSL = true;
enableACME = true;
# useACMEHost = "postgres.pvv.ntnu.no";
};
};
}

View File

@ -1,21 +1,24 @@
{ fp, pkgs, values, ... }:
{ pkgs, values, ... }:
{
imports = [
./hardware-configuration.nix
(fp /base)
(fp /misc/metrics-exporters.nix)
../../base.nix
../../misc/metrics-exporters.nix
./services/nginx
./acmeCert.nix
./services/mysql.nix
./services/postgres.nix
./services/mysql.nix
./services/calendar-bot.nix
# TODO: fix the calendar bot
# ./services/calendar-bot.nix
./services/matrix
];
sops.defaultSopsFile = fp /secrets/bicep/bicep.yaml;
sops.defaultSopsFile = ../../secrets/bicep/bicep.yaml;
sops.age.sshKeyPaths = [ "/etc/ssh/ssh_host_ed25519_key" ];
sops.age.keyFile = "/var/lib/sops-nix/key.txt";
sops.age.generateKey = true;
@ -34,9 +37,6 @@
anyInterface = true;
};
# There are no smart devices
services.smartd.enable = false;
# Do not change, even during upgrades.
# See https://search.nixos.org/options?show=system.stateVersion
system.stateVersion = "22.11";

View File

@ -1,20 +1,12 @@
{ config, fp, lib, pkgs, ... }:
{ config, lib, pkgs, ... }:
let
cfg = config.services.pvv-calendar-bot;
in {
sops.secrets = {
"calendar-bot/matrix_token" = {
sopsFile = fp /secrets/bicep/bicep.yaml;
key = "calendar-bot/matrix_token";
owner = cfg.user;
group = cfg.group;
};
"calendar-bot/mysql_password" = {
sopsFile = fp /secrets/bicep/bicep.yaml;
key = "calendar-bot/mysql_password";
owner = cfg.user;
group = cfg.group;
};
sops.secrets."calendar-bot/matrix_token" = {
sopsFile = ../../../secrets/bicep/bicep.yaml;
key = "calendar-bot/matrix_token";
owner = cfg.user;
group = cfg.group;
};
services.pvv-calendar-bot = {
@ -26,11 +18,6 @@ in {
user = "@bot_calendar:pvv.ntnu.no";
channel = "!gkNLUIhYVpEyLatcRz:pvv.ntnu.no";
};
database = {
host = "mysql.pvv.ntnu.no";
user = "calendar-bot";
passwordFile = config.sops.secrets."calendar-bot/mysql_password".path;
};
secretsFile = config.sops.secrets."calendar-bot/matrix_token".path;
onCalendar = "*-*-* 09:00:00";
};

View File

@ -1,14 +1,14 @@
{ config, lib, fp, pkgs, secrets, values, ... }:
{ config, lib, pkgs, secrets, ... }:
{
sops.secrets."matrix/synapse/turnconfig" = {
sopsFile = fp /secrets/bicep/matrix.yaml;
sopsFile = ../../../../secrets/bicep/matrix.yaml;
key = "synapse/turnconfig";
owner = config.users.users.matrix-synapse.name;
group = config.users.users.matrix-synapse.group;
};
sops.secrets."matrix/coturn/static-auth-secret" = {
sopsFile = fp /secrets/bicep/matrix.yaml;
sopsFile = ../../../../secrets/bicep/matrix.yaml;
key = "coturn/static-auth-secret";
owner = config.users.users.turnserver.name;
group = config.users.users.turnserver.group;
@ -60,14 +60,12 @@
pkey = "${config.security.acme.certs.${realm}.directory}/key.pem";
use-auth-secret = true;
# World readable but I dont think it's that bad
static-auth-secret-file = config.sops.secrets."matrix/coturn/static-auth-secret".path;
secure-stun = true;
listening-ips = [
values.services.turn.ipv4
# values.services.turn.ipv6
];
listening-ips = [ "129.241.210.213" "2001:700:300:1900::213" ];
tls-listening-port = 443;
alt-tls-listening-port = 5349;

View File

@ -10,7 +10,6 @@
./mjolnir.nix
./discord.nix
./hookshot
];

View File

@ -1,4 +1,4 @@
{ config, lib, fp, ... }:
{ config, lib, ... }:
let
cfg = config.services.mx-puppet-discord;
@ -6,42 +6,15 @@ in
{
users.groups.keys-matrix-registrations = { };
sops.secrets."matrix/discord/as_token" = {
sopsFile = fp /secrets/bicep/matrix.yaml;
key = "discord/as_token";
};
sops.secrets."matrix/discord/hs_token" = {
sopsFile = fp /secrets/bicep/matrix.yaml;
key = "discord/hs_token";
};
sops.templates."discord-registration.yaml" = {
sops.secrets."matrix/registrations/mx-puppet-discord" = {
sopsFile = ../../../../secrets/bicep/matrix.yaml;
key = "registrations/mx-puppet-discord";
owner = config.users.users.matrix-synapse.name;
group = config.users.groups.keys-matrix-registrations.name;
content = ''
as_token: "${config.sops.placeholder."matrix/discord/as_token"}"
hs_token: "${config.sops.placeholder."matrix/discord/hs_token"}"
id: discord-puppet
namespaces:
users:
- exclusive: true
regex: '@_discordpuppet_.*'
rooms: []
aliases:
- exclusive: true
regex: '#_discordpuppet_.*'
protocols: []
rate_limited: false
sender_localpart: _discordpuppet_bot
url: 'http://localhost:8434'
de.sorunome.msc2409.push_ephemeral: true
'';
};
systemd.services.mx-puppet-discord = {
serviceConfig.SupplementaryGroups = [
config.users.groups.keys-matrix-registrations.name
];
serviceConfig.SupplementaryGroups = [ config.users.groups.keys-matrix-registrations.name ];
};
@ -56,16 +29,11 @@ in
relay.whitelist = [ ".*" ];
selfService.whitelist = [ "@danio:pvv\\.ntnu\\.no" "@dandellion:dodsorf\\.as" ];
};
services.mx-puppet-discord.serviceDependencies = [
"matrix-synapse.target"
"nginx.service"
];
services.mx-puppet-discord.serviceDependencies = [ "matrix-synapse.target" "nginx.service" ];
services.matrix-synapse-next.settings = {
app_service_config_files = [
config.sops.templates."discord-registration.yaml".path
];
app_service_config_files = [ config.sops.secrets."matrix/registrations/mx-puppet-discord".path ];
use_appservice_legacy_authorization = true;
};

View File

@ -1,139 +0,0 @@
{ config, lib, fp, unstablePkgs, inputs, ... }:
let
cfg = config.services.matrix-hookshot;
webhookListenAddress = "127.0.0.1";
webhookListenPort = 8435;
in
{
imports = [
./module.nix
];
sops.secrets."matrix/hookshot/as_token" = {
sopsFile = fp /secrets/bicep/matrix.yaml;
key = "hookshot/as_token";
};
sops.secrets."matrix/hookshot/hs_token" = {
sopsFile = fp /secrets/bicep/matrix.yaml;
key = "hookshot/hs_token";
};
sops.templates."hookshot-registration.yaml" = {
owner = config.users.users.matrix-synapse.name;
group = config.users.groups.keys-matrix-registrations.name;
content = ''
id: matrix-hookshot
as_token: "${config.sops.placeholder."matrix/hookshot/as_token"}"
hs_token: "${config.sops.placeholder."matrix/hookshot/hs_token"}"
namespaces:
rooms: []
users:
- regex: "@_webhooks_.*:pvv.ntnu.no"
exclusive: true
- regex: "@bot_feeds:pvv.ntnu.no"
exclusive: true
aliases: []
sender_localpart: hookshot
url: "http://${cfg.settings.bridge.bindAddress}:${toString cfg.settings.bridge.port}"
rate_limited: false
# If enabling encryption
de.sorunome.msc2409.push_ephemeral: true
push_ephemeral: true
org.matrix.msc3202: true
'';
};
systemd.services.matrix-hookshot = {
serviceConfig.SupplementaryGroups = [
config.users.groups.keys-matrix-registrations.name
];
};
services.matrix-hookshot = {
enable = true;
package = unstablePkgs.matrix-hookshot;
registrationFile = config.sops.templates."hookshot-registration.yaml".path;
settings = {
bridge = {
bindAddress = "127.0.0.1";
domain = "pvv.ntnu.no";
url = "https://matrix.pvv.ntnu.no";
mediaUrl = "https://matrix.pvv.ntnu.no";
port = 9993;
};
listeners = [
{
bindAddress = webhookListenAddress;
port = webhookListenPort;
resources = [
"webhooks"
# "metrics"
# "provisioning"
"widgets"
];
}
];
generic = {
enabled = true;
outbound = true;
urlPrefix = "https://hookshot.pvv.ntnu.no/webhook/";
userIdPrefix = "_webhooks_";
allowJsTransformationFunctions = false;
waitForComplete = false;
};
feeds = {
enabled = true;
pollIntervalSeconds = 600;
};
serviceBots = [
{ localpart = "bot_feeds";
displayname = "Aya";
avatar = ./feeds.png;
prefix = "!aya";
service = "feeds";
}
];
permissions = [
# Users of the PVV Server
{ actor = "pvv.ntnu.no";
services = [ { service = "*"; level = "commands"; } ];
}
# Members of Medlem space (for people with their own hs)
{ actor = "!pZOTJQinWyyTWaeOgK:pvv.ntnu.no";
services = [ { service = "*"; level = "commands"; } ];
}
# Members of Drift
{ actor = "!eYgeufLrninXxQpYml:pvv.ntnu.no";
services = [ { service = "*"; level = "admin"; } ];
}
# Dan bootstrap
{ actor = "@dandellion:dodsorf.as";
services = [ { service = "*"; level = "admin"; } ];
}
];
};
};
services.matrix-hookshot.serviceDependencies = [
"matrix-synapse.target"
"nginx.service"
];
services.matrix-synapse-next.settings = {
app_service_config_files = [
config.sops.templates."hookshot-registration.yaml".path
];
};
services.nginx.virtualHosts."hookshot.pvv.ntnu.no" = {
enableACME = true;
locations."/" = {
proxyPass = "http://${webhookListenAddress}:${toString webhookListenPort}";
};
};
}

Binary file not shown.

Before

Width:  |  Height:  |  Size: 1.1 MiB

View File

@ -1,127 +0,0 @@
{
config,
pkgs,
lib,
...
}:
let
cfg = config.services.matrix-hookshot;
settingsFormat = pkgs.formats.yaml { };
configFile = settingsFormat.generate "matrix-hookshot-config.yml" cfg.settings;
in
{
options = {
services.matrix-hookshot = {
enable = lib.mkEnableOption "matrix-hookshot, a bridge between Matrix and project management services";
package = lib.mkPackageOption pkgs "matrix-hookshot" { };
registrationFile = lib.mkOption {
type = lib.types.path;
description = ''
Appservice registration file.
As it contains secret tokens, you may not want to add this to the publicly readable Nix store.
'';
example = lib.literalExpression ''
pkgs.writeText "matrix-hookshot-registration" \'\'
id: matrix-hookshot
as_token: aaaaaaaaaa
hs_token: aaaaaaaaaa
namespaces:
rooms: []
users:
- regex: "@_webhooks_.*:foobar"
exclusive: true
sender_localpart: hookshot
url: "http://localhost:9993"
rate_limited: false
\'\'
'';
};
settings = lib.mkOption {
description = ''
{file}`config.yml` configuration as a Nix attribute set.
For details please see the [documentation](https://matrix-org.github.io/matrix-hookshot/latest/setup/sample-configuration.html).
'';
example = {
bridge = {
domain = "example.com";
url = "http://localhost:8008";
mediaUrl = "https://example.com";
port = 9993;
bindAddress = "127.0.0.1";
};
listeners = [
{
port = 9000;
bindAddress = "0.0.0.0";
resources = [ "webhooks" ];
}
{
port = 9001;
bindAddress = "localhost";
resources = [
"metrics"
"provisioning"
];
}
];
};
default = { };
type = lib.types.submodule {
freeformType = settingsFormat.type;
options = {
passFile = lib.mkOption {
type = lib.types.path;
default = "/var/lib/matrix-hookshot/passkey.pem";
description = ''
A passkey used to encrypt tokens stored inside the bridge.
File will be generated if not found.
'';
};
};
};
};
serviceDependencies = lib.mkOption {
type = with lib.types; listOf str;
default = lib.optional config.services.matrix-synapse.enable config.services.matrix-synapse.serviceUnit;
defaultText = lib.literalExpression ''
lib.optional config.services.matrix-synapse.enable config.services.matrix-synapse.serviceUnit
'';
description = ''
List of Systemd services to require and wait for when starting the application service,
such as the Matrix homeserver if it's running on the same host.
'';
};
};
};
config = lib.mkIf cfg.enable {
systemd.services.matrix-hookshot = {
description = "a bridge between Matrix and multiple project management services";
wantedBy = [ "multi-user.target" ];
wants = [ "network-online.target" ] ++ cfg.serviceDependencies;
after = [ "network-online.target" ] ++ cfg.serviceDependencies;
preStart = ''
if [ ! -f '${cfg.settings.passFile}' ]; then
mkdir -p $(dirname '${cfg.settings.passFile}')
${pkgs.openssl}/bin/openssl genpkey -out '${cfg.settings.passFile}' -outform PEM -algorithm RSA -pkeyopt rsa_keygen_bits:4096
fi
'';
serviceConfig = {
Type = "simple";
Restart = "always";
ExecStart = "${cfg.package}/bin/matrix-hookshot ${configFile} ${cfg.registrationFile}";
};
};
};
meta.maintainers = with lib.maintainers; [ flandweber ];
}

View File

@ -1,8 +1,8 @@
{ config, lib, fp, ... }:
{ config, lib, ... }:
{
sops.secrets."matrix/mjolnir/access_token" = {
sopsFile = fp /secrets/bicep/matrix.yaml;
sopsFile = ../../../../secrets/bicep/matrix.yaml;
key = "mjolnir/access_token";
owner = config.users.users.mjolnir.name;
group = config.users.users.mjolnir.group;
@ -11,7 +11,7 @@
services.mjolnir = {
enable = true;
pantalaimon.enable = false;
homeserverUrl = "https://matrix.pvv.ntnu.no";
homeserverUrl = http://127.0.0.1:8008;
accessTokenFile = config.sops.secrets."matrix/mjolnir/access_token".path;
managementRoom = "!gsdeCoWjvYRBrzuiRq:pvv.ntnu.no";
protectedRooms = map (a: "https://matrix.to/#/${a}") [

View File

@ -1,4 +1,4 @@
{ config, lib, fp, pkgs, values, inputs, ... }:
{ config, lib, pkgs, values, inputs, ... }:
let
cfg = config.services.matrix-synapse-next;
@ -10,18 +10,23 @@ let
in {
sops.secrets."matrix/synapse/signing_key" = {
key = "synapse/signing_key";
sopsFile = fp /secrets/bicep/matrix.yaml;
sopsFile = ../../../../secrets/bicep/matrix.yaml;
owner = config.users.users.matrix-synapse.name;
group = config.users.users.matrix-synapse.group;
};
sops.secrets."matrix/synapse/user_registration" = {
sopsFile = fp /secrets/bicep/matrix.yaml;
sopsFile = ../../../../secrets/bicep/matrix.yaml;
key = "synapse/signing_key";
owner = config.users.users.matrix-synapse.name;
group = config.users.users.matrix-synapse.group;
};
sops.secrets."matrix/sliding-sync/env" = {
sopsFile = ../../../../secrets/bicep/matrix.yaml;
key = "sliding-sync/env";
};
services.matrix-synapse-next = {
enable = true;
@ -38,6 +43,8 @@ in {
workers.eventPersisters = 2;
workers.useUserDirectoryWorker = true;
enableSlidingSync = true;
enableNginx = true;
settings = {
@ -130,13 +137,16 @@ in {
};
};
services.matrix-synapse.sliding-sync.environmentFile = config.sops.secrets."matrix/sliding-sync/env".path;
services.redis.servers."".enable = true;
services.nginx.virtualHosts."matrix.pvv.ntnu.no" = lib.mkMerge [
{
({
kTLS = true;
}
{
})
({
locations."/.well-known/matrix/server" = {
return = ''
200 '{"m.server": "matrix.pvv.ntnu.no:443"}'
@ -146,43 +156,35 @@ in {
add_header Access-Control-Allow-Origin *;
'';
};
}
{
locations."/_synapse/admin" = {
proxyPass = "http://$synapse_backend";
extraConfig = ''
allow 127.0.0.1;
allow ::1;
allow ${values.hosts.bicep.ipv4};
allow ${values.hosts.bicep.ipv6};
deny all;
'';
};
}
{
})
({
locations = let
connectionInfo = w: matrix-lib.workerConnectionResource "metrics" w;
socketAddress = w: let c = connectionInfo w; in "${c.host}:${toString c.port}";
socketAddress = w: let c = connectionInfo w; in "${c.host}:${toString (c.port)}";
metricsPath = w: "/metrics/${w.type}/${toString w.index}";
proxyPath = w: "http://${socketAddress w}/_synapse/metrics";
in lib.mapAttrs' (n: v: lib.nameValuePair
(metricsPath v) {
(metricsPath v) ({
proxyPass = proxyPath v;
extraConfig = ''
allow ${values.hosts.ildkule.ipv4};
allow ${values.hosts.ildkule.ipv6};
allow ${values.hosts.ildkule.ipv4_global};
allow ${values.hosts.ildkule.ipv6_global};
deny all;
'';
})
}))
cfg.workers.instances;
}
{
})
({
locations."/metrics/master/1" = {
proxyPass = "http://127.0.0.1:9000/_synapse/metrics";
extraConfig = ''
allow ${values.hosts.ildkule.ipv4};
allow ${values.hosts.ildkule.ipv6};
allow ${values.hosts.ildkule.ipv4_global};
allow ${values.hosts.ildkule.ipv6_global};
deny all;
'';
};
@ -200,5 +202,5 @@ in {
labels = { };
}]) + "/";
};
}];
})];
}

View File

@ -15,12 +15,12 @@
mysqld = {
# PVV allows a lot of connections at the same time
max_connect_errors = 10000;
bind-address = values.services.mysql.ipv4;
skip-networking = 0;
bind-address = values.services.mysql.ipv4;
skip-networking = 0;
# This was needed in order to be able to use all of the old users
# during migration from knakelibrak to bicep in Sep. 2023
secure_auth = 0;
# This was needed in order to be able to use all of the old users
# during migration from knakelibrak to bicep in Sep. 2023
secure_auth = 0;
};
};

View File

@ -1,4 +1,7 @@
{ config, pkgs, ... }:
let
sslCert = config.security.acme.certs."postgres.pvv.ntnu.no";
in
{
services.postgresql = {
enable = true;
@ -76,16 +79,12 @@
systemd.services.postgresql.serviceConfig = {
LoadCredential = [
"cert:/etc/certs/postgres.crt"
"key:/etc/certs/postgres.key"
"cert:${sslCert.directory}/cert.pem"
"key:${sslCert.directory}/key.pem"
];
};
environment.snakeoil-certs."/etc/certs/postgres" = {
owner = "postgres";
group = "postgres";
subject = "/C=NO/O=Programvareverkstedet/CN=postgres.pvv.ntnu.no/emailAddress=drift@pvv.ntnu.no";
};
users.groups.acme.members = [ "postgres" ];
networking.firewall.allowedTCPPorts = [ 5432 ];
networking.firewall.allowedUDPPorts = [ 5432 ];

View File

@ -1,16 +1,16 @@
{ config, fp, pkgs, values, ... }:
{ config, pkgs, values, ... }:
{
imports = [
# Include the results of the hardware scan.
./hardware-configuration.nix
(fp /base)
(fp /misc/metrics-exporters.nix)
../../base.nix
../../misc/metrics-exporters.nix
./disks.nix
(fp /misc/builder.nix)
../../misc/builder.nix
];
sops.defaultSopsFile = fp /secrets/bob/bob.yaml;
sops.defaultSopsFile = ../../secrets/bob/bob.yaml;
sops.age.sshKeyPaths = [ "/etc/ssh/ssh_host_ed25519_key" ];
sops.age.keyFile = "/var/lib/sops-nix/key.txt";
sops.age.generateKey = true;

View File

@ -1,10 +1,10 @@
{ config, fp, pkgs, values, ... }:
{ config, pkgs, values, ... }:
{
imports = [
# Include the results of the hardware scan.
./hardware-configuration.nix
(fp /base)
(fp /misc/metrics-exporters.nix)
../../base.nix
../../misc/metrics-exporters.nix
./services/grzegorz.nix
];

View File

@ -1,6 +1,6 @@
{ config, fp, ... }:
{ config, ... }:
{
imports = [ (fp /modules/grzegorz.nix) ];
imports = [ ../../../modules/grzegorz.nix ];
services.nginx.virtualHosts."${config.networking.fqdn}" = {
serverAliases = [

View File

@ -0,0 +1,42 @@
{ config, pkgs, values, ... }:
{
imports = [
./hardware-configuration.nix
../../base.nix
../../misc/metrics-exporters.nix
];
sops.defaultSopsFile = ../../secrets/buskerud/buskerud.yaml;
sops.age.sshKeyPaths = [ "/etc/ssh/ssh_host_ed25519_key" ];
sops.age.keyFile = "/var/lib/sops-nix/key.txt";
sops.age.generateKey = true;
# buskerud does not support efi?
# boot.loader.systemd-boot.enable = true;
# boot.loader.efi.canTouchEfiVariables = true;
boot.loader.grub.enable = true;
boot.loader.grub.device = "/dev/sdb";
networking.hostName = "buskerud";
networking.search = [ "pvv.ntnu.no" "pvv.org" ];
networking.nameservers = [ "129.241.0.200" "129.241.0.201" ];
networking.tempAddresses = "disabled";
systemd.network.networks."enp3s0f0" = values.defaultNetworkConfig // {
matchConfig.Name = "enp3s0f0";
address = with values.hosts.buskerud; [ (ipv4 + "/25") (ipv6 + "/64") ];
};
# List packages installed in system profile
environment.systemPackages = with pkgs; [
];
# This value determines the NixOS release from which the default
# settings for stateful data, like file locations and database versions
# on your system were taken. Its perfectly fine and recommended to leave
# this value at the release version of the first install of this system.
# Before changing this value read the documentation for this option
# (e.g. man configuration.nix or on https://nixos.org/nixos/options.html).
system.stateVersion = "23.05"; # Did you read the comment?
}

View File

@ -0,0 +1,37 @@
# 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, ... }:
{
imports =
[ (modulesPath + "/installer/scan/not-detected.nix")
];
boot.initrd.availableKernelModules = [ "uhci_hcd" "ehci_pci" "ata_piix" "hpsa" "usb_storage" "usbhid" "sd_mod" "sr_mod" ];
boot.initrd.kernelModules = [ ];
boot.kernelModules = [ "kvm-intel" ];
boot.extraModulePackages = [ ];
fileSystems."/" =
{ device = "/dev/disk/by-uuid/ed9654fe-575a-4fb3-b6ff-1b059479acff";
fsType = "ext4";
};
swapDevices = [ ];
# Enables DHCP on each ethernet and wireless interface. In case of scripted networking
# (the default) this is the recommended approach. When using systemd-networkd it's
# still possible to use this option, but it's recommended to use it in conjunction
# with explicit per-interface declarations with `networking.interfaces.<interface>.useDHCP`.
networking.useDHCP = lib.mkDefault true;
# networking.interfaces.enp14s0f0.useDHCP = lib.mkDefault true;
# networking.interfaces.enp14s0f1.useDHCP = lib.mkDefault true;
# networking.interfaces.enp3s0f0.useDHCP = lib.mkDefault true;
# networking.interfaces.enp3s0f1.useDHCP = lib.mkDefault true;
# networking.interfaces.enp4s0f0.useDHCP = lib.mkDefault true;
# networking.interfaces.enp4s0f1.useDHCP = lib.mkDefault true;
nixpkgs.hostPlatform = lib.mkDefault "x86_64-linux";
hardware.cpu.intel.updateMicrocode = lib.mkDefault config.hardware.enableRedistributableFirmware;
}

View File

@ -0,0 +1,21 @@
{config, ...}:
{
sops.secrets."bluemap_ssh_key" = {
owner = "root";
mode = "0400";
};
services.bluemap = {
enable = true;
eula = true;
defaultWorld = "/var/lib/bluemap/vanilla";
host = "minecraft.pvv.ntnu.no";
};
systemd.services."render-bluemap-maps".preStart = ''
rsync -e 'ssh -i ${config.sops.secrets."bluemap_ssh_key".path} -o "StrictHostKeyChecking accept-new"' \
root@innovation.pvv.ntnu.no:/var/backups/minecraft/current/ \
/var/lib/bluemap/vanilla"
'';
}

View File

@ -1,12 +1,12 @@
{ config, fp, pkgs, values, ... }:
{ config, pkgs, values, ... }:
{
imports = [
# Include the results of the hardware scan.
./hardware-configuration.nix
(fp /base)
(fp /misc/metrics-exporters.nix)
../../base.nix
../../misc/metrics-exporters.nix
(fp /modules/grzegorz.nix)
../../modules/grzegorz.nix
];
boot.loader.systemd-boot.enable = true;

View File

@ -1,16 +1,16 @@
{ config, fp, pkgs, lib, values, ... }:
{ config, pkgs, values, ... }:
{
imports = [
# Include the results of the hardware scan.
./hardware-configuration.nix
(fp /base)
(fp /misc/metrics-exporters.nix)
../../base.nix
../../misc/metrics-exporters.nix
./services/monitoring
./services/nginx
];
sops.defaultSopsFile = fp /secrets/ildkule/ildkule.yaml;
sops.defaultSopsFile = ../../secrets/ildkule/ildkule.yaml;
sops.age.sshKeyPaths = [ "/etc/ssh/ssh_host_ed25519_key" ];
sops.age.keyFile = "/var/lib/sops-nix/key.txt";
sops.age.generateKey = true;
@ -19,37 +19,17 @@
boot.tmp.cleanOnBoot = true;
zramSwap.enable = true;
# Openstack Neutron and systemd-networkd are not best friends, use something else:
systemd.network.enable = lib.mkForce false;
networking = let
hostConf = values.hosts.ildkule;
in {
hostName = "ildkule";
tempAddresses = "disabled";
useDHCP = lib.mkForce true;
search = values.defaultNetworkConfig.domains;
nameservers = values.defaultNetworkConfig.dns;
defaultGateway.address = hostConf.ipv4_internal_gw;
interfaces."ens4" = {
ipv4.addresses = [
{ address = hostConf.ipv4; prefixLength = 32; }
{ address = hostConf.ipv4_internal; prefixLength = 24; }
];
ipv6.addresses = [
{ address = hostConf.ipv6; prefixLength = 64; }
];
};
networking.hostName = "ildkule"; # Define your hostname.
systemd.network.networks."30-all" = values.defaultNetworkConfig // {
matchConfig.Name = "en*";
DHCP = "yes";
gateway = [ ];
};
# List packages installed in system profile
environment.systemPackages = with pkgs; [
];
# No devices with SMART
services.smartd.enable = false;
system.stateVersion = "23.11"; # Did you read the comment?
}

View File

@ -3,14 +3,7 @@
imports = [ (modulesPath + "/profiles/qemu-guest.nix") ];
boot.initrd.availableKernelModules = [ "ata_piix" "uhci_hcd" "xen_blkfront" "vmw_pvscsi" ];
boot.initrd.kernelModules = [ "nvme" ];
fileSystems."/" = {
device = "/dev/disk/by-uuid/e35eb4ce-aac3-4f91-8383-6e7cd8bbf942";
fsType = "ext4";
};
fileSystems."/data" = {
device = "/dev/disk/by-uuid/0a4c1234-02d3-4b53-aeca-d95c4c8d534b";
fsType = "ext4";
};
fileSystems."/" = { device = "/dev/vda1"; fsType = "ext4"; };
networking.useDHCP = lib.mkDefault true;
}

View File

@ -34,13 +34,13 @@ in {
{
name = "Ildkule Prometheus";
type = "prometheus";
url = "http://${config.services.prometheus.listenAddress}:${toString config.services.prometheus.port}";
isDefault = true;
url = ("http://${config.services.prometheus.listenAddress}:${toString config.services.prometheus.port}");
isDefault = true;
}
{
name = "Ildkule loki";
type = "loki";
url = "http://${config.services.loki.configuration.server.http_listen_address}:${toString config.services.loki.configuration.server.http_listen_port}";
url = ("http://${config.services.loki.configuration.server.http_listen_address}:${toString config.services.loki.configuration.server.http_listen_port}");
}
];
dashboards.settings.providers = [
@ -56,13 +56,13 @@ in {
url = "https://raw.githubusercontent.com/matrix-org/synapse/develop/contrib/grafana/synapse.json";
options.path = dashboards/synapse.json;
}
# TODO: enable once https://github.com/NixOS/nixpkgs/pull/242365 gets merged
# {
# name = "MySQL";
# type = "file";
# url = "https://raw.githubusercontent.com/prometheus/mysqld_exporter/main/mysqld-mixin/dashboards/mysql-overview.json";
# options.path = dashboards/mysql.json;
# }
# TODO: enable once https://github.com/NixOS/nixpkgs/pull/242365 gets merged
# {
# name = "MySQL";
# type = "file";
# url = "https://raw.githubusercontent.com/prometheus/mysqld_exporter/main/mysqld-mixin/dashboards/mysql-overview.json";
# options.path = dashboards/mysql.json;
# }
{
name = "Postgresql";
type = "file";
@ -75,12 +75,6 @@ in {
url = "https://grafana.com/api/dashboards/240/revisions/3/download";
options.path = dashboards/go-processes.json;
}
{
name = "Gitea Dashbaord";
type = "file";
url = "https://grafana.com/api/dashboards/17802/revisions/3/download";
options.path = dashboards/gitea-dashbaord.json;
}
];
};

View File

@ -2,7 +2,6 @@
let
cfg = config.services.loki;
stateDir = "/data/monitoring/loki";
in {
services.loki = {
enable = true;
@ -17,7 +16,7 @@ in {
ingester = {
wal = {
enabled = true;
dir = "${stateDir}/wal";
dir = "/var/lib/loki/wal";
};
lifecycler = {
address = "127.0.0.1";
@ -49,30 +48,33 @@ in {
storage_config = {
boltdb_shipper = {
active_index_directory = "${stateDir}/boltdb-shipper-index";
cache_location = "${stateDir}/boltdb-shipper-cache";
active_index_directory = "/var/lib/loki/boltdb-shipper-index";
cache_location = "/var/lib/loki/boltdb-shipper-cache";
# shared_store = "filesystem";
cache_ttl = "24h";
};
filesystem = {
directory = "${stateDir}/chunks";
directory = "/var/lib/loki/chunks";
};
};
limits_config = {
allow_structured_metadata = false;
# enforce_metric_name = false;
reject_old_samples = true;
reject_old_samples_max_age = "72h";
};
compactor = {
working_directory = "${stateDir}/compactor";
working_directory = "/var/lib/loki/compactor";
# shared_store = "filesystem";
};
# ruler = {
# storage = {
# type = "local";
# local = {
# directory = "${stateDir}/rules";
# directory = "/var/lib/loki/rules";
# };
# };
# rule_path = "/etc/loki/rules";

View File

@ -1,26 +1,18 @@
{ config, ... }: let
stateDir = "/data/monitoring/prometheus";
in {
{ config, ... }: {
imports = [
./gitea.nix
./gogs.nix
./matrix-synapse.nix
# TODO: enable once https://github.com/NixOS/nixpkgs/pull/242365 gets merged
# ./mysqld.nix
./node.nix
./postgres.nix
./machines.nix
];
services.prometheus = {
enable = true;
listenAddress = "127.0.0.1";
port = 9001;
ruleFiles = [ rules/synapse-v2.rules ];
};
fileSystems."/var/lib/prometheus2" = {
device = stateDir;
options = [ "bind" ];
};
}

View File

@ -1,16 +0,0 @@
{ ... }:
{
services.prometheus.scrapeConfigs = [{
job_name = "gitea";
scrape_interval = "60s";
scheme = "https";
static_configs = [
{
targets = [
"git.pvv.ntnu.no:443"
];
}
];
}];
}

View File

@ -0,0 +1,16 @@
{ config, ... }: let
cfg = config.services.prometheus;
in {
services.prometheus.scrapeConfigs = [{
job_name = "git-gogs";
scheme = "https";
metrics_path = "/-/metrics";
static_configs = [
{
targets = [
"essendrop.pvv.ntnu.no:443"
];
}
];
}];
}

View File

@ -1,54 +0,0 @@
{ config, ... }: let
cfg = config.services.prometheus;
in {
services.prometheus.scrapeConfigs = [{
job_name = "base_info";
static_configs = [
{ labels.hostname = "ildkule";
targets = [
"ildkule.pvv.ntnu.no:${toString cfg.exporters.node.port}"
"ildkule.pvv.ntnu.no:${toString cfg.exporters.systemd.port}"
];
}
{ labels.hostname = "bekkalokk";
targets = [
"bekkalokk.pvv.ntnu.no:9100"
"bekkalokk.pvv.ntnu.no:9101"
];
}
{ labels.hostname = "bicep";
targets = [
"bicep.pvv.ntnu.no:9100"
"bicep.pvv.ntnu.no:9101"
];
}
{ labels.hostname = "brzeczyszczykiewicz";
targets = [
"brzeczyszczykiewicz.pvv.ntnu.no:9100"
"brzeczyszczykiewicz.pvv.ntnu.no:9101"
];
}
{ labels.hostname = "georg";
targets = [
"georg.pvv.ntnu.no:9100"
"georg.pvv.ntnu.no:9101"
];
}
{ labels.hostname = "hildring";
targets = [
"hildring.pvv.ntnu.no:9100"
];
}
{ labels.hostname = "isvegg";
targets = [
"isvegg.pvv.ntnu.no:9100"
];
}
{ labels.hostname = "microbel";
targets = [
"microbel.pvv.ntnu.no:9100"
];
}
];
}];
}

View File

@ -0,0 +1,22 @@
{ config, ... }: let
cfg = config.services.prometheus;
in {
services.prometheus.scrapeConfigs = [{
job_name = "node";
static_configs = [
{
targets = [
"ildkule.pvv.ntnu.no:${toString cfg.exporters.node.port}"
"microbel.pvv.ntnu.no:9100"
"isvegg.pvv.ntnu.no:9100"
"knakelibrak.pvv.ntnu.no:9100"
"hildring.pvv.ntnu.no:9100"
"bicep.pvv.ntnu.no:9100"
"essendrop.pvv.ntnu.no:9100"
"andresbu.pvv.ntnu.no:9100"
"bekkalokk.pvv.ntnu.no:9100"
];
}
];
}];
}

View File

@ -2,7 +2,6 @@
let
cfg = config.services.uptime-kuma;
domain = "status.pvv.ntnu.no";
stateDir = "/data/monitoring/uptime-kuma";
in {
services.uptime-kuma = {
enable = true;
@ -18,9 +17,4 @@ in {
kTLS = true;
locations."/".proxyPass = "http://${cfg.settings.HOST}:${cfg.settings.PORT}";
};
fileSystems."/var/lib/uptime-kuma" = {
device = stateDir;
options = [ "bind" ];
};
}

View File

@ -1,13 +1,13 @@
{ config, fp, pkgs, values, ... }:
{ config, pkgs, values, ... }:
{
imports = [
# Include the results of the hardware scan.
./hardware-configuration.nix
(fp /base)
(fp /misc/metrics-exporters.nix)
../../base.nix
../../misc/metrics-exporters.nix
];
sops.defaultSopsFile = fp /secrets/shark/shark.yaml;
sops.defaultSopsFile = ../../secrets/shark/shark.yaml;
sops.age.sshKeyPaths = [ "/etc/ssh/ssh_host_ed25519_key" ];
sops.age.keyFile = "/var/lib/sops-nix/key.txt";
sops.age.generateKey = true;

View File

@ -1,25 +0,0 @@
export GUM_FILTER_HEIGHT := "15"
nom := `if command -v nom >/dev/null; then echo nom; else echo nix; fi`
@_default:
just "$(gum choose --ordered --header "Pick a recipie..." $(just --summary --unsorted))"
check:
nix flake check --keep-going
build-machine machine=`just _a_machine`:
{{nom}} build .#nixosConfigurations.{{ machine }}.config.system.build.toplevel
run-vm machine=`just _a_machine`:
nixos-rebuild build-vm --flake .#{{ machine }}
QEMU_NET_OPTS="hostfwd=tcp::8080-:80,hostfwd=tcp::8081-:443,hostfwd=tcp::2222-:22" ./result/bin/run-*-vm
@update-inputs:
nix eval .#inputs --apply builtins.attrNames --json \
| jq '.[]' -r \
| gum choose --no-limit --height=15 \
| xargs -L 1 nix flake lock --update-input
_a_machine:
nix eval .#nixosConfigurations --apply builtins.attrNames --json | jq .[] -r | gum filter

View File

@ -14,31 +14,13 @@
"::1"
values.hosts.ildkule.ipv4
values.hosts.ildkule.ipv6
values.hosts.ildkule.ipv4_global
values.hosts.ildkule.ipv6_global
];
};
services.prometheus.exporters.systemd = {
enable = true;
port = 9101;
extraFlags = [
"--systemd.collector.enable-restart-count"
"--systemd.collector.enable-ip-accounting"
];
};
systemd.services.prometheus-systemd-exporter.serviceConfig = {
IPAddressDeny = "any";
IPAddressAllow = [
"127.0.0.1"
"::1"
values.hosts.ildkule.ipv4
values.hosts.ildkule.ipv6
];
};
networking.firewall.allowedTCPPorts = [ 9100 9101 ];
networking.firewall.allowedTCPPorts = [ 9100 ];
services.promtail = {
enable = true;

View File

@ -1,26 +1,31 @@
{config, lib, pkgs, ...}:
let
grg = config.services.greg-ng;
grg = config.services.grzegorz;
grgw = config.services.grzegorz-webui;
in {
services.greg-ng = {
enable = true;
settings.host = "localhost";
settings.port = 31337;
enableSway = true;
enablePipewire = true;
services.pipewire.enable = true;
services.pipewire.alsa.enable = true;
services.pipewire.alsa.support32Bit = true;
services.pipewire.pulse.enable = true;
users.users.pvv = {
isNormalUser = true;
description = "pvv";
};
services.grzegorz-webui = {
enable = true;
listenAddr = "localhost";
listenPort = 42069;
listenWebsocketPort = 42042;
hostName = "${config.networking.fqdn}";
apiBase = "http://${grg.settings.host}:${toString grg.settings.port}/api";
};
services.grzegorz.enable = true;
services.grzegorz.listenAddr = "localhost";
services.grzegorz.listenPort = 31337;
services.grzegorz-webui.enable = true;
services.grzegorz-webui.listenAddr = "localhost";
services.grzegorz-webui.listenPort = 42069;
services.grzegorz-webui.listenWebsocketPort = 42042;
services.grzegorz-webui.hostName = "${config.networking.fqdn}";
services.grzegorz-webui.apiBase = "http://${toString grg.listenAddr}:${toString grg.listenPort}/api";
services.nginx.enable = true;
services.nginx.virtualHosts."${config.networking.fqdn}" = {
forceSSL = true;
enableACME = true;
@ -35,19 +40,20 @@ in {
'';
locations."/" = {
proxyPass = "http://${grgw.listenAddr}:${toString grgw.listenPort}";
proxyPass = "http://localhost:${builtins.toString config.services.grzegorz-webui.listenPort}";
};
# https://github.com/rawpython/remi/issues/216
locations."/websocket" = {
proxyPass = "http://${grgw.listenAddr}:${toString grgw.listenWebsocketPort}";
proxyPass = "http://localhost:${builtins.toString config.services.grzegorz-webui.listenWebsocketPort}";
proxyWebsockets = true;
};
locations."/api" = {
proxyPass = "http://${grg.settings.host}:${toString grg.settings.port}";
proxyPass = "http://localhost:${builtins.toString config.services.grzegorz.listenPort}";
};
locations."/docs" = {
proxyPass = "http://${grg.settings.host}:${toString grg.settings.port}";
proxyPass = "http://localhost:${builtins.toString config.services.grzegorz.listenPort}";
};
};
}

View File

@ -36,10 +36,10 @@ in
type = lib.types.str;
default = "${name}.key";
};
subject = lib.mkOption {
type = lib.types.str;
default = "/C=NO/O=Programvareverkstedet/CN=*.pvv.ntnu.no/emailAddress=drift@pvv.ntnu.no";
};
subject = lib.mkOption {
type = lib.types.str;
default = "/C=NO/O=Programvareverkstedet/CN=*.pvv.ntnu.no/emailAddress=drift@pvv.ntnu.no";
};
};
}));
};
@ -50,27 +50,25 @@ in
serviceConfig.Type = "oneshot";
script = let
openssl = lib.getExe pkgs.openssl;
in lib.concatMapStringsSep "\n" ({ name, value }: ''
in lib.concatMapStringsSep "\n----------------\n" ({ name, value }: ''
mkdir -p $(dirname "${value.certificate}") $(dirname "${value.certificateKey}")
if ! ${openssl} x509 -checkend 86400 -noout -in ${value.certificate}
then
echo "Regenerating '${value.certificate}'"
${openssl} req \
-newkey rsa:4096 \
-new -x509 \
-days "${toString value.daysValid}" \
-nodes \
-subj "${value.subject}" \
-out "${value.certificate}" \
-keyout "${value.certificateKey}" \
${lib.escapeShellArgs value.extraOpenSSLArgs}
echo "Regenerating '${value.certificate}'"
${openssl} req \
-newkey rsa:4096 \
-new -x509 \
-days "${toString value.daysValid}" \
-nodes \
-subj "${value.subject}" \
-out "${value.certificate}" \
-keyout "${value.certificateKey}" \
${lib.escapeShellArgs value.extraOpenSSLArgs}
fi
chown "${value.owner}:${value.group}" "${value.certificate}"
chown "${value.owner}:${value.group}" "${value.certificateKey}"
chmod "${value.mode}" "${value.certificate}"
chmod "${value.mode}" "${value.certificateKey}"
echo "\n-----------------\n"
'') (lib.attrsToList cfg);
};
systemd.timers."generate-snakeoil-certs" = {

View File

@ -1,30 +0,0 @@
{ lib, stdenvNoCC, fetchurl, makeWrapper, jre }:
stdenvNoCC.mkDerivation rec {
pname = "bluemap";
version = "5.2";
src = fetchurl {
url = "https://github.com/BlueMap-Minecraft/BlueMap/releases/download/v${version}/BlueMap-${version}-cli.jar";
hash = "sha256-4vld+NBwzBxdwbMtsKuqvO6immkbh4HB//6wdjXaxoU=";
};
dontUnpack = true;
nativeBuildInputs = [ makeWrapper ];
installPhase = ''
runHook preInstall
makeWrapper ${jre}/bin/java $out/bin/bluemap --add-flags "-jar $src"
runHook postInstall
'';
meta = {
description = "3D minecraft map renderer";
homepage = "https://bluemap.bluecolored.de/";
sourceProvenance = with lib.sourceTypes; [ binaryBytecode ];
license = lib.licenses.mit;
maintainers = with lib.maintainers; [ dandellion ];
mainProgram = "bluemap";
};
}

View File

@ -1,95 +1,8 @@
{ pkgs, lib }:
let
kebab-case-name = project-name: lib.pipe project-name [
(builtins.replaceStrings
lib.upperChars
(map (x: "-${x}") lib.lowerChars)
)
(lib.removePrefix "-")
];
mw-ext = {
name
, commit
, hash
, tracking-branch ? "REL1_41"
, kebab-name ? kebab-case-name name
, fetchgit ? pkgs.fetchgit
}:
{
${name} = (fetchgit {
name = "mediawiki-${kebab-name}-source";
url = "https://gerrit.wikimedia.org/r/mediawiki/extensions/${name}";
rev = commit;
inherit hash;
}).overrideAttrs (_: {
passthru = { inherit name kebab-name tracking-branch; };
});
};
in
# NOTE: to add another extension, you can add an mw-ext expression
# with an empty (or even wrong) commit and empty hash, and
# run the update script
lib.mergeAttrsList [
(mw-ext {
name = "CodeEditor";
commit = "7d8447035e381d76387e38b92e4d1e2b8d373a01";
hash = "sha256-v2AlbP0vZma3qZyEAWGjZ/rLcvOpIMroyc1EixKjlAU=";
})
(mw-ext {
name = "CodeMirror";
commit = "a7b4541089f9b88a0b722d9d790e4cf0f13aa328";
hash = "sha256-clyzN3v3+J4GjdyhrCsytBrH7VR1tq5yd0rB+32eWCg=";
})
(mw-ext {
name = "DeleteBatch";
commit = "cad869fbd95637902673f744581b29e0f3e3f61a";
hash = "sha256-M1ek1WdO1/uTjeYlrk3Tz+nlb/fFZH+O0Ok7b10iKak=";
})
(mw-ext {
name = "PluggableAuth";
commit = "4111a57c34e25bde579cce5d14ea094021e450c8";
hash = "sha256-aPtN8A9gDxLlq2+EloRZBO0DfHtE0E5kbV/adk82jvM=";
})
(mw-ext {
name = "Popups";
commit = "f1bcadbd8b868f32ed189feff232c47966c2c49e";
hash = "sha256-PQAjq/X4ZYwnnZ6ADCp3uGWMIucJy0ZXxsTTbAyxlSE=";
})
(mw-ext {
name = "Scribunto";
commit = "7b99c95f588b06635ee3c487080d6cb04617d4b5";
hash = "sha256-pviueRHQAsSlv4AtnUpo2Cjci7CbJ5aM75taEXY+WrI=";
})
(mw-ext {
name = "SimpleSAMLphp";
kebab-name = "simple-saml-php";
commit = "ecb47191fecd1e0dc4c9d8b90a9118e393d82c23";
hash = "sha256-gKu+O49XrAVt6hXdt36Ru7snjsKX6g2CYJ0kk/d+CI8=";
})
(mw-ext {
name = "TemplateData";
commit = "1ec66ce80f8a4322138efa56864502d0ee069bad";
hash = "sha256-Lv3Lq9dYAtdgWcwelveTuOhkP38MTu0m5kmW8+ltRis=";
})
(mw-ext {
name = "TemplateStyles";
commit = "581180e898d6a942e2a65c8f13435a5d50fffa67";
hash = "sha256-zW8O0mzG4jYfQoKi2KzsP+8iwRCLnWgH7qfmDE2R+HU=";
})
(mw-ext {
name = "UserMerge";
commit = "c17c919bdb9b67bb69f80df43e9ee9d33b1ecf1b";
hash = "sha256-+mkzTCo8RVlGoFyfCrSb5YMh4J6Pbi1PZLFu5ps8bWY=";
})
(mw-ext {
name = "VisualEditor";
commit = "90bb3d455892e25317029ffd4bda93159e8faac8";
hash = "sha256-SZAVELQUKZtwSM6NVlxvIHdFPodko8fhZ/uwB0LCFDA=";
})
(mw-ext {
name = "WikiEditor";
commit = "8dba5b13246d7ae09193f87e6273432b3264de5f";
hash = "sha256-vF9PBuM+VfOIs/a2X1JcPn6WH4GqP/vUJDFkfXzWyFU=";
})
]
{
DeleteBatch = pkgs.callPackage ./delete-batch { };
PluggableAuth = pkgs.callPackage ./pluggable-auth { };
SimpleSAMLphp = pkgs.callPackage ./simple-saml-php { };
UserMerge = pkgs.callPackage ./user-merge { };
VisualEditor = pkgs.callPackage ./visual-editor { };
}

View File

@ -0,0 +1,13 @@
{ fetchzip }:
let
commit = "a53af3b8269ed19ede3cf1fa811e7ec8cb00af92";
project-name = "UserMerge";
tracking-branch = "REL1_41";
in
fetchzip {
name = "mediawiki-delete-batch";
url = "https://gerrit.wikimedia.org/r/plugins/gitiles/mediawiki/extensions/${project-name}/+archive/${commit}.tar.gz";
hash = "sha256-0ofCZhhv4aVTGq469Fdu7k0oVQu3kG3HFa8zaBbUr/M=";
stripRoot = false;
passthru = { inherit project-name tracking-branch; };
}

View File

@ -0,0 +1,13 @@
{ fetchzip }:
let
commit = "d5b3ad8f03b65d3746e025cdd7fe3254ad6e4026";
project-name = "PluggableAuth";
tracking-branch = "REL1_41";
in
fetchzip {
name = "mediawiki-pluggable-auth-source";
url = "https://gerrit.wikimedia.org/r/plugins/gitiles/mediawiki/extensions/${project-name}/+archive/${commit}.tar.gz";
hash = "sha256-mLepavgeaNUGYxrrCKVpybGO2ecjc3B5IU8q+gZTx2U=";
stripRoot = false;
passthru = { inherit project-name tracking-branch; };
}

View File

@ -0,0 +1,13 @@
{ fetchzip }:
let
commit = "9ae0678d77a9175285a1cfadd5adf28379dbdb3d";
project-name = "SimpleSAMLphp";
tracking-branch = "REL1_41";
in
fetchzip {
name = "mediawiki-simple-saml-php-source";
url = "https://gerrit.wikimedia.org/r/plugins/gitiles/mediawiki/extensions/${project-name}/+archive/${commit}.tar.gz";
hash = "sha256-s6Uw1fNzGBF0HEMl0LIRLhJkOHugrCE0aTnqawYi/pE=";
stripRoot = false;
passthru = { inherit project-name tracking-branch; };
}

View File

@ -1,5 +1,5 @@
#!/usr/bin/env nix-shell
#!nix-shell -i python3 -p "python3.withPackages(ps: with ps; [ beautifulsoup4 requests ])" nix-prefetch-git
#!nix-shell -i python3 -p "python3.withPackages(ps: with ps; [ beautifulsoup4 requests ])"
import os
from pathlib import Path
@ -8,148 +8,99 @@ import subprocess
from collections import defaultdict
from pprint import pprint
from dataclasses import dataclass
from functools import cache
import json
import bs4
import requests
BASE_WEB_URL = "https://gerrit.wikimedia.org/r/plugins/gitiles/mediawiki/extensions"
BASE_GIT_URL = "https://gerrit.wikimedia.org/r/mediawiki/extensions/"
BASE_URL = "https://gerrit.wikimedia.org/r/plugins/gitiles/mediawiki/extensions"
@dataclass
class PluginMetadata:
project_name: str
tracking_branch: str | None
tracking_branch: str
commit: str
hash_: str
@cache
def get_package_listing_path():
return Path(__file__).parent / "default.nix"
@cache
def get_global_tracking_branch() -> str:
with open(get_package_listing_path()) as file:
file_content = file.read()
return re.search(r'\btracking-branch\b \? "([^"]+?)"', file_content).group(1)
def get_metadata(package_expression: str) -> PluginMetadata | None:
project_name_search = re.search(r'\bname\b = "([^"]+?)";', package_expression)
tracking_branch_search = re.search(r'\btracking-branch\b = "([^"]+?)";', package_expression)
commit_search = re.search(r'\bcommit\b = "([^"]*?)";', package_expression)
hash_search = re.search(r'\bhash\b = "([^"]*?)";', package_expression)
if project_name_search is None:
print("Could not find project name in package:")
print(package_expression)
return None
tracking_branch = None;
if tracking_branch_search is not None:
tracking_branch = tracking_branch_search.group(1)
def get_metadata(file_content: str) -> dict[str,str] | None:
commit_search = re.search(f'commit = "([^"]*?)";', file_content)
tracking_branch_search = re.search(f'tracking-branch = "([^"]+?)";', file_content)
project_name_search = re.search(f'project-name = "([^"]+?)";', file_content)
if commit_search is None:
print("Could not find commit in package:")
print(package_expression)
print("Could not find commit in file:")
print(file_content)
return None
if hash_search is None:
print("Could not find hash in package:")
print(package_expression)
if tracking_branch_search is None:
print("Could not find tracking branch in file:")
print(file_content)
return None
if project_name_search is None:
print("Could not find project name in file:")
print(file_content)
return None
return PluginMetadata(
commit = commit_search.group(1),
tracking_branch = tracking_branch,
tracking_branch = tracking_branch_search.group(1),
project_name = project_name_search.group(1),
hash_ = hash_search.group(1),
)
def update_metadata(package_expression: str, metadata: PluginMetadata) -> str:
result = package_expression
result = re.sub(r'\bcommit\b = "[^"]*";', f'commit = "{metadata.commit}";', result)
result = re.sub(r'\bhash\b = "[^"]*";', f'hash = "{metadata.hash_}";', result)
return result
def get_newest_commit(project_name: str, tracking_branch: str) -> str:
content = requests.get(f"{BASE_WEB_URL}/{project_name}/+log/refs/heads/{tracking_branch}/").text
content = requests.get(f"{BASE_URL}/{project_name}/+log/refs/heads/{tracking_branch}/").text
soup = bs4.BeautifulSoup(content, features="html.parser")
try:
a = soup.find('li').findChild('a')
commit_sha = a['href'].split('/')[-1]
except AttributeError:
print(f"ERROR: Could not parse page for {project_name}:")
print(soup.prettify())
exit(1)
a = soup.find('li').findChild('a')
commit_sha = a['href'].split('/')[-1]
return commit_sha
def get_nix_hash(url: str, commit: str) -> str:
def get_nix_hash(tar_gz_url: str) -> str:
out, err = subprocess.Popen(
["nix-prefetch-git", "--url", url, "--rev", commit, "--fetch-submodules", "--quiet"],
["nix-prefetch-url", "--unpack", "--type", "sha256", tar_gz_url],
stdout=subprocess.PIPE,
stderr=subprocess.PIPE
).communicate()
out, err = subprocess.Popen(
["nix", "hash", "to-sri", "--type", "sha256", out.decode().strip()],
stdout=subprocess.PIPE,
stderr=subprocess.PIPE
).communicate()
return json.loads(out.decode().strip())['hash']
return out.decode().strip()
def update_expression(package_expression: str) -> str:
old_metadata = get_metadata(package_expression)
if old_metadata is None:
print("ERROR: could not find metadata for expression:")
print(package_expression)
return
def set_commit_and_hash(file_content: str, commit: str, sha256: str) -> str:
result = file_content
result = re.sub('commit = "[^"]*";', f'commit = "{commit}";', result)
result = re.sub('hash = "[^"]*";', f'hash = "{sha256}";', result)
return result
if old_metadata.commit == "":
old_metadata.commit = "<none>"
if old_metadata.hash_ == "":
old_metadata.hash_ = "<none>"
tracking_branch = old_metadata.tracking_branch
if tracking_branch is None:
tracking_branch = get_global_tracking_branch()
new_commit = get_newest_commit(old_metadata.project_name, tracking_branch)
new_hash = get_nix_hash(f"{BASE_GIT_URL}/{old_metadata.project_name}", new_commit)
if new_hash is None or new_hash == "":
print(f"ERROR: could not fetch hash for {old_metadata.project_name}")
exit(1)
print(f"Updating {old_metadata.project_name}[{tracking_branch}]: {old_metadata.commit} -> {new_commit}")
new_metadata = PluginMetadata(
project_name = old_metadata.project_name,
tracking_branch = old_metadata.tracking_branch,
commit = new_commit,
hash_ = new_hash,
)
return update_metadata(package_expression, new_metadata)
def update_all_expressions_in_default_nix() -> None:
with open(get_package_listing_path()) as file:
def update(package_file: Path) -> None:
with open(package_file) as file:
file_content = file.read()
new_file_content = re.sub(
r"\(mw-ext\s*\{(?:.|\n)+?\}\)",
lambda m: update_expression(m.group(0)),
file_content,
flags = re.MULTILINE,
)
metadata = get_metadata(file_content)
if metadata is None:
return
if metadata.commit == "":
metadata.commit = "<none>"
with open(get_package_listing_path(), 'w') as file:
new_commit = get_newest_commit(metadata.project_name, metadata.tracking_branch)
if new_commit == metadata.commit:
return
new_url = f"{BASE_URL}/{metadata.project_name}/+archive/{new_commit}.tar.gz"
new_hash = get_nix_hash(new_url)
print(f"Updating {metadata.project_name}: {metadata.commit} -> {new_commit}")
new_file_content = set_commit_and_hash(file_content, new_commit, new_hash)
with open(package_file, 'w') as file:
file.write(new_file_content)
if __name__ == "__main__":
update_all_expressions_in_default_nix()
for direntry in os.scandir(Path(__file__).parent):
if direntry.is_dir():
package_file = Path(direntry) / "default.nix"
assert package_file.is_file()
update(package_file)

View File

@ -0,0 +1,13 @@
{ fetchzip }:
let
commit = "a53af3b8269ed19ede3cf1fa811e7ec8cb00af92";
project-name = "UserMerge";
tracking-branch = "REL1_41";
in
fetchzip {
name = "mediawiki-user-merge-source";
url = "https://gerrit.wikimedia.org/r/plugins/gitiles/mediawiki/extensions/${project-name}/+archive/${commit}.tar.gz";
hash = "sha256-0ofCZhhv4aVTGq469Fdu7k0oVQu3kG3HFa8zaBbUr/M=";
stripRoot = false;
passthru = { inherit project-name tracking-branch; };
}

View File

@ -0,0 +1,13 @@
{ fetchzip }:
let
commit = "bb92d4b0bb81cebd73a3dbabfb497213dac349f2";
project-name = "VisualEditor";
tracking-branch = "REL1_40";
in
fetchzip {
name = "mediawiki-visual-editor-source";
url = "https://gerrit.wikimedia.org/r/plugins/gitiles/mediawiki/extensions/${project-name}/+archive/${commit}.tar.gz";
hash = "sha256-lShpSoR+NLfdd5i7soM6J40pq+MzCMG0M1tSYsS+jAg=";
stripRoot = false;
passthru = { inherit project-name tracking-branch; };
}

View File

@ -29,7 +29,7 @@ php.buildComposerProject rec {
mkdir -p $(dirname "${target_path}")
cp -r "${source_path}" "${target_path}"
''))
lib.concatLines
(lib.concatStringsSep "\n")
];
postInstall = ''

View File

@ -1,13 +1,10 @@
gitea:
web-secret-provider:
token: ENC[AES256_GCM,data:pHmBKxrNcLifl4sjR44AGEElfdachja35Tl/InsqvBWturaeTv4R0w==,iv:emBWfXQs2VNqtpDp5iA5swNC+24AWDYYXo6nvN+Fwx4=,tag:lkhSVSs6IqhHpfDPOX0wQA==,type:str]
password: ENC[AES256_GCM,data:hlNzdU1ope0t50/3aztyLeXjMHd2vFPpwURX+Iu8f49DOqgSnEMtV+KtLA==,iv:qljRnSnchL5cFmaUAfCH9GQYQxcy5cyWejgk1x6bFgI=,tag:tIhboFU5kZsj5oAQR3hLbw==,type:str]
database: ENC[AES256_GCM,data:UlS33IdCEyeSvT6ngpmnkBWHuSEqsB//DT+3b7C+UwbD8UXWJlsLf1X8/w==,iv:mPRW5ldyZaHP+y/0vC2JGSLZmlkhgmkvXPk4LazkSDs=,tag:gGk6Z/nbPvzE1zG+tJC8Sw==,type:str]
email-password: ENC[AES256_GCM,data:KRwC+aL1aPvJuXt91Oq1ttATMnFTnuUy,iv:ats8TygB/2pORkaTZzPOLufZ9UmvVAKoRcWNvYF1z6w=,tag:Do0fA+4cZ3+l7JJyu8hjBg==,type:str]
passwd-ssh-key: ENC[AES256_GCM,data:L0lF0wvpayss1NU9m3A45cH0bCMQzODTFVrq6EPd1JHx54wIcoaRBYLmxXKXASzBlCg9zlwXMUIk3OQcS3kdzMKL0iqcSL2iicAcKjFIHyrWLqXgwV5pRSP/tRPcVw8KW8gz0bh33EgESs5ReddZ3VZ0Cy1s2YupMRQvBXr89k1+Hv70OWB6P06hvxhv/zKcMGI1N/dWLroMgrQuT9imw4+/Q1RqwzTYeEU+eUn24AM9GjcBg4qf3OI+6g0nXUat/upIYE28iF5J3lbUSmDSmirBLc8xgHLdOyyJPTObWYWYxlSL78T7IqiMm9lI3rtBlpJDDcn/YxZpVqN5bg2154GISNK+uR0TVSLdJ+drdGHIfIX3G78XSxf2L9rbJyRn8MQlgStfdBIQicLavQKVMrmj+XQfvEMez23WbPLjH4oViBQFI+GrOHOGy/f16cz8Sn4n+69OcsOeTxs3tKYdfq6r1XLYSJ/fe/zvxBpaZiyGXljsuyEdIyBL2A8D6uSXe3Nd3/DAdBtceFfIdN1olCdutixzVWgxaJnrel161z5A/4w=,iv:Uy46yY3jFYSvpxrgCHxRMUksnWfhf5DViLMvCXVMMl4=,tag:wFEJ5+icFrOKkc56gY0A5g==,type:str]
gpg-signing-key: ENC[AES256_GCM,data:y/g1rpsEgiGEJ9BGii6te166ABpg1jgsyYMT1Ji5njLbT8/juBBMc7BFEM5BcIxKpQGijymsB+Htl8CZAN4Bl3FHSRyrnXGuMCnveJfw1qTVjMa6soriHv7EdTDFPCp3TYMbs1OgY/bhGJIvp8e4hCVd4F3x8eAlFmiwHhkxr62qQNHjH7SRNIyUNibf/TTttOeEcercxOy7FeUE99D+CWG4pnJNEYyRHDdddalgpSJyZIJvPpXoKmeCDk3futnxiZ15Vr7bDS5u4dqnE+no7DKoZ5fvk38f/77JH3w/Qom7NCYSG6L+unJ3r3RKuuGMRDjdz09TPZ4APpmrlyOElfGMmm134g6mdhgXmwNCo65Z7VOd1OKFA/uyZm2b7XsT3tCgRalE8gBa0R3MBMi3JK+5KUdS6ZUvYXDt8D8C68ldM3K9E7lyeeHn775rV6L4JIXcj/NL1O23sXtjeVuUPQmsUesgYlllRaiTSTfY7K+yOIG3wqqCuCDSAeILQICkvod4iw4xdVMQzd8eQtbD6bCjOzHwvBcu+rOSN6ti+xOQ7bJ9+6xhCgJJsiADkp2q09cUu8mDbUh+YJxfu+oZhPomOJVDMSqfS4qNXcVM9mbak/L9KPR4b83GqTpmXHnDMlGe4BHGXrkIUKPsBQ5TmdckXbpRDBQFrnjVvFT+Gfx3xwHxWc9fbxcFID2wp69EzQrGC77bDPCFxBT5vAVwffGYUezPQEo25bKRpCWxTFTpiIQfACrwzZc/O9cmwDgrYN7bTZyrrp8cbyBtllZGYmXxLDkDOzIqzpLG3b0yJC2jSnw0f1DkU6M2mD/j9FRTVW1MVymyLPiZQ7T9QyZ3MekHEEY1QqmyiJMIOekSzC5+3Us6Nl32MeBrIry6NuV8ewIQF5bcZEHtSmZ0k/wBtK0fpFHUuc/vETFuRUiQw/InhN5W8iH78vFvflxBfg61Qp7PzEx0k0axwEc6VAKbEg/uFNL+fhUKKt7sYiEBmwg2Vsj3pyZgdmjPZEsOQ86+psaxv+2feH94wog47jDHFRrc4iRC5w7kZ6UJXHfZt9lkBbwl4qNwiOLlPnUUcR+CpTBpPoKD9ulidQGfcYY49+iE+PM5dAI2CtisKpLQiwmrvjOzB1a/rC9QnH679frgH5Ebb57WRL4uSAVNRdIvIGzAF5MNwQOu+cxKoiW6ZmuNJSb547XUB1UO,iv:aKzrgAV30sLfPEpgdQ26ZzdM3+gYtoSpZ9mNyqCqf/M=,tag:vjywN4qxh2zsCE3RPG6Yrw==,type:str]
ssh-known-hosts: ENC[AES256_GCM,data:zlRLoelQeumMxGqPmgMTB69X1RVWXIs2jWwc67lk0wrdNOHUs5UzV5TUA1JnQ43RslBU92+js7DkyvE5enGzw7zZE5F1ZYdGv/eCgvkTMC9BoLfzHzP6OzayPLYEt3xJ5PRocN8JUAD55cuu4LgsuebuydHPi2oWOfpbSUBKSeCh6dvk5Pp1XRDprPS5SzGLW8Xjq98QlzmfGv50meI9CDJZVF9Wq/72gkyfgtb3YVdr,iv:AF06TBitHegfWk6w07CdkHklh4ripQCmA45vswDQgss=,tag:zKh7WVXMJN2o9ZIwIkby3Q==,type:str]
import-user-env: ENC[AES256_GCM,data:wArFwTd0ZoB4VXHPpichfnmykxGxN8y2EQsMgOPHv7zsm6A+m2rG9BWDGskQPr5Ns9o=,iv:gPUzYFSNoALJb1N0dsbNlgHIb7+xG7E9ANpmVNZURQ0=,tag:JghfRy2OcDFWKS9zX1XJ9A==,type:str]
import-user-env: ENC[AES256_GCM,data:vfaqjGEnUM9VtOPvBurz7nFwzGZt3L2EqijrQej4wiOcGCrRA4tN6kBV6NmhHqlFPsw=,iv:viPGkyOOacCWcgTu25da4qH7DC4wz2qdeC1W2WcMUdI=,tag:BllNqGQoaxqUo3lTz9LGnw==,type:str]
runners:
alpha: ENC[AES256_GCM,data:gARxCufePz+EMVwEwRsL2iZUfh9HUowWqtb7Juz3fImeeAdbt+k3DvL/Nwgegg==,iv:3fEaWd7v7uLGTy2J7EFQGfN0ztI0uCOJRz5Mw8V5UOU=,tag:Aa6LwWeW2hfDz1SqEhUJpA==,type:str]
beta: ENC[AES256_GCM,data:DVjS78IKWiWgf+PuijCZKx4ZaEJGhQr7vl+lc7QOg1JlA4p9Kux/tOD8+f2+jA==,iv:tk3Xk7lKWNdZ035+QVIhxXy2iJbHwunI4jRFM4It46E=,tag:9Mr6o//svYEyYhSvzkOXMg==,type:str]
@ -19,8 +16,6 @@ mediawiki:
postgres_password: ENC[AES256_GCM,data:FzykBVtJbA+Bey1GE5VqnSuv2GeobH1j,iv:wayQH3+y0FYFkr3JjmulI53SADk0Ikur/2mUS5kFrTk=,tag:d+nQ/se2bDA5aaQfBicnPQ==,type:str]
cookie_salt: ENC[AES256_GCM,data:BioRPAvL4F9ORBJDFdqHot81RhVpAOf32v1ah3pvOLq8E88bxGyKFQZxAwpIL3UkWQIsWMnEerm5MEMYL1C2OQ==,iv:yMVqiPTQ8hO1IVAax6PIkD0V9YTOEunwDTtnGcmy6Kc=,tag:Z4+bZF4olLlkx7YpXeQiUw==,type:str]
admin_password: ENC[AES256_GCM,data:4eUXvcO7NLOWke9XShfKzj+x3FvqPONa,iv:3iZ+BTBTZ7yMJ0HT14cEMebKZattWUcYEevRsl/6WOk=,tag:CU0iDhPP2ndztdX5U5A4cw==,type:str]
roundcube:
postgres_password: ENC[AES256_GCM,data:fGHmq6r/ZCeIseHL8/gmm5DfWQYorI3OJq1TW0EHvh7rHL62M4TE+Lrlrmq8AIlmGLSWtO8AQzOP3toxidL6xWX3pcwLxtTefa1gom2oQf6ZL4TbAZLidHksdiro6pWtpMOO66bb8O9eXvZmns4=,iv:Irnb2/bgx8WilDyRLleWfo6HHafZ+vlDEwxIcgm1f18=,tag:eTNBUELmLwO7DsQN9CLX7Q==,type:str]
idp:
cookie_salt: ENC[AES256_GCM,data:cyV6HDCPHKQIa8T1+rFBFh6EuHtG5B508lg6uFYENK7qVpYuiTUIokdVQhY8SRLs2mECx/ampgnUHxCRB/Cc/A==,iv:QRrRUhzRQrLkmg38rrYtCEfF8U4/7ZHZUDSEq++BlbI=,tag:fLqFSLd+CKqJvmCh1fx8vg==,type:str]
admin_password: ENC[AES256_GCM,data:Vf33Oenk6x6BIij1uW8RQDjTPcKhUVYA,iv:RNeyCNpTAYdBPrZwE3Y6CCjoAML/3XUvjfJCrr06IEU=,tag:zVOrx1oXnEyr/VwFCFaCDQ==,type:str]
@ -33,11 +28,6 @@ nettsiden:
postgres_password: ENC[AES256_GCM,data:SvbrdHF4vQ94DgoEfy67QS5oziAsMT8H,iv:LOHBqMecA6mgV3NMfmfTh3zDGiDve+t3+uaO53dIxt4=,tag:9ffz84ozIqytNdGB1COMhA==,type:str]
cookie_salt: ENC[AES256_GCM,data:VmODSLOP1YDBrpHdk/49qx9BS+aveEYDQ1D24d4zCi06kZsCENCr+vdPAnTeM1pw98RTr3yZAEQTh4s90b6v8Q==,iv:vRClu6neyYPFdtD63kjnvK2iNOIHMbh+9qEGph7CI60=,tag:66fgppVxY0egs4+9XfDBPA==,type:str]
admin_password: ENC[AES256_GCM,data:SADr/zN3F0tW339kSK1nD9Pb38rw7hz8,iv:s5jgl1djXd5JKwx1WG/w2Q4STMMpjJP91qxOwAoNcL0=,tag:N8bKnO9N0ei06HDkSGt6XQ==,type:str]
vaultwarden:
environ: ENC[AES256_GCM,data:CST5I8x8qAkrTy/wbMLL6aFSPDPIU7aWsD1L1MnIATRmk7fcUhfTSFds7quJmIpb2znsIT/WxNI/V/7UW+9ZdPKI64hfPR8MtvrJcbOhU5Fe2IiytFymFbhcOgWAXjbGzs7knQmpfMxSl98sU71oLkRuFdkousdnh4VQFZhUCYM=,iv:Is6xQ7DGdcAQgrrXCS9NbJk67O2uR82rbKOXBTzZHWw=,tag:XVEjCEM5t8qJl6jL89zrkw==,type:str]
bluemap:
ssh-key: ENC[AES256_GCM,data:nPwsT4RYbMbGp2MChLUh6NXW4ckYr7SQcd6Gy2G8CEU+ugew5pt4d6GOK1fyekspDtet3EkPL2F1AsoPFBB2Rv0boARMslAhBqwWSsbBJTXeTEgAABSMxTPJRBtfJucvv426nyIj3uApoknz6mDCQh1OI6mER0fis7MPaM1506HlDlnIT0FV9EairEsaAmbd0yddByGJSccKIza2vW0qWqrz83P+xrakEONxFz0fJlkO5PRXCcQJVBCqWQfnaHNrWeBWv0QA7vAHlT0yjqJCpDRxN2KYrPWsz7sUbB4UZOtykCRM5kKFq73GUaOKqVECJQhcJi6tERhpJELwjjS8MSqvBD90UTKTshGugfuygTaOyUx4wou3atxMR2Rah9+uZ6mBrLAOLX3JKiAtyhFewPMWjd/UhbMPuzNageVBNz2EMpa4POSVwz5MyViKNSgr9cPcNGqmrnjvr/W/lnj6Ec+W80RiXQlADSE4Q6diLLwB9nlHvKs8NTDgv6sUafcPHpJ2+N4Jkb96dE14bMffQ385SI4vLDcQ8xCQ,iv:WdJIHRzjlm8bEldolCx1Q7pZJvjxGkNZALSOy3IjizU=,tag:5ZAikiqttq/76+thG+4LMw==,type:str]
ssh-known-hosts: ENC[AES256_GCM,data:J6V+NJ9TvYUL2gmcqWWYt8X+n0M7i0RpDpBelWAbFMH64+e9ztHNnC491sm+RogDxqKk0kwQyX2Mz00iq3Gc3wDYyozGOdv3tBKrp7/LcfjUQ9T9hi0yTD3eNV0LAjlAWMTdlW65VGHqGst8ncKbUuVxbBASVlh3A321toZgD+xxUAtNz7qKFa6fDbOS0xLD1+CmTwVp+aPos//QIKzjuk1HqxfBNK82maKtD4JHPS+Y3be2wIEjGWq3H6JYN/RDojD88D/jzo9RwvEjpqLXoOVfy8uX/fbEsgkgfAmPiaG+ePCnchSExEe3a6Y0E+I6YIzvP+tGThJpu4HaT/yW2Rww/jvsxKrXSUhtBZI/SIX5ZAIFB3sFjJXQefJjfNpQTQWhbspLfdemafGaRiDnzVgKDhNL1HNMNsXKDfWa0SLs4//dqerom/QCCNsaqV+4HVzv5x44srChGERadQI/Wh4UG2R19xxbdyIsKPHzv7BhEKufJkjc5upBjWygQrGAkTRHugFpw2Tdkz9yUQSujMkaeRKhVkA+ZUAjwnY5TwqNZBj7U3K2JXoNVHAq194XmrA2dNghh0OmRrvKGwM3HKexX22SXT0bPlpdWRQpMbUgV+uHLMerlDpNMFTIueEBkaF/FWeSW2N5WUrUb1uJ91QcJ8JBgN1riuD1Oxv9RRPrY9VVNJMrYjpAAREN8i8brMTOCJ35s7jnqIei0dNmnNXOoQZPs9kUMeEtUc/Df1E8/aO2Y4yU9gHUuevXnAJWFAiu2IxssgPk6CcNxvapJEmlwkLK/JyuDsWwFxVOHfw5QIEsoDVWXt6eMhquqUgzJI1q7QrTWUQsBb5A5sQKYWQHempOaXuQn1bzA7mU3Gzsr8bNNc6tpy+6j3zTXYR067EX00yqPG+kqRn4QVIuhByxXP3cwXLUG9uD1lsqWrGzs6WCnHr7txhRBXf4WbBVmXModO3uf36cDYEwrUa6yBsARtSl8PJ0UadfY/xULcT5PFvu9+Hi2qj3vp4IU3JCJa9AvXB+11pbSdawprjuDhwQtPwkJ4CQyvZsom3/BOrmwYM5+EyMDIluEQ0z6eDE5buiIVbX6IvXnDCKbrnqVwavX2wqyiDduFLjRfWL/3U2O1yRim78smrDMJABJZvtW+a+GfmlnTd/gnFvS70Fmm/lgtY051ISL/iFx6toJRoBMMiI/Zvy13uQry+w/HbyFl42DIank8tf7kuN3E9M7ADGMubRJJ0AZOcQddrFnR4Gl2nU2+3RS5fLHaBf9QHK6W92/n//xmPkYqrkPacew4eBjUqM32jVGuBpDc964fK9kdtIdw8q5P1s/ph3I79Y24kGeuO1AVJuZvkaTv1Z7GgI9+K9TstKJ9XpRCidLpLSP+uHOWkqcNsQlt6ilTlfHj+MKoD85dKZ315QMmpiuYEvzCSP1aYTb9dpd61Su/IVuM3r2NuINNEZ166YlHQVsLNpDn8E5ahk3ZInOAg6/kaKTmjUI8KEvX4BR3PbbViAlJJb3suJ0oZBGPUlrW5uLRmADvf2mMDVO5zY7/m9DQwxjt4Miu0l8ZaUc0YJQ850lBKucQ==,iv:GI8w7h7xX8gMHuAoWUyrW+BQb85LNlASoYvGBPlCZaI=,tag:WnHNMevfFSMc0ikBZwWn/g==,type:str]
sops:
kms: []
gcp_kms: []
@ -47,79 +37,52 @@ sops:
- recipient: age12nj59tguy9wg882updc2vjdusx5srnxmjyfaqve4zx6jnnsaw3qsyjq6zd
enc: |
-----BEGIN AGE ENCRYPTED FILE-----
YWdlLWVuY3J5cHRpb24ub3JnL3YxCi0+IFgyNTUxOSBNbjFxWk5lY0kxaStxcnVh
SnlYamw5WXBRTkU0ZGFEWnZvME1nZk94TlIwCmlhVGFtckJpN1RZdXRBYkxDbnVS
UmZtWENzZWNYRmptY2kwem42ek1LbXcKLS0tIElsRXBmNHNmdjdqTmFLL2ltMnFC
VG11M3ZpeUJPUGlEQmExOEdSZFJERE0KSIo1pzx8AcoJWEzNzEDoV3eM7194IHxL
4pCSSztKDCF+XdJZLh5sgudaYLJGtX5n7q1hbuL0wOmotM9bN2YLog==
YWdlLWVuY3J5cHRpb24ub3JnL3YxCi0+IFgyNTUxOSBDbDc0NXZqYko1Z25qYkhq
T2p4cGZ1bTZRS25YdjJ0K3JhSklCT1NwSHhzCi9MVnM2YTRuUERwTVlaM2lxNEtp
Mk9hcDREcTErZXJtSEI0aE1PV2NDV1EKLS0tIDY2MEN6a3NWb3JpeU5JVkhoOFVR
MjVqdHg0SnF5N3VEV2U4a2dvbTZjem8K8J6KQMJwpiC8gqlgi29x3dpSORAmuVQ6
cX5jXggOoz5vME6BMQ3s/bglZG2pdEgWpGZVbc4x2iMwUWgJLHdgXg==
-----END AGE ENCRYPTED FILE-----
- recipient: age17tagmpwqjk3mdy45rfesrfey6h863x8wfq38wh33tkrlrywxducs0k6tpq
enc: |
-----BEGIN AGE ENCRYPTED FILE-----
YWdlLWVuY3J5cHRpb24ub3JnL3YxCi0+IFgyNTUxOSBybXRjNEM3ZDYwa21LdWpE
dDg1MUxaeHlJSHRhWk40TndYbHZLWHVsVWk4CkxkRVJ4c1lhaXZodGxhNGhkUy9q
M0I1SHdjeXVXL1E4OXgxS2x0cU9ESFkKLS0tIFpNMjNKLzNDWWtvTkhHRDFSTklH
T1k1cXp4NXVvVGdkYXp0VVNJejVJRkkK6K31gqRRvo0mbJy6aCTKotVmrfqZoARG
w6wKe1TJLWJv8RAD3GQrub9MJwQhUG38Jtj1WrXgNMlF24zFPlZDEQ==
YWdlLWVuY3J5cHRpb24ub3JnL3YxCi0+IFgyNTUxOSB1SHMrVmxsL0orQlk3dy9H
NDMzWEZYMXhkamVkTy84VGEzUm1BU3lNY2dNCkNwOGJteVQzYlZESGlScTg0RnFx
emNXbmZhL3BHWThPRUI4MVIzMU1POTgKLS0tIHRmQ0llR1NCSm9KMHZsOGJXYmxk
eGpDUlFHdEZmWkZHTEw4Mmk2UWRnUU0Ki5GK2mzDIc2iTryjn6lf5lMqVZcCcxQ2
a3Y/o/NMFDhMZpLlEljuWQVnuOyJZ3RSDCFN9BSEkxg05PaoSluUzQ==
-----END AGE ENCRYPTED FILE-----
- recipient: age1mrnldl334l2nszuta6ywvewng0fswv2dz9l5g4qcwe3nj4yxf92qjskdx6
enc: |
-----BEGIN AGE ENCRYPTED FILE-----
YWdlLWVuY3J5cHRpb24ub3JnL3YxCi0+IFgyNTUxOSB2azhwMEJRZ3JQRnhDNlFR
a283MitGTTdaMTZURmFYam85TU43RkdXYTI0CnQxWnRUZ2F6MHd1TWlHMDZ4b1p0
WStOVndGTUpmdncvd1k0WlV3c0xKYmMKLS0tIFpSb1hKbHJyM1dCOVBMa1Jabndp
NWlGSFhQUngvWG5BQ1lyOFAxanlGdlEKt09a9bMErR3wqbutxhDRfSWp40mmfShJ
KAAO2TEMKkEGFvaxYu+G9rbR37h/ZttikJMvIVlfRzmVADlFwO7eHw==
YWdlLWVuY3J5cHRpb24ub3JnL3YxCi0+IFgyNTUxOSBZY2ZiazhzdkxNZFZldjBV
SjBCR2lXdFZZUUpJTnJVWUVMNTcybGQvbmpNClVDOEdMK0JIOUEvaVYxcm4yeVp4
dVY5b292WVE5L2JXNGQvSENiTjBWVkkKLS0tIGIvdzBxMVNYbGN4ZXBBNDg1bFNB
akVjeTNTeGorZjJQOVlMeCtPRUVYL3MK+VMvGxrbzGz4Q3sdaDDWjal+OiK+JYKX
GHiMXVHQJZu/RrlxMjHKN6V3iaqxZpuvLAEJ2Lzy5EOHPtuiiRyeHQ==
-----END AGE ENCRYPTED FILE-----
- recipient: age1hmpdk4h69wxpwqk9tkud39f66hprhehxtzhgw97r6dvr7v0mx5jscsuhkn
enc: |
-----BEGIN AGE ENCRYPTED FILE-----
YWdlLWVuY3J5cHRpb24ub3JnL3YxCi0+IFgyNTUxOSBtYVJLMTZma08xZVo3cEZs
Ym1FTU9ZdmxlcUxselltWDRwdUhUdU1udnpjCmh4TlJEK09UdlNFLzN0YnN3WGtt
aGpzd25Vckc1TmVCamQ0ekk2QWpraUEKLS0tIG9CNzBOM1g2aTRlQmt3WWVrTlNB
ZWsrZy9HSWt4OUdMb3ZZQmNjNGZNZjQKMhvkRnis8P2iV3hoigiN2IXeIFvFuYRK
FeMG/cNOtAUsOgHMs4xDPqpLrhpay7IEvwQukBxscd/88I8/ZdGeHQ==
-----END AGE ENCRYPTED FILE-----
- recipient: age1wrssr4z4g6vl3fd3qme5cewchmmhm0j2xe6wf2meu4r6ycn37anse98mfs
enc: |
-----BEGIN AGE ENCRYPTED FILE-----
YWdlLWVuY3J5cHRpb24ub3JnL3YxCi0+IFgyNTUxOSBtazZ2RUo3ZjdKeStLWW0r
bm1NVWJRbjZpZTVRcEFWTnJwYkp2YUN3OTM4CnhRa2RpOS83MW9zaWlUV1M4b21t
OG5Ub3VkK1dSMkVzN2VtT0JrWkFSTkEKLS0tIGMvOFU2U243RnpUTThRRWthaHpZ
SjBhZjJpNGlUclF3bXRKOXk0KzlHdzQKp/asp39bRfNXyetc3ySVpnzfO6it9D/e
XWyhq0yKRFAC8yMYeAuA4kIcNM4DGRc0PnwA/ce3IgHsV1ZNdvdWfg==
-----END AGE ENCRYPTED FILE-----
- recipient: age1zhxul786an743u0fascv4wtc5xduu7qfy803lfs539yzhgmlq5ds2lznt5
enc: |
-----BEGIN AGE ENCRYPTED FILE-----
YWdlLWVuY3J5cHRpb24ub3JnL3YxCi0+IFgyNTUxOSBnT3lTUEFaN3pOMGhsQ1Ra
SVZ6cE90a1BteXgzaldsN3ZTSGZpZXlyWHdvClhJM2ZDRHR0VzVSQXd0b1drK3hG
aW8zUWlHcVFkTFpJYXpxWlAwVHV0ckUKLS0tIGVmR0g2Vk56dlZCU01Dd3NzUFZU
UHpLRkdQTnhkeGlWVG9VS1hkWktyckEKAdwnA9URLYZ50lMtXrU9Q09d0L3Zfsyr
4UsvjjdnFtsXwEZ9ZzOQrpiN0Oz24s3csw5KckDni6kslaloJZsLGg==
-----END AGE ENCRYPTED FILE-----
lastmodified: "2024-11-24T02:02:00Z"
mac: ENC[AES256_GCM,data:hTye1yv7J/jEjLXtIyFPJZFuY3wol2tX1kZi7JtwTa6zs/JTg7piPL76/CkgWjVxGdv6DpSdlCt+AjIMQarbBpyKc/ux83zHrgI2BUZfYTtjwKLfoafsRjsjoz17ZRE55ozbjb6UHCCHLIJXUmHop35AeGwNcexx3UH267lpPZs=,iv:GhU0u7D9Dg/PqM4gEm7j9pPlCPGTxgWDMv0dNxr9HMk=,tag:fZHfgJdpKtT2mNaeOU7agg==,type:str]
lastmodified: "2024-05-12T00:24:29Z"
mac: ENC[AES256_GCM,data:/fh5yc09YTLT62oWVsz2CwW/mhEUI7uRh5fDRgLNeeBc/4bvM3z83xmy9veehmQhhCWjju2/CtYhaihm3bUPN4hu3wVzviIxvrS9lTcBUG+F/AH4SnF5Z1CGWb94Gqi/6OhQRIpA6azjISyv8lTAQ4TCqcOC4fz/c9KjqQ/CiGY=,iv:HjzzMRFz3+kZ4iDLn9kI80BwMDALkRX5gyOHARZSgDA=,tag:1ez7NiIavshfp4CTZNkW/Q==,type:str]
pgp:
- created_at: "2024-08-04T00:03:28Z"
enc: |-
- created_at: "2023-05-21T00:28:40Z"
enc: |
-----BEGIN PGP MESSAGE-----
hQIMA0av/duuklWYAQ/7BlyYej03uyhLheXS406h3Ew7v7D+rHHvHjiw3FCJxHoC
1revUrMa/M6iTNQteaBvBcYVR4+SpUpRyN/6BSzEQBrNhUBR+70VWL2yzeeb6Bw7
GBtuyS7O3DEd0froE3aFETR0NfQ1FfcndOBd3SDKOsCgL5nfJSyOPQtr1OMLKzoW
+CARt457xEx0KY7IIpN6e57IT7bVjJx5UuDcN0ZncUyuGUAKHdn0nAHzWqiSZV9w
bIftLJ936zvBOhhl3DkzvALnI9+//KPSMM3o/1ti07FoAx8cK2w83VA5Ia9qeNkB
wfVuE6f5a2KP/KrfnVCfvweMh/MIEUGb14XEaniyYwvlW5vwF9YgPH6HGc0c+lH6
UWy8+Iw7kXkUEJuhtNWyBPJeVKheSBieoWUBZZAK4uWUpChJxfc5M3+P3mgzTIP+
7P04xdtS0GwrNwMBiQFqc56hoYDAwMYbn9lFzM3LLq+h8Ztg2G4X9LXjD956TP5C
bPV7BFcjTSaAt1TDJcDJRxfrtx6Mo/DLknpGTMRM0UfQ/22uMz2GAH38L0C7lD9B
RrKlpDuMKzj/LUihO33Ry9J0IpZ3XF6oaSl/+P+uO9QYNxA/zkuxuSWfqoysldyN
bSo1dHGapY/+PVMjM0E/2Dkk9T2IbQUlkVxPrlvuUd3YfrJ7bCva2GDjLvXSp7LS
XgGgLgrj54YoOn4uUFsxzDIS7yVps3fCkByVtc1Lc3C8uPPF1B+jOX7O87kZOHag
XvT2ze2ITfdxPzoyZO1nWVIGO8rAtQ/vK/Iv2/hHtc4gfzL+gy7GeUWGHkvZ1Kk=
=wDmH
hQIMA0av/duuklWYAQ//TewS5bITIo3bx0HEM0p8bwnSJAmNqGJmuILXg4k8eszF
JHS9eCfU/Vz4Z8eMDJjntFIWvNCl0QOycvp37uNaqPedDE3v1nNpCxOZ76vLT9I5
smXKpRmfgYxQAkWQRJ6aUV+DoVjSY/hT9JWD7u4uWgavG5D7/3SwiJC3uM0/8mxM
gwbp5eVEO0mTvXZsmqIRJ00NKX+RIMuUZFvzu3ajGywZfQxFs7zUhx7Lc6ry/MYI
FFrbXssgpH8U9dHMgBsGzeyQS4qQLGFHJuNBBzz48U+Dr5EgHqZ2ZXZschW+40qX
TH8d4qyOROTiHKpKp3+nUoRiz1JPkJ0rqHg+9hOrFNpl1NZQ6w1UOc+0Ki6ZAwMd
yNF733/I+OaI2b4nxhG+la6U9Z1fOat3BPRoxp8ZlLRrPq8ljxV78TMVfv7/lPO6
MZopBmSOeV19t/QypYi2pl+QYRaVs2QaBFotulob+KbKpWC4T2tMEMnPngsTxOhk
26VY5ahIp01QbewPxylpY6r1jx1tb8KcMmsGlaLrgOo9Q526bh5QGRDx9NCj064c
uJ2ed7hY9tNHs6qN/94rcr1hOAq5kVh+36UvJBZYQuxwIXIws4Xw+obzoKVAAqEC
qEZWL1NB0hXynom7Vc2e2MzT2guogXDHvlCDHjtt9ekGcmU+tQ/JdgTOJ93hEInS
XgEjcd1xpnzebDo9SpNBq/J/uSKAKLPOI2y+LZzvs6oiFtc4QLcgGors38x9SiAP
JSiQnUAC9XZtiugGdCOVy6MG1x3smAafW6kcH7yr+vWoJoQLbbF60PhuhAJ0N4Q=
=3iQC
-----END PGP MESSAGE-----
fp: F7D37890228A907440E1FD4846B9228E814A2AAC
unencrypted_suffix: _unencrypted
version: 3.9.1
version: 3.8.1

View File

@ -1,6 +1,5 @@
calendar-bot:
matrix_token: ENC[AES256_GCM,data:zJv9sw6pEzb9hxKT682wsD87HC9iejbps2wl2Z5QW1XZUSBHdcqyg1pxd+jFKTeKGQ==,iv:zDbvF1H98NsECjCtGXS+Y9HIhXowzz9HF9mltqnArog=,tag:/ftcOSQ13ElkVJBxYIMUGQ==,type:str]
mysql_password: ENC[AES256_GCM,data:Gqag8yOgPH3ntoT5TmaqJWv1j+si2qIyz5Ryfw5E2A==,iv:kQDcxnPfwJQcFovI4f87UDt18F8ah3z5xeY86KmdCyY=,tag:A1sCSNXJziAmtUWohqwJgg==,type:str]
mysql:
password: ENC[AES256_GCM,data:KqEe0TVdeMIzPKsmFg9x0X9xWijnOk306ycyXTm2Tpqo/O0F,iv:Y+hlQ8n1ZIP9ncXBzd2kCSs/DWVTWhiEluFVwZFKRCA=,tag:xlaUk0Wftk62LpYE5pKNQw==,type:str]
sops:
@ -12,79 +11,52 @@ sops:
- recipient: age1sl43gc9cw939z5tgha2lpwf0xxxgcnlw7w4xem4sqgmt2pt264vq0dmwx2
enc: |
-----BEGIN AGE ENCRYPTED FILE-----
YWdlLWVuY3J5cHRpb24ub3JnL3YxCi0+IFgyNTUxOSBiOVc1eXg1bU9BZmc0cXhM
L0dpbVBvQTNzcnFWcktSaW5rQXhnZks4dlhRCmVla3kzWDlJN2V0dDFYWkxJUUVo
RTlqNWM4c0lmbkc3cUM0dTgyWGpSNWcKLS0tIEx4SkxDdTFGUi9OQ0NRVGxXeSs4
b3Zaa3p1MnU1UTk1T3hmejVkM2RDLzAKmk63I60GEenLt0l4FHmz9mBAumw105Qs
mDbQBfAj1m1FTE6tl38J8wVyFI8LT550bqYdymvnT2mnEIAIP/04ag==
YWdlLWVuY3J5cHRpb24ub3JnL3YxCi0+IFgyNTUxOSB2RFpLOEtUQ0ZLeUdmTGxl
VXlTOG82Ly8vdjdldnB0dGFzTkdxUHNML1VJCmxDWHhyMHYrbmtMVWVJYTdrWjVn
aE5qWWtHWSszYnNWc3l2VmFwUGl4R3MKLS0tIG9ocThFNm1pcUtMNHNlMlFsS2lx
MDhubWVxamxlSVk0dUtIWnhyUlBNM00KRunPljgLCHkwn4HCPGpkNbLitCIF7hYL
jRYVzu+Wddd13A4QfvHvAI7bJB5Zsv/xwmggVlICG1pky7gPNDwGcA==
-----END AGE ENCRYPTED FILE-----
- recipient: age17tagmpwqjk3mdy45rfesrfey6h863x8wfq38wh33tkrlrywxducs0k6tpq
enc: |
-----BEGIN AGE ENCRYPTED FILE-----
YWdlLWVuY3J5cHRpb24ub3JnL3YxCi0+IFgyNTUxOSB5dmJpdUxVcllPYXpxRlN6
ZnYyc25sbjdWNUNEQnE3UU5Ea0JPK3o0Ukc0CnFIOU0rOU5lV0tGb2NuNnQzejhw
cTBkOFJHTXJIMFhzZ0tpODJ6N1pJRTgKLS0tIEhPVlBMcjdHNVRKWDhkTXFTOFFu
NUREdmFNR2NkY0Uzcm9tbmhteHFtSTgKSUTGoNb2/0rljN7oojVk1fMAulK669ud
fpacGQFBJzJOusx29YC01W6mn8TW8Cdw6mKmS3QEsYYx7S4HpX0v1g==
YWdlLWVuY3J5cHRpb24ub3JnL3YxCi0+IFgyNTUxOSBvem5LODRyU0VlcElOS0tY
a1FaNHc0SDJLQ1llalBqQ2VEQjZpbUFyd0hNCldQNUpTdFZ5NTlxWU9icXN2Mm5a
S0JQOUkvdEZRK3NBOGpEZkJleTB1TXMKLS0tIHdVcFRETFlBVWI3TTZYZGJMMkcv
RkRXTTVURDRFNjFvci8zRVpqbkxVclEKW86hoVO0grt2x5YMt/YnmDI6J0QFKjZZ
Mnmd/Z1S6a+rajCy0GkeM+Q8AbBqBrNei2H5Xp1PlxNyicGib6+Ngg==
-----END AGE ENCRYPTED FILE-----
- recipient: age1mrnldl334l2nszuta6ywvewng0fswv2dz9l5g4qcwe3nj4yxf92qjskdx6
enc: |
-----BEGIN AGE ENCRYPTED FILE-----
YWdlLWVuY3J5cHRpb24ub3JnL3YxCi0+IFgyNTUxOSBRUmNyQWU2Ym5NMjJnUUpu
Vi9yeWhFM0NDTGZtRThXQWMxYVI2aEUrNUVvCklxTldQRnp4dTVXMjRXWU5DNWhz
dzllOXp1RVRaMDFNWExuK01maFk0blEKLS0tIC9hUENybThmWlBab3IwSTQxSHBj
Q0IyL20vdlRBNWZyNXc3MGVtcUNza1UKLDq74TMy5hXhimnDA06/Ku5RJQcDvkjn
QKSGCxZ6FJ/io22qNiw0vDRzTfW1Dz+9/Yog3Pi870IcAljkdmoxEA==
YWdlLWVuY3J5cHRpb24ub3JnL3YxCi0+IFgyNTUxOSB4bHNiY3ZCNHZsYlUrOHMy
OG55QjVmQVUxbXl0bkdNQ0FEais5Sng0ZkRBCm5KdmMvNmN6VmdsREZrbGd4ZFpM
VVpsQk43MlBxU042ZkE4L1hHK1R4RVEKLS0tIGttL01XcG1IUnBMbUVqKzJMK09o
QmVlRnJhSk4xYWFVbGVxdlFxSDlXSGMKJvjMDaX4Aa98gT+GPjGaKKdnG67jNG3C
nLsbxU4vNpFvjF4WI5vdvIQe5UGzoCYQZp3oHFnGq+Jp/hJ1HFF0GQ==
-----END AGE ENCRYPTED FILE-----
- recipient: age1hmpdk4h69wxpwqk9tkud39f66hprhehxtzhgw97r6dvr7v0mx5jscsuhkn
enc: |
-----BEGIN AGE ENCRYPTED FILE-----
YWdlLWVuY3J5cHRpb24ub3JnL3YxCi0+IFgyNTUxOSBOTUpYam1KQ2laek42V1NE
eUY2TlY2Q0JNTHR6QUEvZEhhem5ZKzhPQ0JFClZldDE3dDVIeTQrOVpJNGI5dDlR
YStuTlRDcXdiWE9LdThaUERnbEpkU28KLS0tIDNidFQ3ZTdINXpTZGljZmh3Q1ky
Ynk3aUtFOFdGV1NHb2d4YXJXb0xNYU0K07jwIfF+US++qz9rKn0TgR/vZam12vvr
lq5s694hHkSRmAP5uJ4lNQKUkacH9qlBXB+aU+D98vKRDGYIkKhlQg==
-----END AGE ENCRYPTED FILE-----
- recipient: age1wrssr4z4g6vl3fd3qme5cewchmmhm0j2xe6wf2meu4r6ycn37anse98mfs
enc: |
-----BEGIN AGE ENCRYPTED FILE-----
YWdlLWVuY3J5cHRpb24ub3JnL3YxCi0+IFgyNTUxOSBjaURPbENOQ2l2N2lsd2l4
aUdQNlUyWjNFM2JhcXF1Z1NJZ0lzZWFjYmhNCnF0VmZzd0hJSjJvekpzN3hoYnlq
UDg0VHVlMUFTc2xNdGtLb2VXVzBySHMKLS0tIHdVWjlnTmdxSGpMR09zOFpVYmZF
M3ljcDgyUHB3Zm00bUxWeHRvK3o1bE0KGWWaSuPmvzA4PqBg3y+XOpnVCkv34eV3
ZEnPJood5bkBlVqfiBbwJaF98rCH1f5WI6S0NA/5ol5kckDpfwpePg==
-----END AGE ENCRYPTED FILE-----
- recipient: age1zhxul786an743u0fascv4wtc5xduu7qfy803lfs539yzhgmlq5ds2lznt5
enc: |
-----BEGIN AGE ENCRYPTED FILE-----
YWdlLWVuY3J5cHRpb24ub3JnL3YxCi0+IFgyNTUxOSBMczFnbUlONTI0M083bzNB
RVdYQ3ZIT2dwbVJVS3pjZjc4d1htMVQxZGtZCjlPejdVNFVrV0t2MjJ5NEZuYklt
U0ZiUWgzdytMSHd1N3FPdmNmb3B3UkEKLS0tIGtPdmhpT0NQSGpPWWVublF6dVZt
cTh5bnJ3WW90aXRCSUp6NHFYeU1tZ0kK4afdtJwGNu6wLRI0fuu+mBVeqVeB0rgX
0q5hwyzjiRnHnyjF38CmcGgydSfDRmF6P+WIMbCwXC6LwfRhAmBGPg==
-----END AGE ENCRYPTED FILE-----
lastmodified: "2024-08-15T21:18:33Z"
mac: ENC[AES256_GCM,data:uR5HgeDAYqoqB9kk1V6p0T30+v6WpQJi4+qIeCDRnoUPnQKUVR10hvBhICck+E+Uh8p+tGhM6Uf3YrAJAV0ZCUiNJjtwDJQQLUDT53vdOAXN4xADCQqNuhgVwVMaruoTheEiwOswRuhFeEwy0gBj3Ze2pu47lueHYclmEzumLeQ=,iv:t0UyXN2YaR2m7M/pV2wTLJG5wVfqTIUs7wSQMmyeTVw=,tag:O7dIffzrDAXz3kGx5uazhw==,type:str]
lastmodified: "2023-09-05T23:28:56Z"
mac: ENC[AES256_GCM,data:pCWTkmCQgBOqhejK2sCLQ3H8bRXmXlToQxYmOG0IWDo2eGiZOLuIkZ1/1grYgfxAGiD4ysJod0nJuvo+eAsMeYAy6QJVtrOqO2d9V2NEdzLckXyYvwyJyZoFbNC5EW9471V0m4jLRSh5821ckNo/wtWFR11wfO15tI3MqtD1rtA=,iv:QDnckPl0LegaH0b7V4WAtmVXaL4LN+k3uKHQI2dkW7E=,tag:mScUQBR0ZHl1pi/YztrvFg==,type:str]
pgp:
- created_at: "2024-08-04T00:03:40Z"
enc: |-
- created_at: "2023-08-27T00:12:42Z"
enc: |
-----BEGIN PGP MESSAGE-----
hQIMA0av/duuklWYAQ//XP1HnmkjG/wdSC2lQm2XJkB5hMU+eJxglsPVaQpqTODr
dtVslBr/4nvCLypWhwYCG4jSz9YHU1sI9kDOsuo7PtwCrhfefeOL6CO+O40ECFMR
CEMmPLrTXg3LV3TzulchXY6x72LRzJ/aJ1Ra/6sGmffL7JHJ7vHz+U63oXyYivdX
9zsxP+iGRpQBK6wcA+Wg30rFV1ENE77H5Wh3PGRRXBSVE1fF6I3USgOxlQvGGnK8
cobLecH6V2TwSAptVcGk1gEmn6RUZdxATBnt0vE/Wr/zxZLuoRJgxmiwXuL5+kYW
QjCvCgAAEyFJtDRycwPPpDtTCBECPV97Ryev0Z8PdrYHfjNcgNVgDwNH9L3TuIEY
QL/f/+9PgNuUjf/7nktn1c5eAvmMyKJCiy9yKYZ1H9ynwN5Bxf+KJflVtTWbdJJo
ITXP2RyU2ttM2WjAM87E0HJD3XZ9x9I8Se/f5eQbg2Om7E2HXYr/v2uWf2ByRn5y
PV232/rR/whf/vpiwChDsBT97ZfZJibU8Xot7WMkQhgjCJaYH0wzYcrnvg3EIAo6
MBN1ufKNAp8BoXrM2P4yu+UOjrN8O+54Sxg7CSwg/a/ldDdjUnsGfbf3vzY1EJcY
2lhLZ8sOQyl+Ppe095pcTLvcYp2FOihf6d3i7GGG6Q9Uh2Ljs7EB02GDKP1XozjS
XgEsx/GScE/PE15VKlOHhrrF7OJj8P+uvlriVqk/MSWUVO2+X1yS09gXFtazLZBo
yqK2yWAOsjFnrMv4A8YHM7COkKvJ9BGdefsoGQu1O838/T7R9+e1OK9iDhfbcMM=
=vMG8
hQIMA0av/duuklWYAQ//edQVXnTS4Xarwt14tF6yyhWM9/JFSVWW97lTO6xTNe5S
jNROmF/tHl29IPX0/QHXj/d4jMF/nteHdD53nD9s312CPOBv3SEwl4e7hfMf3rUN
4YOahX9J4ryoB+ZleK5leoYSsWaVBDJfERMkYT9Ta/xv4EC5zHBTlZDpLRuS04eZ
W5MG57TKBC0oifPvhCuv22OURNUp9t/bysSuKgU1v0Czu6ozuVgw9AO8G+PstFpW
7lyIMUNJQ7g3hiKDrrPPYcrKTeBbhxTINObe29nv00y0lycnfx3PxWrXpBoyv82y
xRgtalVvlYre1w6IFkqDFtpJD6N3zPFnPq4ZQ0nHN7A943Kxli5JnlkRH9Ak098K
PuykZ+V2X+qFNf4LS+Gnjx9wZKaLEChMaDhILUDKuUcwPIU5EiaaBOS1Y8NQ4Lha
pzyWzvpejV87Qvg2iog9UYLsK33GuxcFzYaklnknrI+9SotM7LRGQTVkVOwykh86
8d+Sake0J/1xjOcxUNbaYreTA3myyklVlvoybyNOdSzxGveEq3KvGgcORnQxYwe3
QDoCdVNTmU5ELwDPALVMenDr7VixN085oJkYqZJ6v5E0K1Bhtrb6PItoC5Kea55s
zWP+0rYxFx884cqpf8/JuC1Jbs1DpljqMMW9aD6A0htzOwEyHzDKWxy7zxCJrgjS
XgFHIr6sG1geqUzIhw8NzUpdOkdlQ6YFKP3MsUfxIqPHWVQWt1+LLvA5BX/wXIe6
kPTa9qXwmK7Hrh5TyPPEjrO16qT3UE0nvRAI0s79L6U+99xXfhKIXhg2OMSZCR8=
=xnr5
-----END PGP MESSAGE-----
fp: F7D37890228A907440E1FD4846B9228E814A2AAC
unencrypted_suffix: _unencrypted
version: 3.9.0
version: 3.7.3

View File

@ -2,16 +2,14 @@ synapse:
turnconfig: ENC[AES256_GCM,data:mASRjYa4C9WRow4x0XYRrlCE5LMJUYaId+o62r1qhsyJPa2LzrI=,iv:5vYdubvMDjLS6soiWx2DzkEAATb9NFbSS/Jhuuz1yI8=,tag:wOW07CQMDbOiZNervee/pg==,type:str]
user_registration: ENC[AES256_GCM,data:ZDZfEEvyw8pg0WzhrdC8747ed+ZR2ZA8/WypJd/iDkmIy2RmxOeI0sE=,iv:l61mOlvzpCql4fC/eubBSU6px21et2WcpxQ6rFl14iw=,tag:sVDEAa3xipKIi/6isCjWew==,type:str]
signing_key: ENC[AES256_GCM,data:6UpfiRlX9pRM7zhdm7Mc8y8EItLzugWkHSgE0tGpEmudCTa1wc60oNbYfhKDWU81DT/U148pZOoX1A==,iv:UlqCPicPm5eNBz1xBMI3A3Rn4t/GtldNIDdMH5MMnLw=,tag:HHaw6iMjEAv5b9mjHSVpwA==,type:str]
sliding-sync:
env: ENC[AES256_GCM,data:DsU1qKTy5sn06Y0S5kFUqZHML20n6HdHUdXsQRUw,iv:/TNTc+StAZbf6pBY9CeXdxkx8E+3bak/wOqHyBNMprU=,tag:er5u4FRlSmUZrOT/sj+RhQ==,type:str]
coturn:
static-auth-secret: ENC[AES256_GCM,data:y5cG/LyrorkDH+8YrgcV7DY=,iv:ca90q2J3+NOy51mUBy4TMKfYMgWL4hxWDdsKIuxRBgU=,tag:hpFCns1lpi07paHyGB7tGQ==,type:str]
mjolnir:
access_token: ENC[AES256_GCM,data:ERFqZjK7MRD0xWt91FNCIxP1YC6Qj54QgnckHlCTtcQVLWaM1h2h9lHS+K8=,iv:1d7vmFkXAPcsmumzlmOT31amdrKLWtL5sJiS8G9g+LE=,tag:2l0vWzJ6P12ofuBdf5CCWw==,type:str]
discord:
as_token: ENC[AES256_GCM,data:cnPZjBbODZUA1p0kLNeWpKh1oGkDPxDw/g7163XnoRCIgpqk,iv:Uu4L36uDPMBgzdXE2Lt9U0qrBSl3Xuufh1313BD8B/U=,tag:nTm6s7IGd4vNzZ95mfxDpA==,type:str]
hs_token: ENC[AES256_GCM,data:UzcaNsJtJPKvFT4gQDNfat0nmyJzmQ6OcSI73pANibzOVrWl,iv:ujgRM2jb1rbeloPB4UPLBEvQ7uue4a+bHiqsZAHIqtk=,tag:uIfuaTWSTeVvpQx5o28HPA==,type:str]
hookshot:
as_token: ENC[AES256_GCM,data:L4vEw5r4RhcgritOeDTLHN5E/dM=,iv:pC8BLzxf6NaVAGsotoq6chOceBVdMLvrsQn1LGw9H9w=,tag:SI3CDFHAvgQZEvf/oms3EA==,type:str]
hs_token: ENC[AES256_GCM,data:2ufSJfYzzAB5IO+edwKSra5d/+M=,iv:cmTycGzNL+IeRRKZGbkhTtiksYTtbxED0k0B5haFw7k=,tag:FmWe5sGi9rlapUeAE6lKvg==,type:str]
registrations:
mx-puppet-discord: ENC[AES256_GCM,data:FleyXxgOmc05nTP6M2DBJlacufN3p/05eZm4kB8+K4ci0k24o3zli988wlM/kyeZmxu4pgQlJ3lNLte4uip2hBXHWG5t5Ldzmr7bNCUD+r7nM+I1lfNkrDROPZ54bHysmn9O5CHpEa16rSo6RJgncIPqsLJxTwjC7qZlkOpzqvMhkq/MHCVOpvg0M/6AUR+AlSZoggujBMoXLznQNQapN13foEsbuo/QxjszM/ObGmhYMVyaS+TDBXzQLA8Yuj50Q/gZCIINWZ4G2qmgsGxxNR4I+usUQml/jxCtIXS4zn/ettXfL9G4Fdm2F9u1v11DehtTGa5xoxDq94M9rIxOqeJpvgEQEyyKAyFUIrlINfGl7tAj4Zu7+9Z8JTRAnppjM1q8iInwn/Z2L9KgB0YFi/Go1whgXly+TH6hpreo7m5klXV/ff/aV3ghOgFCGA8nBrZFqE8Uw268q9tV1s1dxCb6TbpGf19V5c9MD6BsCIVeoq+j9I/I8iZpzg2Reb4IlHhMDwbwsL2w2ks30wiZ9XO/CFrXDY4uBlI=,iv:3vvkGvldS8Raibg6tzlV8VY1O9NCLxSuNX/lwi1QgiA=,tag:D/noIsE3xlOiYM6Pk+cc8Q==,type:str]
sops:
kms: []
gcp_kms: []
@ -21,79 +19,52 @@ sops:
- recipient: age1sl43gc9cw939z5tgha2lpwf0xxxgcnlw7w4xem4sqgmt2pt264vq0dmwx2
enc: |
-----BEGIN AGE ENCRYPTED FILE-----
YWdlLWVuY3J5cHRpb24ub3JnL3YxCi0+IFgyNTUxOSBJcndkMFhyZzdCK0JDN2FZ
ME4rTWo5dm9yVGFSQS92M0FpaW5WMGpzRm13CnZ3OEluNWNnMHJWaTBuZXc1dk9X
VXRDOHlXUmloYUVYT2pzT2llYU8rK2sKLS0tIENJVUgxUzFxTFg0S1BScm5tNU5x
M09CZ0Y3NTQzUVY2ZXA3cG9pYUx1SG8KkZXHZmB5yBh/zoMBMdMwlHyjIQE31EK7
cwAfWYVLjk0CDM1JScTCy7RoQpbqNsMWFyUpu1p+1N0FE8IgefOU6w==
YWdlLWVuY3J5cHRpb24ub3JnL3YxCi0+IFgyNTUxOSBSZ1dKNy93WmNTVkNzOE50
SGQ3d1NvcXlMeW9LQ3JCT05aQk5qSTNIUVR3CmlDeE1wTUUzQVZrREdEeDZSeW15
dEsyd0w5OUpabEZHNm54UDlmaU41V00KLS0tIGJZTXhVdUJJS0VIdGdnV21DUlhL
MjNrRytKUXBXZWhPN2dpUk4wYUJyemsK5sspkZA7AOkVtq4e8p7QhtG2yLZE2TG0
qOhodWBMqi9VWnwg6HTKtQK6hfZ17McB93J4wtciCFGB7Pa8d79TFw==
-----END AGE ENCRYPTED FILE-----
- recipient: age17tagmpwqjk3mdy45rfesrfey6h863x8wfq38wh33tkrlrywxducs0k6tpq
enc: |
-----BEGIN AGE ENCRYPTED FILE-----
YWdlLWVuY3J5cHRpb24ub3JnL3YxCi0+IFgyNTUxOSBTekd4bHhLeVh3RkNsRjBu
V2h0azluRmJzalZGdy9MR2RENkY2WkpyakN3CkdFWHB3cUhQYkZlU2Q3d1ZtcUlr
UTBzUU1lVFZZaHUrUENiWlFCYXErT3cKLS0tIEZUcVNRN1QwdnNPYnI0ejRyNDBJ
QXJzMmFkdDh3SHJCSjlCQmVSKy9McU0Ki8UxAzALy7EPr6Nve8UGLmOCqstCcOfP
OkTpjXFcTBJ9wMj1ZXCoH3KYqvJSu0gvB97phnkN9X8aXkf2DsOCfQ==
YWdlLWVuY3J5cHRpb24ub3JnL3YxCi0+IFgyNTUxOSBEZ1l6SDdpdXl2cFNubjBn
eTU0UCtGTWhFYWIybk0yaGswKyt2clJQekhZCkVkbXdrM1QwaGZ4TXFpOTE1eEJJ
dUZKampwMjFzQXJqUUx0RTVwQzFoVnMKLS0tIEErNjhFZzhrVTJucXgwSVp2RlFi
QllFM3MxbXBBbFNTQkNKWHhyQ09EVGcKJIJ3DB8YmhlL+6sNhp38PojDBcDItsR1
SKyJC3nTJjwtPD/8P0LivCTn9Gi0Yjd5HVIXq/76RF4aB85HLZLgSg==
-----END AGE ENCRYPTED FILE-----
- recipient: age1mrnldl334l2nszuta6ywvewng0fswv2dz9l5g4qcwe3nj4yxf92qjskdx6
enc: |
-----BEGIN AGE ENCRYPTED FILE-----
YWdlLWVuY3J5cHRpb24ub3JnL3YxCi0+IFgyNTUxOSBwT05zbjVqY0NNQ2ozdEhx
MWFlMWpvMUorR2RnY1Nva3h3VHRjZTJiQlFjCjNtUzZxRlRlZkxGNncyQVExSVN4
UTJINkxHZU13aXpOdDhRNW56M3RXMUUKLS0tIHBqWHNIZ0dYTWNaclVDVk5sS3I5
YlFkckxlcjROank3eXdtdWhMY2N2Sm8Khqzk4NUSeaPBYkMbHBhBkagFBQs7Z9MX
HYLiY5pOdCkOteDSOGlqSdiKI7yVNsETjDXeXybLHk/RNaJbhvhqwg==
YWdlLWVuY3J5cHRpb24ub3JnL3YxCi0+IFgyNTUxOSAwY2VLT3Ara1dXTk5EVXBi
b1l6ekd2cEp0TzgrclVNMmR6bXBtZ2Z5V3k0CjRkd0JIUzBCd2NvWDJDU0FyRzR6
MHJUSis3RHlBSm1raFRSaUY2NHpmWlkKLS0tIEk3VDhLSnU5YjRzNWFtb1ZMcy9o
cGxZVnFhdXRka2drTGdkVk1iM0pFL1kK2ry7b2cLYPfntWi/BV3K2O+mHt3242Ef
sI2JLLQYHeAhxjFdCzP1RDR+Wu/pRxZje6xuTZ9I9TKNmm+LhAXHQw==
-----END AGE ENCRYPTED FILE-----
- recipient: age1hmpdk4h69wxpwqk9tkud39f66hprhehxtzhgw97r6dvr7v0mx5jscsuhkn
enc: |
-----BEGIN AGE ENCRYPTED FILE-----
YWdlLWVuY3J5cHRpb24ub3JnL3YxCi0+IFgyNTUxOSBQNUU3aE84RnpaR1pET1l1
b2dDYjZmSVd3N05iMTloKzVTc3phOVVGYlRrCkpGMUZhL0Ywd1dEZm5TYStCNjlX
ZUJnWU8yZ0htbHowMzNBekNRSDBjWVkKLS0tIDlXczh1VDNsdDYzTDMvK1U3TWxQ
V2tXdk9BUG50c2ZCMVRoY0hxeFlkYkkK+XdRap/LtxzZ3q4ulPRb3LQyeeuO0mu8
So+7G2acSDhcNqZtW4jsu/NzSNqcv1bwd4XcKe7xqVDVYRpN8LBb2Q==
-----END AGE ENCRYPTED FILE-----
- recipient: age1wrssr4z4g6vl3fd3qme5cewchmmhm0j2xe6wf2meu4r6ycn37anse98mfs
enc: |
-----BEGIN AGE ENCRYPTED FILE-----
YWdlLWVuY3J5cHRpb24ub3JnL3YxCi0+IFgyNTUxOSBhMW8wMi9rdStMSkx5dlpL
V250UlpET1k0NmZzaFpYRG15OG9NWVBKMGtnClFxeERxc1kvS1QxNTc0WFFQTDU4
UmNGaTluelF4NElXUWhHQ3ZnN2FYa1EKLS0tIEJHT1FZZEFwc3lxYWJFc083ZG92
TllFaWFqOXZhVldlcVJwQ09TSGRFMzQK+smZIE1hYx8urWrAqqAb9zId6ZblQesr
pc7lDe5AAumIh8t8tzFwl72XtSMrStDqaneibbRjr0N39L0xN/nhTw==
-----END AGE ENCRYPTED FILE-----
- recipient: age1zhxul786an743u0fascv4wtc5xduu7qfy803lfs539yzhgmlq5ds2lznt5
enc: |
-----BEGIN AGE ENCRYPTED FILE-----
YWdlLWVuY3J5cHRpb24ub3JnL3YxCi0+IFgyNTUxOSBnZ2gvZXFXNmdod1IxWm1o
djN2Sm1iVkpHYTJ4LzdLWVI3dGJIZTdQK0VrCjJqVnA5NFlXVGFFUDhXdE9GZmRJ
K3ZNTnVDZ2w2NjZEemRNUnVoaXJhN28KLS0tIFVxa0NBNlVVNlBDZ1pxSWRZNFY5
WEh5NFN6SFF1TlltdWFWTGw4MHRHUkUKrKIvC87xjEmwxPQhH8dN+ZuaJTCgPY28
pR62KxmoKFICLTHPpYP3euiAx5M9BWvgvCnA/US/5klpk8MtlreNFA==
-----END AGE ENCRYPTED FILE-----
lastmodified: "2024-10-13T23:30:01Z"
mac: ENC[AES256_GCM,data:vdsAZmg7gPqzeucBhLhPemtRVkcxRecIdB6PXZ4paU+Uv5UorBKcTZ3jseN2cLi6ot3ycTIm+UI6uhlCy87vAJVynVJhuJS+ICFRS2+DfoVyuttLjZQGC2sr3+dEBHxIH7sZJSo9PIzbIWw3qHrpOPAZj0//1pFyp/k15k3vidM=,iv:jWtV+WAPt08lgdrVvtXOl35rDB4QflkZWuGBW1+ESyw=,tag:YxSHncZZOAW5uDxXtb/krw==,type:str]
lastmodified: "2023-10-22T00:31:46Z"
mac: ENC[AES256_GCM,data:UpnaUfRxvdyzBy5x4EC3w5LQ1qWxILTQhpyVPd9whTzQMAivAHT0pVmP9aE4T9w3NcWTaghp+f70GmQXx/OCC6DsRCWtU9pFHRj12YUowM3yB5lVTOomOLZQ9m4gUXw5I2GZHWBJn8CyosDcBMlXz2tiR91v/8Ulh6sDSAO86U0=,iv:5GcgRvbpqDEslZruKHM/TcMaF52A5X7AK41DEbrsRIQ=,tag:ndDgCRyX1aDRnzEUNmpoMw==,type:str]
pgp:
- created_at: "2024-08-04T00:03:46Z"
enc: |-
- created_at: "2023-05-06T21:31:39Z"
enc: |
-----BEGIN PGP MESSAGE-----
hQIMA0av/duuklWYAQ//TtjTsxf5xHnu4g5Y22qvyMud17MN4j4hCoLXjRSbzG8K
/E+0Gs08P3QqV6DddmLvxeAcnLBTAdE4XCMFsRX9eK0BLqPe++yoamOpoPe896zm
BW2BXn/oemGdOFVOf43LRuMEYn32pjg4RNzR4bn3om2TY3S0nr7GP5J9B1QrSPfH
AFdR78MwX7PrOkkh4jSLPftjAI8jUtvS/TzX8AXnzy1A8xSkWxww00GMvTvSSAwZ
wxU6fePkLwuxVwZVqI5pdsjAscwy7FE7NWDgE9GMIxxwAJRRwJcsJ+eVM6ykWMyq
Xqo24kWkAqgs7vbxU55gOqPVHN50M22fQ4+RYaLnLyj6BO+0WegW1OmK88q0flaA
QADZHLGrsuiVgc4KxHskwQou1RuHZnPUSqn+Nhnsp8rtAfboHS28v7ekRNTmhTWG
qPVPlOlVnY0AemohDjBnk3o4rCxJhviL9KTjmAtIGTK03Fqzk2v23H3+LRo/rocm
gQCXzN6Igdwn7n9x8wXmuO6iL9Jftu4MoaQ0W55hZiBfh8pG76TGdNhycZr2T40w
MBnRX3ydwH2T+y2pGM9tJY+nlgGsyTiOw01SN7/mio3YdCSvChXTkV3PaX28u+CJ
5TaYLM2IP8W5DJU3r3dV3I3JYED1O5Arq7Xrv5Z4qr8vwamnCN6SZGe2qCqxTOrS
XgEHGwiK1pFQIBxkI0gFmGX0ckd1NYUfsUCyYrFkcAsicWetBhdlgMjLc86bVHwQ
7p4iGLGsr7GZEArBnP0J5Ee+Hr9MCiW/OCLY4M4jlTsyimlsdgDgyr+RqoOnvig=
=SRZU
hQIMA0av/duuklWYARAAmj8qTRTeTXx9PNtqOFwCGmLlKGhj860JPE3BUR2n3QOE
h9fdVJa9yqK7Lshyuf2t1HbgG+Ah4p4BaO5gYGsMLV9ybZpyNFuCgSZ3DZ4zSfxM
GSqelcHJF5qbV5gwoJvtyVFV3qtKD9FpOJwh9MfEVe98VkoISCQsPl3CHDH4ot0l
zKa56vOReHRmaCid2LNsN0nHlh1KPpwn7HdgaKyiPFexMFe4L/Q56UrlZx9XyPOb
AJ91ayfI6jWH8Hj0xxyqx0shdA74nJ/Y6ZB3JxLXnGuPvAlC3XJRQUImqYsa7p11
4Hus4hRAGEJGpmpxhazInHkWOT5ECtzxMd5LlUSq0AGYlEWJL+jtnrvy86HqpYRj
jpMfwsuwY7dJ0Tll05+goWqn0zB0yZjax71Ynky/ie5Iv8FKaUHHh2HWAzqjUaKg
6Yp3hzmMdP61fAm7ka4mxQLXQ0lrUbVnOk+pkaTrVrhcQial3W3lIgIhyo0EVi2V
Z7yEFkec7XZieMklhkL7tq9SJlWJYG1T+bavD7JSWjOXu+NlSP1hLKytM7xjp5jH
qZMEsjOaUEPvIO8Kd1f8MpLLe/+EhtmQJJMN8lwA8t/N+aOVYsW1GCspwX5mI+Ob
ZCIPkmeBz+UhJvqFD9QwWB44VWH7429VCg9hL+iWR2UfIUQHQhRFWD3604QBppzS
XgHEqjgLremZkvBsTAZsaLrTFlm7KwgjZsAkA5k+RZR5SH7xCXoSUSMnM8pWTway
24M8mPHKyshggzR5B50YME5BY1qVKtOMEmTjwN5gpn4CQDcsQ7A3eafZg7uGd64=
=4DU6
-----END PGP MESSAGE-----
fp: F7D37890228A907440E1FD4846B9228E814A2AAC
unencrypted_suffix: _unencrypted
version: 3.8.1
version: 3.7.3

View File

@ -0,0 +1,39 @@
bluemap_ssh_key: ENC[AES256_GCM,data:2kv/cDEEQMHJdwTmmTxtyxOZz8duggaT61U69IuiOJ2yuwqkujOHZ2gkCtGa1VyFPn6wg4OTiSA/Loz+QmTSKz+8HqvY/Lybks+offDZ1mukL5NiWLUVmNZdfdHaMeEyiZsxiMoWEgFtMiKvgmdMMPa/BCHZCMCxMWFAcuiZgbhGyGukdo0wQd5RcEDaY4JZ7q95ndAn4K7gi9q1K7MLOvI5t2hGibj8DrqriXqg9mahsiFZdKWxjf3tBX0MzS85wAtleQWXmH5FRvECmdOj3OSp92JMqU/WDlQih3xjnw1Ci3L/hdwgGLHZTf/RzuPpGh2OD26A7gUjOFh+M5z2dVVtZ40F8tQFxpQxkkJBsqTNbDKuw7/KPpZUJkn4UYBkhzraG/62md/9sS9+GjTHBhfYQYHbDU8ZbPO5ZSoZfshRDUuP0qYXiQw7cxA5BQIhwYdn26uy2ghiHsP713Tz91ESVjlCZLLduGySWEQNAxSdzFu9yEyp4xdl8l9udlnxVV2/5Xm5kQEdiUMwiBpUhrghdEl6lOzome5h,iv:uiYaQgOnhFvWze/oHGSpAu8+m89l4tGCgRauDzU3ZqE=,tag:eCYgCH+e8hNYpBIFWFOTbA==,type:str]
sops:
kms: []
gcp_kms: []
azure_kv: []
hc_vault: []
age:
- recipient: age1tmn5qahlyf0e579e4camckdyxrexjzffv54hdzdnrw7lzqs7kyqq0f2fr3
enc: |
-----BEGIN AGE ENCRYPTED FILE-----
YWdlLWVuY3J5cHRpb24ub3JnL3YxCi0+IFgyNTUxOSAvL2dqdHFwWURFSWJEUkVl
eXR2cTQyTXpzUEFra0drdUgzRUNmSXA4eGc0CmRoWnp5UUUyQy9kK0dHVjF3WkFp
M0loS1RXeWxHSGNTQUljS05jaDBxMDQKLS0tIDhyUGdvcE1iMWxJeWhYb3JFTi9q
Y0RrVHNhcVU3WFd2NitlQ3l4Ry9JTkEKALBawjOt7hChok/cHRa38HkB0KVEKvik
r2jO26j9AUU5mqjR/dIko3jvfcXoNUNRYrMwaBfRa6AFnNBoN3g0ng==
-----END AGE ENCRYPTED FILE-----
- recipient: age17tagmpwqjk3mdy45rfesrfey6h863x8wfq38wh33tkrlrywxducs0k6tpq
enc: |
-----BEGIN AGE ENCRYPTED FILE-----
YWdlLWVuY3J5cHRpb24ub3JnL3YxCi0+IFgyNTUxOSBzV1R0cWxoTXNKNnpsUjE5
c01Oc3J5M2F2cDVKOTNma0J3eFVwa0pXQmpjCkdxRjJZTlFWSlh2UFR2emx4OVVY
T3gzSWdXNTlyS0VJSXRnTXZweER6V00KLS0tIGdFU3oxZ3lzQTBjU0hyYjV5M2cr
VnUvcGZDbEZuZitQS1g1NmRtb3JnNDAKV6otQlYUSF5ScyYL6LlstPU1pkLMY8r0
/NEuN9A7l2m9Wy8iItx+ZhwGp9pEPsgdsQLJQtJFfaA6lNuFhbgqfg==
-----END AGE ENCRYPTED FILE-----
- recipient: age1ju7rd26llahz3g8tz7cy5ld52swj8gsmg0flrmrxngc0nj0avq3ssh0sn5
enc: |
-----BEGIN AGE ENCRYPTED FILE-----
YWdlLWVuY3J5cHRpb24ub3JnL3YxCi0+IFgyNTUxOSBNbmpMaWhpQTQzR05Cd0cw
b3dJRXVoUmFzZGxMeC9tVk9acndMemlrTHhzCkVtMHJ1bE94T25wRmpTZnpHbUdq
NzQ4T0pLZW56TEV2emQ5RHVXTDAvdmsKLS0tIFJ0OWxNYkIxOVBVV1hmZDdoeEhm
blB3M2JIMmk3Tmh6WjIzQjlHSW9GNDAKB3gdJL9AlF4fsCMujd/6HnieDwhCZnex
QDU87yTePHAppnqLp+ZuVdSbqcsnQclmbm92M3S6LuKpoDhGxeHrEw==
-----END AGE ENCRYPTED FILE-----
lastmodified: "2024-06-08T23:34:34Z"
mac: ENC[AES256_GCM,data:CLsz6UgS1LO/5SArmT7utald3TzQUWwEiSRw3dF1RaCwyb0Fc16/5DxJSk0KGLiJRlDXses/ynSjoyaBdTagijJPKQZCpx3fHZFqEJk6Wne4zQ4EoFbY1SpPrkhGVGMYaUg/H/NapoAEiq619YudR9W6GqF8ZkauXE76wls63FM=,iv:I09LFoSkeMAWHmvXtIF4+FURZ4tOQGCXQqbNrKz5t7s=,tag:xauT9sah+26A9pRrwXlsiQ==,type:str]
pgp: []
unencrypted_suffix: _unencrypted
version: 3.8.1

View File

@ -26,78 +26,51 @@ sops:
- recipient: age1x28hmzvuv6f2n66c0jtqcca3h9rput8d7j5uek6jcpx8n9egd52sqpejq0
enc: |
-----BEGIN AGE ENCRYPTED FILE-----
YWdlLWVuY3J5cHRpb24ub3JnL3YxCi0+IFgyNTUxOSBNbW1FZmt2ZDRZcWs4SEkr
R3ZDaUgyVlVvRHNNRTZCS2pxQThsT0NmYkFJCkk1Y1NpT1RSTFp1MWJ4aVNrelVx
blYvS0l3ZHczaVcvZDE3U0k4ejVtZmsKLS0tIC84WEE0WERiTCtKNTN0NmZUbDhV
c1QwV1l5b1ZQNitFRnFhQmIzSWNZd2MKokg6XMIFfjxB6sO8EBjBc7E7Ur3zBw1o
akXuA4I1Xw2H1W8B6HkVSDp4BpBEe8xi0z8TUmzkA9/IBoypG5EJKA==
YWdlLWVuY3J5cHRpb24ub3JnL3YxCi0+IFgyNTUxOSBURkY4WTZhQzJoREpxV1Vr
aUExZ1dxNkIyMkJtUXpqOWtTT1J0MGpmMkY4ClR4Wm1FTmhKN2pIMENRdERrWVY2
SUlHblpEc3VackMrbFpHUUJwM2ltZHcKLS0tIEovMEtiOWc1L2tzZDh3ekZKbStr
NEFkcW03ZTRJODNxTlVuUnFlcFFUUncKEZzOeUtRsZiuugTLzG2xU4eJ3XtVuop7
hhlDBL/YoFn/CO3HjqFdCVv33QoPu7KKMeV52pbVEnv93mvdEeFxVA==
-----END AGE ENCRYPTED FILE-----
- recipient: age17tagmpwqjk3mdy45rfesrfey6h863x8wfq38wh33tkrlrywxducs0k6tpq
enc: |
-----BEGIN AGE ENCRYPTED FILE-----
YWdlLWVuY3J5cHRpb24ub3JnL3YxCi0+IFgyNTUxOSBrQzVtTFRFTnNNQTFXL2dF
UC84d1o5Z0p2by80QW9Sck8zVHJvMjdjd25nCitBRWtzVVdTUU85RzFpN1FmOVQ1
SlNESXBKc1BUdTRaWk5nSENvUXdraWMKLS0tIDlkUFZRVUV2Qi9iSUpFRmN1Tm5S
dW9lTkxsNXBBN0wwZ0NFbThRdzlvOU0KbLzteBt0VTr825sfKLNs3i3FT0/dgn2z
kOpJQf7KZKEVBkInUOkPmobtw6oM9vfWha035tTJPYjWy+Lp939tBw==
YWdlLWVuY3J5cHRpb24ub3JnL3YxCi0+IFgyNTUxOSBSY3cxSGFvdDdWcFVLRTRy
Zng2VnhjZlFkc1RQN0NqUjJGeW02WlFaMlFZCjVZc2x2UXNXS1I2WDBxeHdjNUdr
WnZGc0l5NlArekUwUGU3Qkdub25EVm8KLS0tIDB2bGo3ZURtZ0pSZjFzcGpOdW5D
aTI3aTBUS0d1MzFmMTVMbUlFYTR4VlUKzOvNCAzan1GTXjoRxeySkUYIYtI4Mpvu
MC0Q8e350SyoOsrF7fUvw+Ru68fDMLW27H6Ly36xP7D3eo/h4eZVXw==
-----END AGE ENCRYPTED FILE-----
- recipient: age1mrnldl334l2nszuta6ywvewng0fswv2dz9l5g4qcwe3nj4yxf92qjskdx6
enc: |
-----BEGIN AGE ENCRYPTED FILE-----
YWdlLWVuY3J5cHRpb24ub3JnL3YxCi0+IFgyNTUxOSBCR25sQzNkMHhETzY5cXRm
Y3QzYXZOemFTTmN3aTVpODlQclB1Y0JRNlRRCi9wQWVGUVFYd3ppMUVMdUVQNnBC
bVVRVHlsTWIzMitqNlQxN2NKcWl3a28KLS0tIEJrNk44TEN0ZzJ5L0JaKzFZaE9M
MmxPN3RUT0hDRW9MSm92LzZJY1lCZlUKM+r/35me5K74KkidKLUTZxqMqR++izHK
69gXZEHY+ZSvJ+9IBzcIxcFdSFyVUAN7wobBWZGDxmGJRClS/8jcHw==
-----END AGE ENCRYPTED FILE-----
- recipient: age1hmpdk4h69wxpwqk9tkud39f66hprhehxtzhgw97r6dvr7v0mx5jscsuhkn
enc: |
-----BEGIN AGE ENCRYPTED FILE-----
YWdlLWVuY3J5cHRpb24ub3JnL3YxCi0+IFgyNTUxOSBXbzZHMHVqVkVrTVdiUmli
OVhhVTZhbVRVU3VKd1Jxa0Y5dlFReXQ0QmlZCkVtVEhCcVlHamozeDYrQlVvRjlZ
YUNXM3FML2ZLOW5PZ0tpZjlPc2lpdlkKLS0tIHVXZHoyRmlscSt2TlpLb2lDd3Bt
bmJJS3JPWlVMd0FRaExUZEZMdXk5N0kKY6qYVva2aOkvo1huKH50gkT1iQAUhZCB
ieUD1aQumHe1OYVeEWJCf2nYgApwq1tPjea5nqc4VzOogTbLVcKMFA==
-----END AGE ENCRYPTED FILE-----
- recipient: age1wrssr4z4g6vl3fd3qme5cewchmmhm0j2xe6wf2meu4r6ycn37anse98mfs
enc: |
-----BEGIN AGE ENCRYPTED FILE-----
YWdlLWVuY3J5cHRpb24ub3JnL3YxCi0+IFgyNTUxOSBrNWc0RVNQRzJkRTBKS2xD
R3ArQ2lkc3F3QXN3bldZbkJMaFhoaDI4Mm1RClhuSmdRbWxlM1lxOURRWWVocC9X
dWFSOG5yN2x3Vm9CZ0pSN1BLTWk1ZmsKLS0tIHRpRmJmL3FmaTFpL0czV0tIOWhX
NHZLaEx3dEozc21MR3ROWHRBQzR3T00KQQiQ4SxpyMTDZyGY7TZrdQEioZAB+BQ/
u24WgbBdSP6VDvqmq2gG8BqZ3Aog2/7SQ0CVzrsimAoXi7YCWCTetA==
-----END AGE ENCRYPTED FILE-----
- recipient: age1zhxul786an743u0fascv4wtc5xduu7qfy803lfs539yzhgmlq5ds2lznt5
enc: |
-----BEGIN AGE ENCRYPTED FILE-----
YWdlLWVuY3J5cHRpb24ub3JnL3YxCi0+IFgyNTUxOSBVcERwTTJmdlgvZjhWeTBP
eGJ0aG5RQ0xrRVBSMldEMEFpUHo0TnM1aFNzCkhReEZ2dWVGelNadjdITCthcTZn
RzlQZmh0MzF5RmZGRW5UVXhYL3RHRFkKLS0tIEtrV1ZjQkovZFlmcDM2OUNYaHZx
WDRSdDZRa1lIbEVTdDlhU1dwUXUzQTgK5iE4Cf/zjsPYHKcqYA0rFqY0TNcCnzNU
vTM+cEPaA+/FXTwLfPpaiSkg5Fq8k2XdeMQsjQnglTBSWCwAJin27g==
YWdlLWVuY3J5cHRpb24ub3JnL3YxCi0+IFgyNTUxOSBFbDBYMDNQcWkySC8vN05t
U3hLMjlYVUE3Zms3U2R4R0VnMUtFcmVQclZvClY4aWZEYWZPdkltMElkUWxQeUtP
TEF0a0txbVQ4d3lrelp3cG9TbG5OSkEKLS0tIHR1V3JIVEwwUjM3RVdES2pQUmhP
T1MwME1tbGQ2NysrOEVNYVZRT1R0YmcKFpfe9GfH7s779CNQswRm/W7zwYO6wK11
z6IGPxtBlUGdshYiHA1BEz7fMVg3ZolL2D98cTNMM24U89Gssiw9qw==
-----END AGE ENCRYPTED FILE-----
lastmodified: "2024-04-20T23:41:59Z"
mac: ENC[AES256_GCM,data:38Ask+adT2FshF8DYEfCWeVWt4KiaJsTXhF7Ib3xxdfQ6vAixM2OXTaK/qqUvN6gQok9TFF+HMJBJ+jezV00nVcKUYn04FaU2/D2zdam44eEEYEEovmfAZ6vbC+CiDv4d/DCc3hnYtDZCEgUTfP4gsZ9rLZFAOwaOFWRJxcDi6Y=,iv:BzuWdTjn6LhscNeouHjM7IYKxTahA8PzzlHSCYZ618s=,tag:BWtPbNwzdOJb788eOO5ZNA==,type:str]
pgp:
- created_at: "2024-08-04T00:03:54Z"
- created_at: "2024-04-20T23:15:17Z"
enc: |-
-----BEGIN PGP MESSAGE-----
hQIMA0av/duuklWYARAAs0o2EHlphoU4JcO5fhmplhmHQp7GXjaUc5zakGACrl0w
0NVVLXf3hlb3saPgbRkf+ugVXd5dRDYfa3vbIDKpQwHVLSNVrVb7M8eIc0RXM41q
MqpueXLo6YfxbgOvsfNlgCvDFgMoBMVv/rWz0QGTj8VCvD5AkxiLQJxZ8TnlKn0w
NF6yQ7LCGgKVU8YHpKYjPmmDU/VegRYVe6wz4ackk0MZ5ITSFXF4qOG93Uj2SZfe
ocpPYZ9BrOnxzCYd9ZS1yUmMRLRC61l66oG1hGrBTN7fcmHZaycCdcvABWOB/fxJ
940zMb5NYK6whToCWY++m3I6123k+/vLJe+3NoFc/wYdvpnxVqLZqijxYPZZkbRN
gCtRE67AFWny0VQ2k1CGzBGbRAxM2EtIfDlbNgMUNBNuGST4tgxApp5QEa1yecHC
mr3jDhR8UuFdIrq2sTz/uMUptTrsB3oaZmfuZ47pCVHtDNc2ri4U1gsI6oI03utO
u/q6nMHiJlf8HUwI59GemBaHTiMgzKl0REAoV3SpdfjWSDZiro42au6E20M1dgup
rQG8Gz33QnIHg5ezEHcTSeHk3SgMTbAqQy7/aD3pqI6wEgXqU2neDFZEkNu4FnzD
ofnm1oAGnbOIH2+SFtd33hDe/2nuFBo3CYEyz/fezhbMwCwoA4Iwd7FBQW4ideXS
XAGU2gt1hdPfgMQ55GeRI01C2dqiLQOpvTHy2uBl9ekPtSw2Ws27hVhdHvU7B5ZG
Jr388jC5d5dKGNv1I8nVNlfmPvb4hwGazrHdCYiQdwrpggajFtWD/LIgUcW2
=aK5J
hQIMA0av/duuklWYAQ/+LSTWjii2dblTAkuqHan3uuuRRpt1ppmHEgHYkQZD+RzE
g+ljNaM/BPqci7Kr1NHFDw+cU2MYm/40Tz63l1cvfE3NEoVefsmoA5voNI3G/bx/
LTAe2aacPwO/TNoLtrCgRkzNyKXluUkM9OoIvkvB5DEGjYbe82+gI5Zi+NbW9N/p
5ilr9Cc1jvIivjZMGGPLRgkAc/twOOuyrZlsFd9kddAL9YFO7wpd/dko886y1jE5
jz9n9F4SKYOcgLPqZuG1iZ8qaA2zGT2bP2caai/QJAmL90stQCiRWtQgB8KeWugm
nRFBm5BLamtoqjXXwzdtXGKbFAhvL5/h+kPxnJDjylfFVbgCpoWJ/fxdE5xxxZtq
zCcGCQQsaa85eWkBByhu7TdwyAW7bJCm8z6kfFPGqhNDkS8ifxnEWm6ulgYVokiL
WVBvuQCd1s8KSExs6zNWGcGlqgvcbovHXyVlmLeqZfBA7i/vYqksZtBT47rG7nCS
YGfHy69yVrMdj4KrLuMXNfjtS92hkQqWmCyl5X5zOSJXqEL2dorMzSZn89gK4nL4
V4zOKkKtsj2MqynYn/XAoUf3AfYs2wtRhJiU+r/q+rx9Hx31H8mnUuUerT58yQCY
mAkjIhTzvZcWIalQo7xnZhos4p1IYaA7MAuGC6HxuWVaOsyiFkRaKwB9svWyZ/DS
XAFID3fQ1xfNyYsW8nvXQmvZubnhE+dAQPaiAFP9ujY4RVXWBFOrV6NAs7y/LID/
89lpfWN87JWSJWUk6DCD3AQ+1GiBCFy7uswUJkG4zou1RQBSl7X88ziVDILU
=tXkN
-----END PGP MESSAGE-----
fp: F7D37890228A907440E1FD4846B9228E814A2AAC
unencrypted_suffix: _unencrypted

View File

@ -19,78 +19,51 @@ sops:
- recipient: age1gp8ye4g2mmw3may5xg0zsy7mm04glfz3788mmdx9cvcsdxs9hg0s0cc9kt
enc: |
-----BEGIN AGE ENCRYPTED FILE-----
YWdlLWVuY3J5cHRpb24ub3JnL3YxCi0+IFgyNTUxOSBmLzAzMzNCdGxSMVdiNUVK
SFlJeTEyRW5SenQrMnFGZEJ5TGJxNDIvSmhzCkdBUnYvNDVxZ1ZNSkYxanZQY3Iw
akhuK01haFVRTUlKcjloVU9QVmhldGMKLS0tIDZmMjk1WlNNYUFXN2pWQ0oxRjRv
bzFmcnJUaUJmU2pCZTRnRTZZZHVkQnMKrKLbYFE2+0rj5BUchhYtWghzbRJTFDaY
+RQpJC+5gSinmUuP3nMGR2bv+gL9v/EOJKeVrC7/sZM9mQeXI36CUg==
YWdlLWVuY3J5cHRpb24ub3JnL3YxCi0+IFgyNTUxOSBXY29wUXJnMURlWk4rUTRh
alZsb0xSTlI2MFFTb3B4dzhDT2l5M1pLMWg4CkgzT1h0VHBMTTNhRTJRNEZLWWlk
dyt0aCt0c3NTR1ovS1FIM1VBTW9Ha0kKLS0tIHN0eDNqbzJXQUZFcTFGaFEyME5t
djJpWDlRNGhGemZXR0tMc0RhYVZpMWcKG/Airf45TgfJ82vPfXxMLtRRLPvZR/Iu
teoToXtddxFVY675nFy0gfq9P21qHJ7MvTYwVBhQAT/TitTZ/q2u9A==
-----END AGE ENCRYPTED FILE-----
- recipient: age17tagmpwqjk3mdy45rfesrfey6h863x8wfq38wh33tkrlrywxducs0k6tpq
enc: |
-----BEGIN AGE ENCRYPTED FILE-----
YWdlLWVuY3J5cHRpb24ub3JnL3YxCi0+IFgyNTUxOSBtU0xjY0NEelJvaFJEdjl0
YVVDYXFxbFg4d241ZjdRRjZVM1lJd0R3NldJCjJQRW9EOGMrcHRUNlRhNEJ3cWhS
UWlycHYvaXA4TkxEVjZ1QThQUTlrcjAKLS0tIHNXWk1mQWJFcmU1Qmp4a3YrRngy
LzZ3bU1nd0FLa0hNR25CY0hzNS9GZjQKRoRMDXESUtwRGDat2gJ9Fjqy/m6FThzk
k6byBSt605skrUd2YQZ+JF9cUs6p9y9Fm6t+HfK/kHQ7jchiS3ZLmQ==
YWdlLWVuY3J5cHRpb24ub3JnL3YxCi0+IFgyNTUxOSBxQnlmMVE1aDRycXNmclk4
OWgyQzhDdzJrdlEvL2NzeURoa3hZa3lEMzJJCk11ai90L0ZGd3U2VUhHdm1mQ1VC
eCt0WjVKVEt0N0tkRHl1QW4vRWdtMG8KLS0tIEVjVER2QXlIbnZXQUNONzlGbnRl
dDZ4RGFqaktTZ05yNjhqUlhqQmpBcncKTSSe5rZhV/+tsgk3xlV7nEphS8qhxucz
0O1J0U8FEdyfrwF2AOobsf4YIgtTrb20gyXsTdPwIbsQToJ+YqVAgQ==
-----END AGE ENCRYPTED FILE-----
- recipient: age1mrnldl334l2nszuta6ywvewng0fswv2dz9l5g4qcwe3nj4yxf92qjskdx6
enc: |
-----BEGIN AGE ENCRYPTED FILE-----
YWdlLWVuY3J5cHRpb24ub3JnL3YxCi0+IFgyNTUxOSBuSjFQb0I4eHlhL0NMN1ZF
WldhZ2ZiTTZDMXM3aXgxeHUyZm43dmVVNlFvCnQzd0VYdVd1azB4dlJkdDd3bE0r
VHlwMFZzaUhkVzhhanl4cWxGWUlDWFEKLS0tIFdWck9qVVRoTWZsK2RNYzF2WEhN
eFpOY1UzWHpYb3p4eDNRU1VSdnJyZ0UKrF9vihQPmmv4nrDf+tPAssfZLNJbdK1L
N4IlFTUPchiPW1ss22bjtiooekHAuP4ygePYLKlKEi3w1SsKa9REGg==
-----END AGE ENCRYPTED FILE-----
- recipient: age1hmpdk4h69wxpwqk9tkud39f66hprhehxtzhgw97r6dvr7v0mx5jscsuhkn
enc: |
-----BEGIN AGE ENCRYPTED FILE-----
YWdlLWVuY3J5cHRpb24ub3JnL3YxCi0+IFgyNTUxOSBEZEhYTVRBWVJkYndjOEZq
WlF1UCtJN3Uwb0FNdHJITTdiTXZVRWQyUFh3CkJOOHRHSHhXdW5uTEhVeTFHWWNi
QTd1cW5YTkFJZTRaN2RaMnRKQi93T1UKLS0tIEwzSnVleWduTkRhMnduNVFEMjFL
NmVHOFd6eVhXdTQ3RE1adkhUaHB3TVEKPFmS1njkM6FPToIKML396vfM3T39co/v
mvyOUCq921mTIzlPfVpfpXd9pmiyMKi/spDS4xZ2nFLyHMhXMKW20A==
-----END AGE ENCRYPTED FILE-----
- recipient: age1wrssr4z4g6vl3fd3qme5cewchmmhm0j2xe6wf2meu4r6ycn37anse98mfs
enc: |
-----BEGIN AGE ENCRYPTED FILE-----
YWdlLWVuY3J5cHRpb24ub3JnL3YxCi0+IFgyNTUxOSBXbDVRaU9pTkROV0VoNm5p
VUhsenhxR1cyTFZVeDJZd1gvVUx6TXdQY3hzCnBwUDZmaE5FdFdVODZFN0lxbTdB
dXRBVHpUak00RnZBRUpGeFRuajhZK2cKLS0tIGRaODBlM1FnRU5iV0RrWDlEMHUr
U3AybkRZV2EzVjE1QktEcjdwNG00dXcKnWaJwHyA4Q5RFgOWg3wbPwL4E8Mgijph
wCuujSzIUMGBqIBzr6ADbQ38lnUSKjGz8EQyrIa4/vILXzuJ/44SbQ==
-----END AGE ENCRYPTED FILE-----
- recipient: age1zhxul786an743u0fascv4wtc5xduu7qfy803lfs539yzhgmlq5ds2lznt5
enc: |
-----BEGIN AGE ENCRYPTED FILE-----
YWdlLWVuY3J5cHRpb24ub3JnL3YxCi0+IFgyNTUxOSAyQ3RYV2tYVy9ubFQ2cTg3
L0xqNlcycHZiU2hlRGxmd05EZldMa0xMWENzCkhHdmR0dVRYMjZkdit0Mjc4dy9X
ZEtLY3hrbUZjaXpCdHBhVm9wZkJ0WlUKLS0tIHdsNHhNSEZVSHRuWE9tOXdoY3ZK
Ti9TOVhUWVdsVmw2U2ZvazVKajJSRTAKnAxtMLh5U4xL3UsLehdo2JMBRcX9Vy+X
oWlgVviORYtHaaU7Y9MFTmhV3OS+He38wX0l4NZOI0d8mZ/6uJ1JMA==
YWdlLWVuY3J5cHRpb24ub3JnL3YxCi0+IFgyNTUxOSBxeDVwdHEvUk1JTW9FSkx2
VmlxejM0ZkJmZ3JkemQ2cnkvenY2ZmRJRFZzCmFHbUJzZ0VjYWZuelZHei9SWUo2
bjhPSUNrRW5JTWhVWnRzOU9sY25BMlEKLS0tIDF3M3ZFei9qczdDaGVsV0hrTWVU
NktTc2Y4ZDV4VGlza1FVdXBQUUVPZUkKYs9b4a+yAzI5kpv0X5/Ogg8sH0zdTim7
fXnkXZfAJ9oL/0qjVzFZA3j5aQX0xKMffSE/SFcQxUY2sISnwh1Tfw==
-----END AGE ENCRYPTED FILE-----
lastmodified: "2023-02-13T00:12:03Z"
mac: ENC[AES256_GCM,data:FolV94dIwYSL5r1ZHTPdmqMKVTAhrnePG+5M4S1H/wBYbED3sr6oPPmmxwiwm5E4K0YR1+ou4yR/vGTV3lfRdxIGWhfAT0WW8WGTZVIlcJCEk5H7Rels6rkma12BCjZ1zOGjZZCcFTm+4NI2KNv+zTc29zry4539jkkxk+8Skog=,iv:KBxSFVaFI3S5J9xG2Lc7FINUI8TRKxPtrbP3f2wXkHo=,tag:TWAtix03ZnB71+O7cF8b4A==,type:str]
pgp:
- created_at: "2024-08-04T00:04:00Z"
enc: |-
- created_at: "2023-03-26T11:12:37Z"
enc: |
-----BEGIN PGP MESSAGE-----
hQIMA0av/duuklWYAQ//QIfxaAOVl0QStvZe6irI0GHS8+7EExn88dP1QdMnVijv
W/IiVffs/Bb0t0hcNFY3SaU4ea+zOT5bdMOlQGA383hTYvwXXdI+uSFmn3hrysZS
eY7394Z9c8jubEDXfJOHTt0mbpfzOglZjiCcQYnZlhkgOzilDXMCjVsjVvuAN0bz
MFN/DjC50fIdlaeWe7h7NgK3Mu9j39tUrgDCGn2YlCycxcpPz8+83Ge8bOnyskZs
P/04wfkOGSrwb1ingxHjZP9lR2NABdqOqSBzC+x7EQs6xNAmC4XayeTnASBDYp8B
+H/3Hiv1nWtS//PQr/5+KHR1/iLaSNI2fUAUFimIwEQTU1vpMaV2tVmJtpmSQRAg
MpwljVoCSWvhmU4oZU8ObTjcMy58YfWHIOcIN2HHgWBVdITve3sca6J1VHs0rWFm
4tqPElsfa59WPy3HKLGg8pPahoBlj4X1PGJVHxXBMJsPnbX0gg6V7ajQaVdOsJAF
LMgAel7eNq0KBzk/rrVRoV5ii2lipUtKmb+FKTXKvSnwgqhVNkRppsl9BqgeXvTR
P7AsKnNgQBydz9vDTkDOuspyTluDmhXkwNQyhjH0enPAyeQWN2qs/A8qgmfdTXff
TzvlfOEy/6r4zl7V+L+qcw0pYrzi5K2CtemN8TlGhRvAYgiURY/78kD6EGrjMLLS
XAHBQn0q8dYgKf2uA0JcfNehgpI5fr3gZxQFKhnuXkXRa5h9hMn1mzdhtO4VyN1e
d8eL57iFeApC9SAmAGMOz0DBbskD470qnYObUliViWQpcj2VR6W4BwZG28QX
=iviy
hQIMA0av/duuklWYAQ/9GHLOAfLgTqVmfJACvt9xMqlzfrXyiACTJg+J5BD8hEtn
oe2clo/fO9u6df42hk/szQTQH4rJULdxvUNiBzYS0XbWCa+iWzpiOPN+bQZKoV3X
U4sFrHMT0ledUg62rlTbOmqpvLivoP6//DEqHAWl2weUvpplBRFzTFwICo+2+Jjo
18dzdYyBa5sxJ/KZKUoNsxRaCFgXs5L6qTuqzmZpnhnH1pKNW3D6e6Hfb0BmebUy
wt5NgxWJ/4dHFK84i93E1vxPbSusvQ++6JCSWgZtOwZJehnz5AeHgdDBzcHeJY8O
Idq+QrvRsqjisDNvd7blmBleup1Ai0l/CzEtTEYd/h/QipaT1rVaPOP4H/lnHZmO
f0HWGxhPCDfiuLK43DBExrj1QUq4LVUZf145fRGMWZfHtlzHM+4dY+/ijyUi7pFY
cenrE3/Iz8gaUWqRdaYqK/O/vrHq/siUS8IiWY53ALUF+DlBMuRrtc76T/fkSKbR
LuO7MnOnNyBy5HT+MQii1Tat7ODtPXlky+N5leVQQVAUMHrI6ETWAQlctBjDZXyT
UzXh8WVT+pijxNYDqUVMJ4d43AuHKayf2m0PftOZv+Q8n5ZqwUoQN6WbpsLvDFTU
4XweZaChhoq4K68o6vpOb5b7x+vlisiL2j+kYAgMjlWk1vkDY/GsHY8USi0Rj17S
XAGAULPvLDP+ohieT6dP2xLvzu4ghrySCTF6LjQ9sN2gHWfcV2FVw+anA3mxOLGK
P4hOgPPfiP/0O9H0KSHq0gXjhBkackFVAOPixvSAJdvkooVW+PisHjl59Jd6
=exZj
-----END PGP MESSAGE-----
fp: F7D37890228A907440E1FD4846B9228E814A2AAC
unencrypted_suffix: _unencrypted

View File

@ -1,14 +1,9 @@
{ pkgs ? import <nixpkgs> {} }:
pkgs.mkShellNoCC {
packages = with pkgs; [
just
jq
gum
pkgs.mkShell {
nativeBuildInputs = with pkgs; [
sops
gnupg
statix
openstackclient
editorconfig-checker
];
shellHook = ''

View File

@ -1,24 +0,0 @@
ignore = [".direnv"]
nix_version = '2.18' # '2.4'
disabled = [
# "bool_comparison", # W01
# "empty_let_in", # W02
"manual_inherit", # W03
"manual_inherit_from", # W04
# "legacy_let_syntax", # W05
"collapsible_let_in", # W06
# "eta_reduction", # W07
# "useless_parens", # W08
"empty_pattern", # W10
# "redundant_pattern_bind", # W11
# "unquoted_uri", # W12
# "deprecated_is_null", # W13
# "empty_inherit", # W14
# "faster_groupby", # W15
# "faster_zipattrswith", # W16
# "deprecated_to_path", # W17
# "bool_simplification", # W18
# "useless_has_attr", # W19
"repeated_keys", # W20
"empty_list_concat", # W23
]

Some files were not shown because too many files have changed in this diff Show More