Compare commits

..
Author SHA1 Message Date
h7x4 a5dbba9d4e flake.lock: bump 2026-08-10 04:56:46 +09:00
Vegard Bieker Matthey c40972e701 Update README.md 2026-08-07 22:52:31 +02:00
h7x4 6c21e881c0 packages/bluemap: 5.20 -> 5.22 2026-08-06 20:41:18 +09:00
Felix Albrigtsen f6a84fe70e drolsum: unalive 2026-08-03 10:29:28 +02:00
Daniel Olsen e2567e78cf mitigations: patch matrix-synapse 2026-07-28 17:36:31 +02:00
h7x4 6ed3f1d269 flake.lock: bump roowho2 2026-07-28 06:45:28 +09:00
h7x4andoysteikt afc6b3182e ildkule/prometheus/phpfpm: scrape from bekkalokk 2026-07-27 13:58:47 +02:00
h7x4andoysteikt 7ebf1130a9 bekkalokk/prometheus-phpfpm-exporter: init 2026-07-27 13:58:47 +02:00
h7x4andoysteikt f9d39adf53 base/journald-upload: verify server cert against CA bundle 2026-07-27 13:50:39 +02:00
h7x4andoysteikt 65705237ab modules/python-http-handlers: better daemon handling
This commit extends the python http handler template with the following
things:

