Compare commits

...

26 Commits

Author SHA1 Message Date
h7x4
e9c82b4625 kommode/gitea: add robots.txt 2026-01-29 13:09:36 +09:00
h7x4
49d1122ee5 bicep/mysql: enable slow query logs 2026-01-28 14:55:52 +09:00
h7x4
31bbf4b25f bicep/synapse: enable auto-compressor timer 2026-01-28 14:50:57 +09:00
h7x4
2f7e1439d0 bicep/mysql: pin version, upgrade from 11.4 -> 11.8 2026-01-28 14:01:14 +09:00
h7x4
fa31a84bd2 bicep/postgres: upgrade from 15 -> 18 2026-01-28 14:00:25 +09:00
h7x4
b77c8eb5c0 modules/rsync-pull-targets: fix multiple pull targets with same user 2026-01-27 21:10:17 +09:00
h7x4
949661113e bicep/mysql: move backup dir 2026-01-27 20:47:40 +09:00
h7x4
f442c4d65f bicep/minecraft-heatmap: gate remaining config behind cfg.enable 2026-01-27 20:44:20 +09:00
h7x4
690aee634b bicep/postgres: gate remaining config behind cfg.enable 2026-01-27 20:44:20 +09:00
h7x4
2ed1c83858 bicep/{postgres,mysql}: add rsync pull targets for backups 2026-01-27 20:39:12 +09:00
h7x4
d43de08a3b flake.lock: bump 2026-01-27 19:44:45 +09:00
h7x4
e8c7f177e8 kommode: use disko to configure disks 2026-01-27 19:00:12 +09:00
h7x4
fb59a242fb kommode/gitea: add rsync pull target for gitea dump dir 2026-01-27 18:55:25 +09:00
h7x4
65d095feb1 bekkalokk/mediawiki, bicep/matrix/synapse: add keys for rsync targets 2026-01-27 18:55:03 +09:00
h7x4
8273d98788 flake.nix: add disko to default devshell 2026-01-27 18:35:18 +09:00
h7x4
8a84069dcf bicep/mysql: use BindPaths to access dataDir 2026-01-27 17:23:38 +09:00
h7x4
cda84be5b0 bekkalokk/well-known: add note about bug bounty program to security.txt 2026-01-27 17:11:07 +09:00
h7x4
79a46ce3f6 bicep/element: set default country code 2026-01-27 04:11:40 +09:00
h7x4
19e45be83a .mailmap: further dedup 2026-01-27 04:07:25 +09:00
h7x4
a8892e2fb2 hosts/various: bump stateVersion 2026-01-27 04:00:48 +09:00
h7x4
a149f97ac0 bicep: bump stateVersion from 22.11 -> 25.11 2026-01-27 03:59:40 +09:00
h7x4
e76c656378 bekkalokk: bump stateVersion from 22.11 -> 25.11 2026-01-27 03:52:34 +09:00
h7x4
5877ef60b1 modules/rsync-pull-targets: leave TODO about assertion 2026-01-27 00:27:00 +09:00
h7x4
73456de527 bekkalokk/mediawiki, bicep/matrix/synapse: leave principal rsync target stubs 2026-01-27 00:26:42 +09:00
h7x4
2f8e9ea190 modules/rsync-pull-targets: init, migrate bekkalokk/website/fetch-gallery 2026-01-26 23:57:20 +09:00
h7x4
c3c98392ad bicep/hookshot: add passkey to sops 2026-01-26 21:52:58 +09:00
27 changed files with 627 additions and 103 deletions

View File

@@ -23,3 +23,9 @@ Adrian Gunnar Lauterer <adriangl@pvv.ntnu.no> Adrian Gunnar Lauterer <adrian@lau
Fredrik Robertsen <frero@pvv.ntnu.no> frero <frero@pvv.ntnu.no> Fredrik Robertsen <frero@pvv.ntnu.no> frero <frero@pvv.ntnu.no>
Fredrik Robertsen <frero@pvv.ntnu.no> fredrikr79 <fredrikrobertsen7@gmail.com> Fredrik Robertsen <frero@pvv.ntnu.no> fredrikr79 <fredrikrobertsen7@gmail.com>
Fredrik Robertsen <frero@pvv.ntnu.no> fredrik <fredrikr79@pm.me>
Vegard Bieker Matthey <vegardbm@pvv.ntnu.no> Vegard Matthey <VegardMatthey@protonmail.com>
Vegard Bieker Matthey <vegardbm@pvv.ntnu.no> Vegard Bieker Matthey <VegardMatthey@protonmail.com>
Albert Bayazidi <albertba@pvv.ntnu.no> Albert <albert.bayazidi@gmail.com>

66
flake.lock generated
View File

