Compare commits

..

44 Commits

Author SHA1 Message Date
h7x4 9d1b0bc345 lupine5: register knutsen-vpn ip 2026-07-05 02:36:23 +09:00
h7x4 897f1244b6 lupine5/openvpn: use certs 2026-07-05 02:35:22 +09:00
h7x4 3f1c470059 sops/lupine: add CA + 2 keypairs for OpenVPN 2026-07-05 02:19:53 +09:00
h7x4 3aa8d0b418 lupine5/openvpn: init 2026-07-05 01:31:15 +09:00
h7x4 293f28abb1 lupine5: set up bridge and tap netdevs 2026-07-05 01:01:35 +09:00
h7x4 f4b1f090e4 flake.lock: bump various 2026-06-30 04:15:37 +09:00
h7x4 7c684e42f0 treewide: fix rsync <-> rrsync communication 2026-06-30 02:41:40 +09:00
h7x4 90bfda9066 kommode/gitea: bump AVATAR_MAX_ORIGIN_SIZE from 2MB to 4MB 2026-06-24 14:33:20 +09:00
h7x4 522d8f18cb flake.{nix,lock}: bump roowho2 2026-06-24 13:38:03 +09:00
h7x4 5e613a03fc treewide: set relatime for most root mounts 2026-06-23 01:12:16 +09:00
h7x4 170fb2a980 bicep/synapse: fix dbname option 2026-06-22 18:55:14 +09:00
h7x4 3e627472e9 flake.{nix,lock}: bump matrix-next 2026-06-22 18:55:13 +09:00
Adrian G L e05c4ed8ca feat: add initialdeploy hashed password to root 2026-06-21 18:24:01 +02:00
h7x4 3fee83ec05 ildkule/loki: restrict incoming connections to pvv + ntnu 2026-06-22 01:23:16 +09:00
h7x4 a1f02fc39d {ildkule/loki,base/fluentbit}: send data over https 2026-06-22 01:23:16 +09:00
Adrian G L 6e37635aac ildkule/loki: firewall all endpoints except push API
Co-authored-by: Øystein Kristoffer Tveit <oysteikt@pvv.ntnu.no>
2026-06-22 01:23:14 +09:00
h7x4 cdc3ad488b bicep/postgres: add script for updating all collations 2026-06-22 01:12:59 +09:00
h7x4 aa2712005a temmie/nfs-mounts: create by-uid bindmounts 2026-06-17 13:43:19 +09:00
h7x4 89921b533b temmie/userweb: further harden log-processor 2026-06-17 12:31:02 +09:00
h7x4 75f87ffab8 temmie/userweb: run passwd sync in different unit 2026-06-17 12:15:23 +09:00
h7x4 b910cf9563 temmie/userweb: suppress erroneous access log for documentRoot 2026-06-17 08:57:55 +09:00
h7x4 d23adbd4c2 temmie/userweb: deny access to documentRoot 2026-06-17 08:49:44 +09:00
h7x4 48c0a4e504 temmie/userweb: fix directory denylist enforcement 2026-06-17 08:23:08 +09:00
h7x4 374d9b1bc7 flake.nix: passthru machine config, pkgs and config.system.build
This shortens down the path needed to build both overlayed packages and
all the other machine derivations. Here are some examples:

