Compare commits

...

34 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
32 changed files with 1173 additions and 560 deletions
+2
View File
@@ -101,6 +101,8 @@
# 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";
# Trusted users on the nix builder machines
-1
View File
@@ -8,6 +8,5 @@
# Let's not spam LetsEncrypt in `nixos-rebuild build-vm` mode:
virtualisation.vmVariant = {
security.acme.defaults.server = "https://127.0.0.1";
users.users.root.initialPassword = "root";
};
}
+4 -2
View File
@@ -62,8 +62,10 @@ in
name = "loki";
match = "*";
host = "ildkule.pvv.ntnu.no";
port = 3100;
host = "loki.pvv.ntnu.no";
port = 443;
tls = "on";
"tls.verify" = "on";
uri = "/loki/api/v1/push";
compress = "gzip";
Generated
+42 -42
View File
@@ -44,11 +44,11 @@
]
},
"locked": {
"lastModified": 1771267058,
"narHash": "sha256-EEL4SmD1b3BPJPsSJJ4wDTXWMumJqbR+BLzhJJG0skE=",
"lastModified": 1780236125,
"narHash": "sha256-LFFdHbXFthgU81S6P+p9FFKs/Wx868d4CtsFvbgvQqo=",
"ref": "main",
"rev": "e3962d02c78b9c7b4d18148d931a9a4bf22e7902",
"revCount": 254,
"rev": "267af00ebd8693632fa0f80300e49203cfcebbd4",
"revCount": 258,
"type": "git",
"url": "https://git.pvv.ntnu.no/Projects/dibbler.git"
},
@@ -126,10 +126,10 @@
"rust-overlay": "rust-overlay_2"
},
"locked": {
"lastModified": 1777019032,
"narHash": "sha256-29lw7THThWb5DW01rVRj1b816Apwz/P4m2wVWaSIadU=",
"lastModified": 1779345549,
"narHash": "sha256-naEMpFsQrco5eDtYmcTG6cpbPG+kqElOyS7fTb/jw9s=",
"ref": "main",
"rev": "55262afca46c96f75a834d4e00e30d5fb20affb6",
"rev": "5631e1124508fdef0604b08bfcf6343d967a21b3",
"revCount": 61,
"type": "git",
"url": "https://git.pvv.ntnu.no/Grzegorz/greg-ng.git"
@@ -169,11 +169,11 @@
]
},
"locked": {
"lastModified": 1769338528,
"narHash": "sha256-t18ZoSt9kaI1yde26ok5s7aFLkap1Q9+/2icVh2zuaE=",
"lastModified": 1780178524,
"narHash": "sha256-2PcNyNqbGCWBpAMdCU1HxSQmhQiG6evdjxVnPA7w5bQ=",
"ref": "refs/heads/main",
"rev": "7218348163fd8d84df4a6f682c634793e67a3fed",
"revCount": 13,
"rev": "2406de41ce9d0a1404cbf4e55537e3f720f37f23",
"revCount": 15,
"type": "git",
"url": "https://git.pvv.ntnu.no/Projects/libdib.git"
},
@@ -189,16 +189,16 @@
]
},
"locked": {
"lastModified": 1764844095,
"narHash": "sha256-Drf1orxsmFDzO+UbPo85gHjXW7QzAM+6oTPvI7vOSik=",
"lastModified": 1782122067,
"narHash": "sha256-95q3DiYOTHjQGbqR0I1w4ETrH+smtddqW0bBxaB/Egg=",
"owner": "dali99",
"repo": "nixos-matrix-modules",
"rev": "25b9f31ef1dbc3987b4c716de716239f2b283701",
"rev": "0e0fd9f6a407b08dd5e180a2ff6c3808461e2c47",
"type": "github"
},
"original": {
"owner": "dali99",
"ref": "v0.8.0",
"ref": "master",
"repo": "nixos-matrix-modules",
"type": "github"
}
@@ -291,11 +291,11 @@
},
"nixpkgs": {
"locked": {
"lastModified": 1779622335,
"narHash": "sha256-06G98ieM6l+OI7EMhlvchgDBDn+DvIWCNj40LDhKpmc=",
"rev": "705e9929918b43bd7b715dc0a878ac870449bb03",
"lastModified": 1782708249,
"narHash": "sha256-ASIzbiHLqFDHfomCJVMDaW1rsD9IJQ/m997Tw8569tM=",
"rev": "68d68014342a18d2514d6e6f1185cfc24d02fc00",
"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": {
"type": "tarball",
@@ -319,11 +319,11 @@
},
"nixpkgs-unstable": {
"locked": {
"lastModified": 1778586796,
"narHash": "sha256-XmDljcG4x8slQDlsWOc77pCA1YVuYn8JGumkYlhfTxI=",
"rev": "b25e938b89759b5f9466fc53c4a970244f84dc39",
"lastModified": 1782731455,
"narHash": "sha256-vFMOLxoARiCUBQOysAAJ0VmPzilmHUqk3EZfSRweKN8=",
"rev": "9c4c05a947a91dc14625265fab505fb695e93218",
"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": {
"type": "tarball",
@@ -379,11 +379,11 @@
]
},
"locked": {
"lastModified": 1781362709,
"narHash": "sha256-zTzLvvtRdOKKcQMWydoZuduj9fwwkYRfB1RBzKegwHM=",
"lastModified": 1782759909,
"narHash": "sha256-gktjBeZyoRvVBkm2cO1tD99fdQ34iUDyB6iecRdorm4=",
"ref": "main",
"rev": "5fb08a462263e5a8d742ecd93e559e534d5c3af2",
"revCount": 586,
"rev": "ad6c79fb713884a4a2df8aab30914cd0c1c2e6cb",
"revCount": 587,
"type": "git",
"url": "https://git.pvv.ntnu.no/Projects/nettsiden.git"
},
@@ -447,17 +447,17 @@
"rust-overlay": "rust-overlay_4"
},
"locked": {
"lastModified": 1778600367,
"narHash": "sha256-YB0b2xUf4D8792D5Ay//7C3AjHyv+9yoy8K1mTe+wvE=",
"lastModified": 1782275838,
"narHash": "sha256-CW84hEFcypvEegQp+4zZZ4lCnPT7Qn27OpKiQBxiWS8=",
"ref": "main",
"rev": "8e5f2849ff7c9616100fe928261512a7ad647939",
"revCount": 91,
"rev": "71d2b72c34352a79dbee8ebf23ce64f39aead692",
"revCount": 102,
"type": "git",
"url": "https://git.pvv.ntnu.no/Projects/roowho2.git"
},
"original": {
"ref": "main",
"rev": "8e5f2849ff7c9616100fe928261512a7ad647939",
"rev": "71d2b72c34352a79dbee8ebf23ce64f39aead692",
"type": "git",
"url": "https://git.pvv.ntnu.no/Projects/roowho2.git"
}
@@ -491,11 +491,11 @@
]
},
"locked": {
"lastModified": 1777000482,
"narHash": "sha256-CZ5FKUSA8FCJf0h9GWdPJXoVVDL9H5yC74GkVc5ubIM=",
"lastModified": 1779333539,
"narHash": "sha256-lpmN2lrBDZDPjov2cbD3bOOJsI0fkKolKXasYPCqSys=",
"owner": "oxalica",
"repo": "rust-overlay",
"rev": "403c09094a877e6c4816462d00b1a56ff8198e06",
"rev": "672fa5fc5608d5cd82286a6f69aaf84a40b4fe41",
"type": "github"
},
"original": {
@@ -553,11 +553,11 @@
]
},
"locked": {
"lastModified": 1777944972,
"narHash": "sha256-VfGRo1qTBKOe3s2gOv8LSoA6Fk19PvBlwQ1ECN0Evn8=",
"lastModified": 1782165805,
"narHash": "sha256-478kKQBvK6SYTOdN2h9jhKJv94nbXRbFMfuL1WshErg=",
"owner": "Mic92",
"repo": "sops-nix",
"rev": "c591bf665727040c6cc5cb409079acb22dcce33c",
"rev": "56b24064fdcaedca53553b1a6d607fd23b613a24",
"type": "github"
},
"original": {
@@ -575,11 +575,11 @@
]
},
"locked": {
"lastModified": 1773932847,
"narHash": "sha256-IklIAdlonrmO8/lkDxNIVz9+ORL4pcVotMTxeyvxzoc=",
"lastModified": 1780762731,
"narHash": "sha256-EuDaLnasWN0mpi995n+fAQQfPGBhqNW4fNjlQRpHt58=",
"ref": "main",
"rev": "0871a319f51d3cb0d1abb5b11edb768b39906d3f",
"revCount": 104,
"rev": "931bd2d63e285e767c8c81c103dda3c0a63f2965",
"revCount": 108,
"type": "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.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";
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.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";
greg-ng.url = "git+https://git.pvv.ntnu.no/Grzegorz/greg-ng.git?ref=main";
@@ -369,7 +369,12 @@
//
# Machines
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
(let
@@ -16,6 +16,7 @@
fileSystems."/" =
{ device = "/dev/sda1";
fsType = "btrfs";
options = [ "relatime" ];
};
fileSystems."/boot" =
+1 -1
View File
@@ -74,7 +74,7 @@ in {
name = "psycopg2";
args = {
host = "/var/run/postgresql";
dbname = "synapse";
database = "synapse";
user = "matrix-synapse";
cp_min = 1;
cp_max = 5;
+1 -1
View File
@@ -43,7 +43,7 @@ in
sshCommand = ''${pkgs.openssh}/bin/ssh -o UserKnownHostsFile='${knownHostsFile}' -i \"$CREDENTIALS_DIRECTORY\"/sshkey'';
in [
"${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.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."/" =
{ device = "/dev/disk/by-uuid/4e8667f8-55de-4103-8369-b94665f42204";
fsType = "ext4";
options = [ "relatime" ];
};
fileSystems."/boot" =
+1
View File
@@ -16,6 +16,7 @@
fileSystems."/" =
{ device = "/dev/disk/by-uuid/33825f0d-5a63-40fc-83db-bfa1ebb72ba0";
fsType = "ext4";
options = [ "relatime" ];
};
fileSystems."/boot" =
@@ -28,6 +28,7 @@
fileSystems."/" = {
device = "/dev/mapper/pool-root";
fsType = "ext4";
options = [ "relatime" ];
};
fileSystems."/boot" = {
+2 -2
View File
@@ -93,7 +93,7 @@ in {
no-group = true;
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
rsyncArgs = lib.cli.toCommandLineShellGNU { } {
archive = true;
@@ -103,7 +103,7 @@ in {
no-group = true;
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 = [
"sshkey:${config.sops.secrets."bluemap/ssh-key".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
cfg = config.services.loki;
@@ -9,8 +9,8 @@ in {
configuration = {
auth_enabled = false;
server = {
http_listen_port = 3100;
http_listen_address = "0.0.0.0";
http_listen_port = 31832;
http_listen_address = "127.0.0.1";
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;
'';
};
};
};
}
+1
View File
@@ -48,6 +48,7 @@
# swap.swapfile.size = "4G";
mountpoint = "/";
mountOptions = [ "relatime" ];
};
};
+1 -1
View File
@@ -136,7 +136,7 @@ in {
picture = {
AVATAR_MAX_FILE_SIZE = 1024 * 1024 * 5;
# 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;
webhook.ALLOWED_HOST_LIST = lib.concatStringsSep "," [
+52 -3
View File
@@ -5,6 +5,8 @@
(fp /base)
./services/gitea-runner.nix
] ++ lib.optionals (lupineName == "lupine-5") [
./services/openvpn.nix
];
sops.defaultSopsFile = fp /secrets/lupine/lupine.yaml;
@@ -15,14 +17,61 @@
"i686-linux"
];
systemd.network.networks."30-enp0s31f6" = values.defaultNetworkConfig // {
systemd.network = if (lupineName != "lupine-5")
then {
networks."30-enp0s31f6" = (values.defaultNetworkConfig // {
matchConfig.Name = "enp0s31f6";
address = with values.hosts.${lupineName}; [ (ipv4 + "/25") (ipv6 + "/64") ];
networkConfig.LLDP = false;
};
systemd.network.wait-online = {
});
wait-online = {
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.
# 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."/" =
{ device = "/dev/disk/by-uuid/224c45db-9fdc-45d4-b3ad-aaf20b3efa8a";
fsType = "ext4";
options = [ "relatime" ];
};
fileSystems."/boot" =
+1
View File
@@ -31,6 +31,7 @@
type = "filesystem";
format = "ext4";
mountpoint = "/";
mountOptions = [ "relatime" ];
};
};
};
+1
View File
@@ -16,6 +16,7 @@
fileSystems."/" =
{ device = "/dev/disk/by-uuid/c3aed415-0054-4ac5-8d29-75a99cc26451";
fsType = "btrfs";
options = [ "relatime" ];
};
fileSystems."/boot" =
+61 -2
View File
@@ -1,4 +1,4 @@
{ lib, values, ... }:
{ lib, pkgs, values, ... }:
let
# See microbel:/etc/exports
letters = [ "a" "b" "c" "d" "h" "i" "j" "k" "l" "m" "z" ];
@@ -6,6 +6,20 @@ in
{
systemd.targets."pvv-homedirs" = {
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: {
@@ -17,7 +31,7 @@ in
type = "nfs";
what = "homepvv${l}.pvv.ntnu.no:/export/home/pvv/${l}";
where = "/run/pvv-home-mounts/${l}";
where = "/run/pvvhome/${l}";
options = lib.concatStringsSep "," [
"nfsvers=3"
@@ -54,4 +68,49 @@ in
"rw"
];
}) 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 -468
View File
@@ -1,473 +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 = [
./httpd.nix
./log-processor.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
<FilesMatch ".+\.ph(p[3457]?|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>
'';
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 "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 = lib.mapCartesianProduct ({ directoryFn, letter }: "/run/pvv-home-mounts/${letter}:${directoryFn letter}${letter}") {
directoryFn = [
(_: "/home/pvv/")
(l: "/amd/homepvv${l}/")
];
letter = 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 = {
User = "nullmailer-user";
Group = "nullmailer-user";
Slice = "system-userweb.slice";
ReadWritePaths = [
"/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."/" =
{ device = "/dev/disk/by-uuid/4e8ecdd2-d453-4fff-b952-f06da00f3b85";
fsType = "ext4";
options = [ "relatime" ];
};
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-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]
openvpn:
ca:
key: ENC[AES256_GCM,data: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,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: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,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:
age:
- recipient: age18lta9d683yekz487xwtd99da236d8mgk4ftlmv2jffx858p9qf2s9j868l
enc: |
- enc: |
-----BEGIN AGE ENCRYPTED FILE-----
YWdlLWVuY3J5cHRpb24ub3JnL3YxCi0+IFgyNTUxOSBJRDdtTmdvRDRPaU53Mjd3
S25SeU5rUnZibmh2Y01HZUVhZjVWUVBJVXlvCm1uaURNYURGRUhhc25vSmFodEJC
@@ -16,8 +26,8 @@ sops:
VU5jeTBFcGYvNE9tVUVuNmV5WjMycjgKF9GIvJTczigKH+dbTAOHK0S966/QE/7M
HtgdJi9roiyDwI9k56r35/MP3eURffXBWTmc8WZRHTxnhzo1GBpg0A==
-----END AGE ENCRYPTED FILE-----
- recipient: age1e0a4ru707v637wzmuxqv0xywmlkhunzgyfy4mrkjc7a23qq8msgq7nqtvt
enc: |
recipient: age18lta9d683yekz487xwtd99da236d8mgk4ftlmv2jffx858p9qf2s9j868l
- enc: |
-----BEGIN AGE ENCRYPTED FILE-----
YWdlLWVuY3J5cHRpb24ub3JnL3YxCi0+IFgyNTUxOSBqMGtpL3JJaDN2Qm95b1cz
VEF2bHU3VjJLNUQya25lL01qYkFreFpTVGdBCkdHdnBUUjlXOU4yTkE5ZTF2OFll
@@ -25,8 +35,8 @@ sops:
VDcvTUY5YVEvOWFQOG5ULzFlQU9IMTAKQ601N8YNayuYrkZqqsKqlsnHN4rSMzN1
sesAmJVuj7ZddGQlzIJC9cydXkssmY5oDIj92J7DXTzhFQlO0o9tfA==
-----END AGE ENCRYPTED FILE-----
- recipient: age1wmrrhd5deatmgflkas636u3rzuk46u9knl02v4t39ncs37xqquhq9vwzye
enc: |
recipient: age1e0a4ru707v637wzmuxqv0xywmlkhunzgyfy4mrkjc7a23qq8msgq7nqtvt
- enc: |
-----BEGIN AGE ENCRYPTED FILE-----
YWdlLWVuY3J5cHRpb24ub3JnL3YxCi0+IFgyNTUxOSB5ZFV6cWN3OEloVmIrWG9Z
U0RxNVF0RlJ6UDNMK0psQjVKUkJiR0JUMWxBCll3NHpFempRcCtSYUQzWi9kclFP
@@ -34,8 +44,8 @@ sops:
SllNcDVzSE4wTTB5NTNTYXJoemlIMUEKbJwinjEIjgwlShvUr+Jcfay0ha8Ndo6L
KM0QvKlcsx5Z6pqyYt6TvnlhyhcljN1IFfoUO5r3E9lYSyanv3HJRA==
-----END AGE ENCRYPTED FILE-----
- recipient: age1ml48zztcmnrdrhrdsjrlyxf09jtmjgz46u8td4zm59wn3fm4g57qs4wg0l
enc: |
recipient: age1wmrrhd5deatmgflkas636u3rzuk46u9knl02v4t39ncs37xqquhq9vwzye
- enc: |
-----BEGIN AGE ENCRYPTED FILE-----
YWdlLWVuY3J5cHRpb24ub3JnL3YxCi0+IFgyNTUxOSA3SG15dS9JNmRETjBZL001
VnNSN1o1ZENwdStLdnMxaGp2OVg4WFVUWmpvClJESk9KVi8rdkU5Q0ZHSnhOell2
@@ -43,8 +53,8 @@ sops:
THhnZWZNckdTOXNpSjVDUEFWQW8rOE0K5ts7BAbcZ7L3cId+jjbC8ZDOnCEAjFW7
lizGlAPolgH6uNpPczneeFBczfU8nnWOcJTpPXQDxXiWv7y0aemJRQ==
-----END AGE ENCRYPTED FILE-----
- recipient: age12gws5nws69vxryd3kt7q0ayngch90efmhqcrfhnnsmj00lkgxd4qsdkvqn
enc: |
recipient: age1ml48zztcmnrdrhrdsjrlyxf09jtmjgz46u8td4zm59wn3fm4g57qs4wg0l
- enc: |
-----BEGIN AGE ENCRYPTED FILE-----
YWdlLWVuY3J5cHRpb24ub3JnL3YxCi0+IFgyNTUxOSBLQUEwa0cvcndUbnlpTlYr
ZUtEdlRKcmlrQU1USlZVeXNXejhBSUdLdGxNCmpzRHpoM1VNemo5angweW9QMGJ2
@@ -52,8 +62,8 @@ sops:
Q1p0b2dJMXNhRFdYdHV3UFhUQzVmQVEK/3E/fDJcuwN8UJq05Dg0YLHhFRLjl4i7
98dDpycvPV8Py82q4pNpvI+goZ2T19QcxArSLNLQwd3TqIYvLHB+FA==
-----END AGE ENCRYPTED FILE-----
- recipient: age1ug30gg4y7ftuya0wdv7q0vh4egn00wlv2th7mt7cgc2ze46wmvyq9lq6ge
enc: |
recipient: age12gws5nws69vxryd3kt7q0ayngch90efmhqcrfhnnsmj00lkgxd4qsdkvqn
- enc: |
-----BEGIN AGE ENCRYPTED FILE-----
YWdlLWVuY3J5cHRpb24ub3JnL3YxCi0+IFgyNTUxOSAxOEhSZzhkZ25rL1dZVlRw
R0JMaUR2VXQ5cnYvdjRwQjU5VWYwcGRYbUMwClVBYi9nOHZkejBxamxKeHJSZmFC
@@ -61,8 +71,8 @@ sops:
TGpFN2xCTWcybnBBL0o2MVFoQzNRMkEKtprwI3p45huVaLJvqTNLU1k17uSObJaA
QEL/qzgLr//fSxiMQfJRtvqpcGuL/kTnmU56tJdLVCDAfFvW0OH9gQ==
-----END AGE ENCRYPTED FILE-----
- recipient: age1mrnldl334l2nszuta6ywvewng0fswv2dz9l5g4qcwe3nj4yxf92qjskdx6
enc: |
recipient: age1ug30gg4y7ftuya0wdv7q0vh4egn00wlv2th7mt7cgc2ze46wmvyq9lq6ge
- enc: |
-----BEGIN AGE ENCRYPTED FILE-----
YWdlLWVuY3J5cHRpb24ub3JnL3YxCi0+IFgyNTUxOSBZTWVYY3hPMi85QjhYQWlW
R0s0bnVpNEFmalFBS3lISmtWanNPcEpPRlF3CjY2TnliWGJocWtkbjZZQUpPZ3dS
@@ -70,8 +80,8 @@ sops:
a3hmLzNiY2ZQdk5TQzExOGJPeTd0U0kKVqulWO1BniSTpYHa7fYwG0oj+hq+clGq
/XlvYUYNIApaAid3G9LrZNL7g3mhq1ANuDGMY7n0Z6/xhysTZwRzEQ==
-----END AGE ENCRYPTED FILE-----
- recipient: age1hmpdk4h69wxpwqk9tkud39f66hprhehxtzhgw97r6dvr7v0mx5jscsuhkn
enc: |
recipient: age1mrnldl334l2nszuta6ywvewng0fswv2dz9l5g4qcwe3nj4yxf92qjskdx6
- enc: |
-----BEGIN AGE ENCRYPTED FILE-----
YWdlLWVuY3J5cHRpb24ub3JnL3YxCi0+IFgyNTUxOSBsNkM5ZjRIK2FKL1B3S0tl
ZUdzMC9ONStkYnZZRm1VQy9FMVJkNk9SY1IwCnJFTVRTL1FkRlAySmF1ZDdBVUxz
@@ -79,8 +89,8 @@ sops:
cDdvRVl6a3VhZXhwUkl6eHo0OGxxUDQK5/Z3OCFIb4HOBBxHj0B7a0AuPXgPbuh5
TPGvfJpa3Ow/eJSpEdXOm6chTrvPsgGHKYZS75SAgHMP8SHHIPuxuQ==
-----END AGE ENCRYPTED FILE-----
- recipient: age1wrssr4z4g6vl3fd3qme5cewchmmhm0j2xe6wf2meu4r6ycn37anse98mfs
enc: |
recipient: age1hmpdk4h69wxpwqk9tkud39f66hprhehxtzhgw97r6dvr7v0mx5jscsuhkn
- enc: |
-----BEGIN AGE ENCRYPTED FILE-----
YWdlLWVuY3J5cHRpb24ub3JnL3YxCi0+IFgyNTUxOSBzVXhHTE83aDFvN3U3Tncz
TzlYSVB1NzdvQVY5bU1yZTRhU0V1bXgyZ21RCm1WekpqcHE3cG5sRkM4Z2k4UzFK
@@ -88,8 +98,8 @@ sops:
bHpyUUM4NlN3VDhVYVhFNVYyeElqVDQKm44tte4aQ5/0XVMd7IvnahRxdrSePHKn
f6EUC0tBdSAifbe8JdCvTz2DDbUbXRxDxZCJ35ATyB0K1AEgcVEVvA==
-----END AGE ENCRYPTED FILE-----
- recipient: age1zhxul786an743u0fascv4wtc5xduu7qfy803lfs539yzhgmlq5ds2lznt5
enc: |
recipient: age1wrssr4z4g6vl3fd3qme5cewchmmhm0j2xe6wf2meu4r6ycn37anse98mfs
- enc: |
-----BEGIN AGE ENCRYPTED FILE-----
YWdlLWVuY3J5cHRpb24ub3JnL3YxCi0+IFgyNTUxOSA3VTZXR2hZT2FERFNhNXVs
MkREdWxxNWNvZy9jRkp0d2YwNm5IRDY3Zm44CjZ0SC9NWE40TmFtR2NSMUZtMmV2
@@ -97,8 +107,8 @@ sops:
Q2VuWG8yOE1ob1Ayd2Z6NllhNnMxK2MK1BzxHusN/Ad0+2ExwK/q8qyPObDL+112
o5/LeOh2vA3KQOG7QmlfhOK8NEID2dcWXoK3Kg8H24rowZq+WQryqg==
-----END AGE ENCRYPTED FILE-----
- recipient: age1sqs7urnzsdy64efmd0zukzv3gs5pnjksuxd7nqmdwdy5l0nqnunq6hyune
enc: |
recipient: age1zhxul786an743u0fascv4wtc5xduu7qfy803lfs539yzhgmlq5ds2lznt5
- enc: |
-----BEGIN AGE ENCRYPTED FILE-----
YWdlLWVuY3J5cHRpb24ub3JnL3YxCi0+IFgyNTUxOSBXblVrSXJjVUVtaWltVzQy
OGFDR05TNTJEY2M3dUQ5bEtnaVF2dnd3VVdjCmFlL3MwVEFrYml5UE54U3Z5bUNU
@@ -106,8 +116,9 @@ sops:
MTc3MVhaU0s5anZPdUg4RlFiZmU4MHcKepCAfP8iMOJ39LL4S8XA18pXAYZgcdLO
xNV7kAcdXpywk/ffnWAukwI32LegGQ+efNtysCeESNKomSDtXKtm6Q==
-----END AGE ENCRYPTED FILE-----
lastmodified: "2025-12-04T05:53:51Z"
mac: ENC[AES256_GCM,data:o55keAaJEXVOAGvoMp8FWvtlxMgfF/qR50FGnNM1whYz+5+naRJ1dAOW9NKYHWbtOa/ZXEMTkjoFrTJidAaIXza1Ot8llbTGYh56fsnu0FKZfVM+rvecRDhXKWxiAqyiLUvtUfA2fSg9LGveh2U+0dulcU25sb3Wf0RcFrtM3xI=,iv:3/UllekmGIaluv8y8I6Azd/52dJzk+C5ah6XLJj7Zik=,tag:T5ILXiC5hK++0jGOnHCMYA==,type:str]
recipient: age1sqs7urnzsdy64efmd0zukzv3gs5pnjksuxd7nqmdwdy5l0nqnunq6hyune
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:
- created_at: "2026-04-18T16:25:16Z"
enc: |-
@@ -130,4 +141,4 @@ sops:
-----END PGP MESSAGE-----
fp: F7D37890228A907440E1FD4846B9228E814A2AAC
unencrypted_suffix: _unencrypted
version: 3.11.0
version: 3.13.1
+4
View File
@@ -26,6 +26,10 @@ in rec {
ipv4 = pvv-ipv4 213;
ipv6 = pvv-ipv6 213;
};
knutsen-vpn = pvv-ipv4 191;
knutsen-tap = pvv-ipv4 253;
ludvigsen-tap = pvv-ipv4 254;
};
hosts = {