@@ -7,11 +7,11 @@
] ]
}, },
"locked": { "locked": {
"lastModified": 1769400154, "lastModified": 1769510541,
"narHash": "sha256-K0OeXzFCUZTkCBxUDr3U3ah0odS/urtNVG09WDl+HAA=", "narHash": "sha256-jxuQY0anT3YpwpnYB5w7p6EPS6UWIj4vGxzfsOJvC1I=",
"ref": "main", "ref": "main",
"rev": "8e84669d9bf963d5e46bac37fe9b0aa8e8be2d01", "rev": "ec43f67e58f049a709fa2c19601b8c637f38126f",
"revCount": 230, "revCount": 232,
"type": "git", "type": "git",
"url": "https://git.pvv.ntnu.no/Projects/dibbler.git" "url": "https://git.pvv.ntnu.no/Projects/dibbler.git"
}, },
@@ -174,11 +174,11 @@
] ]
}, },
"locked": { "locked": {
"lastModified": 1768749374, "lastModified": 1769500363,
"narHash": "sha256-dhXYLc64d7TKCnRPW4TlHGl6nLRNdabJB2DpJ8ffUw0=", "narHash": "sha256-vFxmdsLBPdTy5j2bf54gbTQi1XnWbZDmeR/BBh8MFrw=",
"ref": "main", "ref": "main",
"rev": "040294f2e1df46e33d995add6944b25859654097", "rev": "2618e434e40e109eaab6a0693313c7e0de7324a3",
"revCount": 37, "revCount": 47,
"type": "git", "type": "git",
"url": "https://git.pvv.ntnu.no/Projects/minecraft-kartverket.git" "url": "https://git.pvv.ntnu.no/Projects/minecraft-kartverket.git"
}, },
@@ -217,11 +217,11 @@
] ]
}, },
"locked": { "locked": {
"lastModified": 1768955766, "lastModified": 1769018862,
"narHash": "sha256-V9ns1OII7sWSbIDwPkiqmJ3Xu/bHgQzj+asgH9cTpOo=", "narHash": "sha256-x3eMpPQhZwEDunyaUos084Hx41XwYTi2uHY4Yc4YNlk=",
"owner": "oddlama", "owner": "oddlama",
"repo": "nix-topology", "repo": "nix-topology",
"rev": "71f27de56a03f6d8a1a72cf4d0dfd780bcc075bc", "rev": "a15cac71d3399a4c2d1a3482ae62040a3a0aa07f",
"type": "github" "type": "github"
}, },
"original": { "original": {
@@ -233,11 +233,11 @@
}, },
"nixpkgs": { "nixpkgs": {
"locked": { "locked": {
"lastModified": 1768877948, "lastModified": 1769484787,
"narHash": "sha256-Bq9Hd6DWCBaZ2GkwvJCWGnpGOchaD6RWPSCFxmSmupw=", "narHash": "sha256-ufhG9uSA8cCEk/97D/7xQEKcO/ftr4IPRH+HQFaKNdE=",
"rev": "43b2e61c9d09cf6c1c9c192fe6da08accc9bfb1d", "rev": "999ca0e5484922624254294ea1adc2b90081579e",
"type": "tarball", "type": "tarball",
"url": "https://releases.nixos.org/nixos/25.11-small/nixos-25.11.4368.43b2e61c9d09/nixexprs.tar.xz" "url": "https://releases.nixos.org/nixos/25.11-small/nixos-25.11.4804.999ca0e54849/nixexprs.tar.xz"
}, },
"original": { "original": {
"type": "tarball", "type": "tarball",
@@ -261,11 +261,11 @@
}, },
"nixpkgs-unstable": { "nixpkgs-unstable": {
"locked": { "locked": {
"lastModified": 1768886240, "lastModified": 1769434638,
"narHash": "sha256-HUAAI7AF+/Ov1u3Vvjs4DL91zTxMkWLC4xJgQ9QxOUQ=", "narHash": "sha256-u19M4QdjvjEySkGhP4fUNyY6rqAbPCdQf/AFw04CkQU=",
"rev": "80e4adbcf8992d3fd27ad4964fbb84907f9478b0", "rev": "9c2822d7024c032e66000a8b8a47e91b4e63ffc8",
"type": "tarball", "type": "tarball",
"url": "https://releases.nixos.org/nixos/unstable-small/nixos-26.05pre930839.80e4adbcf899/nixexprs.tar.xz" "url": "https://releases.nixos.org/nixos/unstable-small/nixos-26.05pre935000.9c2822d7024c/nixexprs.tar.xz"
}, },
"original": { "original": {
"type": "tarball", "type": "tarball",
@@ -300,11 +300,11 @@
] ]
}, },
"locked": { "locked": {
"lastModified": 1768636400, "lastModified": 1769009806,
"narHash": "sha256-AiSKT4/25LS1rUlPduBMogf4EbdMQYDY1rS7AvHFcxk=", "narHash": "sha256-52xTtAOc9B+MBRMRZ8HI6ybNsRLMlHHLh+qwAbaJjRY=",
"ref": "main", "ref": "main",
"rev": "3a8f82b12a44e6c4ceacd6955a290a52d1ee2856", "rev": "aa8adfc6a4d5b6222752e2d15d4a6d3b3b85252e",
"revCount": 573, "revCount": 575,
"type": "git", "type": "git",
"url": "https://git.pvv.ntnu.no/Projects/nettsiden.git" "url": "https://git.pvv.ntnu.no/Projects/nettsiden.git"
}, },
@@ -364,11 +364,11 @@
"rust-overlay": "rust-overlay_3" "rust-overlay": "rust-overlay_3"
}, },
"locked": { "locked": {
"lastModified": 1768140181, "lastModified": 1769325266,
"narHash": "sha256-HfZzup5/jlu8X5vMUglTovVTSwhHGHwwV1YOFIL/ksA=", "narHash": "sha256-q2G2NG7I1tvfFK4GDnn3vt1CCg0GN4ncdo0NSY+Q2Nc=",
"ref": "main", "ref": "main",
"rev": "834463ed64773939798589ee6fd4adfe3a97dddd", "rev": "23b163e828901cb981eec6f3262e922f437f850b",
"revCount": 43, "revCount": 45,
"type": "git", "type": "git",
"url": "https://git.pvv.ntnu.no/Projects/roowho2.git" "url": "https://git.pvv.ntnu.no/Projects/roowho2.git"
}, },
@@ -428,11 +428,11 @@
] ]
}, },
"locked": { "locked": {
"lastModified": 1767322002, "lastModified": 1769309768,
"narHash": "sha256-yHKXXw2OWfIFsyTjduB4EyFwR0SYYF0hK8xI9z4NIn0=", "narHash": "sha256-AbOIlNO+JoqRJkK1VrnDXhxuX6CrdtIu2hSuy4pxi3g=",
"owner": "oxalica", "owner": "oxalica",
"repo": "rust-overlay", "repo": "rust-overlay",
"rev": "03c6e38661c02a27ca006a284813afdc461e9f7e", "rev": "140c9dc582cb73ada2d63a2180524fcaa744fad5",
"type": "github" "type": "github"
}, },
"original": { "original": {
@@ -448,11 +448,11 @@
] ]
}, },
"locked": { "locked": {
"lastModified": 1768863606, "lastModified": 1769469829,
"narHash": "sha256-1IHAeS8WtBiEo5XiyJBHOXMzECD6aaIOJmpQKzRRl64=", "narHash": "sha256-wFcr32ZqspCxk4+FvIxIL0AZktRs6DuF8oOsLt59YBU=",
"owner": "Mic92", "owner": "Mic92",
"repo": "sops-nix", "repo": "sops-nix",
"rev": "c7067be8db2c09ab1884de67ef6c4f693973f4a2", "rev": "c5eebd4eb2e3372fe12a8d70a248a6ee9dd02eff",
"type": "github" "type": "github"
}, },
"original": { "original": {

View File

@@ -129,6 +129,7 @@
] ++ (lib.optionals enableDefaults [ ] ++ (lib.optionals enableDefaults [
sops-nix.nixosModules.sops sops-nix.nixosModules.sops
inputs.roowho2.nixosModules.default inputs.roowho2.nixosModules.default
self.nixosModules.rsync-pull-targets
]) ++ modules; ]) ++ modules;
} }
(builtins.removeAttrs extraArgs [ (builtins.removeAttrs extraArgs [
@@ -146,7 +147,7 @@
in { in {
bakke = stableNixosConfig "bakke" { bakke = stableNixosConfig "bakke" {
modules = [ modules = [
disko.nixosModules.disko inputs.disko.nixosModules.disko
]; ];
}; };
bicep = stableNixosConfig "bicep" { bicep = stableNixosConfig "bicep" {
@@ -194,6 +195,8 @@
]; ];
modules = [ modules = [
inputs.nix-gitea-themes.nixosModules.default inputs.nix-gitea-themes.nixosModules.default
inputs.disko.nixosModules.disko
self.nixosModules.robots-txt
]; ];
}; };
@@ -270,15 +273,25 @@
nixosModules = { nixosModules = {
bluemap = ./modules/bluemap.nix; bluemap = ./modules/bluemap.nix;
snakeoil-certs = ./modules/snakeoil-certs.nix;
snappymail = ./modules/snappymail.nix;
robots-txt = ./modules/robots-txt.nix;
gickup = ./modules/gickup; gickup = ./modules/gickup;
matrix-ooye = ./modules/matrix-ooye.nix; matrix-ooye = ./modules/matrix-ooye.nix;
robots-txt = ./modules/robots-txt.nix;
rsync-pull-targets = ./modules/rsync-pull-targets.nix;
snakeoil-certs = ./modules/snakeoil-certs.nix;
snappymail = ./modules/snappymail.nix;
}; };
devShells = forAllSystems (system: { devShells = forAllSystems (system: {
default = nixpkgs-unstable.legacyPackages.${system}.callPackage ./shell.nix { }; default = let
pkgs = import nixpkgs-unstable {
inherit system;
overlays = [
(final: prev: {
inherit (inputs.disko.packages.${system}) disko;
})
];
};
in pkgs.callPackage ./shell.nix { };
cuda = let cuda = let
cuda-pkgs = import nixpkgs-unstable { cuda-pkgs = import nixpkgs-unstable {
inherit system; inherit system;

View File

@@ -28,5 +28,5 @@
# 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
system.stateVersion = "22.11"; system.stateVersion = "25.11";
} }

View File

@@ -49,6 +49,22 @@ in {
lib.listToAttrs lib.listToAttrs
]; ];
services.rsync-pull-targets = {
enable = true;
locations.${cfg.uploadsDir} = {
user = "root";
rrsyncArgs.ro = true;
authorizedKeysAttrs = [
"restrict"
"no-agent-forwarding"
"no-port-forwarding"
"no-pty"
"no-X11-forwarding"
];
publicKey = "ssh-ed25519 AAAAC3NzaC1lZDI1NTE5AAAAICHFHa3Iq1oKPhbKCAIHgOoWOTkLmIc7yqxeTbut7ig/ mediawiki rsync backup";
};
};
services.mediawiki = { services.mediawiki = {
enable = true; enable = true;
name = "Programvareverkstedet"; name = "Programvareverkstedet";

View File

@@ -3,13 +3,21 @@ let
galleryDir = config.services.pvv-nettsiden.settings.GALLERY.DIR; galleryDir = config.services.pvv-nettsiden.settings.GALLERY.DIR;
transferDir = "${config.services.pvv-nettsiden.settings.GALLERY.DIR}-transfer"; transferDir = "${config.services.pvv-nettsiden.settings.GALLERY.DIR}-transfer";
in { in {
users.users.${config.services.pvv-nettsiden.user} = { # This is pushed from microbel:/var/www/www-gallery/build-gallery.sh
useDefaultShell = true; services.rsync-pull-targets = {
enable = true;
# This is pushed from microbel:/var/www/www-gallery/build-gallery.sh locations.${transferDir} = {
openssh.authorizedKeys.keys = [ user = config.services.pvv-nettsiden.user;
''command="${pkgs.rrsync}/bin/rrsync -wo ${transferDir}",restrict,no-agent-forwarding,no-port-forwarding,no-pty,no-X11-forwarding ssh-ed25519 AAAAC3NzaC1lZDI1NTE5AAAAIIjHhC2dikhWs/gG+m7qP1eSohWzTehn4ToNzDSOImyR gallery-publish'' rrsyncArgs.wo = true;
]; authorizedKeysAttrs = [
"restrict"
"no-agent-forwarding"
"no-port-forwarding"
"no-pty"
"no-X11-forwarding"
];
publicKey = "ssh-ed25519 AAAAC3NzaC1lZDI1NTE5AAAAIIjHhC2dikhWs/gG+m7qP1eSohWzTehn4ToNzDSOImyR gallery-publish";
};
}; };
systemd.paths.pvv-nettsiden-gallery-update = { systemd.paths.pvv-nettsiden-gallery-update = {

View File

@@ -6,7 +6,11 @@ Contact: mailto:cert@pvv.ntnu.no
Preferred-Languages: no, en Preferred-Languages: no, en
Expires: 2032-12-31T23:59:59.000Z Expires: 2032-12-31T23:59:59.000Z
# This file was last updated 2024-09-14. # This file was last updated 2026-02-27.
# You can find a wikipage for our security policies at: # You can find a wikipage for our security policies at:
# https://wiki.pvv.ntnu.no/wiki/CERT # https://wiki.pvv.ntnu.no/wiki/CERT
# Please note that we are a student organization, and unfortunately we do not
# have a bug bounty program or offer monetary compensation for disclosure of
# security vulnerabilities.

View File

@@ -30,5 +30,5 @@
# 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
system.stateVersion = "22.11"; system.stateVersion = "25.11";
} }

View File

@@ -1,8 +1,9 @@
{ config, ... }: { config, ... }:
{ {
imports = [ imports = [
./synapse.nix
./synapse-admin.nix ./synapse-admin.nix
./synapse-auto-compressor.nix
./synapse.nix
./element.nix ./element.nix
./coturn.nix ./coturn.nix
./livekit.nix ./livekit.nix

View File

@@ -37,6 +37,7 @@ in {
# element call group calls # element call group calls
feature_group_calls = true; feature_group_calls = true;
}; };
default_country_code = "NO";
default_theme = "dark"; default_theme = "dark";
# Servers in this list should provide some sort of valuable scoping # Servers in this list should provide some sort of valuable scoping
# matrix.org is not useful compared to matrixrooms.info, # matrix.org is not useful compared to matrixrooms.info,

View File

@@ -14,6 +14,10 @@ in
sopsFile = fp /secrets/bicep/matrix.yaml; sopsFile = fp /secrets/bicep/matrix.yaml;
key = "hookshot/hs_token"; key = "hookshot/hs_token";
}; };
sops.secrets."matrix/hookshot/passkey" = {
sopsFile = fp /secrets/bicep/matrix.yaml;
key = "hookshot/passkey";
};
sops.templates."hookshot-registration.yaml" = { sops.templates."hookshot-registration.yaml" = {
owner = config.users.users.matrix-synapse.name; owner = config.users.users.matrix-synapse.name;
@@ -44,9 +48,14 @@ in
}; };
systemd.services.matrix-hookshot = { systemd.services.matrix-hookshot = {
serviceConfig.SupplementaryGroups = [ serviceConfig = {
config.users.groups.keys-matrix-registrations.name SupplementaryGroups = [
]; config.users.groups.keys-matrix-registrations.name
];
LoadCredential = [
"passkey.pem:${config.sops.secrets."matrix/hookshot/passkey".path}"
];
};
}; };
services.matrix-hookshot = { services.matrix-hookshot = {
@@ -54,6 +63,8 @@ in
package = unstablePkgs.matrix-hookshot; package = unstablePkgs.matrix-hookshot;
registrationFile = config.sops.templates."hookshot-registration.yaml".path; registrationFile = config.sops.templates."hookshot-registration.yaml".path;
settings = { settings = {
passFile = "/run/credentials/matrix-hookshot.service/passkey.pem";
bridge = { bridge = {
bindAddress = "127.0.0.1"; bindAddress = "127.0.0.1";
domain = "pvv.ntnu.no"; domain = "pvv.ntnu.no";
@@ -61,6 +72,7 @@ in
mediaUrl = "https://matrix.pvv.ntnu.no"; mediaUrl = "https://matrix.pvv.ntnu.no";
port = 9993; port = 9993;
}; };
listeners = [ listeners = [
{ {
bindAddress = webhookListenAddress; bindAddress = webhookListenAddress;
@@ -73,6 +85,7 @@ in
]; ];
} }
]; ];
generic = { generic = {
enabled = true; enabled = true;
outbound = true; outbound = true;

View File

@@ -0,0 +1,56 @@
{ config, lib, utils, ... }:
let
cfg = config.services.synapse-auto-compressor;
in
{
services.synapse-auto-compressor = {
# enable = true;
postgresUrl = "postgresql://matrix-synapse@/synapse?host=/run/postgresql";
};
# NOTE: nixpkgs has some broken asserts, vendored the entire unit
systemd.services.synapse-auto-compressor = {
description = "synapse-auto-compressor";
requires = [
"postgresql.target"
];
inherit (cfg) startAt;
serviceConfig = {
Type = "oneshot";
DynamicUser = true;
User = "matrix-synapse";
PrivateTmp = true;
ExecStart = utils.escapeSystemdExecArgs [
"${cfg.package}/bin/synapse_auto_compressor"
"-p"
cfg.postgresUrl
"-c"
cfg.settings.chunk_size
"-n"
cfg.settings.chunks_to_compress
"-l"
(lib.concatStringsSep "," (map toString cfg.settings.levels))
];
LockPersonality = true;
MemoryDenyWriteExecute = true;
NoNewPrivileges = true;
PrivateDevices = true;
PrivateMounts = true;
PrivateUsers = true;
RemoveIPC = true;
RestrictNamespaces = true;
RestrictRealtime = true;
RestrictSUIDSGID = true;
ProcSubset = "pid";
ProtectProc = "invisible";
ProtectSystem = "strict";
ProtectHome = true;
ProtectHostname = true;
ProtectClock = true;
ProtectKernelTunables = true;
ProtectKernelModules = true;
ProtectKernelLogs = true;
ProtectControlGroups = true;
};
};
}

View File

@@ -27,6 +27,22 @@ in {
''; '';
}; };
services.rsync-pull-targets = {
enable = true;
locations.${cfg.settings.media_store_path} = {
user = "root";
rrsyncArgs.ro = true;
authorizedKeysAttrs = [
"restrict"
"no-agent-forwarding"
"no-port-forwarding"
"no-pty"
"no-X11-forwarding"
];
publicKey = "ssh-ed25519 AAAAC3NzaC1lZDI1NTE5AAAAIASnjI9b3j4ZS3BL/D1ggHfws1BkE8iS0v0cGpEmbG+k matrix_media_store rsync backup";
};
};
services.matrix-synapse-next = { services.matrix-synapse-next = {
enable = true; enable = true;

View File

@@ -22,7 +22,7 @@ in
}; };
}; };
systemd.services.minecraft-heatmap-ingest-logs = { systemd.services.minecraft-heatmap-ingest-logs = lib.mkIf cfg.enable {
serviceConfig.LoadCredential = [ serviceConfig.LoadCredential = [
"sshkey:${config.sops.secrets."minecraft-heatmap/ssh-key/private".path}" "sshkey:${config.sops.secrets."minecraft-heatmap/ssh-key/private".path}"
]; ];

View File

@@ -1,4 +1,8 @@
{ pkgs, lib, config, values, ... }: { config, pkgs, lib, values, ... }:
let
cfg = config.services.mysql;
dataDir = "/data/mysql";
in
{ {
sops.secrets."mysql/password" = { sops.secrets."mysql/password" = {
owner = "mysql"; owner = "mysql";
@@ -9,8 +13,7 @@
services.mysql = { services.mysql = {
enable = true; enable = true;
dataDir = "/data/mysql"; package = pkgs.mariadb_118;
package = pkgs.mariadb;
settings = { settings = {
mysqld = { mysqld = {
# PVV allows a lot of connections at the same time # PVV allows a lot of connections at the same time
@@ -21,6 +24,9 @@
# This was needed in order to be able to use all of the old users # This was needed in order to be able to use all of the old users
# during migration from knakelibrak to bicep in Sep. 2023 # during migration from knakelibrak to bicep in Sep. 2023
secure_auth = 0; secure_auth = 0;
slow-query-log = 1;
slow-query-log-file = "/var/log/mysql/mysql-slow.log";
}; };
}; };
@@ -36,20 +42,52 @@
}]; }];
}; };
services.mysqlBackup = { services.mysqlBackup = lib.mkIf cfg.enable {
enable = true; enable = true;
location = "/var/lib/mysql/backups"; location = "/var/lib/mysql-backups";
}; };
networking.firewall.allowedTCPPorts = [ 3306 ]; services.rsync-pull-targets = lib.mkIf cfg.enable {
enable = true;
locations.${config.services.mysqlBackup.location} = {
user = "root";
rrsyncArgs.ro = true;
authorizedKeysAttrs = [
"restrict"
"no-agent-forwarding"
"no-port-forwarding"
"no-pty"
"no-X11-forwarding"
];
publicKey = "ssh-ed25519 AAAAC3NzaC1lZDI1NTE5AAAAIJgj55/7Cnj4cYMJ5sIkl+OwcGeBe039kXJTOf2wvo9j mysql rsync backup";
};
};
systemd.services.mysql.serviceConfig = { networking.firewall.allowedTCPPorts = lib.mkIf cfg.enable [ 3306 ];
IPAddressDeny = "any";
IPAddressAllow = [ systemd.tmpfiles.settings."10-mysql".${dataDir}.d = lib.mkIf cfg.enable {
values.ipv4-space inherit (cfg) user group;
values.ipv6-space mode = "0700";
values.hosts.ildkule.ipv4 };
values.hosts.ildkule.ipv6
systemd.services.mysql = lib.mkIf cfg.enable {
after = [
"systemd-tmpfiles-setup.service"
"systemd-tmpfiles-resetup.service"
]; ];
serviceConfig = {
BindPaths = [ "${dataDir}:${cfg.dataDir}" ];
LogsDirectory = "mysql";
IPAddressDeny = "any";
IPAddressAllow = [
values.ipv4-space
values.ipv6-space
values.hosts.ildkule.ipv4
values.hosts.ildkule.ipv6
];
};
}; };
} }

View File

@@ -1,8 +1,11 @@
{ config, pkgs, values, ... }: { config, lib, pkgs, values, ... }:
let
cfg = config.services.postgresql;
in
{ {
services.postgresql = { services.postgresql = {
enable = true; enable = true;
package = pkgs.postgresql_15; package = pkgs.postgresql_18;
enableTCPIP = true; enableTCPIP = true;
authentication = '' authentication = ''
@@ -74,13 +77,13 @@
}; };
}; };
systemd.tmpfiles.settings."10-postgresql"."/data/postgresql".d = { systemd.tmpfiles.settings."10-postgresql"."/data/postgresql".d = lib.mkIf cfg.enable {
user = config.systemd.services.postgresql.serviceConfig.User; user = config.systemd.services.postgresql.serviceConfig.User;
group = config.systemd.services.postgresql.serviceConfig.Group; group = config.systemd.services.postgresql.serviceConfig.Group;
mode = "0700"; mode = "0700";
}; };
systemd.services.postgresql-setup = { systemd.services.postgresql-setup = lib.mkIf cfg.enable {
after = [ after = [
"systemd-tmpfiles-setup.service" "systemd-tmpfiles-setup.service"
"systemd-tmpfiles-resetup.service" "systemd-tmpfiles-resetup.service"
@@ -95,7 +98,7 @@
}; };
}; };
systemd.services.postgresql = { systemd.services.postgresql = lib.mkIf cfg.enable {
after = [ after = [
"systemd-tmpfiles-setup.service" "systemd-tmpfiles-setup.service"
"systemd-tmpfiles-resetup.service" "systemd-tmpfiles-resetup.service"
@@ -110,18 +113,34 @@
}; };
}; };
environment.snakeoil-certs."/etc/certs/postgres" = { environment.snakeoil-certs."/etc/certs/postgres" = lib.mkIf cfg.enable {
owner = "postgres"; owner = "postgres";
group = "postgres"; group = "postgres";
subject = "/C=NO/O=Programvareverkstedet/CN=postgres.pvv.ntnu.no/emailAddress=drift@pvv.ntnu.no"; subject = "/C=NO/O=Programvareverkstedet/CN=postgres.pvv.ntnu.no/emailAddress=drift@pvv.ntnu.no";
}; };
networking.firewall.allowedTCPPorts = [ 5432 ]; networking.firewall.allowedTCPPorts = lib.mkIf cfg.enable [ 5432 ];
networking.firewall.allowedUDPPorts = [ 5432 ]; networking.firewall.allowedUDPPorts = lib.mkIf cfg.enable [ 5432 ];
services.postgresqlBackup = { services.postgresqlBackup = lib.mkIf cfg.enable {
enable = true; enable = true;
location = "/var/lib/postgres/backups"; location = "/var/lib/postgres-backups";
backupAll = true; backupAll = true;
}; };
services.rsync-pull-targets = lib.mkIf cfg.enable {
enable = true;
locations.${config.services.postgresqlBackup.location} = {
user = "root";
rrsyncArgs.ro = true;
authorizedKeysAttrs = [
"restrict"
"no-agent-forwarding"
"no-port-forwarding"
"no-pty"
"no-X11-forwarding"
];
publicKey = "ssh-ed25519 AAAAC3NzaC1lZDI1NTE5AAAAIGvO7QX7QmwSiGLXEsaxPIOpAqnJP3M+qqQRe5dzf8gJ postgresql rsync backup";
};
};
} }

View File

@@ -17,5 +17,5 @@
# 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
system.stateVersion = "23.05"; system.stateVersion = "25.11";
} }

View File

@@ -32,5 +32,5 @@
# 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
system.stateVersion = "23.05"; system.stateVersion = "25.11";
} }

View File

@@ -4,6 +4,7 @@
# Include the results of the hardware scan. # Include the results of the hardware scan.
./hardware-configuration.nix ./hardware-configuration.nix
(fp /base) (fp /base)
./disks.nix
./services/gitea ./services/gitea
./services/nginx.nix ./services/nginx.nix

80
hosts/kommode/disks.nix Normal file
View File

@@ -0,0 +1,80 @@
{ lib, ... }:
{
disko.devices = {
disk = {
sda = {
type = "disk";
device = "/dev/sda";
content = {
type = "gpt";
partitions = {
root = {
name = "root";
label = "root";
start = "1MiB";
end = "-5G";
content = {
type = "btrfs";
extraArgs = [ "-f" ]; # Override existing partition
# subvolumes = let
# makeSnapshottable = subvolPath: mountOptions: let
# name = lib.replaceString "/" "-" subvolPath;
# in {
# "@${name}/active" = {
# mountpoint = subvolPath;
# inherit mountOptions;
# };
# "@${name}/snapshots" = {
# mountpoint = "${subvolPath}/.snapshots";
# inherit mountOptions;
# };
# };
# in {
# "@" = { };
# "@/swap" = {
# mountpoint = "/.swapvol";
# swap.swapfile.size = "4G";
# };
# "@/root" = {
# mountpoint = "/";
# mountOptions = [ "compress=zstd" "noatime" ];
# };
# }
# // (makeSnapshottable "/home" [ "compress=zstd" "noatime" ])
# // (makeSnapshottable "/nix" [ "compress=zstd" "noatime" ])
# // (makeSnapshottable "/var/lib" [ "compress=zstd" "noatime" ])
# // (makeSnapshottable "/var/log" [ "compress=zstd" "noatime" ])
# // (makeSnapshottable "/var/cache" [ "compress=zstd" "noatime" ]);
# swap.swapfile.size = "4G";
mountpoint = "/";
};
};
swap = {
name = "swap";
label = "swap";
start = "-5G";
end = "-1G";
content.type = "swap";
};
ESP = {
name = "ESP";
label = "ESP";
start = "-1G";
end = "100%";
type = "EF00";
content = {
type = "filesystem";
format = "vfat";
mountpoint = "/boot";
mountOptions = [ "umask=0077" ];
};
};
};
};
};
};
};
}

View File

@@ -13,21 +13,6 @@
boot.kernelModules = [ ]; boot.kernelModules = [ ];
boot.extraModulePackages = [ ]; boot.extraModulePackages = [ ];
fileSystems."/" =
{ device = "/dev/disk/by-uuid/d421538f-a260-44ae-8e03-47cac369dcc1";
fsType = "btrfs";
};
fileSystems."/boot" =
{ device = "/dev/disk/by-uuid/86CD-4C23";
fsType = "vfat";
options = [ "fmask=0077" "dmask=0077" ];
};
swapDevices =
[ { device = "/dev/disk/by-uuid/4cfbb41e-801f-40dd-8c58-0a0c1a6025f6"; }
];
# Enables DHCP on each ethernet and wireless interface. In case of scripted networking # Enables DHCP on each ethernet and wireless interface. In case of scripted networking
# (the default) this is the recommended approach. When using systemd-networkd it's # (the default) this is the recommended approach. When using systemd-networkd it's
# still possible to use this option, but it's recommended to use it in conjunction # still possible to use this option, but it's recommended to use it in conjunction

View File

@@ -193,8 +193,127 @@ in {
}; };
}; };
environment.robots-txt."gitea" = {
virtualHost = domain;
rules = [
{
pre_comment = ''
Gitea internals
See these for more information:
- https://gitea.com/robots.txt
- https://codeberg.org/robots.txt
'';
User-agent = "*";
Disallow = [
"/api/*"
"/avatars"
"/*/*/src/commit/*"
"/*/*/commit/*"
"/*/*/*/refs/*"
"/*/*/*/star"
"/*/*/*/watch"
"/*/*/labels"
"/*/*/activity/*"
"/vendor/*"
"/swagger.*.json"
"/repo/create"
"/repo/migrate"
"/org/create"
"/*/*/fork"
"/*/*/watchers"
"/*/*/stargazers"
"/*/*/forks"
"*/.git/"
"/*.git"
"/*.atom"
"/*.rss"
];
}
{
pre_comment = "Language Spam";
Disallow = "/*?lang=";
}
{
pre_comment = ''
AI bots
Sourced from:
- https://www.vg.no/robots.txt
- https://codeberg.org/robots.txt
'';
User-agent = [
"AI2Bot"
"Ai2Bot-Dolma"
"Amazonbot"
"Applebot-Extended"
"Bytespider"
"CCBot"
"ChatGPT-User"
"Claude-Web"
"ClaudeBot"
"Crawlspace"
"Diffbot"
"FacebookBot"
"FriendlyCrawler"
"GPTBot"
"Google-Extended"
"ICC-Crawler"
"ImagesiftBot"
"Kangaroo Bot"
"Meta-ExternalAgent"
"OAI-SearchBot"
"Omgili"
"Omgilibot"
"PanguBot"
"PerplexityBot"
"PetalBot"
"Scrapy"
"SemrushBot-OCOB"
"Sidetrade indexer bot"
"Timpibot"
"VelenPublicWebCrawler"
"Webzio-Extended"
"YouBot"
"anthropic-ai"
"cohere-ai"
"cohere-training-data-crawler"
"facebookexternalhit"
"iaskspider/2.0"
"img2dataset"
"meta-externalagent"
"omgili"
"omgilibot"
];
Disallow = "/";
}
{
Crawl-delay = "2";
}
{
Sitemap = "https://${domain}/sitemap.xml";
}
];
};
networking.firewall.allowedTCPPorts = [ sshPort ]; networking.firewall.allowedTCPPorts = [ sshPort ];
services.rsync-pull-targets = {
enable = true;
locations.${cfg.dump.backupDir} = {
user = "root";
rrsyncArgs.ro = true;
authorizedKeysAttrs = [
"restrict"
"no-agent-forwarding"
"no-port-forwarding"
"no-pty"
"no-X11-forwarding"
];
publicKey = "ssh-ed25519 AAAAC3NzaC1lZDI1NTE5AAAAIGpMVrOppyqYaDiAhqmAuOaRsubFvcQGBGyz+NHB6+0o gitea rsync backup";
};
};
systemd.services.gitea-dump = { systemd.services.gitea-dump = {
serviceConfig.ExecStart = let serviceConfig.ExecStart = let
args = lib.cli.toGNUCommandLineShell { } { args = lib.cli.toGNUCommandLineShell { } {

View File

@@ -15,5 +15,5 @@
# 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
system.stateVersion = "23.05"; system.stateVersion = "25.11";
} }

View File

@@ -96,11 +96,11 @@
}; };
# https://github.com/NixOS/nixpkgs/issues/84105 # https://github.com/NixOS/nixpkgs/issues/84105
boot.kernelParams = [ boot.kernelParams = lib.mkIf (!config.virtualisation.isVmVariant) [
"console=ttyUSB0,9600" "console=ttyUSB0,9600"
# "console=tty1" # Already part of the module # "console=tty1" # Already part of the module
]; ];
systemd.services."serial-getty@ttyUSB0" = { systemd.services."serial-getty@ttyUSB0" = lib.mkIf (!config.virtualisation.isVmVariant) {
enable = true; enable = true;
wantedBy = [ "getty.target" ]; # to start at boot wantedBy = [ "getty.target" ]; # to start at boot
serviceConfig.Restart = "always"; # restart when session is closed serviceConfig.Restart = "always"; # restart when session is closed

View File

@@ -0,0 +1,146 @@
{ config, lib, pkgs, ... }:
let
cfg = config.services.rsync-pull-targets;
in
{
options.services.rsync-pull-targets = {
enable = lib.mkEnableOption "";
rrsyncPackage = lib.mkPackageOption pkgs "rrsync" { };
locations = lib.mkOption {
type = lib.types.attrsOf (lib.types.submodule ({ name, ... }@submoduleArgs: {
options = {
enable = lib.mkEnableOption "" // {
default = true;
example = false;
};
user = lib.mkOption {
type = lib.types.str;
description = "Which user to use as SSH login";
example = "root";
};
location = lib.mkOption {
type = lib.types.path;
default = name;
defaultText = lib.literalExpression "<name>";
example = "/path/to/rsyncable/item";
};
# TODO: handle autogeneration of keys
# autoGenerateSSHKeypair = lib.mkOption {
# type = lib.types.bool;
# default = config.publicKey == null;
# defaultText = lib.literalExpression "config.services.rsync-pull-targets.<name>.publicKey != null";
# example = true;
# };
publicKey = lib.mkOption {
type = lib.types.str;
# type = lib.types.nullOr lib.types.str;
# default = null;
example = "ssh-ed25519 AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA comment";
};
rrsyncPackage = lib.mkPackageOption pkgs "rrsync" { } // {
default = cfg.rrsyncPackage;
defaultText = lib.literalExpression "config.services.rsync-pull-targets.rrsyncPackage";
};
enableRecommendedHardening = lib.mkEnableOption "a commonly used security profile for authorizedKeys attributes and rrsync args";
rrsyncArgs = {
ro = lib.mkEnableOption "" // {
description = "Allow only reading from the DIR. Implies -no-del and -no-lock.";
};
wo = lib.mkEnableOption "" // {
description = "Allow only writing to the DIR.";
};
munge = lib.mkEnableOption "" // {
description = "Enable rsync's --munge-links on the server side.";
# TODO: set a default?
};
no-del = lib.mkEnableOption "" // {
description = "Disable rsync's --delete* and --remove* options.";
default = submoduleArgs.config.enableRecommendedHardening;
defaultText = lib.literalExpression "config.services.rsync-pull-targets.<name>.enableRecommendedHardening";
};
no-lock = lib.mkEnableOption "" // {
description = "Avoid the single-run (per-user) lock check.";
default = submoduleArgs.config.enableRecommendedHardening;
defaultText = lib.literalExpression "config.services.rsync-pull-targets.<name>.enableRecommendedHardening";
};
no-overwrite = lib.mkEnableOption "" // {
description = "Prevent overwriting existing files by enforcing --ignore-existing";
default = submoduleArgs.config.enableRecommendedHardening;
defaultText = lib.literalExpression "config.services.rsync-pull-targets.<name>.enableRecommendedHardening";
};
};
authorizedKeysAttrs = lib.mkOption {
type = lib.types.listOf lib.types.str;
default = lib.optionals submoduleArgs.config.enableRecommendedHardening [
"restrict"
"no-agent-forwarding"
"no-port-forwarding"
"no-pty"
"no-X11-forwarding"
];
defaultText = lib.literalExpression ''
lib.optionals config.services.rsync-pull-targets.<name>.enableRecommendedHardening [
"restrict"
"no-agent-forwarding"
"no-port-forwarding"
"no-pty"
"no-X11-forwarding"
]
'';
example = [
"restrict"
"no-agent-forwarding"
"no-port-forwarding"
"no-pty"
"no-X11-forwarding"
];
};
};
}));
};
};
config = lib.mkIf cfg.enable {
# assertions = lib.pipe cfg.locations [
# (lib.filterAttrs (_: value: value.enable))
# TODO: assert that there are no duplicate (user, publicKey) pairs.
# if there are then ssh won't know which command to provide and might provide a random one, not sure.
# (lib.mapAttrsToList (_: { user, location, publicKey, ... }: {
# assertion =
# message = "";
# })
# ];
services.openssh.enable = true;
users.users = lib.pipe cfg.locations [
(lib.filterAttrs (_: value: value.enable))
lib.attrValues
# Index locations by SSH user
(lib.foldl (acc: location: acc // {
${location.user} = (acc.${location.user} or [ ]) ++ [ location ];
}) { })
(lib.mapAttrs (_name: locations: {
openssh.authorizedKeys.keys = map ({ user, location, rrsyncPackage, rrsyncArgs, authorizedKeysAttrs, publicKey, ... }: let
rrsyncArgString = lib.cli.toCommandLineShellGNU {
isLong = _: false;
} rrsyncArgs;
# TODO: handle " in location
in "command=\"${lib.getExe rrsyncPackage} ${rrsyncArgString} ${location}\",${lib.concatStringsSep "," authorizedKeysAttrs} ${publicKey}"
) locations;
}))
];
};
}