- Integration with systemd notify
- Named systemd sockets, to avoid depending on expected FD number
- Graceful and customizable handling of SIGHUP reloads
- Graceful shutdown on SIGTERM with timeout
- Multithreaded HTTP server, one thread per request
- Better error message on undefined handler
2026-07-27 13:50:19 +02:00
h7x4andoysteikt ab518714a5 bekkalokk/well-known: advertise TLS SMTP in autoconfig/mail 2026-07-25 23:24:57 +02:00
h7x4 4f6c731d25 flake.lock: bump pvv-nettsiden 2026-07-25 20:51:24 +09:00
h7x4 ee718563c8 bicep/postgresql: don't open udp 5432 in firewall 2026-07-25 07:35:42 +09:00
h7x4 fcc06d47c2 base/sshd: accept some useful envvars 2026-07-24 16:03:54 +09:00
h7x4andoysteikt d13df223bf bicep/mysql: add timed jobs for analyze and optimize 2026-07-22 15:09:10 +02:00
h7x4 1c4e8e7662 base/postfix: remove, base:nullmailer: init 2026-07-22 21:12:00 +09:00
h7x4 207bd1975e kommode/gitea: add robots.txt 2026-07-22 21:02:22 +09:00
h7x4andoysteikt 28794691bf bicep/{postgres,mysql}: bindmount data storage with noatime 2026-07-22 13:01:02 +02:00
h7x4 1ff34d7aab secrets: add passwords for gatus dbms checkers 2026-07-21 18:44:51 +09:00
h7x4 3d551fab52 ildkule/gatus: add healthcheck for mariadb 2026-07-21 18:44:51 +09:00
h7x4 a99a83c0d8 ildkule/gatus: add healthcheck for postgresql 2026-07-21 18:44:50 +09:00
51 changed files with 704 additions and 327 deletions
+2 -2
View File
@@ -34,12 +34,12 @@ revert the changes on the next nightly rebuild (tends to happen when everybody i
| Name | Type | Description |
|----------------------------|----------|-----------------------------------------------------------|
| [bekkalokk][bek] | Physical | Our main web host, webmail, wiki, idp, minecraft map, ... |
| [bekkalokk][bek] | Physical | Our main web host, webmail, wiki, idp, ... |
| [bicep][bic] | Virtual | Database host, matrix, git mirrors, ... |
| bikkje | Virtual | Experimental login box |
| [brzeczyszczykiewicz][brz] | Physical | Shared music player |
| [georg][geo] | Physical | Shared music player |
| [gluttony][glu] | Virtual | General purpose compute |
| [gluttony][glu] | Virtual | General purpose compute, minecraft map |
| [ildkule][ild] | Virtual | Logging and monitoring host, prometheus, grafana, ... |
| [kommode][kom] | Virtual | Gitea + Gitea pages |
| [lupine][lup] | Physical | Gitea CI/CD runners |
+1 -1
View File
@@ -30,9 +30,9 @@
./services/journald-upload.nix
./services/logrotate.nix
./services/nginx.nix
./services/nullmailer.nix
./services/openssh.nix
./services/polkit.nix
./services/postfix.nix
./services/prometheus-flake-input-exporter.nix
./services/prometheus-node-exporter.nix
./services/prometheus-systemd-exporter.nix
+14
View File
@@ -21,4 +21,18 @@ in
boot.blacklistedKernelModules = modulesToBan;
boot.extraModprobeConfig = lib.concatMapStringsSep "\n" (mod: "install ${mod} ${lib.getExe' pkgs.coreutils "false"}") modulesToBan;
nixpkgs.overlays = [
(final: prev: {
matrix-synapse-unwrapped = prev.matrix-synapse-unwrapped.overrideAttrs (old: rec {
version = "1.157.2";
src = final.fetchFromGitHub {
owner = "element-hq";
repo = "synapse";
rev = "v${version}";
hash = "sha256-TUHcNAXrV43+J7jqfstlYdrZrwL5kDCh03yxO+vL/gw=";
};
});
})
];
}
+1 -1
View File
@@ -9,7 +9,7 @@ in
URL = "https://journald.pvv.ntnu.no:${toString config.services.journald.remote.port}";
ServerKeyFile = "-";
ServerCertificateFile = "-";
TrustedCertificateFile = "-";
TrustedCertificateFile = config.security.pki.caBundle;
};
};
+15
View File
@@ -0,0 +1,15 @@
{ config, lib, ... }:
{
services.nullmailer = {
enable = true;
config = {
adminaddr = "root@pvv.ntnu.no";
defaultdomain = "pvv.ntnu.no";
defaulthost = "pvv.ntnu.no";
me = lib.mkDefault config.networking.fqdn;
remotes = lib.mkDefault "smtp.pvv.ntnu.no smtp port=465 tls";
};
};
}
+12 -6
View File
@@ -10,12 +10,18 @@
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"
settings.AcceptEnv = [
"LANG"
"LC_*"
"COLORTERM"
"GIT_PROTOCOL"
];
};
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"
];
}
-22
View File
@@ -1,22 +0,0 @@
{ config, pkgs, lib, ... }:
let
cfg = config.services.postfix;
in
{
services.postfix = {
enable = true;
settings.main = {
myhostname = "${config.networking.hostName}.pvv.ntnu.no";
mydomain = "pvv.ntnu.no";
# Nothing should be delivered to this machine
mydestination = [ ];
relayhost = [ "smtp.pvv.ntnu.no:465" ];
smtp_tls_wrappermode = "yes";
smtp_tls_security_level = "encrypt";
};
};
}
Generated
+29 -29
View File
@@ -126,11 +126,11 @@
"rust-overlay": "rust-overlay_2"
},
"locked": {
"lastModified": 1784553736,
"narHash": "sha256-W1pPlTHmp+EvONwf8Qa5NvCiuyV4LC/yNDdc27RSpuA=",
"lastModified": 1784709844,
"narHash": "sha256-5PW5+UEFFjsru5FiDg9ZRUjQyo7AVyc+nesQlBSqM6c=",
"ref": "main",
"rev": "e06daaef1f48160254c202c59b060ac6f1da9f38",
"revCount": 62,
"rev": "a8fb5df19d1cdcc3ac29cdb8ad192c1d578761f0",
"revCount": 63,
"type": "git",
"url": "https://git.pvv.ntnu.no/Grzegorz/greg-ng.git"
},
@@ -253,11 +253,11 @@
]
},
"locked": {
"lastModified": 1770960722,
"narHash": "sha256-IdhPsWFZUKSJh/nLjGLJvGM5d5Uta+k1FlVYPxTZi0E=",
"lastModified": 1786305372,
"narHash": "sha256-ZKTGJzXQMeskdivpyXmfyonEjR25b42N9tWwx+nvKMM=",
"ref": "main",
"rev": "c2e4aca7e1ba27cd09eeaeab47010d32a11841b2",
"revCount": 15,
"rev": "723a3d8d117bbfa07bda86427afaef1b1b6b7ff5",
"revCount": 19,
"type": "git",
"url": "https://git.pvv.ntnu.no/Drift/nix-gitea-themes.git"
},
@@ -291,11 +291,11 @@
},
"nixpkgs": {
"locked": {
"lastModified": 1784526640,
"narHash": "sha256-UDnuu3uM64qjfVvsGSislJgP1j15FiFiDiKOjbGTv9Q=",
"rev": "036c2421db75172aeef4bb83921988891d4773c9",
"lastModified": 1786245335,
"narHash": "sha256-cAR1Po8rYta0tqfjdotDXYVaPC3oJ1/th2cLcQNQSco=",
"rev": "33ddeb9e7c03403e17814e8aac1f7affe6d70b21",
"type": "tarball",
"url": "https://releases.nixos.org/nixos/26.05-small/nixos-26.05.5692.036c2421db75/nixexprs.tar.xz"
"url": "https://releases.nixos.org/nixos/26.05-small/nixos-26.05.7300.33ddeb9e7c03/nixexprs.tar.xz"
},
"original": {
"type": "tarball",
@@ -319,11 +319,11 @@
},
"nixpkgs-unstable": {
"locked": {
"lastModified": 1784536202,
"narHash": "sha256-7CmHmK10lEXBgymS0DeYj4/4STLpzRWCc/5BfoIxHQo=",
"rev": "94f12be79cb7f961726a0157b4168bc722befeac",
"lastModified": 1786237299,
"narHash": "sha256-ZNjdCWSLUF0mrPSKXijAm606sfbI6889LCg6doYG3B8=",
"rev": "60c768b1d7043edb84f25e2880ab2bd8327f6cfa",
"type": "tarball",
"url": "https://releases.nixos.org/nixos/unstable-small/nixos-26.11pre1037880.94f12be79cb7/nixexprs.tar.xz"
"url": "https://releases.nixos.org/nixos/unstable-small/nixos-26.11pre1050368.60c768b1d704/nixexprs.tar.xz"
},
"original": {
"type": "tarball",
@@ -379,11 +379,11 @@
]
},
"locked": {
"lastModified": 1782759909,
"narHash": "sha256-gktjBeZyoRvVBkm2cO1tD99fdQ34iUDyB6iecRdorm4=",
"lastModified": 1784979981,
"narHash": "sha256-OnvjEXYU/InjJYH2+iIrvHWIjHnc5J9f84qWhrgAWlY=",
"ref": "main",
"rev": "ad6c79fb713884a4a2df8aab30914cd0c1c2e6cb",
"revCount": 587,
"rev": "ffb8ed0c9df2444727e49f16f7e43ea70184dc4b",
"revCount": 590,
"type": "git",
"url": "https://git.pvv.ntnu.no/Projects/nettsiden.git"
},
@@ -447,17 +447,17 @@
"rust-overlay": "rust-overlay_4"
},
"locked": {
"lastModified": 1784550731,
"narHash": "sha256-KDrBGT98fQWlnEBmTvIijPq4n4sVLcETBu8EuL486SM=",
"lastModified": 1785060737,
"narHash": "sha256-tlOCUK+X1Um1y/pP/vToGrygn1wmrtUDKrvQquPLVfA=",
"ref": "main",
"rev": "c0c0e47c8a45673c62462cadf38a489b72fd39ec",
"revCount": 112,
"rev": "35fe97baa795d1564c79b013d8a36ee01698f47b",
"revCount": 126,
"type": "git",
"url": "https://git.pvv.ntnu.no/Projects/roowho2.git"
},
"original": {
"ref": "main",
"rev": "c0c0e47c8a45673c62462cadf38a489b72fd39ec",
"rev": "35fe97baa795d1564c79b013d8a36ee01698f47b",
"type": "git",
"url": "https://git.pvv.ntnu.no/Projects/roowho2.git"
}
@@ -575,11 +575,11 @@
]
},
"locked": {
"lastModified": 1780762731,
"narHash": "sha256-EuDaLnasWN0mpi995n+fAQQfPGBhqNW4fNjlQRpHt58=",
"lastModified": 1785100355,
"narHash": "sha256-wBGnYrF7Kfs4vk3djspT3RdQqsYiqm60fKn7/J3vH4I=",
"ref": "main",
"rev": "931bd2d63e285e767c8c81c103dda3c0a63f2965",
"revCount": 108,
"rev": "611f6ac1a304cc319fc85876d3f0301f49ce458e",
"revCount": 120,
"type": "git",
"url": "https://git.pvv.ntnu.no/Projects/worblehat.git"
},
+2 -1
View File
@@ -35,7 +35,7 @@
minecraft-heatmap.url = "git+https://git.pvv.ntnu.no/Projects/minecraft-heatmap.git?ref=main";
minecraft-heatmap.inputs.nixpkgs.follows = "nixpkgs";
roowho2.url = "git+https://git.pvv.ntnu.no/Projects/roowho2.git?ref=main&rev=c0c0e47c8a45673c62462cadf38a489b72fd39ec";
roowho2.url = "git+https://git.pvv.ntnu.no/Projects/roowho2.git?ref=main&rev=35fe97baa795d1564c79b013d8a36ee01698f47b";
roowho2.inputs.nixpkgs.follows = "nixpkgs";
greg-ng.url = "git+https://git.pvv.ntnu.no/Grzegorz/greg-ng.git?ref=main";
@@ -268,6 +268,7 @@
modules = [
inputs.nix-gitea-themes.nixosModules.default
inputs.disko.nixosModules.disko
self.nixosModules.robots-txt
];
};
+1
View File
@@ -13,6 +13,7 @@
./services/mediawiki
./services/nginx.nix
./services/phpfpm.nix
./services/prometheus-phpfpm-exporter.nix
./services/vaultwarden.nix
./services/webmail
./services/website
@@ -177,11 +177,6 @@ in
};
};
systemd.services."phpfpm-idp" = {
after = [ "sops-install-secrets.service" ];
requires = [ "sops-install-secrets.service" ];
};
services.nginx.virtualHosts."idp.pvv.ntnu.no" = {
forceSSL = true;
enableACME = true;
@@ -287,7 +287,6 @@ in {
systemd.services.mediawiki-init = lib.mkIf cfg.enable {
after = [ "sops-install-secrets.service" ];
requires = [ "sops-install-secrets.service" ];
serviceConfig = {
UMask = lib.mkForce "0007";
};
@@ -295,7 +294,6 @@ in {
systemd.services.phpfpm-mediawiki = lib.mkIf cfg.enable {
after = [ "sops-install-secrets.service" ];
requires = [ "sops-install-secrets.service" ];
serviceConfig = {
UMask = lib.mkForce "0007";
};
@@ -0,0 +1,54 @@
{ config, lib, values, ... }:
let
cfg = config.services.prometheus.exporters.php-fpm;
pools = [
"idp"
"mediawiki"
"pvv-nettsiden"
"roundcube"
"snappymail"
];
in
{
services.phpfpm.pools = lib.genAttrs pools (_: {
settings."pm.status_path" = "/status";
});
services.prometheus.exporters.php-fpm = {
enable = true;
listenAddress = "127.0.0.1";
extraFlags = [
"--phpfpm.scrape-uri=${lib.concatMapStringsSep "," (name: "unix://${config.services.phpfpm.pools.${name}.socket};/status") pools}"
];
};
systemd.services.prometheus-php-fpm-exporter.serviceConfig = {
Slice = "system-monitoring.slice";
SupplementaryGroups = [ config.services.nginx.group ];
RestrictAddressFamilies = lib.mkForce [
"AF_INET"
"AF_INET6"
"AF_UNIX"
];
};
services.nginx = lib.mkIf cfg.enable {
virtualHosts."www.pvv.ntnu.no" = lib.mkIf config.services.nginx.enable {
forceSSL = true;
enableACME = true;
kTLS = true;
locations."/prometheus-php-fpm-exporter/metrics" = {
proxyPass = "http://localhost:${toString cfg.port}/metrics";
extraConfig = ''
allow 127.0.0.1;
allow ::1;
allow ${values.hosts.ildkule.ipv4};
allow ${values.hosts.ildkule.ipv6};
deny all;
'';
};
};
};
}
-5
View File
@@ -61,11 +61,6 @@ in {
};
};
systemd.services.vaultwarden = {
after = [ "sops-install-secrets.service" ];
requires = [ "sops-install-secrets.service" ];
};
services.nginx.virtualHosts."${domain}" = {
forceSSL = true;
enableACME = true;
@@ -49,11 +49,6 @@ in
'';
};
systemd.services."phpfpm-roundcube" = {
after = [ "sops-install-secrets.service" ];
requires = [ "sops-install-secrets.service" ];
};
# TODO: move this back to `webmail.pvv.ntnu.no/roundcube` subpath
services.nginx.virtualHosts.${domain} = {
@@ -116,11 +116,6 @@ in {
];
};
systemd.services."phpfpm-pvv-nettsiden" = {
after = [ "sops-install-secrets.service" ];
requires = [ "sops-install-secrets.service" ];
};
services.nginx.virtualHosts."pvv.ntnu.no" = {
globalRedirect = cfg.domainName;
redirectCode = 307;
@@ -16,8 +16,8 @@
<outgoingServer type="smtp">
<hostname>smtp.pvv.ntnu.no</hostname>
<port>587</port>
<socketType>STARTTLS</socketType>
<port>465</port>
<socketType>SSL</socketType>
<username>%EMAILLOCALPART%</username>
<authentication>password-cleartext</authentication>
<useGlobalPreferredServer>true</useGlobalPreferredServer>
-5
View File
@@ -35,9 +35,4 @@ in {
onCalendar = "*-*-* 09:00:00";
};
};
systemd.services.pvv-calendar-bot = {
after = [ "sops-install-secrets.service" ];
requires = [ "sops-install-secrets.service" ];
};
}
@@ -20,8 +20,6 @@ in
lfs = false;
};
# TODO: add a module setting to specify additional systemd dependencies
# and then mark "sops-install-secrets.service" as a dependency here
instances = let
defaultGithubConfig = {
settings.token_file = config.sops.secrets."gickup/github-token".path;
-5
View File
@@ -55,11 +55,6 @@
# It needs this to be allowed to access the files with the acme group
systemd.services.coturn.serviceConfig.PrivateUsers = lib.mkForce false;
systemd.services.coturn = {
requires = [ "sops-install-secrets.service" ];
after = [ "sops-install-secrets.service" ];
};
systemd.services."acme-${config.services.coturn.realm}".serviceConfig = {
AmbientCapabilities = [ "CAP_NET_BIND_SERVICE" ];
};
-2
View File
@@ -39,8 +39,6 @@ in
};
systemd.services.mx-puppet-discord = {
after = [ "sops-install-secrets.service" ];
requires = [ "sops-install-secrets.service" ];
serviceConfig.SupplementaryGroups = [
config.users.groups.keys-matrix-registrations.name
];
@@ -183,7 +183,6 @@ in
};
services.matrix-hookshot.serviceDependencies = [
"sops-install-secrets.service"
"matrix-synapse.target"
"nginx.service"
];
+1 -6
View File
@@ -43,12 +43,7 @@ in
keyFile = config.sops.templates."matrix-livekit-keyfile".path;
};
systemd.services.lk-jwt-service = lib.mkIf cfg.enable {
after = [ "sops-install-secrets.service" ];
requires = [ "sops-install-secrets.service" ];
environment.LIVEKIT_FULL_ACCESS_HOMESERVERS = builtins.concatStringsSep "," [ "pvv.ntnu.no" "dodsorf.as" ];
};
systemd.services.lk-jwt-service.environment.LIVEKIT_FULL_ACCESS_HOMESERVERS = lib.mkIf cfg.enable (builtins.concatStringsSep "," [ "pvv.ntnu.no" "dodsorf.as" ]);
services.nginx.virtualHosts.${matrixDomain} = lib.mkIf cfg.enable {
locations."^~ /livekit/jwt/" = {
+46 -51
View File
@@ -55,57 +55,52 @@
pantalaimon.username = "bot_admin";
};
systemd.services.mjolnir = {
requires = [ "sops-install-secrets.service" ];
after = [ "sops-install-secrets.service" ];
systemd.services.mjolnir.serviceConfig = {
DynamicUser = true;
RuntimeDirectory = [ "mjolnir/root-mnt" ];
RootDirectory = "/run/mjolnir/root-mnt";
BindReadOnlyPaths = [
config.sops.secrets."matrix/mjolnir/access_token".path
builtins.storeDir
"/etc"
"/run/nscd"
"/var/run/nscd"
];
serviceConfig = {
DynamicUser = true;
RuntimeDirectory = [ "mjolnir/root-mnt" ];
RootDirectory = "/run/mjolnir/root-mnt";
BindReadOnlyPaths = [
config.sops.secrets."matrix/mjolnir/access_token".path
builtins.storeDir
"/etc"
"/run/nscd"
"/var/run/nscd"
];
AmbientCapabilities = "";
CapabilityBoundingSet = "";
LockPersonality = true;
MemoryDenyWriteExecute = false; # node needs this
NoNewPrivileges = true;
PrivateDevices = true;
PrivateMounts = true;
PrivateTmp = true;
PrivateUsers = true;
ProcSubset = "pid";
ProtectClock = true;
ProtectControlGroups = true;
ProtectHome = true;
ProtectHostname = true;
ProtectKernelLogs = true;
ProtectKernelModules = true;
ProtectKernelTunables = true;
ProtectProc = "invisible";
ProtectSystem = "strict";
RemoveIPC = true;
RestrictAddressFamilies = [
"AF_INET"
"AF_INET6"
"AF_UNIX"
];
RestrictNamespaces = true;
RestrictRealtime = true;
RestrictSUIDSGID = true;
SystemCallArchitectures = "native";
SystemCallFilter = [
"@system-service"
"~@privileged"
"~@resources"
];
UMask = "0077";
};
AmbientCapabilities = "";
CapabilityBoundingSet = "";
LockPersonality = true;
MemoryDenyWriteExecute = false; # node needs this
NoNewPrivileges = true;
PrivateDevices = true;
PrivateMounts = true;
PrivateTmp = true;
PrivateUsers = true;
ProcSubset = "pid";
ProtectClock = true;
ProtectControlGroups = true;
ProtectHome = true;
ProtectHostname = true;
ProtectKernelLogs = true;
ProtectKernelModules = true;
ProtectKernelTunables = true;
ProtectProc = "invisible";
ProtectSystem = "strict";
RemoveIPC = true;
RestrictAddressFamilies = [
"AF_INET"
"AF_INET6"
"AF_UNIX"
];
RestrictNamespaces = true;
RestrictRealtime = true;
RestrictSUIDSGID = true;
SystemCallArchitectures = "native";
SystemCallFilter = [
"@system-service"
"~@privileged"
"~@resources"
];
UMask = "0077";
};
}
@@ -56,15 +56,7 @@ in
enableSynapseIntegration = false;
};
systemd.services."matrix-ooye-pre-start" = {
after = [ "sops-install-secrets.service" ];
requires = [ "sops-install-secrets.service" ];
};
systemd.services."matrix-ooye" = {
after = [ "sops-install-secrets.service" ];
requires = [ "sops-install-secrets.service" ];
serviceConfig = {
RuntimeDirectory = [ "matrix-ooye/root-mnt" ];
RootDirectory = "/run/matrix-ooye/root-mnt";
+1 -6
View File
@@ -44,11 +44,6 @@ in {
};
};
systemd.targets."matrix-synapse" = {
after = [ "sops-install-secrets.service" ];
requires = [ "sops-install-secrets.service" ];
};
services.matrix-synapse-next = {
enable = true;
@@ -79,7 +74,7 @@ in {
name = "psycopg2";
args = {
host = "/var/run/postgresql";
dbname = "synapse";
database = "synapse";
user = "matrix-synapse";
cp_min = 1;
cp_max = 5;
@@ -23,15 +23,6 @@ in
};
systemd.services.minecraft-heatmap-ingest-logs = lib.mkIf cfg.enable {
after = [
"sops-install-secrets.service"
"network-online.target"
];
requires = [
"sops-install-secrets.service"
"network-online.target"
];
serviceConfig = {
LoadCredential = [
"sshkey:${config.sops.secrets."minecraft-heatmap/ssh-key/private".path}"
+17 -5
View File
@@ -4,7 +4,10 @@ let
dataDir = "/data/mysql";
in
{
imports = [ ./backup.nix ];
imports = [
./backup.nix
./timed-jobs.nix
];
sops.secrets."mysql/password" = {
owner = "mysql";
@@ -54,17 +57,26 @@ in
mode = "0700";
};
fileSystems.${dataDir} = lib.mkIf cfg.enable {
device = dataDir;
fsType = "none";
options = [
"bind"
"noatime"
"noauto"
"x-systemd.requires=systemd-tmpfiles-setup.service"
"x-systemd.requires=systemd-tmpfiles-resetup.service"
];
};
systemd.services.mysql = lib.mkIf cfg.enable {
after = [
"sops-install-secrets.service"
"systemd-tmpfiles-setup.service"
"systemd-tmpfiles-resetup.service"
];
requires = [
"sops-install-secrets.service"
];
serviceConfig = {
RequiresMountsFor = [ dataDir ];
BindPaths = [ "${dataDir}:${cfg.dataDir}" ];
LogsDirectory = "mysql";
+48
View File
@@ -0,0 +1,48 @@
{ config, lib, pkgs, ... }:
let
cfg = config.services.mysql;
in
{
config = lib.mkIf cfg.enable {
systemd.services = {
mysql-analyze = {
requires = [ "mysql.service" ];
after = [ "mysql.service" ];
description = "Refresh MariaDB optimizer statistics for all databases";
startAt = "Mon 05:00:00";
serviceConfig = {
Type = "oneshot";
User = cfg.user;
Group = cfg.group;
Nice = 19;
IOSchedulingClass = "best-effort";
IOSchedulingPriority = 7;
ExecStart = "${lib.getExe' cfg.package "mariadb-check"} --all-databases --analyze";
};
};
mysql-optimize = {
requires = [ "mysql.service" ];
after = [ "mysql.service" ];
description = "Check, repair and optimize all MariaDB databases";
startAt = "*-*-01 04:00:00";
serviceConfig = {
Type = "oneshot";
User = cfg.user;
Group = cfg.group;
Nice = 19;
IOSchedulingClass = "best-effort";
IOSchedulingPriority = 7;
ExecStart = [
"${lib.getExe' cfg.package "mariadb-check"} --all-databases --auto-repair"
"${lib.getExe' cfg.package "mariadb-check"} --all-databases --optimize"
];
};
};
};
};
}
+14 -1
View File
@@ -99,6 +99,18 @@ in
mode = "0700";
};
fileSystems."/data/postgresql" = lib.mkIf cfg.enable {
device = "/data/postgresql";
fsType = "none";
options = [
"bind"
"noatime"
"noauto"
"x-systemd.requires=systemd-tmpfiles-setup.service"
"x-systemd.requires=systemd-tmpfiles-resetup.service"
];
};
systemd.services.postgresql-setup = lib.mkIf cfg.enable {
after = [
"systemd-tmpfiles-setup.service"
@@ -110,6 +122,7 @@ in
"key:/etc/certs/postgres.key"
];
RequiresMountsFor = [ "/data/postgresql" ];
BindPaths = [ "/data/postgresql:/var/lib/postgresql" ];
};
};
@@ -125,6 +138,7 @@ in
"key:/etc/certs/postgres.key"
];
RequiresMountsFor = [ "/data/postgresql" ];
BindPaths = [ "/data/postgresql:/var/lib/postgresql" ];
};
};
@@ -136,7 +150,6 @@ in
};
networking.firewall.allowedTCPPorts = lib.mkIf cfg.enable [ 5432 ];
networking.firewall.allowedUDPPorts = lib.mkIf cfg.enable [ 5432 ];
environment.systemPackages = [
(pkgs.writeShellApplication {
-9
View File
@@ -82,15 +82,6 @@ in {
};
systemd.services."render-bluemap-maps" = {
after = [
"sops-install-secrets.service"
"network-online.target"
];
requires = [
"sops-install-secrets.service"
"network-online.target"
];
serviceConfig = {
StateDirectory = [ "bluemap/world" ];
ExecStartPre = let
@@ -5,6 +5,8 @@ in
{
imports = [
./minecraft-checker.nix
./postgres-checker.nix
./mariadb-checker.nix
];
services.gatus = {
@@ -80,7 +82,6 @@ in
(mkMachine "buskerud")
(mkMachine "buttercup")
(mkMachine "demiurgen")
(mkMachine "drolsum")
(mkMachine "hildring")
(mkMachine "innovation")
(mkMachine "isvegg")
@@ -133,6 +134,18 @@ in
"[BODY].ok == true"
];
})
(mkService "PostgreSQL" "http://localhost:1338" // {
conditions = [
"[STATUS] == 200"
"[BODY].ok == true"
];
})
(mkService "MariaDB" "http://localhost:1339" // {
conditions = [
"[STATUS] == 200"
"[BODY].ok == true"
];
})
(mkService "Email (SMTP)" "starttls://mail.pvv.ntnu.no:587")
(mkService "Email (POP3)" "tls://mail.pvv.ntnu.no:995")
(mkService "Email (IMAP)" "tls://mail.pvv.ntnu.no:993")
@@ -0,0 +1,79 @@
{ config, pkgs, ... }:
{
sops.secrets."keys/gatus/mariadb" = {
restartUnits = [ "phh-gatus-mariadb-checker.service" ];
};
sops.templates."gatus-mariadb-checker.env" = {
restartUnits = [ "phh-gatus-mariadb-checker.service" ];
content = ''
MYSQL_HOST=mysql.pvv.ntnu.no
MYSQL_PORT=3306
MYSQL_DATABASE=mysql
MYSQL_USER=gatus_healthcheck
MYSQL_PASSWORD=${config.sops.placeholder."keys/gatus/mariadb"}
'';
};
services.python-http-handlers."gatus-mariadb-checker" = {
listenStreams = [ "127.0.0.1:1339" ];
libraries = with pkgs.python3Packages; [
pymysql
];
serviceConfig = {
EnvironmentFile = config.sops.templates."gatus-mariadb-checker.env".path;
};
handler = ''
import os
import json
import pymysql
class Handler(BaseHTTPRequestHandler):
def do_GET(self):
try:
conn = pymysql.connect(
host=os.environ["MYSQL_HOST"],
port=int(os.environ.get("MYSQL_PORT", "3306")),
user=os.environ["MYSQL_USER"],
password=os.environ["MYSQL_PASSWORD"],
database=os.environ.get("MYSQL_DATABASE", "mysql"),
connect_timeout=5,
)
try:
with conn.cursor() as cur:
cur.execute("SELECT VERSION();")
(version,) = cur.fetchone()
cur.execute("SHOW STATUS LIKE 'Threads_connected';")
(_, connections) = cur.fetchone()
cur.execute("SHOW DATABASES;")
databases = cur.fetchall()
finally:
conn.close()
body = {
"ok": True,
"version": version,
"connections": int(connections),
"databases": len(databases),
}
data = json.dumps(body).encode()
self.send_response(200)
self.send_header("Content-Type", "application/json")
self.send_header("Content-Length", str(len(data)))
self.end_headers()
self.wfile.write(data)
except Exception as e:
data = json.dumps({"ok": False, "error": str(e)}).encode()
self.send_response(500)
self.send_header("Content-Type", "application/json")
self.send_header("Content-Length", str(len(data)))
self.end_headers()
self.wfile.write(data)
'';
};
}
@@ -0,0 +1,79 @@
{ config, pkgs, ... }:
{
sops.secrets."keys/gatus/postgres" = {
restartUnits = [ "phh-gatus-postgres-checker.service" ];
};
sops.templates."gatus-postgres-checker.env" = {
restartUnits = [ "phh-gatus-postgres-checker.service" ];
content = ''
PGHOST=postgres.pvv.ntnu.no
PGPORT=5432
PGDATABASE=postgres
PGUSER=gatus_healthcheck
PGPASSWORD=${config.sops.placeholder."keys/gatus/postgres"}
'';
};
services.python-http-handlers."gatus-postgres-checker" = {
listenStreams = [ "127.0.0.1:1338" ];
libraries = with pkgs.python3Packages; [
psycopg2
];
serviceConfig = {
EnvironmentFile = config.sops.templates."gatus-postgres-checker.env".path;
};
handler = ''
import os
import json
import psycopg2
class Handler(BaseHTTPRequestHandler):
def do_GET(self):
try:
conn = psycopg2.connect(
host=os.environ["PGHOST"],
port=os.environ.get("PGPORT", "5432"),
dbname=os.environ.get("PGDATABASE", "postgres"),
user=os.environ["PGUSER"],
password=os.environ["PGPASSWORD"],
connect_timeout=5,
)
try:
with conn.cursor() as cur:
cur.execute("SELECT version();")
(version,) = cur.fetchone()
cur.execute("SELECT count(*) FROM pg_stat_activity;")
(connections,) = cur.fetchone()
cur.execute("SELECT count(*) FROM pg_database WHERE NOT datistemplate;")
(databases,) = cur.fetchone()
finally:
conn.close()
body = {
"ok": True,
"version": version,
"connections": connections,
"databases": databases,
}
data = json.dumps(body).encode()
self.send_response(200)
self.send_header("Content-Type", "application/json")
self.send_header("Content-Length", str(len(data)))
self.end_headers()
self.wfile.write(data)
except Exception as e:
data = json.dumps({"ok": False, "error": str(e)}).encode()
self.send_response(500)
self.send_header("Content-Type", "application/json")
self.send_header("Content-Length", str(len(data)))
self.end_headers()
self.wfile.write(data)
'';
};
}
@@ -79,11 +79,6 @@ in {
};
};
systemd.services.grafana = {
after = [ "sops-install-secrets.service" ];
requires = [ "sops-install-secrets.service" ];
};
services.nginx.virtualHosts.${cfg.settings.server.domain} = {
enableACME = true;
forceSSL = true;
@@ -7,6 +7,7 @@ in {
./machines.nix
./matrix-synapse.nix
./mysqld.nix
./phpfpm.nix
./postgres.nix
];
@@ -0,0 +1,15 @@
{ ... }:
{
services.prometheus.scrapeConfigs = [{
job_name = "phpfpm";
scheme = "https";
metrics_path = "/prometheus-php-fpm-exporter/metrics";
static_configs = [
{
labels.hostname = "bekkalokk";
targets = [ "www.pvv.ntnu.no:443" ];
}
];
}];
}
@@ -37,15 +37,9 @@ in {
};
};
systemd.services.prometheus-postgres-exporter-knakelibrak = {
after = [ "sops-install-secrets.service" ];
requires = [ "sops-install-secrets.service" ];
# TODO: is it really necessary to use recursiveUpdate on the entire attrset here?
# Why don't we just update the relevant attrs directly?
serviceConfig = let
localCfg = config.services.prometheus.exporters.postgres;
in lib.recursiveUpdate config.systemd.services.prometheus-postgres-exporter.serviceConfig {
systemd.services.prometheus-postgres-exporter-knakelibrak.serviceConfig = let
localCfg = config.services.prometheus.exporters.postgres;
in lib.recursiveUpdate config.systemd.services.prometheus-postgres-exporter.serviceConfig {
EnvironmentFile = config.sops.secrets."keys/postgres/postgres_exporter_knakelibrak_env".path;
ExecStart = ''
${pkgs.prometheus-postgres-exporter}/bin/postgres_exporter \
@@ -54,5 +48,4 @@ in {
${lib.concatStringsSep " \\\n " localCfg.extraFlags}
'';
};
};
}
+104 -11
View File
@@ -154,14 +154,8 @@ in {
environment.systemPackages = [ cfg.package ];
systemd.services.gitea = lib.mkIf cfg.enable {
after = [
"sops-install-secrets.service"
"redis-gitea.service"
];
requires = [
"sops-install-secrets.service"
"redis-gitea.service"
];
wants = [ "redis-gitea.service" ];
after = [ "redis-gitea.service" ];
serviceConfig = {
CPUSchedulingPolicy = "batch";
@@ -202,6 +196,108 @@ in {
};
};
environment.robots-txt."gitea" = {
virtualHost = domain;
rules = [
{
pre_comment = ''
Gitea internals
See these for more information:
- https://gitea.com/robots.txt
- https://codeberg.org/robots.txt
'';
User-agent = "*";
Disallow = [
"/api/*"
"/avatars"
"/*/*/src/commit/*"
"/*/*/commit/*"
"/*/*/*/refs/*"
"/*/*/*/star"
"/*/*/*/watch"
"/*/*/labels"
"/*/*/activity/*"
"/vendor/*"
"/swagger.*.json"
"/repo/create"
"/repo/migrate"
"/org/create"
"/*/*/fork"
"/*/*/watchers"
"/*/*/stargazers"
"/*/*/forks"
"*/.git/"
"/*.git"
"/*.atom"
"/*.rss"
];
Crawl-delay = "2";
}
{
pre_comment = "Language Spam";
Disallow = "/*?lang=";
}
{
pre_comment = ''
AI bots
Sourced from:
- https://www.vg.no/robots.txt
- https://codeberg.org/robots.txt
'';
User-agent = [
"AI2Bot"
"Ai2Bot-Dolma"
"Amazonbot"
"Applebot-Extended"
"Bytespider"
"CCBot"
"ChatGPT-User"
"Claude-Web"
"ClaudeBot"
"Crawlspace"
"Diffbot"
"FacebookBot"
"FriendlyCrawler"
"GPTBot"
"Google-Extended"
"ICC-Crawler"
"ImagesiftBot"
"Kangaroo Bot"
"Meta-ExternalAgent"
"OAI-SearchBot"
"Omgili"
"Omgilibot"
"PanguBot"
"PerplexityBot"
"PetalBot"
"Scrapy"
"SemrushBot-OCOB"
"Sidetrade indexer bot"
"Timpibot"
"VelenPublicWebCrawler"
"Webzio-Extended"
"YouBot"
"anthropic-ai"
"cohere-ai"
"cohere-training-data-crawler"
"facebookexternalhit"
"iaskspider/2.0"
"img2dataset"
"meta-externalagent"
"omgili"
"omgilibot"
];
Disallow = "/";
Crawl-delay = "2";
}
{
Sitemap = "https://${domain}/sitemap.xml";
}
];
};
networking.firewall.allowedTCPPorts = [ sshPort ];
services.rsync-pull-targets = {
@@ -222,9 +318,6 @@ in {
};
systemd.services.gitea-dump = {
after = [ "sops-install-secrets.service" ];
requires = [ "sops-install-secrets.service" ];
serviceConfig.ExecStart = let
args = lib.cli.toCommandLineShellGNU { } {
type = cfg.dump.type;
-4
View File
@@ -32,11 +32,7 @@ in
systemd.services.gitea-ensure-gnupg-homedir = {
description = "Import gpg key for gitea";
before = [ "gitea.service" ];
after = [ "sops-install-secrets.service" ];
requires = [ "sops-install-secrets.service" ];
environment = { inherit GNUPGHOME; };
serviceConfig = {
Type = "oneshot";
@@ -12,16 +12,6 @@ in
systemd.services.gitea-import-users = lib.mkIf cfg.enable {
enable = true;
environment.PASSWD_FILE_PATH = "/run/gitea-import-users/passwd";
after = [
"sops-install-secrets.service"
"gitea.service"
"network-online.target"
];
requires = [
"sops-install-secrets.service"
"gitea.service"
"network-online.target"
];
serviceConfig = {
ExecStartPre = ''${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 /run/gitea-import-users/passwd'';
ExecStart = pkgs.writers.writePython3 "gitea-import-users" {
@@ -48,16 +48,7 @@ in
# %d - secrets directory
systemd.services."gitea-web-secret-provider@" = {
description = "Ensure all repos in %i has an SSH key to push web content";
after = [
"sops-install-secrets.service"
"gitea.service"
"network-online.target"
];
requires = [
"sops-install-secrets.service"
"gitea.service"
"network-online.target"
];
requires = [ "gitea.service" "network.target" ];
serviceConfig = {
Slice = "system-giteaweb.slice";
Type = "oneshot";
-5
View File
@@ -94,11 +94,6 @@ in
};
};
systemd.services."openvpn-ov-firewall" = {
after = [ "sops-install-secrets.service" ];
requires = [ "sops-install-secrets.service" ];
};
networking.firewall = {
allowedTCPPorts = [ 1194 ];
allowedUDPPorts = [ 1194 ];
-5
View File
@@ -53,10 +53,5 @@
};
};
systemd.services.drumknotty-screen-session = {
after = [ "sops-install-secrets.service" ];
requires = [ "sops-install-secrets.service" ];
};
services.roowho2.settings.rwhod.ignoreUsers = [ "drumknotty" ];
}
+7 -8
View File
@@ -1,14 +1,13 @@
{ config, lib, pkgs, ... }:
{
services.postfix.enable = lib.mkForce false;
assertions = [{
assertion = config.services.nullmailer.enable;
message = ''
Expected nullmailer to be enabled for temmie userweb.
services.nullmailer = {
enable = true;
config = {
me = config.networking.fqdn;
remotes = "mail.pvv.ntnu.no smtp --port=25";
};
};
If you change the default sendmail implementation, please make sure that temmie userweb works correctly!
'';
}];
services.bro = {
enable = true;
@@ -29,15 +29,9 @@ in
systemd.services."httpd-passwd-sync" = {
requiredBy = [ "userweb.target" ];
after = [
"network-online.target"
"sops-install-secrets.service"
"systemd-tmpfiles-setup.service"
"systemd-tmpfiles-resetup.service"
];
requires = [
"network-online.target"
"sops-install-secrets.service"
];
serviceConfig = {
Type = "oneshot";
Slice = "system-userweb.slice";
+2 -4
View File
@@ -159,6 +159,7 @@ in
description = "Out of Your Element - a Discord bridge for Matrix.";
wants = [
"network-online.target"
"matrix-synapse.service"
"conduit.service"
"dendrite.service"
@@ -167,10 +168,7 @@ in
"matrix-ooye-pre-start.service"
"network-online.target"
];
requires = [
"network-online.target"
"matrix-ooye-pre-start.service"
];
requires = [ "matrix-ooye-pre-start.service" ];
wantedBy = [ "multi-user.target" ];
startLimitIntervalSec = 5;
+117 -10
View File
@@ -36,6 +36,9 @@ in
description = ''
For each item in this list, a `ListenStream`
option in the `[Socket]` section will be created.
Only a single `ListenStream` is currently supported by the handler script; if
you need more than one, you'll have to adjust {option}`handler` accordingly.
'';
};
@@ -98,8 +101,10 @@ in
"E303" # too many blank lines
"E305" # expected 2 blank lines after end of function or class
"E306" # expected 1 blank line before a nested definition
"E402" # module level import not at top of file
"E501" # max line length
"E704" # multiple statements on one line (def)
"F811" # redefined while unused
];
description = ''
A list of flake8 rules to ignore while linting the python code.
@@ -122,6 +127,11 @@ in
self.send_header("Content-Length", str(len(data)))
self.end_headers()
self.wfile.write(data)
def on_reload():
# This function is called when the service receives SIGHUP (e.g. via `systemctl reload`).
# You can use it to clear caches or re-read state. Completely optional
pass
'';
description = ''
Python code including the HTTP handler for the server.
@@ -145,6 +155,7 @@ in
inherit (v) listenStreams;
socketConfig = {
Accept = false;
FileDescriptorName = v.name;
} // v.socketConfig;
};
}))
@@ -157,30 +168,126 @@ in
inherit (v) name;
value = {
serviceConfig = {
Type = "simple";
Type = "notify-reload";
NotifyAccess = "main";
DynamicUser = true;
TimeoutStopSec = "35s";
ExecStart = let
package = pkgs.writers.writePython3Bin "${v.name}-bin" {
inherit (v) libraries flakeIgnore;
} ''
import os
import signal
import socket
import socketserver
import threading
import time
from http.server import HTTPServer, BaseHTTPRequestHandler
${v.handler}
SOCKET_NAME = "${v.name}"
SHUTDOWN_TIMEOUT = 30
def sd_notify(message: str):
addr = os.environ.get("NOTIFY_SOCKET")
if not addr:
return
if addr[0] == "@":
addr = "\0" + addr[1:]
with socket.socket(socket.AF_UNIX, socket.SOCK_DGRAM | socket.SOCK_CLOEXEC) as sock:
sock.connect(addr)
sock.sendall(message.encode())
def sd_listen_fd(name: str) -> int:
if os.environ.get("LISTEN_PID") != str(os.getpid()):
raise RuntimeError("No sockets were passed to this service by systemd")
try:
count = int(os.environ.get("LISTEN_FDS", "0"))
except ValueError:
count = 0
raw_names = os.environ.get("LISTEN_FDNAMES")
names = raw_names.split(":") if raw_names else []
for i in range(count):
if i < len(names) and names[i] == name:
return 3 + i
raise RuntimeError(
"No systemd socket named %r was passed to this service; check the "
"FileDescriptorName= of the corresponding .socket unit" % name
)
class Server(socketserver.ThreadingMixIn, HTTPServer):
daemon_threads = True
class NoBindHTTPServer(HTTPServer):
def server_bind(): pass
def server_activate(): pass
def __init__(self, *args, **kwargs):
super().__init__(*args, **kwargs)
self._request_threads = []
self._request_threads_lock = threading.Lock()
def process_request(self, request, client_address):
thread = threading.Thread(
target=self.process_request_thread,
args=(request, client_address),
)
thread.daemon = self.daemon_threads
with self._request_threads_lock:
self._request_threads.append(thread)
thread.start()
def join_request_threads(self, timeout):
deadline = time.monotonic() + timeout
with self._request_threads_lock:
threads = list(self._request_threads)
for thread in threads:
thread.join(max(deadline - time.monotonic(), 0))
def handle_reload(signum, frame):
monotonic_usec = time.clock_gettime_ns(time.CLOCK_MONOTONIC) // 1000
sd_notify("RELOADING=1\nMONOTONIC_USEC=%d" % monotonic_usec)
on_reload = globals().get("on_reload")
if callable(on_reload):
on_reload()
sd_notify("READY=1")
shutdown_requested = threading.Event()
def handle_sigterm(signum, frame):
sd_notify("STOPPING=1")
shutdown_requested.set()
${v.handler}
assert "Handler" in globals(), "You must define a class Handler(BaseHTTPRequestHandler) in the handler code"
def main():
httpd = NoBindHTTPServer(
("", 0),
Handler,
bind_and_activate=False,
)
httpd.socket = socket.fromfd(3, socket.AF_INET, socket.SOCK_STREAM)
httpd.serve_forever()
signal.signal(signal.SIGHUP, handle_reload)
signal.signal(signal.SIGTERM, handle_sigterm)
fd = sd_listen_fd(SOCKET_NAME)
httpd = Server(("", 0), Handler, bind_and_activate=False)
httpd.socket = socket.socket(fileno=fd)
server_thread = threading.Thread(target=httpd.serve_forever, name="http-server", daemon=True)
server_thread.start()
sd_notify("READY=1")
shutdown_requested.wait()
deadline = time.monotonic() + SHUTDOWN_TIMEOUT
httpd.shutdown()
server_thread.join(max(deadline - time.monotonic(), 0))
httpd.join_request_threads(max(deadline - time.monotonic(), 0))
httpd.server_close()
if __name__ == '__main__':
main()
+2 -2
View File
@@ -4,11 +4,11 @@ let
in
stdenvNoCC.mkDerivation rec {
pname = "bluemap";
version = "5.20";
version = "5.22";
src = fetchurl {
url = "https://github.com/BlueMap-Minecraft/BlueMap/releases/download/v${version}/BlueMap-${version}-cli.jar";
hash = "sha256-txDN/vG429BHT09TrSB8uQhmB8irrmvvOXX4OX3OSC0=";
hash = "sha256-oiidZJ9qg+BM8iKrzT1PLfTjLmEUcBX5IcBQZvY+77c=";
};
dontUnpack = true;
+20 -17
View File
@@ -1,6 +1,9 @@
config:
mysqld_exporter_password: ENC[AES256_GCM,data:I9K+QMqaN3FOOVKzeOR9Q6UERStXX0P8WEHyN1jzzbM=,iv:UxvIdlfAyJvNuxPkU4+guKPa0fiD0vVLzHOTYktcmso=,tag:ltnIqEwESYx9HBu8UN0ZLw==,type:str]
keys:
gatus:
mariadb: ENC[AES256_GCM,data:U7CGtjHacJlKcReEw3JO86okCVgLAkP92iX1bHGNw8qeImpvk5mNw77Ox7tbsChvozrJWa/Npu2pTBsNnVYYYA==,iv:hWa+KPiBc3AnH1tHCGJa8LhPXZ1o8sxufpGe7nUjV0E=,tag:mso5HEfmWAOGw350408X7g==,type:str]
postgres: ENC[AES256_GCM,data:7fI0JeZDK1MX5poXWaMo67PXbjdjvM+xPKioHSHmGdS8iNDGe5Ym6LlS/hOnPvvDuNFyHjKKizqDst0227U2gg==,iv:D3bz/xyFrnQsUCiMEFq8JOjSudyiw+idEMWQ1e6Uk3k=,tag:8XqadKVHK9NMWehK7V5J0Q==,type:str]
grafana:
secret_key: ENC[AES256_GCM,data:+WoAJbDBEgKs0RoHT+7oEELAVQ+/2Xt+5RTMSXg23moCqVRx+Gzll9P5Drw=,iv:AkRn/Y20iEe5i1T+84wAgLCTFtAox2G3giyawAkltAw=,tag:BZbt5Wb5lYLIJBm/pfP4GQ==,type:str]
admin_password: ENC[AES256_GCM,data:ttKwfC4WuXeL/6x4,iv:x1X+e3z08CR992GzC62YnFIN7SGrE81/nDNrgcgVzx0=,tag:YajUoy61kYbpeGeC7yNrXQ==,type:str]
@@ -9,8 +12,7 @@ keys:
postgres_exporter_knakelibrak_env: ENC[AES256_GCM,data:xjC7DGXrW2GIJq8XioIZb+jSe/Hzcz0tv9cUHmX/n1nhI+D64lYt+EKnq1+RX/vJzU4sTaKjveKBh88Qqnv6RQm+MZC//dIxcvnnAdl50qnHZyBCaFFEzSNI8I8vGyArMk8Ja72clBq3kMpUz/pLBP0qDrjblKDoWkU=,iv:ZW98hJy8A5t4Oxtu17R3tM7gou183VLbgBsHA8LFuJY=,tag:VMOvQz3X/XDylV1YFg2Jsg==,type:str]
sops:
age:
- recipient: age102e6y8gah0ntr6fxqnkpepc8ar29p6ls7ks9ka7v8w87q8scm9yqmc2u8d
enc: |
- enc: |
-----BEGIN AGE ENCRYPTED FILE-----
YWdlLWVuY3J5cHRpb24ub3JnL3YxCi0+IFgyNTUxOSAyTWRSM3IwMmxtTmZVcCsw
OUhlakxHZzgrSEhEdUZFTXE1anNjQ2wvdkZFCnB6S1l3TXQ3ZGFYWmtYM1cwMFZT
@@ -18,8 +20,8 @@ sops:
YlltQ3FBU3RBYUx4TnNPRk1SUWNqZG8KAJjc09x553ncaWduGLsnIHdroaOmMasP
/fq0GzW6UNfmE2rQ6qrQti21B37/sN0WMLCSPLUPG45kBgx20GG4hQ==
-----END AGE ENCRYPTED FILE-----
- recipient: age1ug30gg4y7ftuya0wdv7q0vh4egn00wlv2th7mt7cgc2ze46wmvyq9lq6ge
enc: |
recipient: age102e6y8gah0ntr6fxqnkpepc8ar29p6ls7ks9ka7v8w87q8scm9yqmc2u8d
- enc: |
-----BEGIN AGE ENCRYPTED FILE-----
YWdlLWVuY3J5cHRpb24ub3JnL3YxCi0+IFgyNTUxOSBTOWFvcFFzc1lmNVdmV3lX
cVVLNHowcGdENzI5UUJLZTNSMHhjNlI2c0FnCmdwOS9oL1kwTnhwbXRodWxxWVE3
@@ -27,8 +29,8 @@ sops:
eDVwd2dKMG9FRW1OY1pyUkhLeWw3b0EKtJpsQ/Ss39ZLiRNqUhn8sdB3hpQy7Syv
ererqhMkqmDugGEHPk6KpZuj7DVSK1di7JgA2qZOUPzI7UpxjaC0Kg==
-----END AGE ENCRYPTED FILE-----
- recipient: age1mrnldl334l2nszuta6ywvewng0fswv2dz9l5g4qcwe3nj4yxf92qjskdx6
enc: |
recipient: age1ug30gg4y7ftuya0wdv7q0vh4egn00wlv2th7mt7cgc2ze46wmvyq9lq6ge
- enc: |
-----BEGIN AGE ENCRYPTED FILE-----
YWdlLWVuY3J5cHRpb24ub3JnL3YxCi0+IFgyNTUxOSBOQU1iVXRkQmo4b3F1Vngz
S0pkNkVFR1FUb1djdmI0eHh3V3BBTDJTSTJZClA0S0Z0cTdFRmRaOEZQdHQzdGZ3
@@ -36,8 +38,8 @@ sops:
REdjRFZyY2pNdEd6cmgvQisyVDhLUEkKRItJ0CGbzlEB5RNAyem4feMVhTfcLef3
QIqltZ2l4LLexnkECi3FCJZHxrbUa+/RF6p1DsueUw7LLUnOcphB9A==
-----END AGE ENCRYPTED FILE-----
- recipient: age1hmpdk4h69wxpwqk9tkud39f66hprhehxtzhgw97r6dvr7v0mx5jscsuhkn
enc: |
recipient: age1mrnldl334l2nszuta6ywvewng0fswv2dz9l5g4qcwe3nj4yxf92qjskdx6
- enc: |
-----BEGIN AGE ENCRYPTED FILE-----
YWdlLWVuY3J5cHRpb24ub3JnL3YxCi0+IFgyNTUxOSAvZTBpaWM0c1hmODBaK0Iw
bmp1NzRacklXMHU0K2J2d0g5ajBiNlRNWGhRCm1DOWI0cm5BdTdlNmFzM2JVekNk
@@ -45,8 +47,8 @@ sops:
U0ZCT2toZ1ZMZ3E0bXRhSTQvNGFWNVkKhxfQDIDe2LQW7OMBJv0J267AW1wI32df
ZQxd657TEqzm7i19azrCS0jyRbfj2MYzEJAtTGiGZaNC9uKDFzBhKw==
-----END AGE ENCRYPTED FILE-----
- recipient: age1wrssr4z4g6vl3fd3qme5cewchmmhm0j2xe6wf2meu4r6ycn37anse98mfs
enc: |
recipient: age1hmpdk4h69wxpwqk9tkud39f66hprhehxtzhgw97r6dvr7v0mx5jscsuhkn
- enc: |
-----BEGIN AGE ENCRYPTED FILE-----
YWdlLWVuY3J5cHRpb24ub3JnL3YxCi0+IFgyNTUxOSBmRlJROHRKb21YUnlicmc1
MlptQllEcXFhajNKS1krMDdUMWk5QWo4eVJBCndGSlhXS1Vaa2RSTllIcmF1ZVpl
@@ -54,8 +56,8 @@ sops:
TE41aFdjU0h0ekQ2Zjg4Z3VQVjFWcnMK6zjSalqeYjyc4NH6nOeghlhYJydrz4pM
N5ZcXjRbrIVFdhbYnvQGKvGKZm0kK6vjzBjdT7BM6ctr8cq/qrz1xQ==
-----END AGE ENCRYPTED FILE-----
- recipient: age1zhxul786an743u0fascv4wtc5xduu7qfy803lfs539yzhgmlq5ds2lznt5
enc: |
recipient: age1wrssr4z4g6vl3fd3qme5cewchmmhm0j2xe6wf2meu4r6ycn37anse98mfs
- enc: |
-----BEGIN AGE ENCRYPTED FILE-----
YWdlLWVuY3J5cHRpb24ub3JnL3YxCi0+IFgyNTUxOSBIRXpBa2tYc2xEeldub0VK
bkFwOFdlUGRZM0FVT0tyUW1RWnl0TjRUTUh3CnZlMC92MU1hRW1yZU1NSUdoUEZh
@@ -63,8 +65,8 @@ sops:
aXFQWlNVQ2laVm1ETStRemNZRXc3TUEKlPYSU3gp67dsPfbEJkru4ieMvspC7+pu
rfp315HLyj1FGhrA8f2qOxE/PYI2rn0yKm80KffWBV7ylX/uonm4Fg==
-----END AGE ENCRYPTED FILE-----
- recipient: age1sqs7urnzsdy64efmd0zukzv3gs5pnjksuxd7nqmdwdy5l0nqnunq6hyune
enc: |
recipient: age1zhxul786an743u0fascv4wtc5xduu7qfy803lfs539yzhgmlq5ds2lznt5
- enc: |
-----BEGIN AGE ENCRYPTED FILE-----
YWdlLWVuY3J5cHRpb24ub3JnL3YxCi0+IFgyNTUxOSBsaTEzOFBEeG9LVThSVmQ5
VXBoaFpueFRCbFJ1akE4RWc1aE1HUmVGcXdZCjFnbU0wd2drazNsTmNBMHNuOFhO
@@ -72,8 +74,9 @@ sops:
dC9meDZlc3d3aUJEVjc4REF0Y1BLcGcK79LbJzc5KVgEgyJR11crGuX8YcVoJBbT
Fin7Zoon06L7qx0Zw5u27wV7RKMnYT7hOMiWs6660ZTLcYJ5M1aEZQ==
-----END AGE ENCRYPTED FILE-----
lastmodified: "2025-03-16T20:08:18Z"
mac: ENC[AES256_GCM,data:C2tpWppc13jKJq5d4nmAKQOaNWHm27TKwxAxm1fi2lejN1lqUaoz5bHfTBA7MfaWvuP5uZnfbtG32eeu48mnlWpo58XRUFFecAhb9JUpW9s5IR3/nbzLNkGU7H5C0oWPrxI4thd+bAVduIgBjjFyGj1pe6J9db3c0yUWRwNlwGU=,iv:YpoQ4psiFYOWLGipxv1QvRvr034XFsyn2Bhyy39HmOo=,tag:ByiCWygFC/VokVTbdLoLgg==,type:str]
recipient: age1sqs7urnzsdy64efmd0zukzv3gs5pnjksuxd7nqmdwdy5l0nqnunq6hyune
lastmodified: "2026-07-21T09:40:54Z"
mac: ENC[AES256_GCM,data:FLpmsW9I21qNMFs6Tn/1AzFo+RcmCwtVdAaaGIrGlUi2l3gzb//ZK6ruI/VYx1R5DoX1OhD3EIg6aLMSOT6jiHf+8GwfhdijpayG1nrgeZW3SuFbjVlCYNMPH3DOJJB82U3T+ozSbpnZEtdUwmNWcZJt5F2hOEnoaNa+jLEKDao=,iv:qyQuyWuu+w2ynRvhIx0QVtw+tieO3dbQsUxEB5Brzp0=,tag:qYAj4h6foWm16YqIdZ6xbQ==,type:str]
pgp:
- created_at: "2026-05-20T17:35:58Z"
enc: |-
@@ -96,4 +99,4 @@ sops:
-----END PGP MESSAGE-----
fp: F7D37890228A907440E1FD4846B9228E814A2AAC
unencrypted_suffix: _unencrypted
version: 3.9.4
version: 3.13.2
-23
View File
@@ -80,29 +80,6 @@ in {
};
};
nodes.drolsum = mkDevice "drolsum" {
guestType = "proxmox";
parent = config.nodes.powerpuff-cluster.id;
deviceType = "loginbox";
deviceIcon = "${pkgs.super-tiny-icons}/share/icons/SuperTinyIcons/svg/debian.svg";
# TODO: the interface name is likely wrong
interfaceGroups = [ [ "eth0" ] ];
interfaces.eth0 = {
network = "pvv";
# mac = "";
addresses = [
"129.241.210.217"
"2001:700:300:1900::217"
"2001:700:300:1900::1:217"
];
gateways = [
values.hosts.gateway
values.hosts.gateway6
];
};
};
nodes.microbel = mkDevice "microbel" {
deviceIcon = "${pkgs.super-tiny-icons}/share/icons/SuperTinyIcons/svg/debian.svg";