```
nix build .#machine.etc
nix build '.#machine.units."nginx.service".unit'
nix build .#machine.pkgs.overlayed-package
nix build .#machine.config.services.nginx.package
```
2026-06-17 08:10:17 +09:00
h7x4 d84cc73819 temmie/userweb: handle more .php\d suffixes 2026-06-16 19:07:58 +09:00
h7x4 b738f08c09 temmie/userweb: render path denylist into Directory/Files directives 2026-06-16 19:07:57 +09:00
h7x4 8252bba3ad temmie/userweb: enable httpd trace on debugMode 2026-06-16 19:07:57 +09:00
h7x4 a776a5a5fe temmie/userweb: explicitly override mod_perl and mod_userdir 2026-06-16 19:07:57 +09:00
h7x4 ed57744ec3 temmie/userweb: add more patterns to denylist 2026-06-16 16:07:32 +09:00
h7x4 226db1f46e temmie/userweb: add more DirectoryIndex variants 2026-06-16 16:07:32 +09:00
h7x4 51e1656177 temmie/userweb: disable ~pvv 2026-06-16 15:53:52 +09:00
h7x4 47d2dcf9ff temmie/userweb: add bro server to userweb slice 2026-06-16 03:37:28 +09:00
h7x4 254b1d9b14 temmie/userweb: split into more modules 2026-06-16 03:33:28 +09:00
h7x4 2301672a21 temmie/userweb: run log processors as separate systemd units
This lets us divide up some of the logic making httpd itself less
brittle, and also reduces the amount of privileges for httpd.
2026-06-16 02:56:28 +09:00
felixalb 7145abadf3 flake: update input pvv-nettsiden 2026-06-13 16:59:50 +02:00
h7x4 b533b09c8f base/various: add to slice system-monitoring 2026-06-13 04:45:39 +09:00
h7x4 526b55c49a {ildkule/prometheus,base}: send stats over HTTPS through nginx 2026-06-13 02:54:28 +09:00
h7x4 e80189c6eb temmie/userweb: stop cating passwd on startup 2026-06-13 01:41:05 +09:00
h7x4 56a51e4c6f temmie/userweb: mount homedirs under /amd 2026-06-13 01:39:20 +09:00
h7x4 f54109f6f3 temmie/userweb: set handlers for php and perl scripts 2026-06-13 01:26:27 +09:00
Vegard Bieker Matthey 5763a76136 user/vegardbm: change shell to zsh and add ssh key 2026-06-08 11:35:44 +02:00
h7x4 b57a935b4c base/rsyslogd: init 2026-06-08 12:58:37 +09:00
h7x4 b4582a160f skrot/dibbler: rotate database password 2026-06-07 17:58:33 +09:00
h7x4 ac094d350d base/timesyncd: specify ntp servers 2026-06-07 17:52:54 +09:00
44 changed files with 1392 additions and 686 deletions
+9 -1
View File
@@ -14,7 +14,6 @@
./mitigations.nix ./mitigations.nix
./flake-input-exporter.nix
./hardening.nix ./hardening.nix
./networking.nix ./networking.nix
./nix.nix ./nix.nix
@@ -34,12 +33,15 @@
./services/openssh.nix ./services/openssh.nix
./services/polkit.nix ./services/polkit.nix
./services/postfix.nix ./services/postfix.nix
./services/prometheus-flake-input-exporter.nix
./services/prometheus-node-exporter.nix ./services/prometheus-node-exporter.nix
./services/prometheus-systemd-exporter.nix ./services/prometheus-systemd-exporter.nix
./services/roowho2.nix ./services/roowho2.nix
./services/rsyslogd.nix
./services/scrutiny-collector.nix ./services/scrutiny-collector.nix
./services/smartd.nix ./services/smartd.nix
./services/thermald.nix ./services/thermald.nix
./services/timesyncd.nix
./services/uptimed.nix ./services/uptimed.nix
./services/userborn.nix ./services/userborn.nix
./services/userdbd.nix ./services/userdbd.nix
@@ -93,8 +95,14 @@
AllowHibernation = lib.mkDefault false; AllowHibernation = lib.mkDefault false;
}; };
systemd.slices."system-monitoring" = {
description = "Monitoring related services";
};
# users.mutableUsers = lib.mkDefault false; # users.mutableUsers = lib.mkDefault false;
users.users.root.initialHashedPassword = "$y$j9T$ahP6GAdttD17OMBo7Yqeh.$Ad7qBcFvTL7HrJ9uTtrQzksN3220Nj9t/CrP6DwgK34"; # generated using mkpasswd, see huttiheita root on vaultwarden
users.groups."drift".name = "drift"; users.groups."drift".name = "drift";
# Trusted users on the nix builder machines # Trusted users on the nix builder machines
-55
View File
@@ -1,55 +0,0 @@
{
config,
inputs,
lib,
pkgs,
values,
...
}:
let
data = lib.flip lib.mapAttrs inputs (
name: input: {
inherit (input)
lastModified
;
}
);
folder = pkgs.writeTextDir "share/flake-inputs" (
lib.concatMapStringsSep "\n" (
{ name, value }: ''nixos_last_modified_input{flake="${name}"} ${toString value.lastModified}''
) (lib.attrsToList data)
);
port = 9102;
in
{
services.nginx.virtualHosts."${config.networking.fqdn}-nixos-metrics" = {
serverName = config.networking.fqdn;
serverAliases = [
"${config.networking.hostName}.pvv.org"
];
locations."/metrics" = {
root = "${folder}/share";
tryFiles = "/flake-inputs =404";
extraConfig = ''
default_type text/plain;
'';
};
listen = [
{
inherit port;
addr = "0.0.0.0";
}
];
extraConfig = ''
allow ${values.hosts.ildkule.ipv4}/32;
allow ${values.hosts.ildkule.ipv6}/128;
allow 127.0.0.1/32;
allow ::1/128;
allow ${values.ipv4-space};
allow ${values.ipv6-space};
deny all;
'';
};
networking.firewall.allowedTCPPorts = [ port ];
}
-1
View File
@@ -8,6 +8,5 @@
# Let's not spam LetsEncrypt in `nixos-rebuild build-vm` mode: # Let's not spam LetsEncrypt in `nixos-rebuild build-vm` mode:
virtualisation.vmVariant = { virtualisation.vmVariant = {
security.acme.defaults.server = "https://127.0.0.1"; security.acme.defaults.server = "https://127.0.0.1";
users.users.root.initialPassword = "root";
}; };
} }
+5 -2
View File
@@ -62,8 +62,10 @@ in
name = "loki"; name = "loki";
match = "*"; match = "*";
host = "ildkule.pvv.ntnu.no"; host = "loki.pvv.ntnu.no";
port = 3100; port = 443;
tls = "on";
"tls.verify" = "on";
uri = "/loki/api/v1/push"; uri = "/loki/api/v1/push";
compress = "gzip"; compress = "gzip";
@@ -88,6 +90,7 @@ in
systemd.services.fluent-bit = lib.mkIf cfg.enable { systemd.services.fluent-bit = lib.mkIf cfg.enable {
serviceConfig = { serviceConfig = {
Slice = "system-monitoring.slice";
StateDirectory = "fluent-bit"; StateDirectory = "fluent-bit";
# NOTE: This hardening might be way too strong for general purpose use, don't upstream this. # NOTE: This hardening might be way too strong for general purpose use, don't upstream this.
+1
View File
@@ -14,6 +14,7 @@ in
}; };
systemd.services."systemd-journal-upload".serviceConfig = lib.mkIf cfg.enable { systemd.services."systemd-journal-upload".serviceConfig = lib.mkIf cfg.enable {
Slice = "system-monitoring.slice";
IPAddressDeny = "any"; IPAddressDeny = "any";
IPAddressAllow = [ IPAddressAllow = [
values.hosts.ildkule.ipv4 values.hosts.ildkule.ipv4
+2 -24
View File
@@ -1,18 +1,5 @@
{ config, lib, ... }: { 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 = { services.nginx = {
recommendedTlsSettings = true; recommendedTlsSettings = true;
recommendedProxySettings = true; recommendedProxySettings = true;
@@ -60,17 +47,8 @@
]; ];
} }
]; ];
sslCertificate = "/etc/certs/nginx.crt"; };
sslCertificateKey = "/etc/certs/nginx.key";
addSSL = true;
extraConfig = "return 444;";
}; };
${config.networking.fqdn} = { networking.firewall.allowedTCPPorts = lib.mkIf config.services.nginx.enable [ 80 443 ];
sslCertificate = lib.mkDefault "/etc/certs/nginx.crt";
sslCertificateKey = lib.mkDefault "/etc/certs/nginx.key";
addSSL = lib.mkDefault true;
extraConfig = lib.mkDefault "return 444;";
};
};
} }
@@ -0,0 +1,47 @@
{
config,
inputs,
lib,
pkgs,
values,
...
}:
let
data = lib.flip lib.mapAttrs inputs (
name: input: {
inherit (input)
lastModified
;
}
);
folder = pkgs.writeTextDir "share/flake-inputs" (
lib.concatMapStringsSep "\n" (
{ name, value }: ''nixos_last_modified_input{flake="${name}"} ${toString value.lastModified}''
) (lib.attrsToList data)
);
in
{
services.nginx = {
enable = lib.mkDefault true;
virtualHosts.${config.networking.fqdn} = lib.mkIf config.services.nginx.enable {
forceSSL = true;
enableACME = true;
kTLS = true;
locations."/prometheus-nixos-flake-input-exporter/metrics" = {
root = "${folder}/share";
tryFiles = "/flake-inputs =404";
extraConfig = ''
default_type text/plain;
allow 127.0.0.1;
allow ::1;
allow ${values.hosts.ildkule.ipv4};
allow ${values.hosts.ildkule.ipv6};
deny all;
'';
};
};
};
}
+24 -9
View File
@@ -5,19 +5,34 @@ in
{ {
services.prometheus.exporters.node = { services.prometheus.exporters.node = {
enable = lib.mkDefault true; enable = lib.mkDefault true;
listenAddress = "127.0.0.1";
port = 9100; port = 9100;
enabledCollectors = [ "systemd" ]; enabledCollectors = [ "systemd" ];
}; };
systemd.services.prometheus-node-exporter.serviceConfig = lib.mkIf cfg.enable { services.nginx = lib.mkIf cfg.enable {
IPAddressDeny = "any"; enable = lib.mkDefault true;
IPAddressAllow = [
"127.0.0.1" virtualHosts.${config.networking.fqdn} = lib.mkIf config.services.nginx.enable {
"::1" forceSSL = true;
values.hosts.ildkule.ipv4 enableACME = true;
values.hosts.ildkule.ipv6 kTLS = true;
];
locations."/prometheus-node-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;
'';
};
};
}; };
networking.firewall.allowedTCPPorts = lib.mkIf cfg.enable [ cfg.port ]; systemd.services = lib.mkIf cfg.enable {
"prometheus-node-exporter".serviceConfig.Slice = "system-monitoring.slice";
};
} }
+24 -9
View File
@@ -5,6 +5,7 @@ in
{ {
services.prometheus.exporters.systemd = { services.prometheus.exporters.systemd = {
enable = lib.mkDefault true; enable = lib.mkDefault true;
listenAddress = "127.0.0.1";
port = 9101; port = 9101;
extraFlags = [ extraFlags = [
"--systemd.collector.enable-restart-count" "--systemd.collector.enable-restart-count"
@@ -12,15 +13,29 @@ in
]; ];
}; };
systemd.services.prometheus-systemd-exporter.serviceConfig = { services.nginx = lib.mkIf cfg.enable {
IPAddressDeny = "any"; enable = lib.mkDefault true;
IPAddressAllow = [
"127.0.0.1" virtualHosts.${config.networking.fqdn} = lib.mkIf config.services.nginx.enable {
"::1" forceSSL = true;
values.hosts.ildkule.ipv4 enableACME = true;
values.hosts.ildkule.ipv6 kTLS = true;
];
locations."/prometheus-systemd-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;
'';
};
};
}; };
networking.firewall.allowedTCPPorts = lib.mkIf cfg.enable [ cfg.port ]; systemd.services = lib.mkIf cfg.enable {
"prometheus-systemd-exporter".serviceConfig.Slice = "system-monitoring.slice";
};
} }
+20
View File
@@ -0,0 +1,20 @@
{ config, lib, ... }:
let
cfg = config.services.rsyslogd;
in
{
services.rsyslogd = {
enable = lib.mkDefault true;
defaultConfig = ''
*.* @loghost.pvv.ntnu.no
'';
};
services.journald.extraConfig = lib.mkIf cfg.enable ''
ForwardToSyslog=yes
'';
systemd.services = lib.mkIf cfg.enable {
"syslog".serviceConfig.Slice = "system-monitoring.slice";
};
}
+12
View File
@@ -0,0 +1,12 @@
{ ... }:
{
services.timesyncd = {
servers = [ "ntp.ntnu.no" ];
fallbackServers = [
"0.pool.ntp.org"
"1.pool.ntp.org"
"0.no.pool.ntp.org"
];
};
}
+3 -1
View File
@@ -23,7 +23,7 @@ in
}; };
}; };
systemd.services.uptimed = lib.mkIf (cfg.enable) { systemd.services.uptimed = lib.mkIf cfg.enable {
serviceConfig = let serviceConfig = let
uptimed = pkgs.uptimed.overrideAttrs (prev: { uptimed = pkgs.uptimed.overrideAttrs (prev: {
postPatch = '' postPatch = ''
@@ -35,6 +35,8 @@ in
}); });
in { in {
Slice = "system-monitoring.slice";
Type = "notify"; Type = "notify";
ExecStart = lib.mkForce "${uptimed}/sbin/uptimed -f"; ExecStart = lib.mkForce "${uptimed}/sbin/uptimed -f";
Generated
+42 -42
View File
@@ -44,11 +44,11 @@
] ]
}, },
"locked": { "locked": {
"lastModified": 1771267058, "lastModified": 1780236125,
"narHash": "sha256-EEL4SmD1b3BPJPsSJJ4wDTXWMumJqbR+BLzhJJG0skE=", "narHash": "sha256-LFFdHbXFthgU81S6P+p9FFKs/Wx868d4CtsFvbgvQqo=",
"ref": "main", "ref": "main",
"rev": "e3962d02c78b9c7b4d18148d931a9a4bf22e7902", "rev": "267af00ebd8693632fa0f80300e49203cfcebbd4",
"revCount": 254, "revCount": 258,
"type": "git", "type": "git",
"url": "https://git.pvv.ntnu.no/Projects/dibbler.git" "url": "https://git.pvv.ntnu.no/Projects/dibbler.git"
}, },
@@ -126,10 +126,10 @@
"rust-overlay": "rust-overlay_2" "rust-overlay": "rust-overlay_2"
}, },
"locked": { "locked": {
"lastModified": 1777019032, "lastModified": 1779345549,
"narHash": "sha256-29lw7THThWb5DW01rVRj1b816Apwz/P4m2wVWaSIadU=", "narHash": "sha256-naEMpFsQrco5eDtYmcTG6cpbPG+kqElOyS7fTb/jw9s=",
"ref": "main", "ref": "main",
"rev": "55262afca46c96f75a834d4e00e30d5fb20affb6", "rev": "5631e1124508fdef0604b08bfcf6343d967a21b3",
"revCount": 61, "revCount": 61,
"type": "git", "type": "git",
"url": "https://git.pvv.ntnu.no/Grzegorz/greg-ng.git" "url": "https://git.pvv.ntnu.no/Grzegorz/greg-ng.git"
@@ -169,11 +169,11 @@
] ]
}, },
"locked": { "locked": {
"lastModified": 1769338528, "lastModified": 1780178524,
"narHash": "sha256-t18ZoSt9kaI1yde26ok5s7aFLkap1Q9+/2icVh2zuaE=", "narHash": "sha256-2PcNyNqbGCWBpAMdCU1HxSQmhQiG6evdjxVnPA7w5bQ=",
"ref": "refs/heads/main", "ref": "refs/heads/main",
"rev": "7218348163fd8d84df4a6f682c634793e67a3fed", "rev": "2406de41ce9d0a1404cbf4e55537e3f720f37f23",
"revCount": 13, "revCount": 15,
"type": "git", "type": "git",
"url": "https://git.pvv.ntnu.no/Projects/libdib.git" "url": "https://git.pvv.ntnu.no/Projects/libdib.git"
}, },
@@ -189,16 +189,16 @@
] ]
}, },
"locked": { "locked": {
"lastModified": 1764844095, "lastModified": 1782122067,
"narHash": "sha256-Drf1orxsmFDzO+UbPo85gHjXW7QzAM+6oTPvI7vOSik=", "narHash": "sha256-95q3DiYOTHjQGbqR0I1w4ETrH+smtddqW0bBxaB/Egg=",
"owner": "dali99", "owner": "dali99",
"repo": "nixos-matrix-modules", "repo": "nixos-matrix-modules",
"rev": "25b9f31ef1dbc3987b4c716de716239f2b283701", "rev": "0e0fd9f6a407b08dd5e180a2ff6c3808461e2c47",
"type": "github" "type": "github"
}, },
"original": { "original": {
"owner": "dali99", "owner": "dali99",
"ref": "v0.8.0", "ref": "master",
"repo": "nixos-matrix-modules", "repo": "nixos-matrix-modules",
"type": "github" "type": "github"
} }
@@ -291,11 +291,11 @@
}, },
"nixpkgs": { "nixpkgs": {
"locked": { "locked": {
"lastModified": 1779622335, "lastModified": 1782708249,
"narHash": "sha256-06G98ieM6l+OI7EMhlvchgDBDn+DvIWCNj40LDhKpmc=", "narHash": "sha256-ASIzbiHLqFDHfomCJVMDaW1rsD9IJQ/m997Tw8569tM=",
"rev": "705e9929918b43bd7b715dc0a878ac870449bb03", "rev": "68d68014342a18d2514d6e6f1185cfc24d02fc00",
"type": "tarball", "type": "tarball",
"url": "https://releases.nixos.org/nixos/26.05-small/nixos-26.05beta1.705e9929918b/nixexprs.tar.xz" "url": "https://releases.nixos.org/nixos/26.05-small/nixos-26.05.3713.68d68014342a/nixexprs.tar.xz"
}, },
"original": { "original": {
"type": "tarball", "type": "tarball",
@@ -319,11 +319,11 @@
}, },
"nixpkgs-unstable": { "nixpkgs-unstable": {
"locked": { "locked": {
"lastModified": 1778586796, "lastModified": 1782731455,
"narHash": "sha256-XmDljcG4x8slQDlsWOc77pCA1YVuYn8JGumkYlhfTxI=", "narHash": "sha256-vFMOLxoARiCUBQOysAAJ0VmPzilmHUqk3EZfSRweKN8=",
"rev": "b25e938b89759b5f9466fc53c4a970244f84dc39", "rev": "9c4c05a947a91dc14625265fab505fb695e93218",
"type": "tarball", "type": "tarball",
"url": "https://releases.nixos.org/nixos/unstable-small/nixos-26.05pre996582.b25e938b8975/nixexprs.tar.xz" "url": "https://releases.nixos.org/nixos/unstable-small/nixos-26.11pre1024311.9c4c05a947a9/nixexprs.tar.xz"
}, },
"original": { "original": {
"type": "tarball", "type": "tarball",
@@ -379,11 +379,11 @@
] ]
}, },
"locked": { "locked": {
"lastModified": 1779903528, "lastModified": 1782759909,
"narHash": "sha256-4rajaHeBeQ4PjbNSpslE9G3A5mZM1J/64ls+VoufWZo=", "narHash": "sha256-gktjBeZyoRvVBkm2cO1tD99fdQ34iUDyB6iecRdorm4=",
"ref": "main", "ref": "main",
"rev": "bba7413a1c611d4918fbef4d3aa55e465ca3f3fb", "rev": "ad6c79fb713884a4a2df8aab30914cd0c1c2e6cb",
"revCount": 585, "revCount": 587,
"type": "git", "type": "git",
"url": "https://git.pvv.ntnu.no/Projects/nettsiden.git" "url": "https://git.pvv.ntnu.no/Projects/nettsiden.git"
}, },
@@ -447,17 +447,17 @@
"rust-overlay": "rust-overlay_4" "rust-overlay": "rust-overlay_4"
}, },
"locked": { "locked": {
"lastModified": 1778600367, "lastModified": 1782275838,
"narHash": "sha256-YB0b2xUf4D8792D5Ay//7C3AjHyv+9yoy8K1mTe+wvE=", "narHash": "sha256-CW84hEFcypvEegQp+4zZZ4lCnPT7Qn27OpKiQBxiWS8=",
"ref": "main", "ref": "main",
"rev": "8e5f2849ff7c9616100fe928261512a7ad647939", "rev": "71d2b72c34352a79dbee8ebf23ce64f39aead692",
"revCount": 91, "revCount": 102,
"type": "git", "type": "git",
"url": "https://git.pvv.ntnu.no/Projects/roowho2.git" "url": "https://git.pvv.ntnu.no/Projects/roowho2.git"
}, },
"original": { "original": {
"ref": "main", "ref": "main",
"rev": "8e5f2849ff7c9616100fe928261512a7ad647939", "rev": "71d2b72c34352a79dbee8ebf23ce64f39aead692",
"type": "git", "type": "git",
"url": "https://git.pvv.ntnu.no/Projects/roowho2.git" "url": "https://git.pvv.ntnu.no/Projects/roowho2.git"
} }
@@ -491,11 +491,11 @@
] ]
}, },
"locked": { "locked": {
"lastModified": 1777000482, "lastModified": 1779333539,
"narHash": "sha256-CZ5FKUSA8FCJf0h9GWdPJXoVVDL9H5yC74GkVc5ubIM=", "narHash": "sha256-lpmN2lrBDZDPjov2cbD3bOOJsI0fkKolKXasYPCqSys=",
"owner": "oxalica", "owner": "oxalica",
"repo": "rust-overlay", "repo": "rust-overlay",
"rev": "403c09094a877e6c4816462d00b1a56ff8198e06", "rev": "672fa5fc5608d5cd82286a6f69aaf84a40b4fe41",
"type": "github" "type": "github"
}, },
"original": { "original": {
@@ -553,11 +553,11 @@
] ]
}, },
"locked": { "locked": {
"lastModified": 1777944972, "lastModified": 1782165805,
"narHash": "sha256-VfGRo1qTBKOe3s2gOv8LSoA6Fk19PvBlwQ1ECN0Evn8=", "narHash": "sha256-478kKQBvK6SYTOdN2h9jhKJv94nbXRbFMfuL1WshErg=",
"owner": "Mic92", "owner": "Mic92",
"repo": "sops-nix", "repo": "sops-nix",
"rev": "c591bf665727040c6cc5cb409079acb22dcce33c", "rev": "56b24064fdcaedca53553b1a6d607fd23b613a24",
"type": "github" "type": "github"
}, },
"original": { "original": {
@@ -575,11 +575,11 @@
] ]
}, },
"locked": { "locked": {
"lastModified": 1773932847, "lastModified": 1780762731,
"narHash": "sha256-IklIAdlonrmO8/lkDxNIVz9+ORL4pcVotMTxeyvxzoc=", "narHash": "sha256-EuDaLnasWN0mpi995n+fAQQfPGBhqNW4fNjlQRpHt58=",
"ref": "main", "ref": "main",
"rev": "0871a319f51d3cb0d1abb5b11edb768b39906d3f", "rev": "931bd2d63e285e767c8c81c103dda3c0a63f2965",
"revCount": 104, "revCount": 108,
"type": "git", "type": "git",
"url": "https://git.pvv.ntnu.no/Projects/worblehat.git" "url": "https://git.pvv.ntnu.no/Projects/worblehat.git"
}, },
+8 -3
View File
@@ -26,7 +26,7 @@
worblehat.url = "git+https://git.pvv.ntnu.no/Projects/worblehat.git?ref=main"; worblehat.url = "git+https://git.pvv.ntnu.no/Projects/worblehat.git?ref=main";
worblehat.inputs.nixpkgs.follows = "nixpkgs"; worblehat.inputs.nixpkgs.follows = "nixpkgs";
matrix-next.url = "github:dali99/nixos-matrix-modules/v0.8.0"; matrix-next.url = "github:dali99/nixos-matrix-modules/master";
matrix-next.inputs.nixpkgs.follows = "nixpkgs"; matrix-next.inputs.nixpkgs.follows = "nixpkgs";
nix-gitea-themes.url = "git+https://git.pvv.ntnu.no/Drift/nix-gitea-themes.git?ref=main"; nix-gitea-themes.url = "git+https://git.pvv.ntnu.no/Drift/nix-gitea-themes.git?ref=main";
@@ -35,7 +35,7 @@
minecraft-heatmap.url = "git+https://git.pvv.ntnu.no/Projects/minecraft-heatmap.git?ref=main"; minecraft-heatmap.url = "git+https://git.pvv.ntnu.no/Projects/minecraft-heatmap.git?ref=main";
minecraft-heatmap.inputs.nixpkgs.follows = "nixpkgs"; minecraft-heatmap.inputs.nixpkgs.follows = "nixpkgs";
roowho2.url = "git+https://git.pvv.ntnu.no/Projects/roowho2.git?ref=main&rev=8e5f2849ff7c9616100fe928261512a7ad647939"; roowho2.url = "git+https://git.pvv.ntnu.no/Projects/roowho2.git?ref=main&rev=71d2b72c34352a79dbee8ebf23ce64f39aead692";
roowho2.inputs.nixpkgs.follows = "nixpkgs"; roowho2.inputs.nixpkgs.follows = "nixpkgs";
greg-ng.url = "git+https://git.pvv.ntnu.no/Grzegorz/greg-ng.git?ref=main"; greg-ng.url = "git+https://git.pvv.ntnu.no/Grzegorz/greg-ng.git?ref=main";
@@ -369,7 +369,12 @@
// //
# Machines # Machines
lib.genAttrs allMachines lib.genAttrs allMachines
(machine: self.nixosConfigurations.${machine}.config.system.build.toplevel) (machine: self.nixosConfigurations.${machine}.config.system.build.toplevel.overrideAttrs (prev: {
passthru =
(prev.passthru or { })
// self.nixosConfigurations.${machine}.config.system.build
// { inherit (self.nixosConfigurations.${machine}) pkgs config; };
}))
// //
# Nix-topology # Nix-topology
(let (let
@@ -16,6 +16,7 @@
fileSystems."/" = fileSystems."/" =
{ device = "/dev/sda1"; { device = "/dev/sda1";
fsType = "btrfs"; fsType = "btrfs";
options = [ "relatime" ];
}; };
fileSystems."/boot" = fileSystems."/boot" =
+1 -1
View File
@@ -74,7 +74,7 @@ in {
name = "psycopg2"; name = "psycopg2";
args = { args = {
host = "/var/run/postgresql"; host = "/var/run/postgresql";
dbname = "synapse"; database = "synapse";
user = "matrix-synapse"; user = "matrix-synapse";
cp_min = 1; cp_min = 1;
cp_max = 5; cp_max = 5;
+1 -1
View File
@@ -43,7 +43,7 @@ in
sshCommand = ''${pkgs.openssh}/bin/ssh -o UserKnownHostsFile='${knownHostsFile}' -i \"$CREDENTIALS_DIRECTORY\"/sshkey''; sshCommand = ''${pkgs.openssh}/bin/ssh -o UserKnownHostsFile='${knownHostsFile}' -i \"$CREDENTIALS_DIRECTORY\"/sshkey'';
in [ in [
"${lib.getExe' pkgs.coreutils "mkdir"} -p '${cfg.minecraftLogsDir}'" "${lib.getExe' pkgs.coreutils "mkdir"} -p '${cfg.minecraftLogsDir}'"
"${lib.getExe pkgs.rsync} ${rsyncArgs} --rsh=\"${sshCommand}\" root@innovation.pvv.ntnu.no:/ '${cfg.minecraftLogsDir}'/" "${lib.getExe pkgs.rsync} ${rsyncArgs} --rsh=\"${sshCommand}\" root@innovation.pvv.ntnu.no:. '${cfg.minecraftLogsDir}'/"
]; ];
}; };
}; };
@@ -127,4 +127,27 @@ in
networking.firewall.allowedTCPPorts = lib.mkIf cfg.enable [ 5432 ]; networking.firewall.allowedTCPPorts = lib.mkIf cfg.enable [ 5432 ];
networking.firewall.allowedUDPPorts = lib.mkIf cfg.enable [ 5432 ]; networking.firewall.allowedUDPPorts = lib.mkIf cfg.enable [ 5432 ];
environment.systemPackages = [
(pkgs.writeShellApplication {
name = "postgres-update-collations.sh";
runtimeInputs = [
config.systemd.package
cfg.package
];
text = ''
run0 --user=postgres psql <${pkgs.writeText "postgres-update-collations.sql" ''
CREATE FUNCTION exec(text) returns text language plpgsql volatile
AS $f$
BEGIN
EXECUTE $1;
RETURN $1;
END;
$f$;
SELECT exec('ALTER DATABASE "' || datname || '" REFRESH COLLATION VERSION') FROM pg_database WHERE datistemplate = false;
''}
'';
})
];
} }
@@ -16,6 +16,7 @@
fileSystems."/" = fileSystems."/" =
{ device = "/dev/disk/by-uuid/4e8667f8-55de-4103-8369-b94665f42204"; { device = "/dev/disk/by-uuid/4e8667f8-55de-4103-8369-b94665f42204";
fsType = "ext4"; fsType = "ext4";
options = [ "relatime" ];
}; };
fileSystems."/boot" = fileSystems."/boot" =
+1
View File
@@ -16,6 +16,7 @@
fileSystems."/" = fileSystems."/" =
{ device = "/dev/disk/by-uuid/33825f0d-5a63-40fc-83db-bfa1ebb72ba0"; { device = "/dev/disk/by-uuid/33825f0d-5a63-40fc-83db-bfa1ebb72ba0";
fsType = "ext4"; fsType = "ext4";
options = [ "relatime" ];
}; };
fileSystems."/boot" = fileSystems."/boot" =
@@ -28,6 +28,7 @@
fileSystems."/" = { fileSystems."/" = {
device = "/dev/mapper/pool-root"; device = "/dev/mapper/pool-root";
fsType = "ext4"; fsType = "ext4";
options = [ "relatime" ];
}; };
fileSystems."/boot" = { fileSystems."/boot" = {
+2 -2
View File
@@ -93,7 +93,7 @@ in {
no-group = true; no-group = true;
rsh = "${pkgs.openssh}/bin/ssh -o UserKnownHostsFile=%d/ssh-known-hosts -i %d/sshkey"; rsh = "${pkgs.openssh}/bin/ssh -o UserKnownHostsFile=%d/ssh-known-hosts -i %d/sshkey";
}; };
in "${lib.getExe pkgs.rsync} ${rsyncArgs} root@innovation.pvv.ntnu.no:/ ${vanillaSurvival}"; in "${lib.getExe pkgs.rsync} ${rsyncArgs} root@innovation.pvv.ntnu.no:. ${vanillaSurvival}";
ExecStartPost = let ExecStartPost = let
rsyncArgs = lib.cli.toCommandLineShellGNU { } { rsyncArgs = lib.cli.toCommandLineShellGNU { } {
archive = true; archive = true;
@@ -103,7 +103,7 @@ in {
no-group = true; no-group = true;
rsh = "${pkgs.openssh}/bin/ssh -o UserKnownHostsFile=%d/ssh-known-hosts -i %d/sshkey"; rsh = "${pkgs.openssh}/bin/ssh -o UserKnownHostsFile=%d/ssh-known-hosts -i %d/sshkey";
}; };
in "${lib.getExe pkgs.rsync} ${rsyncArgs} --groupmap=root:nginx ${config.services.bluemap.webRoot}/ root@bekkalokk.pvv.ntnu.no:/"; in "${lib.getExe pkgs.rsync} ${rsyncArgs} --groupmap=root:nginx ${config.services.bluemap.webRoot}/ root@bekkalokk.pvv.ntnu.no:.";
LoadCredential = [ LoadCredential = [
"sshkey:${config.sops.secrets."bluemap/ssh-key".path}" "sshkey:${config.sops.secrets."bluemap/ssh-key".path}"
"ssh-known-hosts:${config.sops.secrets."bluemap/ssh-known-hosts".path}" "ssh-known-hosts:${config.sops.secrets."bluemap/ssh-known-hosts".path}"
+24 -4
View File
@@ -1,4 +1,4 @@
{ config, pkgs, ... }: { config, pkgs, values, ... }:
let let
cfg = config.services.loki; cfg = config.services.loki;
@@ -9,8 +9,8 @@ in {
configuration = { configuration = {
auth_enabled = false; auth_enabled = false;
server = { server = {
http_listen_port = 3100; http_listen_port = 31832;
http_listen_address = "0.0.0.0"; http_listen_address = "127.0.0.1";
grpc_listen_port = 9096; grpc_listen_port = 9096;
}; };
@@ -81,5 +81,25 @@ in {
}; };
}; };
networking.firewall.allowedTCPPorts = [ cfg.configuration.server.http_listen_port ]; services.nginx.virtualHosts."loki.pvv.ntnu.no" = {
forceSSL = true;
enableACME = true;
kTLS = true;
locations = {
"/".return = "403";
"/loki/api/v1/push" = {
proxyPass = "http://${cfg.configuration.server.http_listen_address}:${toString cfg.configuration.server.http_listen_port}/loki/api/v1/push";
extraConfig = ''
allow 127.0.0.1;
allow ::1;
allow ${values.ipv4-space};
allow ${values.ipv6-space};
allow ${values.ntnu.ipv4-space};
allow ${values.ntnu.ipv6-space};
deny all;
'';
};
};
};
} }
@@ -6,32 +6,63 @@
targets = map (port: "${name}.pvv.ntnu.no:${toString port}") ports; targets = map (port: "${name}.pvv.ntnu.no:${toString port}") ports;
}; };
nixosMachines = [
"ildkule"
"bekkalokk"
"bicep"
"brzeczyszczykiewicz"
"georg"
"gluttony"
"kommode"
"lupine-1"
"lupine-2"
"lupine-3"
"lupine-4"
"lupine-5"
# TODO: export prometheus stats via apache on temmie
# "temmie"
"wenche"
];
defaultNodeExporterPort = 9100; defaultNodeExporterPort = 9100;
defaultSystemdExporterPort = 9101;
defaultNixosExporterPort = 9102;
in { in {
services.prometheus.scrapeConfigs = [{ services.prometheus.scrapeConfigs = [
job_name = "base_info"; {
job_name = "nixos-node";
scheme = "https";
metrics_path = "/prometheus-node-exporter/metrics";
static_configs = map (name: {
labels.hostname = name;
targets = [ "${name}.pvv.ntnu.no:443" ];
}) nixosMachines;
}
{
job_name = "nixos-systemd";
scheme = "https";
metrics_path = "/prometheus-systemd-exporter/metrics";
static_configs = map (name: {
labels.hostname = name;
targets = [ "${name}.pvv.ntnu.no:443" ];
}) nixosMachines;
}
{
job_name = "nixos-flake-input";
scheme = "https";
metrics_path = "/prometheus-nixos-flake-input-exporter/metrics";
static_configs = map (name: {
labels.hostname = name;
targets = [ "${name}.pvv.ntnu.no:443" ];
}) nixosMachines;
}
{
job_name = "non-nixos-node";
scheme = "http";
metrics_path = "/metrics";
static_configs = [ static_configs = [
(mkHostScrapeConfig "ildkule" [ cfg.exporters.node.port cfg.exporters.systemd.port defaultNixosExporterPort ])
(mkHostScrapeConfig "bekkalokk" [ defaultNodeExporterPort defaultSystemdExporterPort defaultNixosExporterPort ])
(mkHostScrapeConfig "bicep" [ defaultNodeExporterPort defaultSystemdExporterPort defaultNixosExporterPort ])
(mkHostScrapeConfig "brzeczyszczykiewicz" [ defaultNodeExporterPort defaultSystemdExporterPort defaultNixosExporterPort ])
(mkHostScrapeConfig "georg" [ defaultNodeExporterPort defaultSystemdExporterPort defaultNixosExporterPort ])
(mkHostScrapeConfig "gluttony" [ defaultNodeExporterPort defaultSystemdExporterPort defaultNixosExporterPort ])
(mkHostScrapeConfig "kommode" [ defaultNodeExporterPort defaultSystemdExporterPort defaultNixosExporterPort ])
(mkHostScrapeConfig "lupine-1" [ defaultNodeExporterPort defaultSystemdExporterPort defaultNixosExporterPort ])
(mkHostScrapeConfig "lupine-2" [ defaultNodeExporterPort defaultSystemdExporterPort defaultNixosExporterPort ])
(mkHostScrapeConfig "lupine-3" [ defaultNodeExporterPort defaultSystemdExporterPort defaultNixosExporterPort ])
(mkHostScrapeConfig "lupine-4" [ defaultNodeExporterPort defaultSystemdExporterPort defaultNixosExporterPort ])
(mkHostScrapeConfig "lupine-5" [ defaultNodeExporterPort defaultSystemdExporterPort defaultNixosExporterPort ])
(mkHostScrapeConfig "temmie" [ defaultNodeExporterPort defaultSystemdExporterPort defaultNixosExporterPort ])
(mkHostScrapeConfig "wenche" [ defaultNodeExporterPort defaultSystemdExporterPort defaultNixosExporterPort ])
(mkHostScrapeConfig "hildring" [ defaultNodeExporterPort ]) (mkHostScrapeConfig "hildring" [ defaultNodeExporterPort ])
(mkHostScrapeConfig "isvegg" [ defaultNodeExporterPort ]) (mkHostScrapeConfig "isvegg" [ defaultNodeExporterPort ])
(mkHostScrapeConfig "microbel" [ defaultNodeExporterPort ]) (mkHostScrapeConfig "microbel" [ defaultNodeExporterPort ])
]; ];
}]; }
];
} }
+1
View File
@@ -48,6 +48,7 @@
# swap.swapfile.size = "4G"; # swap.swapfile.size = "4G";
mountpoint = "/"; mountpoint = "/";
mountOptions = [ "relatime" ];
}; };
}; };
+1 -1
View File
@@ -136,7 +136,7 @@ in {
picture = { picture = {
AVATAR_MAX_FILE_SIZE = 1024 * 1024 * 5; AVATAR_MAX_FILE_SIZE = 1024 * 1024 * 5;
# NOTE: go any bigger than this, and gitea will freeze your gif >:( # NOTE: go any bigger than this, and gitea will freeze your gif >:(
AVATAR_MAX_ORIGIN_SIZE = 1024 * 1024 * 2; AVATAR_MAX_ORIGIN_SIZE = 1024 * 1024 * 4;
}; };
actions.ENABLED = true; actions.ENABLED = true;
webhook.ALLOWED_HOST_LIST = lib.concatStringsSep "," [ webhook.ALLOWED_HOST_LIST = lib.concatStringsSep "," [
+52 -3
View File
@@ -5,6 +5,8 @@
(fp /base) (fp /base)
./services/gitea-runner.nix ./services/gitea-runner.nix
] ++ lib.optionals (lupineName == "lupine-5") [
./services/openvpn.nix
]; ];
sops.defaultSopsFile = fp /secrets/lupine/lupine.yaml; sops.defaultSopsFile = fp /secrets/lupine/lupine.yaml;
@@ -15,14 +17,61 @@
"i686-linux" "i686-linux"
]; ];
systemd.network.networks."30-enp0s31f6" = values.defaultNetworkConfig // { systemd.network = if (lupineName != "lupine-5")
then {
networks."30-enp0s31f6" = (values.defaultNetworkConfig // {
matchConfig.Name = "enp0s31f6"; matchConfig.Name = "enp0s31f6";
address = with values.hosts.${lupineName}; [ (ipv4 + "/25") (ipv6 + "/64") ]; address = with values.hosts.${lupineName}; [ (ipv4 + "/25") (ipv6 + "/64") ];
networkConfig.LLDP = false; networkConfig.LLDP = false;
}; });
systemd.network.wait-online = {
wait-online = {
anyInterface = true; anyInterface = true;
}; };
}
else {
netdevs."10-br0".netdevConfig = {
Name = "br0";
Kind = "bridge";
};
netdevs."20-tap0".netdevConfig = {
Name = "tap0";
Kind = "tap";
};
networks."10-enp0s31f6" = {
matchConfig.Name = "enp0s31f6";
bridge = [ "br0" ];
};
networks."20-br0" = {
matchConfig.Name = "br0";
address = with values.hosts.${lupineName}; [
(ipv4 + "/25")
(ipv6 + "/64")
values.services.knutsen-vpn
];
networkConfig.LLDP = false;
dns = ["129.241.0.200" "129.241.0.201" "2001:700:300:1900::200" "2001:700:300:1900::201"];
domains = ["pvv.ntnu.no" "pvv.org"];
gateway = [values.hosts.gateway values.hosts.gateway6];
networkConfig.IPv6AcceptRA = "no";
DHCP = "no";
};
networks."30-tap0" = {
matchConfig.Name = "tap0";
bridge = [ "br0" ];
};
wait-online = {
anyInterface = true;
};
};
# Don't change (even during upgrades) unless you know what you are doing. # Don't change (even during upgrades) unless you know what you are doing.
# See https://search.nixos.org/options?show=system.stateVersion # See https://search.nixos.org/options?show=system.stateVersion
+92
View File
@@ -0,0 +1,92 @@
{ config, pkgs, lib, values, ... }:
let
renderConfig = attrs: lib.pipe attrs [
(lib.filterAttrs (_: value: !(builtins.isNull value || value == false)))
(builtins.mapAttrs (_: value:
if builtins.isList value then builtins.concatStringsSep " " (map toString value)
else if value == true then value
else if builtins.any (f: f value) [
builtins.isString
builtins.isInt
builtins.isFloat
lib.isPath
lib.isDerivation
] then toString value
else throw "Unknown value in lupine openvpn config:\n${value}"
))
(lib.mapAttrsToList (name: value: if value == true then name else "${name} ${value}"))
(builtins.concatStringsSep "\n")
(x: x + "\n\n")
];
in
{
sops.secrets = {
"openvpn/ca/crt" = { };
"openvpn/server/crt" = { };
"openvpn/server/key" = { };
};
services.openvpn.servers."ov-tunnel" = {
config = renderConfig {
# TODO: use aliases
local = values.services.knutsen-vpn;
port = 1194;
proto = "udp";
dev = "tap0";
dev-type = "tap";
script-security = 0;
ca = config.sops.secrets."openvpn/ca/crt".path;
cert = config.sops.secrets."openvpn/server/crt".path;
key = config.sops.secrets."openvpn/server/key".path;
dh = "none";
# Maintain a record of client <-> virtual IP address
# associations in this file. If OpenVPN goes down or
# is restarted, reconnecting clients can be assigned
# the same virtual IP address from the pool that was
# previously assigned.
# ifconfig-pool-persist = ./ipp.txt;
server-bridge = builtins.concatStringsSep " " [
# Gateway
"129.241.210.129"
# Netmask
"255.255.255.128"
# Pool start
values.services.knutsen-tap
# Pool end
values.services.ludvigsen-tap
];
keepalive = "10 120";
data-ciphers = "none";
user = "nobody";
group = "nobody";
status = "/var/log/openvpn-status.log";
client-config-dir = pkgs.writeTextDir "ludvigsen" ''
# Sett IP-adr. for tap0 til ludvigsens PVV-addresse.
ifconfig-push ${values.services.ludvigsen-tap} 255.255.255.128
# Hvordan skal man faa dette til aa funke, tro?
# ifconfig-ipv6-push 2001:700:300:1900::xxx/64
# La ludvigsen bruke std. PVV-gateway til all trafikk (unntatt VPN-tunnellen).
push "redirect-gateway"
'';
persist-key = true;
persist-tun = true;
verb = 5;
explicit-exit-notify = 1;
};
};
}
+1
View File
@@ -16,6 +16,7 @@
fileSystems."/" = fileSystems."/" =
{ device = "/dev/disk/by-uuid/224c45db-9fdc-45d4-b3ad-aaf20b3efa8a"; { device = "/dev/disk/by-uuid/224c45db-9fdc-45d4-b3ad-aaf20b3efa8a";
fsType = "ext4"; fsType = "ext4";
options = [ "relatime" ];
}; };
fileSystems."/boot" = fileSystems."/boot" =
+1
View File
@@ -31,6 +31,7 @@
type = "filesystem"; type = "filesystem";
format = "ext4"; format = "ext4";
mountpoint = "/"; mountpoint = "/";
mountOptions = [ "relatime" ];
}; };
}; };
}; };
+1
View File
@@ -16,6 +16,7 @@
fileSystems."/" = fileSystems."/" =
{ device = "/dev/disk/by-uuid/c3aed415-0054-4ac5-8d29-75a99cc26451"; { device = "/dev/disk/by-uuid/c3aed415-0054-4ac5-8d29-75a99cc26451";
fsType = "btrfs"; fsType = "btrfs";
options = [ "relatime" ];
}; };
fileSystems."/boot" = fileSystems."/boot" =
+61 -2
View File
@@ -1,4 +1,4 @@
{ lib, values, ... }: { lib, pkgs, values, ... }:
let let
# See microbel:/etc/exports # See microbel:/etc/exports
letters = [ "a" "b" "c" "d" "h" "i" "j" "k" "l" "m" "z" ]; letters = [ "a" "b" "c" "d" "h" "i" "j" "k" "l" "m" "z" ];
@@ -6,6 +6,20 @@ in
{ {
systemd.targets."pvv-homedirs" = { systemd.targets."pvv-homedirs" = {
description = "PVV Homedir Partitions"; description = "PVV Homedir Partitions";
requires = map (l: "pvv-homedir-create-uidmapped-bindmounts@${l}.service") letters;
};
systemd.tmpfiles.settings."10-pvv-homedirs" = {
"/run/pvvhome".d = {
user = "root";
group = "root";
mode = "0755";
};
"/run/pvvhome/by-uid".d = {
user = "root";
group = "root";
mode = "0755";
};
}; };
systemd.mounts = map (l: { systemd.mounts = map (l: {
@@ -17,7 +31,7 @@ in
type = "nfs"; type = "nfs";
what = "homepvv${l}.pvv.ntnu.no:/export/home/pvv/${l}"; what = "homepvv${l}.pvv.ntnu.no:/export/home/pvv/${l}";
where = "/run/pvv-home-mounts/${l}"; where = "/run/pvvhome/${l}";
options = lib.concatStringsSep "," [ options = lib.concatStringsSep "," [
"nfsvers=3" "nfsvers=3"
@@ -54,4 +68,49 @@ in
"rw" "rw"
]; ];
}) letters; }) letters;
systemd.services."pvv-homedir-create-uidmapped-bindmounts@" = {
bindsTo = [ "run-pvvhome-%i.mount" ];
after = [ "run-pvvhome-%i.mount" ];
serviceConfig = {
Type = "oneshot";
};
path = with pkgs; [
coreutils
systemdMinimal
];
scriptArgs = "%i";
script = ''
for dir in "/run/pvvhome/$1"/*/; do
[[ -d "$dir" ]] || continue
uid="$(stat -c '%u' "$dir")"
mountpoint="/run/pvvhome/by-uid/$uid"
mkdir -p "$mountpoint"
unit_name=$(systemd-escape --path --suffix=mount "$mountpoint")
if systemctl --quiet is-active "$unit_name" ||
systemctl --quiet is-failed "$unit_name"; then
echo "Skipping existing mount unit: $unit_name"
continue
fi
systemd-mount \
--collect \
--fsck=no \
--type=none \
--options=bind \
--property=BindsTo=$(systemd-escape --path --suffix=mount "/run/pvvhome/$1") \
--property=After=$(systemd-escape --path --suffix=mount "/run/pvvhome/$1") \
"$dir" \
"$mountpoint" \
|| echo "Failed mounting for uid $uid"
done
'';
};
} }
+5 -450
View File
@@ -1,455 +1,10 @@
{ config, lib, pkgs, ... }:
let
cfg = config.services.httpd;
# NOTE Enable this if you want to strace stuff in the sandbox...
debug = false;
homeLetters = [ "a" "b" "c" "d" "h" "i" "j" "k" "l" "m" "z" ];
phpOptions = lib.concatStringsSep "\n" (lib.mapAttrsToList (k: v: "${k} = ${v}"){
display_errors = "Off";
display_startup_errors = "Off";
post_max_size = "40M";
upload_max_filesize = "40M";
});
apache-log-processor = pkgs.callPackage ./apache-log-processor { };
# https://nixos.org/manual/nixpkgs/stable/#ssec-php-user-guide-installing-with-extensions
phpEnv = pkgs.php.buildEnv {
extensions = { all, ... }: with all; [
bz2
curl
decimal
gd
imagick
mysqli
mysqlnd
pgsql
posix
protobuf sqlite3
uuid
xml
xsl
zlib
zstd
pdo
pdo_mysql
pdo_pgsql
pdo_sqlite
];
extraConfig = phpOptions;
};
perlEnv = (pkgs.perl.withPackages (ps: with ps; [
pkgs.exiftool
pkgs.ikiwiki
pkgs.irssi
pkgs.nix.libs.nix-perl-bindings
CGI
DBDPg
DBDSQLite
DBDmysql
DBI
Git
ImageMagick
JSON
TemplateToolkit
])).overrideAttrs (prev: {
# NOTE: `pkgs.perl.propagatedBuildInputs` don't actually propagate through the
# wrapper derivation created by `withPackages`. This should compensate
# for that.
postBuild = prev.postBuild + ''
cp -r '${pkgs.perl}/nix-support' "$out"/nix-support
'';
});
# https://nixos.org/manual/nixpkgs/stable/#python.buildenv-function
pythonEnv = pkgs.python3.buildEnv.override {
extraLibs = with pkgs.python3Packages; [
legacy-cgi
matplotlib
requests
];
ignoreCollisions = true;
};
# https://nixos.org/manual/nixpkgs/stable/#sec-building-environment
fhsEnv = pkgs.buildEnv {
name = "userweb-env";
ignoreCollisions = true;
paths = with pkgs; [
bash
config.services.bro.instances.userweb-sendmail.client.package
perlEnv
pythonEnv
phpEnv
]
++ (with phpEnv.packages; [
# composer
])
++ [
# Useful packages for homepages
exiftool
gnuplot
ikiwiki-full
imagemagick
jhead
ruby
sbcl
sourceHighlight
# Missing packages from tom
# blosxom
# pyblosxom
# mediawiki (TODO: do people host their own mediawikis in userweb?)
# nanoblogger
# Version control
cvs
rcs
git
# Compression/Archival
bzip2
gnutar
gzip
lz4
unzip
xz
zip
zstd
# Other tools you might expect to find on a normal system
acl
coreutils-full
curl
diffutils
file
findutils
gawk
gnugrep
gnumake
gnupg
gnused
less
man
util-linux
vim
wget
which
xdg-utils
] ++ lib.optionals debug [
glibc.getent
strace
systemd
];
extraOutputsToInstall = [
"man"
"doc"
];
};
in
{ {
imports = [ imports = [
./httpd.nix
./log-processor.nix
./mail.nix ./mail.nix
./module.nix
./packages.nix
./passwd-sync.nix
]; ];
sops.secrets = {
"httpd/passwd-ssh-key" = { };
"httpd/ssh-known-hosts" = { };
};
services.httpd = {
enable = true;
adminAddr = "drift@pvv.ntnu.no";
# TODO: consider upstreaming systemd support
# TODO: mod_log_journald in v2.5
package = pkgs.apacheHttpd.overrideAttrs (prev: {
nativeBuildInputs = prev.nativeBuildInputs ++ [ pkgs.pkg-config ];
buildInputs = prev.buildInputs ++ [ pkgs.systemdLibs ];
configureFlags = prev.configureFlags ++ [ "--enable-systemd" ];
});
enablePHP = true;
phpPackage = phpEnv;
inherit phpOptions;
enablePerl = true;
# TODO: mod_log_journald in v2.5
extraModules = [
"systemd"
"userdir"
{
name = "perl";
path = let
mod_perl = pkgs.symlinkJoin {
name = "userweb_modperl_with_custom_perl_env";
ignoreCollisions = true;
paths = [
(pkgs.apacheHttpdPackages.mod_perl.override {
apacheHttpd = cfg.package.out;
})
perlEnv
];
};
in "${mod_perl}/modules/mod_perl.so";
}
];
logPerVirtualHost = false;
extraConfig = ''
TraceEnable on
LogLevel warn rewrite:trace3
'';
virtualHosts."temmie.pvv.ntnu.no" = {
forceSSL = true;
enableACME = true;
serverAliases = [
"www2.pvv.ntnu.no"
];
extraConfig = ''
CustomLog "${cfg.logDir}/access.log" combined
CustomLog "|${lib.getExe apache-log-processor} access" combined
ErrorLog "|${lib.getExe apache-log-processor} error"
ScriptLog "${cfg.logDir}/cgi.log"
UserDir ${lib.concatMapStringsSep " " (l: "/home/pvv/${l}/*/web-docs") homeLetters}
UserDir disabled root
AddHandler cgi-script .cgi
DirectoryIndex index.html index.html.var index.php index.php3 index.cgi index.phtml index.shtml meg.html
SetEnvIf Request_URI "^/~([^/]+)" USERDIR_USER=$1
<Directory "/home/pvv/?/*/web-docs">
Options MultiViews Indexes SymLinksIfOwnerMatch ExecCGI IncludesNoExec
AllowOverride All
Require all granted
</Directory>
<DirectoryMatch "^/home/pvv/.*/web-docs/(${lib.concatStringsSep "|" [
"\\.git"
"\\.hg"
"\\.svn"
"\\.ssh"
"\\.env"
"\\.envrc"
"\\.bzr"
"\\.venv"
"CVS"
"RCS"
".*\\.swp"
".*\\.bak"
".*~"
]})(/|$)">
AllowOverride All
Require all denied
</DirectoryMatch>
'';
};
};
networking.firewall.allowedTCPPorts = [
80
443
];
# socket activation comes in v2.5
# systemd.sockets.httpd = {
# wantedBy = [ "sockets.target" ];
# description = "HTTPD socket";
# listenStreams = [
# "0.0.0.0:80"
# "0.0.0.0:443"
# ];
# };
# NOTE: 54 -> 33, this is the UID/GID we used for www-data on tom in the past.
# Any files accessed by or created by httpd will do so over NFS with this
# UID/GID pair as its credentials.
# This overlaps with the hardcoded `disnix` uid in nixpkgs, but we *probably*
# won't be using that for the foreseeable future.
users.users."wwwrun".uid = lib.mkForce 33;
users.groups."wwwrun".gid = lib.mkForce 33;
systemd.services.httpd = {
after = [ "pvv-homedirs.target" ];
requires = [ "pvv-homedirs.target" ];
environment = {
PATH = lib.mkForce "/usr/bin";
};
serviceConfig = {
Type = lib.mkForce "notify";
ExecStartPre = let
rsyncCommand = ''${lib.getExe pkgs.rsync} -e "${pkgs.openssh}/bin/ssh -o UserKnownHostsFile=%d/ssh-known-hosts -i %d/sshkey" -avz'';
in lib.mkForce [
"${lib.getExe (pkgs.writeShellApplication {
name = "http-exec-start-pre-remove-old-semaphores";
text = ''
# Get rid of old semaphores. These tend to accumulate across
# server restarts, eventually preventing it from restarting
# successfully.
for i in $(${pkgs.util-linux}/bin/ipcs -s | grep ' ${cfg.user} ' | cut -f2 -d ' '); do
${pkgs.util-linux}/bin/ipcrm -s "$i"
done
'';
})}"
"${rsyncCommand} pvv@smtp.pvv.ntnu.no:/etc/passwd /run/httpd/pamunix-in/"
"${rsyncCommand} pvv@smtp.pvv.ntnu.no:/etc/group /run/httpd/pamunix-in/"
(let
args = lib.cli.toCommandLineShellGNU { } {
passwd-file = "/run/httpd/pamunix-in/passwd";
group-file = "/run/httpd/pamunix-in/group";
output-dir = "/run/httpd/pamunix-out";
shadow-file = pkgs.emptyFile;
output-passwd = true;
ignore-user-file = toString ./ignore_user_file.txt;
ignore-group-file = toString ./ignore_group_file.txt;
};
in ''${lib.getExe pkgs.passwd2systemd-users} ${args}'')
"${lib.getExe' pkgs.coreutils "shred"} -u /run/httpd/pamunix-in/passwd /run/httpd/pamunix-in/group"
":${lib.getExe pkgs.gnused} -i '$ a\\\\root:x:0:0:System administrator:/root:/run/current-system/sw/bin/bash' /run/httpd/pamunix-out/passwd"
":${lib.getExe pkgs.gnused} -i '$ a\\\\wwwrun:x:54:54:Apache httpd user:/var/empty:/run/current-system/sw/bin/bash' /run/httpd/pamunix-out/passwd"
":${lib.getExe pkgs.gnused} -i '$ a\\\\root:x:0:' /run/httpd/pamunix-out/group"
":${lib.getExe pkgs.gnused} -i '$ a\\\\wwwrun:x:54:' /run/httpd/pamunix-out/group"
"${lib.getExe' pkgs.coreutils "cat"} /run/httpd/pamunix-out/passwd"
"+${lib.getExe' pkgs.coreutils "chown"} root:root /run/httpd/pamunix-out/passwd /run/httpd/pamunix-out/group"
"+${lib.getExe' pkgs.coreutils "chmod"} 0644 /run/httpd/pamunix-out/passwd /run/httpd/pamunix-out/group"
"+${lib.getExe pkgs.mount} --bind /run/httpd/pamunix-out/passwd /etc/passwd"
"+${lib.getExe pkgs.mount} --bind /run/httpd/pamunix-out/group /etc/group"
];
ExecStart = lib.mkForce "${cfg.package}/bin/httpd -D FOREGROUND -f /etc/httpd/httpd.conf -k start";
ExecReload = lib.mkForce "${cfg.package}/bin/httpd -f /etc/httpd/httpd.conf -k graceful";
ExecStop = lib.mkForce "";
KillMode = "mixed";
LoadCredential=[
"sshkey:${config.sops.secrets."httpd/passwd-ssh-key".path}"
"ssh-known-hosts:${config.sops.secrets."httpd/ssh-known-hosts".path}"
];
ConfigurationDirectory = [ "httpd" ];
LogsDirectory = [ "httpd" ];
LogsDirectoryMode = "0700";
AmbientCapabilities = [ "CAP_NET_BIND_SERVICE" "CAP_SETUID" "CAP_SETGID" ] ++ lib.optionals debug [ "CAP_SYS_PTRACE" ];
CapabilityBoundingSet = [ "CAP_NET_BIND_SERVICE" "CAP_SETUID" "CAP_SETGID" ] ++ lib.optionals debug [ "CAP_SYS_PTRACE" ];
LockPersonality = !debug;
PrivateDevices = true;
PrivateTmp = true;
# NOTE: this removes CAP_NET_BIND_SERVICE...
# PrivateUsers = true;
ProtectClock = true;
ProtectControlGroups = true;
ProtectHome = "tmpfs";
ProtectKernelLogs = true;
ProtectKernelModules = true;
ProtectSystem = true;
RemoveIPC = true;
RestrictAddressFamilies = [
"AF_INET"
"AF_INET6"
"AF_UNIX"
"AF_NETLINK"
];
RestrictNamespaces = true;
RestrictRealtime = true;
RestrictSUIDSGID = true;
SocketBindDeny = "any";
SocketBindAllow = [
"tcp:80"
"tcp:443"
];
SystemCallArchitectures = "native";
SystemCallFilter = lib.mkIf (!debug) [
"@system-service"
"@setuid"
];
UMask = "0077";
RuntimeDirectoryMode = "0750";
RuntimeDirectory = [
"httpd/root-mnt"
"httpd/pamunix-in"
"httpd/pamunix-out"
];
RootDirectory = "/run/httpd/root-mnt";
MountAPIVFS = true;
BindReadOnlyPaths = [
builtins.storeDir
"/etc"
"/dev/null"
"/etc/resolv.conf"
"/var/lib/acme"
"-/run/httpd/pamunix-out/passwd:/etc/passwd"
"-/run/httpd/pamunix-out/group:/etc/group"
"${pkgs.writeText "userweb-fake-nsswitch.conf" ''
passwd: files
group: files
shadow: files
sudoers: files
hosts: mymachines resolve [!UNAVAIL=return] files myhostname dns
networks: files
ethers: files
services: files
protocols: files
rpc: files
subuid: files
subgid: files
''}:/etc/nsswitch.conf"
"${fhsEnv}/bin:/bin"
"${fhsEnv}/sbin:/sbin"
"${fhsEnv}/lib:/lib"
"${fhsEnv}/share:/share"
] ++ (lib.mapCartesianProduct ({ parent, child }: "${fhsEnv}${child}:${parent}${child}") {
parent = [
"/local"
"/opt"
"/opt/local"
"/store"
"/store/gnu"
"/usr"
"/usr/local"
"/run/current-system/sw"
];
child = [
"/bin"
"/sbin"
"/lib"
"/libexec"
"/include"
"/share"
];
});
BindPaths = map (l: "/run/pvv-home-mounts/${l}:/home/pvv/${l}") homeLetters;
};
};
# TODO: create phpfpm pools with php environments that contain packages similar to those present on tom
} }
+318
View File
@@ -0,0 +1,318 @@
{ config, lib, pkgs, ... }:
let
cfg = config.services.httpd;
mcfg = config.services.pvv-userweb;
in
{
services.httpd = {
enable = true;
adminAddr = "drift@pvv.ntnu.no";
# TODO: consider upstreaming systemd support
# TODO: mod_log_journald in v2.5
package = pkgs.apacheHttpd.overrideAttrs (prev: {
nativeBuildInputs = prev.nativeBuildInputs ++ [ pkgs.pkg-config ];
buildInputs = prev.buildInputs ++ [ pkgs.systemdLibs ];
configureFlags = prev.configureFlags ++ [ "--enable-systemd" ];
});
enablePHP = true;
phpPackage = mcfg.php.env;
phpOptions = mcfg.php.options;
# NOTE: we include our own `mod_perl` in `extraModules` instead.
enablePerl = false;
# NOTE: we include `mod_userdir` in `extraModules` and configure this in `extraConfig` ourselves.
# enableUserDir = false;
# TODO: mod_log_journald in v2.5
extraModules = [
"systemd"
"userdir"
{
name = "perl";
path = let
mod_perl = pkgs.symlinkJoin {
name = "userweb_modperl_with_custom_perl_env";
ignoreCollisions = true;
paths = [
(pkgs.apacheHttpdPackages.mod_perl.override {
apacheHttpd = cfg.package.out;
})
mcfg.perl.env
];
};
in "${mod_perl}/modules/mod_perl.so";
}
];
logPerVirtualHost = false;
extraConfig = lib.mkIf mcfg.debugMode ''
TraceEnable on
LogLevel warn rewrite:trace3
'';
virtualHosts."temmie.pvv.ntnu.no" = {
forceSSL = true;
enableACME = true;
serverAliases = [
"www2.pvv.ntnu.no"
];
extraConfig = ''
<Directory "${pkgs.emptyDirectory}">
Require all denied
LogLevel authz_core:crit
</Directory>
CustomLog "${cfg.logDir}/access.log" combined
CustomLog "/run/httpd-log-processor-access.fifo" combined
ErrorLog "/run/httpd-log-processor-error.fifo"
ScriptLog "${cfg.logDir}/cgi.log"
UserDir ${lib.concatMapStringsSep " " (l: "/home/pvv/${l}/*/web-docs") mcfg.homeLetters}
UserDir disabled root
UserDir disabled pvv
AddHandler cgi-script .cgi
DirectoryIndex ${lib.concatStringsSep " " [
"index.htm"
"index.html"
"index.html.var"
"index.shtml"
"index.xhtml"
"index.php"
"index.php3"
"index.php4"
"index.php5"
"index.php7"
"index.php8"
"index.pht"
"index.phtml"
"index.cgi"
"index.txt"
"meg.html"
]}
SetEnvIf Request_URI "^/~([^/]+)" USERDIR_USER=$1
<Directory "/home/pvv/?/*/web-docs">
Options MultiViews Indexes SymLinksIfOwnerMatch ExecCGI IncludesNoExec
AllowOverride All
Require all granted
</Directory>
${lib.concatMapStringsSep "\n" (d: ''
<DirectoryMatch "/${d}(/|$)">
Require all denied
</DirectoryMatch>
'') [
"\\.git"
"\\.hg"
"\\.svn"
"\\.ssh"
"\\.bzr"
"\\.venv"
"CVS"
"RCS"
".*\\.bak"
".*\\.bak.*"
".*\\.bkp"
".*\\.bkp.*"
".*\\.backup"
".*\\.backup.*"
]}
${lib.concatMapStringsSep "\n" (d: ''
<Files "${d}">
Require all denied
</Files>
'') [
".env"
".env.*"
".envs"
".envs.*"
".envrc"
"*.swp"
"*~"
"*.bak"
"*.bak*"
"*.bkp"
"*.bkp*"
"*.backup"
"*.backup*"
"*.lck"
"*.lock"
"LCK..*"
]}
<FilesMatch ".+\.ph(p[34578]?|t|tml)$">
SetHandler application/x-httpd-php
</FilesMatch>
<FilesMatch ".+\.phps$">
SetHandler application/x-httpd-php-source
Require all denied
</FilesMatch>
<FilesMatch "\.pl$">
SetHandler modperl
PerlResponseHandler ModPerl::Registry
Options +ExecCGI
</FilesMatch>
'';
};
};
networking.firewall.allowedTCPPorts = [
80
443
];
# socket activation comes in v2.5
# systemd.sockets.httpd = {
# wantedBy = [ "sockets.target" ];
# description = "HTTPD socket";
# listenStreams = [
# "0.0.0.0:80"
# "0.0.0.0:443"
# ];
# };
# NOTE: 54 -> 33, this is the UID/GID we used for www-data on tom in the past.
# Any files accessed by or created by httpd will do so over NFS with this
# UID/GID pair as its credentials.
# This overlaps with the hardcoded `disnix` uid in nixpkgs, but we *probably*
# won't be using that for the foreseeable future.
users.users."wwwrun".uid = lib.mkForce 33;
users.groups."wwwrun".gid = lib.mkForce 33;
systemd.targets.userweb = {
description = "PVV HTTPD UserWeb";
};
systemd.slices.system-userweb = {
description = "PVV HTTPD UserWeb";
};
systemd.services.httpd = {
after = [
"pvv-homedirs.target"
"httpd-log-processor@access.socket"
"httpd-log-processor@error.socket"
];
requires = [
"pvv-homedirs.target"
"httpd-log-processor@access.socket"
"httpd-log-processor@error.socket"
];
requiredBy = [ "userweb.target" ];
environment = {
PATH = lib.mkForce "/usr/bin";
};
serviceConfig = {
Type = lib.mkForce "notify";
ExecStart = lib.mkForce "${cfg.package}/bin/httpd -D FOREGROUND -f /etc/httpd/httpd.conf -k start";
ExecReload = lib.mkForce "${cfg.package}/bin/httpd -f /etc/httpd/httpd.conf -k graceful";
ExecStop = lib.mkForce "";
KillMode = "mixed";
Slice = "system-userweb.slice";
ConfigurationDirectory = [ "httpd" ];
LogsDirectory = [ "httpd" ];
LogsDirectoryMode = "0700";
AmbientCapabilities = [ "CAP_NET_BIND_SERVICE" ] ++ lib.optionals mcfg.debugMode [ "CAP_SYS_PTRACE" ];
CapabilityBoundingSet = [ "CAP_NET_BIND_SERVICE" ] ++ lib.optionals mcfg.debugMode [ "CAP_SYS_PTRACE" ];
LockPersonality = !mcfg.debugMode;
PrivateDevices = true;
PrivateTmp = true;
# NOTE: this removes CAP_NET_BIND_SERVICE...
# PrivateUsers = true;
ProtectClock = true;
ProtectControlGroups = true;
ProtectHome = "tmpfs";
ProtectKernelLogs = true;
ProtectKernelModules = true;
ProtectSystem = true;
RemoveIPC = true;
RestrictAddressFamilies = [
"AF_INET"
"AF_INET6"
"AF_UNIX"
"AF_NETLINK"
];
RestrictNamespaces = true;
RestrictRealtime = true;
RestrictSUIDSGID = true;
SocketBindDeny = "any";
SocketBindAllow = [
"tcp:80"
"tcp:443"
];
SystemCallArchitectures = "native";
SystemCallFilter = lib.mkIf (!mcfg.debugMode) [ "@system-service" ];
UMask = "0077";
RuntimeDirectoryMode = "0750";
RuntimeDirectory = [ "httpd/root-mnt" ];
RootDirectory = "/run/httpd/root-mnt";
MountAPIVFS = true;
BindReadOnlyPaths = [
builtins.storeDir
"/etc"
"/dev/null"
"/var/lib/acme"
"/var/run/nscd"
"${mcfg.fhsEnv}/bin:/bin"
"${mcfg.fhsEnv}/sbin:/sbin"
"${mcfg.fhsEnv}/lib:/lib"
"${mcfg.fhsEnv}/share:/share"
] ++ (lib.mapCartesianProduct ({ parent, child }: "${mcfg.fhsEnv}${child}:${parent}${child}") {
parent = [
"/local"
"/opt"
"/opt/local"
"/store"
"/store/gnu"
"/usr"
"/usr/local"
"/run/current-system/sw"
];
child = [
"/bin"
"/sbin"
"/lib"
"/libexec"
"/include"
"/share"
];
});
BindPaths = (lib.mapCartesianProduct ({ directoryFn, letter }: "/run/pvvhome/${letter}:${directoryFn letter}${letter}") {
directoryFn = [
(_: "/home/pvv/")
(l: "/amd/homepvv${l}/")
];
letter = mcfg.homeLetters;
}) ++ [
"/run/httpd-log-processor-access.fifo"
"/run/httpd-log-processor-error.fifo"
];
};
};
# TODO: create phpfpm pools with php environments that contain packages similar to those present on tom
}
@@ -0,0 +1,113 @@
{ config, lib, pkgs, values, ... }:
let
mcfg = config.services.pvv-userweb;
in
{
systemd.targets.sockets.wants = [
"httpd-log-processor@access.socket"
"httpd-log-processor@error.socket"
];
systemd.sockets."httpd-log-processor@" = lib.mkIf config.services.httpd.enable {
requiredBy = [ "userweb.target" ];
socketConfig = {
ListenFIFO = "/run/httpd-log-processor-%i.fifo";
RemoveOnStop = true;
SocketUser = "wwwrun";
SocketGroup = "wwwrun";
SocketMode = "0600";
};
};
systemd.services."httpd-log-processor@" = lib.mkIf config.services.httpd.enable {
requiredBy = [ "userweb.target" ];
after = [ "httpd-passwd-sync.service" ];
requires = [ "httpd-passwd-sync.service" ];
serviceConfig = {
User = "wwwrun";
Group = "wwwrun";
Slice = "system-userweb.slice";
Restart = "on-failure";
StandardInput = "socket";
StandardOutput = "journal";
StandardError = "journal";
ExecStart = "${lib.getExe mcfg.apacheLogProcessorPackage} %i";
AmbientCapabilities = [ "CAP_SETUID" "CAP_SETGID" ];
CapabilityBoundingSet = [ "CAP_SETUID" "CAP_SETGID" ];
DeviceAllow = [ "" ];
IPAddressDeny = "any";
LockPersonality = true;
MemoryDenyWriteExecute = true;
NoNewPrivileges = true;
PrivateDevices = true;
PrivateIPC = true;
PrivateNetwork = true;
PrivateTmp = true;
PrivateUsers = false;
ProcSubset = "pid";
ProtectClock = true;
ProtectControlGroups = true;
ProtectHome = "tmpfs";
ProtectHostname = true;
ProtectKernelLogs = true;
ProtectKernelModules = true;
ProtectKernelTunables = true;
ProtectProc = "invisible";
ProtectSystem = "strict";
RemoveIPC = true;
RestrictAddressFamilies = [ "none" ];
RestrictNamespaces = true;
RestrictRealtime = true;
RestrictSUIDSGID = true;
SocketBindDeny = "any";
SystemCallArchitectures = "native";
SystemCallFilter = [
"@system-service"
"@setuid"
"~@resources"
];
UMask = "0077";
RootDirectory = "/run/httpd-log-processor-%i/root-mnt";
MountAPIVFS = true;
RuntimeDirectoryMode = "0750";
RuntimeDirectory = [ "httpd-log-processor-%i/root-mnt" ];
BindReadOnlyPaths = [
builtins.storeDir
"/etc"
"/var/lib/httpd-passwd-sync/passwd:/etc/passwd"
"/var/lib/httpd-passwd-sync/group:/etc/group"
"${pkgs.writeText "userweb-fake-nsswitch.conf" ''
passwd: files
group: files
shadow: files
sudoers: files
hosts: mymachines resolve [!UNAVAIL=return] files myhostname dns
networks: files
ethers: files
services: files
protocols: files
rpc: files
subuid: files
subgid: files
''}:/etc/nsswitch.conf"
] ++ lib.optionals mcfg.debugMode [
"/bin"
];
BindPaths = map (l: "/run/pvvhome/${l}:/home/pvv/${l}") mcfg.homeLetters ++ [
"/var/log/httpd"
];
};
};
}
+1
View File
@@ -70,6 +70,7 @@
serviceConfig = { serviceConfig = {
User = "nullmailer-user"; User = "nullmailer-user";
Group = "nullmailer-user"; Group = "nullmailer-user";
Slice = "system-userweb.slice";
ReadWritePaths = [ ReadWritePaths = [
"/var/spool/nullmailer" "/var/spool/nullmailer"
+118
View File
@@ -0,0 +1,118 @@
{ config, lib, pkgs, ... }:
let
cfg = config.services.pvv-userweb;
in
{
options.services.pvv-userweb = {
enable = lib.mkEnableOption "" // {
default = true;
};
debugMode = lib.mkEnableOption "";
apacheLogProcessorPackage = lib.mkOption {
type = lib.types.package;
default = pkgs.callPackage ./apache-log-processor { };
};
homeLetters = lib.mkOption {
type = lib.types.listOf lib.types.str;
default = [ "a" "b" "c" "d" "h" "i" "j" "k" "l" "m" "z" ];
readOnly = true;
};
packages = lib.mkOption {
type = lib.types.listOf lib.types.package;
default = _: [ ];
};
php.extensions = lib.mkOption {
type = lib.types.functionTo (lib.types.listOf lib.types.package);
default = _: [ ];
};
php.options = lib.mkOption {
type = lib.types.attrsOf lib.types.str;
default = {
display_errors = "Off";
display_startup_errors = "Off";
post_max_size = "40M";
upload_max_filesize = "40M";
};
apply = attrs: lib.concatStringsSep "\n" (lib.mapAttrsToList (k: v: "${k} = ${v}") attrs);
};
# https://nixos.org/manual/nixpkgs/stable/#ssec-php-user-guide-installing-with-extensions
php.env = lib.mkOption {
type = lib.types.package;
readOnly = true;
default = pkgs.php.buildEnv {
extensions = cfg.php.extensions;
extraConfig = cfg.php.options;
};
};
perl.packages = lib.mkOption {
type = lib.types.functionTo (lib.types.listOf lib.types.package);
default = _: [ ];
};
perl.env = lib.mkOption {
type = lib.types.package;
readOnly = true;
default = (pkgs.perl.withPackages cfg.perl.packages).overrideAttrs (prev: {
# NOTE: `pkgs.perl.propagatedBuildInputs` don't actually propagate through the
# wrapper derivation created by `withPackages`. This should compensate
# for that.
postBuild = prev.postBuild + ''
cp -r '${pkgs.perl}/nix-support' "$out"/nix-support
'';
});
};
python3.packages = lib.mkOption {
type = lib.types.functionTo (lib.types.listOf lib.types.package);
default = _: [ ];
};
python3.env = lib.mkOption {
type = lib.types.package;
readOnly = true;
default = pkgs.python3.buildEnv.override {
extraLibs = cfg.python3.packages pkgs.python3Packages;
ignoreCollisions = true;
};
};
fhsEnv = lib.mkOption {
type = lib.types.package;
readOnly = true;
default = let
in pkgs.buildEnv {
name = "userweb-env";
ignoreCollisions = true;
paths = with pkgs; [
bash
config.services.bro.instances.userweb-sendmail.client.package
cfg.perl.env
cfg.python3.env
cfg.php.env
] ++ cfg.packages;
extraOutputsToInstall = [
"man"
"doc"
];
};
};
};
config = lib.mkIf cfg.enable {
services.pvv-userweb.packages = lib.mkIf cfg.debugMode (with pkgs; [
glibc.getent
strace
systemd
]);
};
}
+104
View File
@@ -0,0 +1,104 @@
{ pkgs, ... }:
{
services.pvv-userweb = {
packages = with pkgs; [
# Useful packages for homepages
exiftool
gnuplot
ikiwiki-full
imagemagick
jhead
ruby
sbcl
sourceHighlight
# Missing packages from tom
# blosxom
# pyblosxom
# mediawiki (TODO: do people host their own mediawikis in userweb?)
# nanoblogger
# Version control
cvs
rcs
git
# Compression/Archival
bzip2
gnutar
gzip
lz4
unzip
xz
zip
zstd
# Other tools you might expect to find on a normal system
acl
coreutils-full
curl
diffutils
file
findutils
gawk
gnugrep
gnumake
gnupg
gnused
less
man
util-linux
vim
wget
which
xdg-utils
];
php.extensions = { all, ... }: with all; [
bz2
curl
decimal
gd
imagick
mysqli
mysqlnd
pgsql
posix
protobuf sqlite3
uuid
xml
xsl
zlib
zstd
pdo
pdo_mysql
pdo_pgsql
pdo_sqlite
];
perl.packages = perlPkgs: with perlPkgs; [
pkgs.exiftool
pkgs.ikiwiki
pkgs.irssi
pkgs.nix.libs.nix-perl-bindings
CGI
DBDPg
DBDSQLite
DBDmysql
DBI
Git
ImageMagick
JSON
TemplateToolkit
];
python3.packages = pythonPkgs: with pythonPkgs; [
legacy-cgi
matplotlib
requests
];
};
}
@@ -0,0 +1,147 @@
{ config, lib, pkgs, values, ... }:
let
mcfg = config.services.pvv-userweb;
in
{
config = lib.mkIf mcfg.enable {
sops.secrets = {
"httpd/passwd-ssh-key" = { };
"httpd/ssh-known-hosts" = { };
};
# NOTE: because we are running as `DynamicUser` and we want the result files to be available to
# other services, this directory needs to be created via systemd-tmpfiles
systemd.tmpfiles.settings."10-httpd-passwd-sync"."/var/lib/httpd-passwd-sync".d = {
user = "root";
group = "root";
mode = "0700";
};
systemd.timers.httpd-passwd-sync = {
wantedBy = [ "timers.target" ];
timerConfig = {
OnCalendar = "daily";
Persistent = true;
Unit = "httpd-passwd-sync.service";
};
};
systemd.services."httpd-passwd-sync" = {
requiredBy = [ "userweb.target" ];
after = [
"systemd-tmpfiles-setup.service"
"systemd-tmpfiles-resetup.service"
];
serviceConfig = {
Type = "oneshot";
Slice = "system-userweb.slice";
Restart = "on-failure";
RestartSec = "3s";
DynamicUser = true;
LoadCredential = [
"sshkey:${config.sops.secrets."httpd/passwd-ssh-key".path}"
"ssh-known-hosts:${config.sops.secrets."httpd/ssh-known-hosts".path}"
];
ExecStart = let
rsyncArgs = lib.cli.toCommandLineShellGNU { } {
verbose = true;
compress = true;
rsh = "${lib.getExe' pkgs.openssh "ssh"} -o BatchMode=yes -o UserKnownHostsFile=%d/ssh-known-hosts -i %d/sshkey";
};
inputDir = "/run/httpd-passwd-sync/in";
wipDir = "/run/httpd-passwd-sync/wip";
outputDir = "/var/lib/httpd-passwd-sync";
in [
"${lib.getExe pkgs.rsync} ${rsyncArgs} pvv@smtp.pvv.ntnu.no:/etc/passwd ${inputDir}/"
"${lib.getExe pkgs.rsync} ${rsyncArgs} pvv@smtp.pvv.ntnu.no:/etc/group ${inputDir}/"
(let
args = lib.cli.toCommandLineShellGNU { } {
passwd-file = "${inputDir}/passwd";
group-file = "${inputDir}/group";
output-dir = wipDir;
shadow-file = pkgs.emptyFile;
output-passwd = true;
ignore-user-file = toString ./ignore_user_file.txt;
ignore-group-file = toString ./ignore_group_file.txt;
};
in ''${lib.getExe pkgs.passwd2systemd-users} ${args}'')
"${lib.getExe' pkgs.coreutils "shred"} -u ${inputDir}/passwd ${inputDir}/group"
":${lib.getExe pkgs.gnused} -i '$ a\\\\root:x:0:0:System administrator:/root:/run/current-system/sw/bin/bash' ${wipDir}/passwd"
":${lib.getExe pkgs.gnused} -i '$ a\\\\wwwrun:x:54:54:Apache httpd user:/var/empty:/run/current-system/sw/bin/bash' ${wipDir}/passwd"
":${lib.getExe pkgs.gnused} -i '$ a\\\\root:x:0:' ${wipDir}/group"
":${lib.getExe pkgs.gnused} -i '$ a\\\\wwwrun:x:54:' ${wipDir}/group"
"+${lib.getExe' pkgs.coreutils "install"} -m644 -o root -g root -t '${outputDir}' ${wipDir}/passwd ${wipDir}/group"
"${lib.getExe' pkgs.coreutils "shred"} -u ${wipDir}/passwd ${wipDir}/group"
];
AmbientCapabilities = [ "" ];
CapabilityBoundingSet = [ "" ];
DeviceAllow = [ "" ];
LockPersonality = true;
MemoryDenyWriteExecute = true;
PrivateDevices = true;
PrivateTmp = true;
PrivateUsers = true;
ProcSubset = "pid";
ProtectClock = true;
ProtectControlGroups = true;
ProtectHome = "tmpfs";
ProtectHostname = true;
ProtectKernelLogs = true;
ProtectKernelModules = true;
ProtectProc = "invisible";
ProtectSystem = "strict";
ProtectKernelTunables = true;
RemoveIPC = true;
RestrictAddressFamilies = [
"AF_INET"
"AF_INET6"
"AF_UNIX"
];
RestrictNamespaces = true;
RestrictRealtime = true;
RestrictSUIDSGID = true;
SocketBindDeny = "any";
SystemCallArchitectures = "native";
SystemCallFilter = [
"@system-service"
"~@resources"
];
UMask = "0077";
IPAddressAllow = [
values.hosts.microbel.ipv4
values.hosts.microbel.ipv6
];
IPAddressDeny = "any";
RootDirectory = "/run/httpd-passwd-sync/root-mnt";
MountAPIVFS = true;
RuntimeDirectoryMode = "0750";
RuntimeDirectory = [
"httpd-passwd-sync/root-mnt"
"httpd-passwd-sync/in"
"httpd-passwd-sync/wip"
];
BindPaths = [
"/var/lib/httpd-passwd-sync"
];
BindReadOnlyPaths = [
builtins.storeDir
"/etc"
"/var/run/nscd"
];
};
};
};
}
+1
View File
@@ -13,6 +13,7 @@
fileSystems."/" = fileSystems."/" =
{ device = "/dev/disk/by-uuid/4e8ecdd2-d453-4fff-b952-f06da00f3b85"; { device = "/dev/disk/by-uuid/4e8ecdd2-d453-4fff-b952-f06da00f3b85";
fsType = "ext4"; fsType = "ext4";
options = [ "relatime" ];
}; };
swapDevices = [ { swapDevices = [ {
+36 -25
View File
@@ -5,10 +5,20 @@ gitea:
lupine-3: ENC[AES256_GCM,data:STJw6hmlOFcy14nfev+E9nin+WJzxAgGwV4IKIVuoqjF7rIqniY4MQ==,iv:+72Qro4naAzdqXvCGi7utHVkT1xeyQkXktahpOTpRjQ=,tag:R66yUHSOT/czhlNcTPXRtg==,type:str] lupine-3: ENC[AES256_GCM,data:STJw6hmlOFcy14nfev+E9nin+WJzxAgGwV4IKIVuoqjF7rIqniY4MQ==,iv:+72Qro4naAzdqXvCGi7utHVkT1xeyQkXktahpOTpRjQ=,tag:R66yUHSOT/czhlNcTPXRtg==,type:str]
lupine-4: ENC[AES256_GCM,data:5Yw/iv2P1WxarZbRuT7XjxZfdYI9msOBJrl5l4XusivX+BOq95hcSw==,iv:TY9K+8NCCof6oq1CI1E8h3GeF4oJM1KgF5+cufXIfdg=,tag:Cd6+hgxfClsQAlsS+cZTjQ==,type:str] lupine-4: ENC[AES256_GCM,data:5Yw/iv2P1WxarZbRuT7XjxZfdYI9msOBJrl5l4XusivX+BOq95hcSw==,iv:TY9K+8NCCof6oq1CI1E8h3GeF4oJM1KgF5+cufXIfdg=,tag:Cd6+hgxfClsQAlsS+cZTjQ==,type:str]
lupine-5: ENC[AES256_GCM,data:+PYUtLBx9MdIebR0nWSNGKKCyKcGpI62BXj7AN1iV4wU4+2awrWZ2Q==,iv:PALEU/sYebhPTO4ZXEm2uV6z9hN678ZxqOSnaHVlyro=,tag:Enb08N6TYlOh+x70pcpJYA==,type:str] lupine-5: ENC[AES256_GCM,data:+PYUtLBx9MdIebR0nWSNGKKCyKcGpI62BXj7AN1iV4wU4+2awrWZ2Q==,iv:PALEU/sYebhPTO4ZXEm2uV6z9hN678ZxqOSnaHVlyro=,tag:Enb08N6TYlOh+x70pcpJYA==,type:str]
openvpn:
ca:
key: ENC[AES256_GCM,data:6LSyHn3ixYyz8U8P/jxHJjKJApMRzltX6+iDs3ePzRk/MLOem/9+ViVgPzdhqJ8ZWCF79FECxt0l6o9P6hHa46H/EjTLo/ymtXFu+OzXCCulD3QBGxU6WLzL0ud1BnJg0FSV3Gp9yAPHD0MLppb5svCNSt5ZZC8qMh11jyM7sYA1GFGZ6ySYUOvuKYNaMtGArA/J8Z96zv/o8BQXVo9uiBdzonW+THgM3vbiyRZfyjmfoMA/AfZoicsNDNZr1zJ95AXHwLMlEqJYrJHF74Vg0VSQINMK/aYJ59z/fB2BTp6K5NZG7f1Z27zV+z5GwIh4Dm+8R4OY1Me3fWaLliix8Qofdx9FSYEJZXkitly2KHvJRm2sbv5Oll+NNniI/Sh3eucCoWr6iYyfVUV+n0tCu4sMW3kp6rvhjbq3IynqMEgk7zKhEUkwT5jPkPOy0EFlk07/BztKtX24Bn4GTyeadNW/8B5vgkGJAZcD97Zh06FndzmB0gDL23WMxTLqD8VRObmc4R5Fy/xMH18uv+EDcjBi9b6p55x5uhBWl8uMzAxu1c0ke6pwOszEik0SjCIb36cPzR13ieVimmEloBSGhCxFQ36vTkqgdCG6CWzRu7KFOAzZ/O+06hOCRWqDaxaYvGRvvi4huAI+H5M8a9Qr4fMEATIw4M6b9td2aAogZs0I+v9VJCFUPAfYRhRrxw0450t/saxamkqsfdt2deCSCVBDlWx+J6865vyYylwB1y2aIQAoDMpmYK02OygST16dJt4nLg4O/MBHCxrWEQUb/wJI7aJfZOqD5hgkPQkskg9p8KbNMaKD9JpTRD50w2htXTkAl9/kDjOH8bq5XDXiby3fhbBb2BPqHHG2IEaoqKgkiB4fqpXa52uVXQvXbvZuq3GBDIu1dLjZZEvLxbVvYw/ctCpcudeZGJtE6+2s5JccoZ4aeDsEg/8/OFYHU+q5f/WkZC5tjiRA5gXnWi2LI25WjDr/PkrHg6G+hK/OuL4tHnelH6l/zgXzWp+OMfmPQMUMBwAGTVUJ75BrXSoTUGgQWVQHRP25jGprL2eiBXuR2IWTBVqR31T8dkca4CqzbCXT3eVH1aBWcyxnNcGuoePneJSBMrYGj3D4eXvqwRb/beugImeg0qQ+BxQlEF/uOKAyaVIgZKb0gmejgmKL5se+VD9MdrqGdLHJn0oJ9B4cdscJAsSMIWl04pkyj53RdMCoG8JSU09Z+Dz2jH0aAxoS2gsamaBlOIw5eH7kskuIwokPXZTr1n3n3+jIlPXkw12F8jT3piXqeLO/d5HhJtB2/gYkpQB44C1Hu3DmDID7JqeK8e1H1vUl+ATWDpj2vYkf4vBHF8Ndiq3btmLBlaPjAYVXd6q430lg3vnBCuu8xlYPcT+EHZxDiRY5EdXd75zSV3zmD9D4m/Nq1WvBGRNDzS73MBHQtDYqmvN3tkCu3N28Tx+ua5Lt96II5vTyNvcXn/raFlJJAeKtO4M5MXxkcbnrtq40xNvZauNJ7SJJho8Qoe1cRnN5pmSrCPZCcMgQo//E8yQzfDgxntQBA6tmqRHaPQLClwtOMKdtaYk1vunD2/0UaxXA6t8yNLnp7H8J1bR8PkzjkUBSUZDYtdonSnRuC4JBXsF6MPR1v5YbUbsXpGxrdUBWUMdTNOEMpkQNxb5HdVjarW5OMNxWz+JudiD8eyBUvi+ThB7gOSkNUMzIdOhC27jzLrjN9LVqgB16GbUwDptBEDmf2Y6gHYCUTFXSvKN8nkk2tu2QJdIpG7qkhYpPpsbLh7SGMvzYXSrVDfrlBgnxzkFeiVuwA3p8m4BhwSdNumJBLjlTp5KmvDoYFzM97+alQ0drvdOiLC1YX42LfLcjtrvXm4cN1UV9J/FRjEawqHX1iqT6fBf9g6dmWIM2GhSMeN8hezmHRof+SMKdWfynnCszk6koA5HR5pLurrcO9eEmyBaYJl3RWaXeEBiFRHRYggihm7UDkWFx6FgsxQRq/jrs77uUuxulZmiP3vWIYKWqpCclo7KBcRGouzq166IVBkSHr5z9zb6D0eKbZsmW2JCOt0Rk5pFR16xENF6oBKLrTqX5E0KcHu3lxcywJjRaSmMQAxUKdE5XGZ7QpXbskWJD9Tt2VHGxcDimvc6wkJPPKi+xJGA/ixsD4XU2aiiyeQc1ZuWZPWG174JlahXwhVO4slcF3l+tEXa5dgPCIKnJF9oy8PnUsyrVZRyUkaIJlMMcRHZPYB0DMidY+RhSLZfPXj9bZAByDDZQ3VkvryUuvVOcqMJUpw5rrGtgM4D3Gdotsh8uq0Ow08sfrRcSIcZ6UcvL8Tbb1gmV4bkcvpY9jj28rIxsnboKxduEhJEC85N49+L1Pa0vPwVMga9WJqcJkn/qk4vxO47LH0icRjxW+zzjgCDslunXLMQK2h+J2J4Lgg6ZEkiOQ/eiHdxTgDuCV6qp1sNFdYjGJ/k+Jvg//Qn1wsrje9qZD41wsfuqBfo43JQQbc2ffr1U+grnaVHRmk07y100dzYAkbnVDDL8KtN57YwE5uPa2EWrrskmfwI57hT5OpOILfVwH90TLhW58tveoMMqpXfHwq9BKUTUjcX/0A63hJQ4HSfrjIGbFhokMHBnRf4WuOknkTm2NOETBwqoFiTl/j2FrxZjQwjsZHi3+DyKJ5FcEyo2jQSD+vlX01ztw9PuzeRhTb9VwqXMEuoO37oLtB0IffeRW+ufWDyO0tEd5dfPrJhuxHEVXTKVMYifglD12Q05As3+cws4hyP7WIj2+Po3mwuiDTBomIyNb7AAAbWtcwnqsd0c5gF7R1DhoQfHd6GpOn9ScrDPisXWdakkRqyj+rYtRpsd63csrSfWAW5GbeqrEepbMFmvgPwmkbqKW1gStoKWdwOXM6IkS+xNI1wAEd+12Y051oWb/pnbDjNgGM1QRJmocGckjTaue07wzqbU1ESG6iaOv4nwOVjPEFCN73UaUCaQvhxOn/iUvCrR+OP49S8yMuVu6orbECLRoO1/7DF8QwyW/kdZv71JhVGgrN3N+0buasFR002fZpDmp5O9NpRTz6t5myNuuDlvfLOuShxaL/xRSaShKv/wYN4Te7K15FjJYR68Cz4Dh3SB3+zT6M2c1y+lIqTZTfJ0dOlglspYWvju9NMugmsP/2qURVZ54gAd3twcsmD7YkGAfCUxkkfW1YUe6ac+JM9QMvUwGUUg1br5zMdMUdQrauOOJHP2RcIgFGLl8GWqgteuRxUg+7KoIjdDb0SbTuBlM7A+M9zkqJqTfUoXPOTdmH7hgOp9Y/oNRVX24B1wQMZYaEkKz4ms4TlQusv90P8Zo72wc3BO7feIpbO4GtIyEH1eW22+JsbnuZ378+3FFu1kOb5lnxc3BFdGVWqCZsr/+7HHQvhaUqQ9vazzDY/Q2p3/n59f6v0fP+aFGmaLsMFWwfy3AS1KVjNltemwurkGfWEgUiqul/jcKqpMku6Kn8EIJwupcCDiKI6eHGPjhX7S4lcAe4M4Xn7DXkmsf9ewlo/dpD1pY15OVk+WTD1vr0UIRhgqXSqNglV7yTafkh2mdIM5UhvpFniSgtNoDjfS6ipDE0ACGI4v+CSibr8B+BIqLxJoPacFrE7613ZTFe1qUokFeKFYYNd3bizZSIBBfrKQL5w13kQzQvjPX1o/oiO/apK7OYzupmSSbg2emQtVioCeH/ek1TpTUX1kXbzsOA2aVsovi5VLWZeesJYKOexI2hj2mb97ZB9WEoYOyAJU425uUBu3n+2I5NyqZHDMHW5ieiHX+cCzhdJwFFIeHPei3e0q0WXLZh8aDtbnGIMZ8rBNk6nBE5KTen7B4J6PWXMcQtXVskLYAjuYat29yU5l5ZuT4jF29R6J0q54JExApLqaAlj1IuigU1jCMIuNGIQJQcJxhD/R2YUChzmD2QUFOIjPfSVEjRaisoKbIQAxKhkz9VoMgSeLNy14Gxpw3y2dP5J7UNfqceYToFg+Ioag0u5nB+Fw8bvNqkaloQwu1T/qB43SUXEM442SHjTRJNEmJb7gvz5YtfRxqrMeZEQV8aZngsLoy9U9DQvDNEaju+2IphPjn5GUnvO/eI6sw6O/ZHNiwHGxKqUYwlJdqCt01gKmKhM5Q/F0wGEu8bfFHRQqSIJOGZq8n54TX7K2OXmRgX9f89CLzPXaKJmWPdLRN+L/FPR1usTR4tMeuYl/1URSpAb8XVHexK87tteY9ZzsvvvKuiPWAqEBGCSr5DPobEPU2zqmedrt0uAEVWFO22dKGBollIdVGk976aoG9GgKYHd23MrAtKzfxUN/r6GU9tgdnOUGaG/bpY27V3stPoRdsK+VZWg4QuFBIUhq1ZJ6m+0=,iv:2VZ/63Z9fapKVvC0/Vc5+l2C+czVxIx9XerF/IZnU6Q=,tag:0oS+Lkf/QO7+PmYhCcLwLw==,type:str]
crt: ENC[AES256_GCM,data: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,iv:CUT5zri3Z3T3ADt6tk1raLmu+zDVeLi5PNJ68RFhF0A=,tag:MXKk78bKNJn/PT8AnX15ug==,type:str]
srl: ENC[AES256_GCM,data:71ZcIRRiJgjDhSElj7gpWrxw2933zk8CYaTS/+t65jUpuZ4u9H7vhA==,iv:zPq5hzhujKEjZT1q3FlKf/wsIlc6o0XZw+mRJjZvdwA=,tag:wSgSHGKdmZSO6QVJydgf/g==,type:str]
server:
key: ENC[AES256_GCM,data:CqSltle0xWStH3iGCd8Zvwh9idqaznypqgt/UklN1Ql+/Y8+jFg6L/Uw1i3qcvaMxYtrUSMFcTMbjSG7nX3iSeIMJ/s/VJS6Xyb5oOYvi8Lp+D6c4agm1cVnVYRj8F1M2p8vFy2b8c3WAMNIAbLkyyrh8N08d6XFGi8rtdfXOUYe0SxX96fgSiXHRKOijp46NPHCm2CiyqjLjtaaCNDZRUIxIAIZ20rL9jDjFJad4ue+yVqqNnFsuLTZGe3GrBHQaf6A1sSLKirgyQLN8dOzVSlqFDOB/9Omy5gGT9/4BboJRyDZnB2iAIEbMo9pX3iZHebPLG3xb8kEgUyGoywf/CF2OzRkfHhdAKRczFfTtxFfNVRFOrQBGv+ErqVmjPy9JmpJUj9XEnJ/4JJTxBbtVh4Jbihfv8ArJwNQj4JhyMfOAUo3MdmY70Nd7NVg0XfLUF4RdoqfQwS0yAZ1ERl8ZFUskkjTzIe+QVbHikHc+wD7i83yr+1TTC2KF/iIf4udsEmNFUUyRfb+3xFBnh5ahvzI8+ICjuj1MoWMIx6S8uYmSViq5LzBdPPfnRb182EdbK3nCcosarEgnN/QBAdTEdO8y4cBnyy4Sre/iqTU287HwmCd/hDAVLE0XASlxzxicvWIg0fQz973058ArP65sryV7Q7diiTY9oGrSC9tcBBNvpT/n8JSjKqSGViVn0LiEPaifmGHxRx0w2kS95XvQMFSIBqd03/DFKf2IDq/Ln17/YqdOpryAxwza+unQjKHgR5oxT3Ho3UUwKWXRzVD2flLdQy3gXcKro21f4vmO4UOIdO4KyehRjGSyLkM9DLLH7FH3c4JjZUDsov+Xq+UlKs5fLVvYeX1aifZWjUCtVd2t7RuXVrdScl/8/HxIEctny1jnX9mTpM1IF4SUSaNwSbE7cNMGpulyY61wyxyn9thKq+R+kLQYpSOFPWeOG8+SwEajKy8MCf84Vdj48RAWCBlZKW+cgI++Xe0nSJj9AcrH8vZaG6NGcWWrYIsn62Y1o6GSVot9rvsR7g9tsoyZ4o0/zBzPslkQVRm6lXW/OCACXBRZK+dt48UMjiiO0EElUKq9Y+CWQHSO/7h7SssGEXvA1H0vRr5scEhDGmzOVBQ2C/zwYQILxAocngMRPeYx/yCSRqahf2wGDfn6eNJp5zfBQmbBrJW/MKct3Ei51pCuFedToENResF+fCbWxy5JjIbr/O9VEcJsD2ZU5qg21f1DYXbCNUH40K5TnAKe852v66Eo4lhj7O7CpkYFR3g/wyhFrtWs740uic+oN4WHVvPdFqYaC9a8K508WEUk/ZYhMVbg2uRztujJIv6Bdfjo8MaVnpu0m0cCMxaIO8oiqRigYhhzbAQQgHaW5qX+eBQl3Y3tQZKkeWdRFf+KsQ2jiqxi4WF43NmNvyBCLKXa17BtV3OttieHY875YEWkzKqRqYn6325DvizJ1k3CmbigFgqjG1zfCqsU9p2HNNiI3pMHMxnyYtLX50Omy+mXVWhMMvvFw2JuB5f/fK/0f5k02AXP4wOFZOrlNjyTr7BR4FAEOeVNNV4j9TYgA8vxTnFd1aw9lVw8qUsIv0F++yTY9avEv1V/3O442DcfmmuAYNXOgkREdmzYT5/JjfxdYNI1mgqdCSoeCHRzssQr0cFmpb7vr4w5KdWY9JnJo41qX4YImJFuOhh8yCRd8U9a5KjSL/J3kPkFECd09uxts5LvEwKJLPs6fVImmSm2dVe+WsNgXIaCQrRyuw9maAYMfPPKZ47RJ2df2GtjFHXIaN376jHnnPiDIVMNkQUC1RdmBR60sQeaD/GDCdwHmv1tSewVDW2AGTBn2uNLOqjacTixbWe426ZtgssY6mh9WpZYXn3iI9p9xdtPYDTkisQPUzan+KnnBZsidFCuwahxkCyT0dmDfVT3Ua/xAbDtdsPSeIl/92t/RRfcAEHYKqAYzgZToZ35LTbG+wjgJs06pOogAs82qLIKxVGotF8hgDpja9srEky2gjYwNgZ48KlV+Gg4obXEGLd0Qbehj5sUMW1GlSU9ewFdL9eY0ODRlNpw6EJxZKuDbk4EBgdz3r7g6LXucbrHv2G2iQDLyPKBmMhV9nmjT/wz8Pl18GbZhjEvAdMzrCEfrLLBK2BtC1MO8QiDhinT9bL77GduFjy1ndvIJWFIgc/4gJMNdFcRVxOx9rcqiDjItIiYVu88FP2Em/EKin0ODAJODotzqU61Nlm9CL6Qu0Cxf4PpzJ454lMjINfxqr0b+XI,iv:qulX1ovZpeV9E9xTe8nyVMWZV9yclNbGag5PGvuv6L8=,tag:5sB+gGI4JlQ7nry8BL4WPg==,type:str]
crt: ENC[AES256_GCM,data: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,iv:iGPrxSSmbWA94nF1hQ8yY2w9NGqAzbWDI+PYJrCMdfg=,tag:0ndoe3MI9z5R45FyoFAHaQ==,type:str]
client:
key: ENC[AES256_GCM,data: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,iv:SDvI7nbhJUMEWp7fnfq6rxWJkwHsyfKA49p5HqwZlns=,tag:9SvAOtBMVJAJjbfB7YmCCA==,type:str]
crt: ENC[AES256_GCM,data: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,iv:GOycAPjOLkJjhOXu4TxohfPg6vGYWAOFRhQ2BGI/AAw=,tag:vJCRcTItk2jWEQs3hXzvYw==,type:str]
sops: sops:
age: age:
- recipient: age18lta9d683yekz487xwtd99da236d8mgk4ftlmv2jffx858p9qf2s9j868l - enc: |
enc: |
-----BEGIN AGE ENCRYPTED FILE----- -----BEGIN AGE ENCRYPTED FILE-----
YWdlLWVuY3J5cHRpb24ub3JnL3YxCi0+IFgyNTUxOSBJRDdtTmdvRDRPaU53Mjd3 YWdlLWVuY3J5cHRpb24ub3JnL3YxCi0+IFgyNTUxOSBJRDdtTmdvRDRPaU53Mjd3
S25SeU5rUnZibmh2Y01HZUVhZjVWUVBJVXlvCm1uaURNYURGRUhhc25vSmFodEJC S25SeU5rUnZibmh2Y01HZUVhZjVWUVBJVXlvCm1uaURNYURGRUhhc25vSmFodEJC
@@ -16,8 +26,8 @@ sops:
VU5jeTBFcGYvNE9tVUVuNmV5WjMycjgKF9GIvJTczigKH+dbTAOHK0S966/QE/7M VU5jeTBFcGYvNE9tVUVuNmV5WjMycjgKF9GIvJTczigKH+dbTAOHK0S966/QE/7M
HtgdJi9roiyDwI9k56r35/MP3eURffXBWTmc8WZRHTxnhzo1GBpg0A== HtgdJi9roiyDwI9k56r35/MP3eURffXBWTmc8WZRHTxnhzo1GBpg0A==
-----END AGE ENCRYPTED FILE----- -----END AGE ENCRYPTED FILE-----
- recipient: age1e0a4ru707v637wzmuxqv0xywmlkhunzgyfy4mrkjc7a23qq8msgq7nqtvt recipient: age18lta9d683yekz487xwtd99da236d8mgk4ftlmv2jffx858p9qf2s9j868l
enc: | - enc: |
-----BEGIN AGE ENCRYPTED FILE----- -----BEGIN AGE ENCRYPTED FILE-----
YWdlLWVuY3J5cHRpb24ub3JnL3YxCi0+IFgyNTUxOSBqMGtpL3JJaDN2Qm95b1cz YWdlLWVuY3J5cHRpb24ub3JnL3YxCi0+IFgyNTUxOSBqMGtpL3JJaDN2Qm95b1cz
VEF2bHU3VjJLNUQya25lL01qYkFreFpTVGdBCkdHdnBUUjlXOU4yTkE5ZTF2OFll VEF2bHU3VjJLNUQya25lL01qYkFreFpTVGdBCkdHdnBUUjlXOU4yTkE5ZTF2OFll
@@ -25,8 +35,8 @@ sops:
VDcvTUY5YVEvOWFQOG5ULzFlQU9IMTAKQ601N8YNayuYrkZqqsKqlsnHN4rSMzN1 VDcvTUY5YVEvOWFQOG5ULzFlQU9IMTAKQ601N8YNayuYrkZqqsKqlsnHN4rSMzN1
sesAmJVuj7ZddGQlzIJC9cydXkssmY5oDIj92J7DXTzhFQlO0o9tfA== sesAmJVuj7ZddGQlzIJC9cydXkssmY5oDIj92J7DXTzhFQlO0o9tfA==
-----END AGE ENCRYPTED FILE----- -----END AGE ENCRYPTED FILE-----
- recipient: age1wmrrhd5deatmgflkas636u3rzuk46u9knl02v4t39ncs37xqquhq9vwzye recipient: age1e0a4ru707v637wzmuxqv0xywmlkhunzgyfy4mrkjc7a23qq8msgq7nqtvt
enc: | - enc: |
-----BEGIN AGE ENCRYPTED FILE----- -----BEGIN AGE ENCRYPTED FILE-----
YWdlLWVuY3J5cHRpb24ub3JnL3YxCi0+IFgyNTUxOSB5ZFV6cWN3OEloVmIrWG9Z YWdlLWVuY3J5cHRpb24ub3JnL3YxCi0+IFgyNTUxOSB5ZFV6cWN3OEloVmIrWG9Z
U0RxNVF0RlJ6UDNMK0psQjVKUkJiR0JUMWxBCll3NHpFempRcCtSYUQzWi9kclFP U0RxNVF0RlJ6UDNMK0psQjVKUkJiR0JUMWxBCll3NHpFempRcCtSYUQzWi9kclFP
@@ -34,8 +44,8 @@ sops:
SllNcDVzSE4wTTB5NTNTYXJoemlIMUEKbJwinjEIjgwlShvUr+Jcfay0ha8Ndo6L SllNcDVzSE4wTTB5NTNTYXJoemlIMUEKbJwinjEIjgwlShvUr+Jcfay0ha8Ndo6L
KM0QvKlcsx5Z6pqyYt6TvnlhyhcljN1IFfoUO5r3E9lYSyanv3HJRA== KM0QvKlcsx5Z6pqyYt6TvnlhyhcljN1IFfoUO5r3E9lYSyanv3HJRA==
-----END AGE ENCRYPTED FILE----- -----END AGE ENCRYPTED FILE-----
- recipient: age1ml48zztcmnrdrhrdsjrlyxf09jtmjgz46u8td4zm59wn3fm4g57qs4wg0l recipient: age1wmrrhd5deatmgflkas636u3rzuk46u9knl02v4t39ncs37xqquhq9vwzye
enc: | - enc: |
-----BEGIN AGE ENCRYPTED FILE----- -----BEGIN AGE ENCRYPTED FILE-----
YWdlLWVuY3J5cHRpb24ub3JnL3YxCi0+IFgyNTUxOSA3SG15dS9JNmRETjBZL001 YWdlLWVuY3J5cHRpb24ub3JnL3YxCi0+IFgyNTUxOSA3SG15dS9JNmRETjBZL001
VnNSN1o1ZENwdStLdnMxaGp2OVg4WFVUWmpvClJESk9KVi8rdkU5Q0ZHSnhOell2 VnNSN1o1ZENwdStLdnMxaGp2OVg4WFVUWmpvClJESk9KVi8rdkU5Q0ZHSnhOell2
@@ -43,8 +53,8 @@ sops:
THhnZWZNckdTOXNpSjVDUEFWQW8rOE0K5ts7BAbcZ7L3cId+jjbC8ZDOnCEAjFW7 THhnZWZNckdTOXNpSjVDUEFWQW8rOE0K5ts7BAbcZ7L3cId+jjbC8ZDOnCEAjFW7
lizGlAPolgH6uNpPczneeFBczfU8nnWOcJTpPXQDxXiWv7y0aemJRQ== lizGlAPolgH6uNpPczneeFBczfU8nnWOcJTpPXQDxXiWv7y0aemJRQ==
-----END AGE ENCRYPTED FILE----- -----END AGE ENCRYPTED FILE-----
- recipient: age12gws5nws69vxryd3kt7q0ayngch90efmhqcrfhnnsmj00lkgxd4qsdkvqn recipient: age1ml48zztcmnrdrhrdsjrlyxf09jtmjgz46u8td4zm59wn3fm4g57qs4wg0l
enc: | - enc: |
-----BEGIN AGE ENCRYPTED FILE----- -----BEGIN AGE ENCRYPTED FILE-----
YWdlLWVuY3J5cHRpb24ub3JnL3YxCi0+IFgyNTUxOSBLQUEwa0cvcndUbnlpTlYr YWdlLWVuY3J5cHRpb24ub3JnL3YxCi0+IFgyNTUxOSBLQUEwa0cvcndUbnlpTlYr
ZUtEdlRKcmlrQU1USlZVeXNXejhBSUdLdGxNCmpzRHpoM1VNemo5angweW9QMGJ2 ZUtEdlRKcmlrQU1USlZVeXNXejhBSUdLdGxNCmpzRHpoM1VNemo5angweW9QMGJ2
@@ -52,8 +62,8 @@ sops:
Q1p0b2dJMXNhRFdYdHV3UFhUQzVmQVEK/3E/fDJcuwN8UJq05Dg0YLHhFRLjl4i7 Q1p0b2dJMXNhRFdYdHV3UFhUQzVmQVEK/3E/fDJcuwN8UJq05Dg0YLHhFRLjl4i7
98dDpycvPV8Py82q4pNpvI+goZ2T19QcxArSLNLQwd3TqIYvLHB+FA== 98dDpycvPV8Py82q4pNpvI+goZ2T19QcxArSLNLQwd3TqIYvLHB+FA==
-----END AGE ENCRYPTED FILE----- -----END AGE ENCRYPTED FILE-----
- recipient: age1ug30gg4y7ftuya0wdv7q0vh4egn00wlv2th7mt7cgc2ze46wmvyq9lq6ge recipient: age12gws5nws69vxryd3kt7q0ayngch90efmhqcrfhnnsmj00lkgxd4qsdkvqn
enc: | - enc: |
-----BEGIN AGE ENCRYPTED FILE----- -----BEGIN AGE ENCRYPTED FILE-----
YWdlLWVuY3J5cHRpb24ub3JnL3YxCi0+IFgyNTUxOSAxOEhSZzhkZ25rL1dZVlRw YWdlLWVuY3J5cHRpb24ub3JnL3YxCi0+IFgyNTUxOSAxOEhSZzhkZ25rL1dZVlRw
R0JMaUR2VXQ5cnYvdjRwQjU5VWYwcGRYbUMwClVBYi9nOHZkejBxamxKeHJSZmFC R0JMaUR2VXQ5cnYvdjRwQjU5VWYwcGRYbUMwClVBYi9nOHZkejBxamxKeHJSZmFC
@@ -61,8 +71,8 @@ sops:
TGpFN2xCTWcybnBBL0o2MVFoQzNRMkEKtprwI3p45huVaLJvqTNLU1k17uSObJaA TGpFN2xCTWcybnBBL0o2MVFoQzNRMkEKtprwI3p45huVaLJvqTNLU1k17uSObJaA
QEL/qzgLr//fSxiMQfJRtvqpcGuL/kTnmU56tJdLVCDAfFvW0OH9gQ== QEL/qzgLr//fSxiMQfJRtvqpcGuL/kTnmU56tJdLVCDAfFvW0OH9gQ==
-----END AGE ENCRYPTED FILE----- -----END AGE ENCRYPTED FILE-----
- recipient: age1mrnldl334l2nszuta6ywvewng0fswv2dz9l5g4qcwe3nj4yxf92qjskdx6 recipient: age1ug30gg4y7ftuya0wdv7q0vh4egn00wlv2th7mt7cgc2ze46wmvyq9lq6ge
enc: | - enc: |
-----BEGIN AGE ENCRYPTED FILE----- -----BEGIN AGE ENCRYPTED FILE-----
YWdlLWVuY3J5cHRpb24ub3JnL3YxCi0+IFgyNTUxOSBZTWVYY3hPMi85QjhYQWlW YWdlLWVuY3J5cHRpb24ub3JnL3YxCi0+IFgyNTUxOSBZTWVYY3hPMi85QjhYQWlW
R0s0bnVpNEFmalFBS3lISmtWanNPcEpPRlF3CjY2TnliWGJocWtkbjZZQUpPZ3dS R0s0bnVpNEFmalFBS3lISmtWanNPcEpPRlF3CjY2TnliWGJocWtkbjZZQUpPZ3dS
@@ -70,8 +80,8 @@ sops:
a3hmLzNiY2ZQdk5TQzExOGJPeTd0U0kKVqulWO1BniSTpYHa7fYwG0oj+hq+clGq a3hmLzNiY2ZQdk5TQzExOGJPeTd0U0kKVqulWO1BniSTpYHa7fYwG0oj+hq+clGq
/XlvYUYNIApaAid3G9LrZNL7g3mhq1ANuDGMY7n0Z6/xhysTZwRzEQ== /XlvYUYNIApaAid3G9LrZNL7g3mhq1ANuDGMY7n0Z6/xhysTZwRzEQ==
-----END AGE ENCRYPTED FILE----- -----END AGE ENCRYPTED FILE-----
- recipient: age1hmpdk4h69wxpwqk9tkud39f66hprhehxtzhgw97r6dvr7v0mx5jscsuhkn recipient: age1mrnldl334l2nszuta6ywvewng0fswv2dz9l5g4qcwe3nj4yxf92qjskdx6
enc: | - enc: |
-----BEGIN AGE ENCRYPTED FILE----- -----BEGIN AGE ENCRYPTED FILE-----
YWdlLWVuY3J5cHRpb24ub3JnL3YxCi0+IFgyNTUxOSBsNkM5ZjRIK2FKL1B3S0tl YWdlLWVuY3J5cHRpb24ub3JnL3YxCi0+IFgyNTUxOSBsNkM5ZjRIK2FKL1B3S0tl
ZUdzMC9ONStkYnZZRm1VQy9FMVJkNk9SY1IwCnJFTVRTL1FkRlAySmF1ZDdBVUxz ZUdzMC9ONStkYnZZRm1VQy9FMVJkNk9SY1IwCnJFTVRTL1FkRlAySmF1ZDdBVUxz
@@ -79,8 +89,8 @@ sops:
cDdvRVl6a3VhZXhwUkl6eHo0OGxxUDQK5/Z3OCFIb4HOBBxHj0B7a0AuPXgPbuh5 cDdvRVl6a3VhZXhwUkl6eHo0OGxxUDQK5/Z3OCFIb4HOBBxHj0B7a0AuPXgPbuh5
TPGvfJpa3Ow/eJSpEdXOm6chTrvPsgGHKYZS75SAgHMP8SHHIPuxuQ== TPGvfJpa3Ow/eJSpEdXOm6chTrvPsgGHKYZS75SAgHMP8SHHIPuxuQ==
-----END AGE ENCRYPTED FILE----- -----END AGE ENCRYPTED FILE-----
- recipient: age1wrssr4z4g6vl3fd3qme5cewchmmhm0j2xe6wf2meu4r6ycn37anse98mfs recipient: age1hmpdk4h69wxpwqk9tkud39f66hprhehxtzhgw97r6dvr7v0mx5jscsuhkn
enc: | - enc: |
-----BEGIN AGE ENCRYPTED FILE----- -----BEGIN AGE ENCRYPTED FILE-----
YWdlLWVuY3J5cHRpb24ub3JnL3YxCi0+IFgyNTUxOSBzVXhHTE83aDFvN3U3Tncz YWdlLWVuY3J5cHRpb24ub3JnL3YxCi0+IFgyNTUxOSBzVXhHTE83aDFvN3U3Tncz
TzlYSVB1NzdvQVY5bU1yZTRhU0V1bXgyZ21RCm1WekpqcHE3cG5sRkM4Z2k4UzFK TzlYSVB1NzdvQVY5bU1yZTRhU0V1bXgyZ21RCm1WekpqcHE3cG5sRkM4Z2k4UzFK
@@ -88,8 +98,8 @@ sops:
bHpyUUM4NlN3VDhVYVhFNVYyeElqVDQKm44tte4aQ5/0XVMd7IvnahRxdrSePHKn bHpyUUM4NlN3VDhVYVhFNVYyeElqVDQKm44tte4aQ5/0XVMd7IvnahRxdrSePHKn
f6EUC0tBdSAifbe8JdCvTz2DDbUbXRxDxZCJ35ATyB0K1AEgcVEVvA== f6EUC0tBdSAifbe8JdCvTz2DDbUbXRxDxZCJ35ATyB0K1AEgcVEVvA==
-----END AGE ENCRYPTED FILE----- -----END AGE ENCRYPTED FILE-----
- recipient: age1zhxul786an743u0fascv4wtc5xduu7qfy803lfs539yzhgmlq5ds2lznt5 recipient: age1wrssr4z4g6vl3fd3qme5cewchmmhm0j2xe6wf2meu4r6ycn37anse98mfs
enc: | - enc: |
-----BEGIN AGE ENCRYPTED FILE----- -----BEGIN AGE ENCRYPTED FILE-----
YWdlLWVuY3J5cHRpb24ub3JnL3YxCi0+IFgyNTUxOSA3VTZXR2hZT2FERFNhNXVs YWdlLWVuY3J5cHRpb24ub3JnL3YxCi0+IFgyNTUxOSA3VTZXR2hZT2FERFNhNXVs
MkREdWxxNWNvZy9jRkp0d2YwNm5IRDY3Zm44CjZ0SC9NWE40TmFtR2NSMUZtMmV2 MkREdWxxNWNvZy9jRkp0d2YwNm5IRDY3Zm44CjZ0SC9NWE40TmFtR2NSMUZtMmV2
@@ -97,8 +107,8 @@ sops:
Q2VuWG8yOE1ob1Ayd2Z6NllhNnMxK2MK1BzxHusN/Ad0+2ExwK/q8qyPObDL+112 Q2VuWG8yOE1ob1Ayd2Z6NllhNnMxK2MK1BzxHusN/Ad0+2ExwK/q8qyPObDL+112
o5/LeOh2vA3KQOG7QmlfhOK8NEID2dcWXoK3Kg8H24rowZq+WQryqg== o5/LeOh2vA3KQOG7QmlfhOK8NEID2dcWXoK3Kg8H24rowZq+WQryqg==
-----END AGE ENCRYPTED FILE----- -----END AGE ENCRYPTED FILE-----
- recipient: age1sqs7urnzsdy64efmd0zukzv3gs5pnjksuxd7nqmdwdy5l0nqnunq6hyune recipient: age1zhxul786an743u0fascv4wtc5xduu7qfy803lfs539yzhgmlq5ds2lznt5
enc: | - enc: |
-----BEGIN AGE ENCRYPTED FILE----- -----BEGIN AGE ENCRYPTED FILE-----
YWdlLWVuY3J5cHRpb24ub3JnL3YxCi0+IFgyNTUxOSBXblVrSXJjVUVtaWltVzQy YWdlLWVuY3J5cHRpb24ub3JnL3YxCi0+IFgyNTUxOSBXblVrSXJjVUVtaWltVzQy
OGFDR05TNTJEY2M3dUQ5bEtnaVF2dnd3VVdjCmFlL3MwVEFrYml5UE54U3Z5bUNU OGFDR05TNTJEY2M3dUQ5bEtnaVF2dnd3VVdjCmFlL3MwVEFrYml5UE54U3Z5bUNU
@@ -106,8 +116,9 @@ sops:
MTc3MVhaU0s5anZPdUg4RlFiZmU4MHcKepCAfP8iMOJ39LL4S8XA18pXAYZgcdLO MTc3MVhaU0s5anZPdUg4RlFiZmU4MHcKepCAfP8iMOJ39LL4S8XA18pXAYZgcdLO
xNV7kAcdXpywk/ffnWAukwI32LegGQ+efNtysCeESNKomSDtXKtm6Q== xNV7kAcdXpywk/ffnWAukwI32LegGQ+efNtysCeESNKomSDtXKtm6Q==
-----END AGE ENCRYPTED FILE----- -----END AGE ENCRYPTED FILE-----
lastmodified: "2025-12-04T05:53:51Z" recipient: age1sqs7urnzsdy64efmd0zukzv3gs5pnjksuxd7nqmdwdy5l0nqnunq6hyune
mac: ENC[AES256_GCM,data:o55keAaJEXVOAGvoMp8FWvtlxMgfF/qR50FGnNM1whYz+5+naRJ1dAOW9NKYHWbtOa/ZXEMTkjoFrTJidAaIXza1Ot8llbTGYh56fsnu0FKZfVM+rvecRDhXKWxiAqyiLUvtUfA2fSg9LGveh2U+0dulcU25sb3Wf0RcFrtM3xI=,iv:3/UllekmGIaluv8y8I6Azd/52dJzk+C5ah6XLJj7Zik=,tag:T5ILXiC5hK++0jGOnHCMYA==,type:str] lastmodified: "2026-07-04T17:19:48Z"
mac: ENC[AES256_GCM,data:XpN/4euqp0/9/aPj8PumBsQbqp/bNZm4xvkxwQIDyrEp8Y6O0z6NrZMiCBSepsjrLib6hhMcj3v8lIKixm91cw1/HYryl1D8UIU6iPSItPpEiFRKJRtz6LNEieSQrDJyHtorVQkCgmkJfPfpegYMDeFWhYahv1Vk1oPPy0KZq9U=,iv:IRLDKvyPEHsgDYzucC+DEB09xb+ol636kzSognhz93M=,tag:Y5YGvjwFmFpsOKTP0+w51A==,type:str]
pgp: pgp:
- created_at: "2026-04-18T16:25:16Z" - created_at: "2026-04-18T16:25:16Z"
enc: |- enc: |-
@@ -130,4 +141,4 @@ sops:
-----END PGP MESSAGE----- -----END PGP MESSAGE-----
fp: F7D37890228A907440E1FD4846B9228E814A2AAC fp: F7D37890228A907440E1FD4846B9228E814A2AAC
unencrypted_suffix: _unencrypted unencrypted_suffix: _unencrypted
version: 3.11.0 version: 3.13.1
+18 -18
View File
@@ -1,13 +1,12 @@
dibbler: dibbler:
postgresql: postgresql:
password: ENC[AES256_GCM,data:3X9A3jOpFVRuBg0gRiCEsZVKfLI=,iv:XC7LBNUhALk9IEhItV8fO5p/m7VKL0REBY1W2IZt7G4=,tag:l18R7EhbOlucZHFQiEvpHw==,type:str] password: ENC[AES256_GCM,data:ZeNKipcCB+z8QVGeg1iV3MUXqALjotVz,iv:xCtgOoe6Pkr6Cq3vL+T4L+GW1KAcgP/xUz3YbHs5bCc=,tag:/X5phRYDAws8Aam1j+UaTw==,type:str]
worblehat: worblehat:
postgresql: postgresql:
password: ENC[AES256_GCM,data:WpJR6MumY+7WUYdVVgAqv1af+NmqecTMO9aP5lidSpE=,iv:7aoN8mjXckd81LxasMSG3R2vqj0SvzSl7wrEQ1LwToo=,tag:zeeNcEpkYnqyd8be0ZS+kQ==,type:str] password: ENC[AES256_GCM,data:WpJR6MumY+7WUYdVVgAqv1af+NmqecTMO9aP5lidSpE=,iv:7aoN8mjXckd81LxasMSG3R2vqj0SvzSl7wrEQ1LwToo=,tag:zeeNcEpkYnqyd8be0ZS+kQ==,type:str]
sops: sops:
age: age:
- recipient: age1hzkvnktkr8t5gvtq0ccw69e44z5z6wf00n3xhk3hj24emf07je5s6q2evr - enc: |
enc: |
-----BEGIN AGE ENCRYPTED FILE----- -----BEGIN AGE ENCRYPTED FILE-----
YWdlLWVuY3J5cHRpb24ub3JnL3YxCi0+IFgyNTUxOSAvTk5YU3Z2Yy9HS1R4ME5I YWdlLWVuY3J5cHRpb24ub3JnL3YxCi0+IFgyNTUxOSAvTk5YU3Z2Yy9HS1R4ME5I
UU1PRWVncHJYcXY5RlFpOWVQUWZsdy93ZDFBCnlxWkpaL1g5WmNSckNYd202WE40 UU1PRWVncHJYcXY5RlFpOWVQUWZsdy93ZDFBCnlxWkpaL1g5WmNSckNYd202WE40
@@ -15,8 +14,8 @@ sops:
ZnllQzJiK1ZkRmFndmtYdW9IclFWY1EK82f1iGt3nt8dJnEQlMujNqConf6Qq6GX ZnllQzJiK1ZkRmFndmtYdW9IclFWY1EK82f1iGt3nt8dJnEQlMujNqConf6Qq6GX
hqoqPoc2EM4kun28Bbpq4pAY7eEPRrWFqOkjYVvgIRoS88D7xT3LWg== hqoqPoc2EM4kun28Bbpq4pAY7eEPRrWFqOkjYVvgIRoS88D7xT3LWg==
-----END AGE ENCRYPTED FILE----- -----END AGE ENCRYPTED FILE-----
- recipient: age1ug30gg4y7ftuya0wdv7q0vh4egn00wlv2th7mt7cgc2ze46wmvyq9lq6ge recipient: age1hzkvnktkr8t5gvtq0ccw69e44z5z6wf00n3xhk3hj24emf07je5s6q2evr
enc: | - enc: |
-----BEGIN AGE ENCRYPTED FILE----- -----BEGIN AGE ENCRYPTED FILE-----
YWdlLWVuY3J5cHRpb24ub3JnL3YxCi0+IFgyNTUxOSA5WTJIOUcxRlBuNmRrNUZo YWdlLWVuY3J5cHRpb24ub3JnL3YxCi0+IFgyNTUxOSA5WTJIOUcxRlBuNmRrNUZo
MXFxeVJBTEhDK00yTUw1U2dHckNFYWZKWkhNCnYxYmtrUEVvd1RaYUI5WTRTRW16 MXFxeVJBTEhDK00yTUw1U2dHckNFYWZKWkhNCnYxYmtrUEVvd1RaYUI5WTRTRW16
@@ -24,8 +23,8 @@ sops:
eTB4WldMNW9GNUwwaEUzRThsemxRVzQKGpa0J2PBzDRdHijm0e3nFAaxQCHUjz+L eTB4WldMNW9GNUwwaEUzRThsemxRVzQKGpa0J2PBzDRdHijm0e3nFAaxQCHUjz+L
KataXJEMCijJ6k+7vpb5QMxe2jB1J2PMxNGFp0bWAy2Al3p/Ez2Kww== KataXJEMCijJ6k+7vpb5QMxe2jB1J2PMxNGFp0bWAy2Al3p/Ez2Kww==
-----END AGE ENCRYPTED FILE----- -----END AGE ENCRYPTED FILE-----
- recipient: age1mrnldl334l2nszuta6ywvewng0fswv2dz9l5g4qcwe3nj4yxf92qjskdx6 recipient: age1ug30gg4y7ftuya0wdv7q0vh4egn00wlv2th7mt7cgc2ze46wmvyq9lq6ge
enc: | - enc: |
-----BEGIN AGE ENCRYPTED FILE----- -----BEGIN AGE ENCRYPTED FILE-----
YWdlLWVuY3J5cHRpb24ub3JnL3YxCi0+IFgyNTUxOSBZaW1ZSXhVeFVTQW9WYzVh YWdlLWVuY3J5cHRpb24ub3JnL3YxCi0+IFgyNTUxOSBZaW1ZSXhVeFVTQW9WYzVh
WkVUM2JkOU5VNU9oQXE2Y2pvcFlOWTdvbnpJClduS0RHL2xja291a2doQ0wzbzhQ WkVUM2JkOU5VNU9oQXE2Y2pvcFlOWTdvbnpJClduS0RHL2xja291a2doQ0wzbzhQ
@@ -33,8 +32,8 @@ sops:
ZUdnS2RvOXI1dGNYQTl6ZHE1cUdMWHMK4ycAJQLyKCgJIzjQ02bPjz4Ct9eO6ivw ZUdnS2RvOXI1dGNYQTl6ZHE1cUdMWHMK4ycAJQLyKCgJIzjQ02bPjz4Ct9eO6ivw
kfWhyMaoWwM9PhFcwSak0cLpX0C/IOzSzO78pf3WhG16pV7aXapdog== kfWhyMaoWwM9PhFcwSak0cLpX0C/IOzSzO78pf3WhG16pV7aXapdog==
-----END AGE ENCRYPTED FILE----- -----END AGE ENCRYPTED FILE-----
- recipient: age1hmpdk4h69wxpwqk9tkud39f66hprhehxtzhgw97r6dvr7v0mx5jscsuhkn recipient: age1mrnldl334l2nszuta6ywvewng0fswv2dz9l5g4qcwe3nj4yxf92qjskdx6
enc: | - enc: |
-----BEGIN AGE ENCRYPTED FILE----- -----BEGIN AGE ENCRYPTED FILE-----
YWdlLWVuY3J5cHRpb24ub3JnL3YxCi0+IFgyNTUxOSBqaml0OVlhcUJSU1hSY3lP YWdlLWVuY3J5cHRpb24ub3JnL3YxCi0+IFgyNTUxOSBqaml0OVlhcUJSU1hSY3lP
bkM0cUV4Z2ZLeERHZ3BUNExuYS9KSU5CekQ4CmQ3SE1vdDBtdFJ6czZYR3U5Tk1X bkM0cUV4Z2ZLeERHZ3BUNExuYS9KSU5CekQ4CmQ3SE1vdDBtdFJ6czZYR3U5Tk1X
@@ -42,8 +41,8 @@ sops:
Sy9XbjhwOFR6SFpaNHZLd3ZxdmxOVUEKBBbGmdVVlKHxO+/iODznLP3+dJGppybW Sy9XbjhwOFR6SFpaNHZLd3ZxdmxOVUEKBBbGmdVVlKHxO+/iODznLP3+dJGppybW
+1k9uenVHzie+pDKcrQpSyX2WDnmgg7hUAUiXPuz1eEWmwbRJnU/5w== +1k9uenVHzie+pDKcrQpSyX2WDnmgg7hUAUiXPuz1eEWmwbRJnU/5w==
-----END AGE ENCRYPTED FILE----- -----END AGE ENCRYPTED FILE-----
- recipient: age1wrssr4z4g6vl3fd3qme5cewchmmhm0j2xe6wf2meu4r6ycn37anse98mfs recipient: age1hmpdk4h69wxpwqk9tkud39f66hprhehxtzhgw97r6dvr7v0mx5jscsuhkn
enc: | - enc: |
-----BEGIN AGE ENCRYPTED FILE----- -----BEGIN AGE ENCRYPTED FILE-----
YWdlLWVuY3J5cHRpb24ub3JnL3YxCi0+IFgyNTUxOSBXK01vOVV5YlhsZ2ljYS91 YWdlLWVuY3J5cHRpb24ub3JnL3YxCi0+IFgyNTUxOSBXK01vOVV5YlhsZ2ljYS91
OUVEaEpTbXFKOHVNVDVoMTlrS05wRmsyM2dvCjZHOXlCUGowd0J4UlQzSzM5dWJ0 OUVEaEpTbXFKOHVNVDVoMTlrS05wRmsyM2dvCjZHOXlCUGowd0J4UlQzSzM5dWJ0
@@ -51,8 +50,8 @@ sops:
RUR6Yi9SUDFCUkZmRk5hYTVFeGloZXcKY/XtaSoW8Pu2wS4oistLSc0T5JvMnt+w RUR6Yi9SUDFCUkZmRk5hYTVFeGloZXcKY/XtaSoW8Pu2wS4oistLSc0T5JvMnt+w
s3yfe/zx9/1K6OtbeljF9FZVOB/dOamvk+Qlfl0T5qush7/WgGzErA== s3yfe/zx9/1K6OtbeljF9FZVOB/dOamvk+Qlfl0T5qush7/WgGzErA==
-----END AGE ENCRYPTED FILE----- -----END AGE ENCRYPTED FILE-----
- recipient: age1zhxul786an743u0fascv4wtc5xduu7qfy803lfs539yzhgmlq5ds2lznt5 recipient: age1wrssr4z4g6vl3fd3qme5cewchmmhm0j2xe6wf2meu4r6ycn37anse98mfs
enc: | - enc: |
-----BEGIN AGE ENCRYPTED FILE----- -----BEGIN AGE ENCRYPTED FILE-----
YWdlLWVuY3J5cHRpb24ub3JnL3YxCi0+IFgyNTUxOSBOM0pFb2tRTURtWmp6elRN YWdlLWVuY3J5cHRpb24ub3JnL3YxCi0+IFgyNTUxOSBOM0pFb2tRTURtWmp6elRN
M0xtajlzMTNPMnppcGhJMVlsNHdwWmNGbFVFCnlxM1JQTkR2elAvdytKUEJ3djBS M0xtajlzMTNPMnppcGhJMVlsNHdwWmNGbFVFCnlxM1JQTkR2elAvdytKUEJ3djBS
@@ -60,8 +59,8 @@ sops:
eWlyWGhaS1JCNitUSVVScFk2WGEvOG8K2rpYPGx5jhyyRK4UkeJR96wDFr4Frzsr eWlyWGhaS1JCNitUSVVScFk2WGEvOG8K2rpYPGx5jhyyRK4UkeJR96wDFr4Frzsr
QWz7fYZRWKWf0H0qn+bm9IfVJiBAlS5i16D1FnipZVmdWefFaZSEPg== QWz7fYZRWKWf0H0qn+bm9IfVJiBAlS5i16D1FnipZVmdWefFaZSEPg==
-----END AGE ENCRYPTED FILE----- -----END AGE ENCRYPTED FILE-----
- recipient: age1sqs7urnzsdy64efmd0zukzv3gs5pnjksuxd7nqmdwdy5l0nqnunq6hyune recipient: age1zhxul786an743u0fascv4wtc5xduu7qfy803lfs539yzhgmlq5ds2lznt5
enc: | - enc: |
-----BEGIN AGE ENCRYPTED FILE----- -----BEGIN AGE ENCRYPTED FILE-----
YWdlLWVuY3J5cHRpb24ub3JnL3YxCi0+IFgyNTUxOSBJVFV0WVZrK0wzbnhkcmcz YWdlLWVuY3J5cHRpb24ub3JnL3YxCi0+IFgyNTUxOSBJVFV0WVZrK0wzbnhkcmcz
c2lIdVlKcFpoYjZIWlNPN0M5N2g2WG9YdlRJCjg5YlNoSzQ5YW5yRUVSeTEzRThY c2lIdVlKcFpoYjZIWlNPN0M5N2g2WG9YdlRJCjg5YlNoSzQ5YW5yRUVSeTEzRThY
@@ -69,8 +68,9 @@ sops:
MmxPMWNPYzJiOFRqY2VYczhvRm5IR3cKpUVV+zsMolsHI2YK9YqC6ecNT6QXv0TV MmxPMWNPYzJiOFRqY2VYczhvRm5IR3cKpUVV+zsMolsHI2YK9YqC6ecNT6QXv0TV
d1SpXRAexZBeWCCHBjSdvQBl8AT4EwrAIP2M2o++6i5DaGoGiEIWZQ== d1SpXRAexZBeWCCHBjSdvQBl8AT4EwrAIP2M2o++6i5DaGoGiEIWZQ==
-----END AGE ENCRYPTED FILE----- -----END AGE ENCRYPTED FILE-----
lastmodified: "2026-03-18T14:56:22Z" recipient: age1sqs7urnzsdy64efmd0zukzv3gs5pnjksuxd7nqmdwdy5l0nqnunq6hyune
mac: ENC[AES256_GCM,data:nBKtFmFKx/Mt9TIFnKuuznsPAXCQpc3+WIspNu5TN9TpIqw75nzYXpxIb2hxRfRu0nbjHXpBy4bkzeMi41BGkvkvV57CZyq11J5i/iIKwuvllaB1IWrdDT2u+6RH3jIspp3KoyxFWdRqcGfNma9dSmtI+1Dd5z7XaxVaoVK2QMI=,iv:6joviyJ2cXmGh/9HH7VEcoK3+4GK5I6i2N/1d65PAN0=,tag:0BFVPWL3BByJH8HbrBTKOw==,type:str] lastmodified: "2026-06-07T08:58:13Z"
mac: ENC[AES256_GCM,data:rchs8pGkw7dthGOQNDB5p/kgQdfdystaC+jRr0bZnA4Q41+PVMu+vBSMIZ+9zZek6oENgchmV5rRS0CEeb9UQMMiPXCk2Q2jMaDfiNCmOmjf0YYeFWRM6g2lA+IZ3RgKjwhXa6i5JOeNrNewMjtx7MFcHTn3EBlg2mztyn1xbT0=,iv:0yvoFPDxpugaBmTtXSmhNz9XusJHrU3E02tBm1hVsZo=,tag:hZ1BzqfmlT1OhPSsn+CCTg==,type:str]
pgp: pgp:
- created_at: "2026-02-10T20:01:32Z" - created_at: "2026-02-10T20:01:32Z"
enc: |- enc: |-
@@ -93,4 +93,4 @@ sops:
-----END PGP MESSAGE----- -----END PGP MESSAGE-----
fp: F7D37890228A907440E1FD4846B9228E814A2AAC fp: F7D37890228A907440E1FD4846B9228E814A2AAC
unencrypted_suffix: _unencrypted unencrypted_suffix: _unencrypted
version: 3.12.1 version: 3.13.0
+3 -1
View File
@@ -1,4 +1,4 @@
{ pkgs, ... }: { pkgs, config, ... }:
{ {
users.users.vegardbm = { users.users.vegardbm = {
isNormalUser = true; isNormalUser = true;
@@ -8,12 +8,14 @@
"drift" "drift"
"nix-builder-users" "nix-builder-users"
]; ];
shell = if config.programs.zsh.enable then pkgs.zsh else pkgs.bash;
packages = with pkgs; [ packages = with pkgs; [
btop btop
eza eza
]; ];
openssh.authorizedKeys.keys = [ openssh.authorizedKeys.keys = [
"ssh-ed25519 AAAAC3NzaC1lZDI1NTE5AAAAIDVA3HqEx3je6L1AC+bP8sTxu3ZTKvTCR0npCyOVAYK5 vbm@arch-xeon" "ssh-ed25519 AAAAC3NzaC1lZDI1NTE5AAAAIDVA3HqEx3je6L1AC+bP8sTxu3ZTKvTCR0npCyOVAYK5 vbm@arch-xeon"
"ssh-ed25519 AAAAC3NzaC1lZDI1NTE5AAAAICrYATHNvBNAHr9G+VwZIaAQPe02iRgAjqtZkW4x/dje vbm@talos"
]; ];
}; };
} }
+4
View File
@@ -26,6 +26,10 @@ in rec {
ipv4 = pvv-ipv4 213; ipv4 = pvv-ipv4 213;
ipv6 = pvv-ipv6 213; ipv6 = pvv-ipv6 213;
}; };
knutsen-vpn = pvv-ipv4 191;
knutsen-tap = pvv-ipv4 253;
ludvigsen-tap = pvv-ipv4 254;
}; };
hosts = { hosts = {