View File

@@ -17,6 +17,7 @@ ooye:
hookshot: hookshot:
as_token: ENC[AES256_GCM,data:L4vEw5r4RhcgritOeDTLHN5E/dM=,iv:pC8BLzxf6NaVAGsotoq6chOceBVdMLvrsQn1LGw9H9w=,tag:SI3CDFHAvgQZEvf/oms3EA==,type:str] as_token: ENC[AES256_GCM,data:L4vEw5r4RhcgritOeDTLHN5E/dM=,iv:pC8BLzxf6NaVAGsotoq6chOceBVdMLvrsQn1LGw9H9w=,tag:SI3CDFHAvgQZEvf/oms3EA==,type:str]
hs_token: ENC[AES256_GCM,data:2ufSJfYzzAB5IO+edwKSra5d/+M=,iv:cmTycGzNL+IeRRKZGbkhTtiksYTtbxED0k0B5haFw7k=,tag:FmWe5sGi9rlapUeAE6lKvg==,type:str] hs_token: ENC[AES256_GCM,data:2ufSJfYzzAB5IO+edwKSra5d/+M=,iv:cmTycGzNL+IeRRKZGbkhTtiksYTtbxED0k0B5haFw7k=,tag:FmWe5sGi9rlapUeAE6lKvg==,type:str]
passkey: ENC[AES256_GCM,data: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,iv:BqwTfYEtqtFazQGfhL6rxfIUrZ2cin+jy070FDaGIuc=,tag:MMUGNmH6m4aNR4U8KAac6w==,type:str]
livekit: livekit:
keyfile: keyfile:
#ENC[AES256_GCM,data:M+SfmEuhPL8sqxOl3uL8mE6Z6pC6naQNxFRskMPbVpLVWYM1Be+QOoLEiTMtWqH2PAf2NZXLcNY63Q99bYINz+BTt/ekllye,iv:DSZJxoZUlUZxPpzfpXyZ4ECeJjq6/WW8I2fvTXIjmfU=,tag:HwHhdQA8yuSKYxM5LcZV/w==,type:comment] #ENC[AES256_GCM,data:M+SfmEuhPL8sqxOl3uL8mE6Z6pC6naQNxFRskMPbVpLVWYM1Be+QOoLEiTMtWqH2PAf2NZXLcNY63Q99bYINz+BTt/ekllye,iv:DSZJxoZUlUZxPpzfpXyZ4ECeJjq6/WW8I2fvTXIjmfU=,tag:HwHhdQA8yuSKYxM5LcZV/w==,type:comment]
@@ -86,8 +87,8 @@ sops:
Qnh1djQ0ZDFhRmxsU2g0eHJZeFlkcU0Kj5H/dHrOwSgiZIzpv3nOc7AWeNMofJg7 Qnh1djQ0ZDFhRmxsU2g0eHJZeFlkcU0Kj5H/dHrOwSgiZIzpv3nOc7AWeNMofJg7
OzSVdRry72qPqYU8YLWjAcoP3ddITZnWr53/yYBVmssW/KeyVyPy9A== OzSVdRry72qPqYU8YLWjAcoP3ddITZnWr53/yYBVmssW/KeyVyPy9A==
-----END AGE ENCRYPTED FILE----- -----END AGE ENCRYPTED FILE-----
lastmodified: "2026-01-21T02:03:24Z" lastmodified: "2026-01-26T12:49:23Z"
mac: ENC[AES256_GCM,data:yVe+78V7zYgYveLFBghKdAeibg97DRafgsRRCZPYkWu8t2iadtD5UqRK0KS4Zcc55ojHJ11otgadaPHQyl8EIzt7Dwlm7ZOVEmmPAYdaweWfnPRdFhDAxcgj8Ejh03LAdLQK8WwlfTF/09Avub2ZUnN0aPwFCen/qD6dYmcGDNk=,iv:y4YE9AqlVVBBtRGoIdfIcNGE4chChBOR0Euy68xkQBA=,tag:/yopCpkvFaEzr2iXxLd3uw==,type:str] mac: ENC[AES256_GCM,data:+rkFq7pYZrGTtLIjjwa5DQC6WFpeV3JS80w6xADcn+kNnjg94p70GVZ3zP6p+f4PZ/Rupjg1cmm3w0g/ranx+FEmmX43N+zSY97NYOC2oxOhlNDDyrnRDElaiCOq41Jd13FxnjX3Jg9gxkD3szGS9hG+gv3wSf9NabOhFFL79GQ=,iv:+9UDVsvfr581CSNdtLRTfrjQ7rsLgMLmyK4cof0NZUU=,tag:9/xq9ThqrDzg+Snh3vSkVw==,type:str]
pgp: pgp:
- created_at: "2026-01-16T06:34:46Z" - created_at: "2026-01-16T06:34:46Z"
enc: |- enc: |-

View File

@@ -1,15 +1,16 @@
{ pkgs ? import <nixpkgs> {} }: { pkgs ? import <nixpkgs> {} }:
pkgs.mkShellNoCC { pkgs.mkShellNoCC {
packages = with pkgs; [ packages = with pkgs; [
just disko
jq editorconfig-checker
gnupg
gum gum
jq
just
openstackclient
sops sops
ssh-to-age ssh-to-age
gnupg
statix statix
openstackclient
editorconfig-checker
]; ];
env = { env = {