Compare commits

..

147 Commits
ozai ... main

Author SHA1 Message Date
Oystein Kristoffer Tveit 5242d99260
bekkalokk/gitea: add gpg signing key 2024-11-24 03:23:54 +01:00
Fredrik Robertsen c60597dc5a Merge pull request 'Let smartd send mail notification' (!92) from add-mail-to-smartd into main
Reviewed-on: #92
Reviewed-by: Oystein Kristoffer Tveit <oysteikt@pvv.ntnu.no>

Closes #92
2024-11-24 01:09:58 +01:00
Fredrik Robertsen 69462bf486 let smartd send mail notification 2024-11-24 01:01:55 +01:00
Oystein Kristoffer Tveit 7d4ccf1972 Merge pull request 'Add user frero' (!91) from add-user-frero into main
Reviewed-on: #91
2024-11-23 22:40:43 +01:00
Fredrik Robertsen c87a81eeee users: add `frero` 2024-11-23 22:39:53 +01:00
Daniel Lovbrotte Olsen 3bdfb4c297 Add function to make paths from flake root
No more ../../../../../../
2024-11-17 00:08:02 +01:00
Felix Albrigtsen 8285d91401 Merge pull request 'Ildkule: Move monitoring state directories to data volume' (!88) from ildkule-data-volume into main
Reviewed-on: #88
Reviewed-by: Daniel Lovbrotte Olsen <danio@pvv.ntnu.no>
2024-11-10 02:30:11 +01:00
Alf Helge Jakobsen b07cd5fbf6 systemd hardening for pvv-nettsiden-gallery-update.service (!90)
#133

Reviewed-on: #90
Reviewed-by: Oystein Kristoffer Tveit <oysteikt@pvv.ntnu.no>
Co-authored-by: Alf Helge Jakobsen <alfhj@stud.ntnu.no>
Co-committed-by: Alf Helge Jakobsen <alfhj@stud.ntnu.no>
2024-11-09 22:22:09 +01:00
Felix Albrigtsen 2d52ebce52 Ildkule: hardware-config: use UUIDs 2024-11-09 21:42:44 +01:00
Oystein Kristoffer Tveit 464576e856
flake.lock: bump greg-ng 2024-11-09 19:43:07 +01:00
Oystein Kristoffer Tveit df35715978 Merge pull request 'Add alfhj.nix' (!89) from newusersconfig into main
Reviewed-on: #89
Reviewed-by: Oystein Kristoffer Tveit <oysteikt@pvv.ntnu.no>
2024-11-09 19:40:03 +01:00
Alf Helge Jakobsen 165ff56948 Add alfhj.nix 2024-11-09 19:35:19 +01:00
Felix Albrigtsen 11f6ef0572 Ildkule: Move monitoring state directories to data volume 2024-11-09 15:21:12 +01:00
Oystein Kristoffer Tveit 815f48c30d
flake.lock: bump greg-ng 2024-10-22 19:50:29 +02:00
Oystein Kristoffer Tveit 4985bac3ba
flake.lock: bump greg-ng 2024-10-20 23:18:35 +02:00
Oystein Kristoffer Tveit 9e41c3374d Merge pull request 'bekkalokk/nginx: host `.well-known`' (!79) from move-well-known-to-bekkalokk into main
Reviewed-on: #79
Reviewed-by: Daniel Lovbrotte Olsen <danio@pvv.ntnu.no>
2024-10-20 01:35:22 +02:00
Oystein Kristoffer Tveit f39fee4213
bekkalokk/nginx: host `.well-known` 2024-10-20 01:34:41 +02:00
Oystein Kristoffer Tveit 4c77c9fc67 Merge pull request 'greg-ng 🎉' (!86) from greg-ng-working-branch into main
Reviewed-on: #86
Reviewed-by: Felix Albrigtsen <felixalb@pvv.ntnu.no>
2024-10-20 01:30:26 +02:00
Oystein Kristoffer Tveit 7938e8135f
flake.lock: bump 2024-10-19 23:31:29 +02:00
Oystein Kristoffer Tveit cbc3490882
modules/grzegorz: use greg-ng 2024-10-19 23:31:28 +02:00
Daniel Lovbrotte Olsen 47ed79986c bicep/matrix: use sops templates for appservice registrations 2024-10-14 15:46:58 +02:00
Daniel Lovbrotte Olsen 5aed665cc8 flake update 2024-10-14 00:24:29 +02:00
Daniel Lovbrotte Olsen 2c86a2d812 bicep/matrix/hookshot: More configuration 2024-10-14 00:13:15 +02:00
Daniel Lovbrotte Olsen d4fd3f8332 bicep/matrix/hookshot: add nginx 2024-10-13 06:03:26 +02:00
Joakim Pettersvold c1833eb07c bicep/matrix/hookshot: Configure matrix-hookshot
Co-authored-by: Daniel Olsen <daniel.olsen99@gmail.com>
2024-10-13 05:50:22 +02:00
Finn Landweber 5ee23ef2e2 bicep/matrix/hookshot: Backported from nixpkgs
Co-authored-by: Joakim Pettersvold <joakimpokemeg@hotmail.no>
2024-10-13 05:50:22 +02:00
Oystein Kristoffer Tveit f5c16f46f1 Merge pull request 'disable-postgres-on-bekkalokk' (!85) from disable-postgres-on-bekkalokk into main
Reviewed-on: #85
Reviewed-by: Daniel Lovbrotte Olsen <danio@pvv.ntnu.no>
2024-10-13 02:34:45 +02:00
Oystein Kristoffer Tveit aa71d497f1
bekkalokk/roundcube: add postgres password 2024-10-12 23:57:27 +02:00
Daniel Lovbrotte Olsen c56d157c3f add registration secret 2024-10-12 23:49:10 +02:00
fredrikr79 4fbd823be6 bekkalokk/roundcube: add `database.host` 2024-10-12 22:53:42 +02:00
Daniel Lovbrotte Olsen 6c9e651e59 bekkalokk/gitea: Add important emoji reactions 2024-10-12 22:42:59 +02:00
Adrian Gunnar Lauterer f56e73548c base: openssh fix 2024-10-12 22:32:18 +02:00
Adrian Gunnar Lauterer c62ea129ed Merge pull request 'base openssh added sleipner ssh keys' (!83) from sleipner-authorised-keys into main
Reviewed-on: #83
2024-10-12 21:48:08 +02:00
Adrian Gunnar Lauterer 4b41ddcf5d base: openssh added sleipner ssh keys 2024-10-12 21:47:31 +02:00
Daniel Lovbrotte Olsen abec66b287 users/danio: add to wheel 2024-10-08 14:08:17 +02:00
Felix Albrigtsen aa884353c7 Merge pull request 'Add ipv6 gateway' (!82) from ipv6-fix into main
Reviewed-on: #82
Reviewed-by: Daniel Lovbrotte Olsen <danio@pvv.ntnu.no>
2024-09-28 21:44:55 +02:00
Felix Albrigtsen 2147b56864 Add ipv6 gateway 2024-09-28 21:35:57 +02:00
Daniel Lovbrotte Olsen a7fe2aabc5 bicep/matrix/coturn: disable ipv6 to fix the service running at all
coturn is just fundamentally broken, look at trying eturnal instead
2024-09-27 07:30:48 +02:00
Daniel Lovbrotte Olsen cd23e35aac bicep/matrix: update module and remove deprecated options 2024-09-27 06:38:12 +02:00
Peder Bergebakken Sundt 06668cda79 Merge pull request 'flake.lock: Update' (!81) from sounding into main
Reviewed-on: #81
Reviewed-by: Oystein Kristoffer Tveit <oysteikt@pvv.ntnu.no>
2024-09-21 22:19:36 +02:00
Peder Bergebakken Sundt 2861f939b7 Merge pull request 'auto-upgrade: store flake input refs' (!80) from retain-flake-inputs into main
Reviewed-on: #80
Reviewed-by: Oystein Kristoffer Tveit <oysteikt@pvv.ntnu.no>
2024-09-21 22:19:18 +02:00
Peder Bergebakken Sundt 166b80988a flake.lock: Update
Flake lock file updates:

• Updated input 'grzegorz':
    'github:Programvareverkstedet/grzegorz/0481aef6553ae9aee86e4edb4ca0ed4f2eba2058' (2024-05-18)
  → 'git+https://git.pvv.ntnu.no/Projects/grzegorz.git?ref=refs/heads/master&rev=d10db19d7df5c5c2cd2dcb878376d5d681f6c2f2' (2024-09-20)
• Updated input 'grzegorz/fix-python':
    'github:GuillaumeDesforges/fix-python/f7f4b33e22414071fc1f9cbf68072c413c3a7fdf' (2024-04-23)
  → 'github:GuillaumeDesforges/fix-python/2926402234c3f99aa8e4608c51d9ffa73ea403c0' (2024-09-04)
• Updated input 'grzegorz-clients':
    'github:Programvareverkstedet/grzegorz-clients/b9444658fbb39cd1bf1c61ee5a1d5f0641c49abe' (2024-05-19)
  → 'git+https://git.pvv.ntnu.no/Projects/grzegorz-clients.git?ref=refs/heads/master&rev=546d921ec46735dbf876e36f4af8df1064d09432' (2024-09-20)
2024-09-20 22:49:19 +02:00
Peder Bergebakken Sundt 4913b22ab9 auto-upgrade: store flake input refs 2024-09-16 02:51:20 +02:00
Peder Bergebakken Sundt 4e81647fb6 auto-upgrade: `--update-input` -> `--override-input` 2024-09-15 19:14:03 +02:00
Felix Albrigtsen 5a76b62700 Merge pull request 'add gitea metrics' (!78) from gitea-metric into main
Reviewed-on: #78
Reviewed-by: Oystein Kristoffer Tveit <oysteikt@pvv.ntnu.no>
2024-09-14 20:33:28 +02:00
Felix Albrigtsen 0f77a42e34 Grafana: Add Gitea Dashbaord [sic] 2024-09-14 20:28:35 +02:00
Felix Albrigtsen c64d28fc26 Prometheus: Monitor gitea metrics 2024-09-14 20:21:12 +02:00
Dung-Bai Yen 179d0743ce gitea: export metric issue #101 2024-09-14 19:26:25 +02:00
Daniel Lovbrotte Olsen 47fa3759c3 buskerud: remove
This is now a proxmox machine :grr:
2024-09-05 18:00:42 +02:00
Daniel Lovbrotte Olsen 3a37fefd4d fixup! Merge pull request 'Fix Ildkule/Openstack networking' (!75) from fix-openstack-networking into main 2024-09-05 14:24:40 +02:00
Daniel Lovbrotte Olsen 47d7b88a05 ildkule/prometheus: consolidate scrape jobs and label with hostname for base info 2024-09-05 14:14:28 +02:00
Daniel Lovbrotte Olsen 78456063ba Merge pull request 'Fix Ildkule/Openstack networking' (!75) from fix-openstack-networking into main
Reviewed-on: #75
2024-09-05 01:58:50 +02:00
Felix Albrigtsen ca287b95c9 Ildkule/openstack: fix networking
Removes systemd-networkd, and configures proper ipv4 and ipv6 in
openstack.
2024-09-05 00:24:22 +02:00
Daniel Lovbrotte Olsen 7e95b77e15 grzegorz: follow stable nix channel
It broke because sanic
2024-09-03 13:28:13 +02:00
Daniel Lovbrotte Olsen 669733309b ildkule: get systemd stats from more machines 2024-09-03 13:10:36 +02:00
Daniel Lovbrotte Olsen 4ed12573ff ildkule: fix system activation by disabling smartd 2024-09-03 13:07:58 +02:00
Daniel Lovbrotte Olsen 8418cc016c fix biceps systemd units failing on activation 2024-09-03 13:00:12 +02:00
Daniel Lovbrotte Olsen b4c602e31c metrics: install systemd exporter 2024-09-02 23:12:24 +02:00
Daniel Lovbrotte Olsen 3a0b8e270d bekkalokk/idp: Disallow bots 2024-09-02 23:11:44 +02:00
Daniel Lovbrotte Olsen 9505223dc9 justfile: fix flake input updating 2024-09-02 19:33:15 +02:00
Daniel Lovbrotte Olsen 201784fa21 bluemap on bekkalokk 💀 2024-09-02 15:11:32 +02:00
Daniel Lovbrotte Olsen ccefcb01fa flake.lock update 2024-09-02 14:12:39 +02:00
Daniel Lovbrotte Olsen f7e2c74f89 base: enable rebuilding nixos-config without updating the channels used 2024-09-01 22:10:58 +02:00
Felix Albrigtsen 161265d346 Bekkalokk/Nettsiden: deploy #78 2024-09-01 20:13:56 +02:00
Oystein Kristoffer Tveit f85d18769f
common: clean `/tmp` on boot by default 2024-09-01 03:29:46 +02:00
Oystein Kristoffer Tveit b47a626427
common/openssh: socket activate 2024-09-01 03:21:13 +02:00
Oystein Kristoffer Tveit 4d65b9fd1d
common/sudo: misc config 2024-09-01 03:17:15 +02:00
Oystein Kristoffer Tveit f3e094520e
common/postfix: init 2024-09-01 03:13:18 +02:00
Oystein Kristoffer Tveit 69f98933a4
common/smartd: add `smartctl` to environment packages 2024-09-01 01:55:38 +02:00
Oystein Kristoffer Tveit bf2959c68d
common/nix: flesh out 2024-09-01 01:44:59 +02:00
Oystein Kristoffer Tveit 17f0268d12
common/irqbalance: init 2024-09-01 01:39:35 +02:00
Oystein Kristoffer Tveit ebce0eb67a
common/smartd: init 2024-09-01 01:23:15 +02:00
Oystein Kristoffer Tveit b48230e811
bekkalokk/btrfs: scrubbalubba dubdub 2024-09-01 01:04:28 +02:00
Daniel Lovbrotte Olsen 914eb35c5a add a route for /_synapse/admin, point mjolnir at it
This is whitelisted to just bicep

As a side-effect it's also much easier to use synapse-admin now
2024-09-01 00:34:42 +02:00
Oystein Kristoffer Tveit 8610a59f35
base.nix: split into multiple files 2024-08-31 22:28:17 +02:00
Oystein Kristoffer Tveit bd42412b94 bekkalokk/gitea/import-users: refactor + add members to groups 2024-08-27 22:07:29 +02:00
Daniel Lovbrotte Olsen ef3b146b58 bekkalokk/gitea: don't autowatch all members to all projects 2024-08-27 09:26:00 +02:00
Oystein Kristoffer Tveit bb4662b345 modules/snakeoil-certs: fix lmao 2024-08-26 20:43:34 +02:00
Oystein Kristoffer Tveit 5b1c04e4b8 bicep/postgres: use snakeoil certs 2024-08-26 20:43:34 +02:00
Oystein Kristoffer Tveit 3fa7f67027 bekkalokk/gitea-web: host pages 2024-08-26 20:36:03 +02:00
Oystein Kristoffer Tveit b0f555667c bekkalokk/gitea: set up gitea-web sync units 2024-08-26 20:36:03 +02:00
Oystein Kristoffer Tveit ef418bf125
base/logrotate: systemd hardening + more 2024-08-22 23:00:45 +02:00
Oystein Kristoffer Tveit 945d53cdb4
bekkalokk/vaultwarden: systemd hardening 2024-08-22 22:59:32 +02:00
Oystein Kristoffer Tveit cf3b62e01e
bekkalokk/phpfpm-*: systemd hardening 2024-08-22 22:58:48 +02:00
Oystein Kristoffer Tveit c12a47cee0
flake.nix: bump calendar bot 2024-08-17 01:19:46 +02:00
Oystein Kristoffer Tveit b9ef27565f
Bump calendar-bot 2024-08-16 09:16:26 +02:00
Oystein Kristoffer Tveit f5c99b58c8
bicep/calendar-bot: reactivate 2024-08-15 23:22:50 +02:00
Peder Bergebakken Sundt c780f7954c Merge pull request 'justfile: add recipe `run-vm`' (!64) from run-vm into main
Reviewed-on: #64
Reviewed-by: Oystein Kristoffer Tveit <oysteikt@pvv.ntnu.no>
2024-08-15 21:14:29 +02:00
Oystein Kristoffer Tveit d64d8edd68 bekkalokk/gitea: add some extra tabs 2024-08-14 17:36:19 +02:00
Peder Bergebakken Sundt 4de7bd09bd Merge pull request 'enable thermald on physical machines' (!61) from thermald into main
Reviewed-on: #61
Reviewed-by: Oystein Kristoffer Tveit <oysteikt@pvv.ntnu.no>
2024-08-14 17:31:44 +02:00
Peder Bergebakken Sundt 0f5c48902b Merge pull request 'users: disable password login for users in @wheel' (!62) from fix-deploy into main
Reviewed-on: #62
Reviewed-by: Oystein Kristoffer Tveit <oysteikt@pvv.ntnu.no>
2024-08-14 17:31:08 +02:00
Peder Bergebakken Sundt 2ff69dfec6 justfile: add recipe `run-vm` 2024-08-14 17:25:55 +02:00
Peder Bergebakken Sundt 36a8868f94 users: disable password login for users in @wheel 2024-08-11 03:42:26 +02:00
Peder Bergebakken Sundt fe3e5d6a3d enable thermald on physical machines 2024-08-10 23:55:29 +02:00
Peder Bergebakken Sundt 2f3bcaf124 shell.nix: fix typo 2024-08-10 18:15:31 +02:00
Peder Bergebakken Sundt c6684d5146 Merge pull request 'justfile: init' (!56) from justfile into main
Reviewed-on: #56
Reviewed-by: Oystein Kristoffer Tveit <oysteikt@pvv.ntnu.no>
2024-08-07 12:22:04 +02:00
Peder Bergebakken Sundt f6cb934ffb Merge pull request 'flake.nix: simplify allMachines' (!59) from attrnames into main
Reviewed-on: #59
Reviewed-by: Daniel Lovbrotte Olsen <danio@pvv.ntnu.no>
2024-08-04 23:44:54 +02:00
Peder Bergebakken Sundt 9625258942 Merge pull request 'flake.nix: export snakeoil-certs and snappymail nixos modules' (!58) from export-modules into main
Reviewed-on: #58
Reviewed-by: Daniel Lovbrotte Olsen <danio@pvv.ntnu.no>
2024-08-04 23:44:19 +02:00
Peder Bergebakken Sundt 34637e383a justfile: add update-inputs recipe 2024-08-04 17:19:40 +02:00
Peder Bergebakken Sundt 0bfa6ac329 flake.nix: export inputs 2024-08-04 17:19:33 +02:00
Peder Bergebakken Sundt 2c3261de74 flake.nix: simplify allMachines 2024-08-04 17:11:21 +02:00
Peder Bergebakken Sundt c2e6f294ea flake.nix: export snakeoil-certs and snappymail nixos modules 2024-08-04 16:48:21 +02:00
Peder Bergebakken Sundt 41e94695f0 Merge pull request 'editorconfig' (!55) from editorconfig into main
Reviewed-on: #55
Reviewed-by: Oystein Kristoffer Tveit <oysteikt@pvv.ntnu.no>
2024-08-04 16:20:23 +02:00
Peder Bergebakken Sundt c6b4ea9929 add .git-blame-ignore-revs 2024-08-04 04:39:17 +02:00
Peder Bergebakken Sundt 9dbf5d56f5 fix whitespacing issues 2024-08-04 04:37:23 +02:00
Peder Bergebakken Sundt 64b5bb548b editorconfig: init 2024-08-04 04:35:25 +02:00
Peder Bergebakken Sundt 261c8e0811 Merge pull request 'Run statix' (!54) from statix into main
Reviewed-on: #54
Reviewed-by: Daniel Lovbrotte Olsen <danio@pvv.ntnu.no>
2024-08-04 04:26:23 +02:00
Peder Bergebakken Sundt 4476cdcbbc justfile: init 2024-08-04 03:28:17 +02:00
Peder Bergebakken Sundt f475243b94 Merge pull request 'sops: add pederbs' (!51) from pederbs-sops into main
Reviewed-on: #51
Reviewed-by: Oystein Kristoffer Tveit <oysteikt@pvv.ntnu.no>
2024-08-04 02:56:31 +02:00
Peder Bergebakken Sundt f382109b4a Merge pull request 'users: add pederbs' (!49) from user-pederbs into main
Reviewed-on: #49
Reviewed-by: Oystein Kristoffer Tveit <oysteikt@pvv.ntnu.no>
2024-08-04 02:46:59 +02:00
Peder Bergebakken Sundt e5e3100639 Merge pull request 'direnv: yes' (!50) from direnv into main
Reviewed-on: #50
Reviewed-by: Oystein Kristoffer Tveit <oysteikt@pvv.ntnu.no>
2024-08-04 02:46:18 +02:00
Peder Bergebakken Sundt 5853e42c1b Merge pull request 'SimpleSamlPHP: use concatLines' (!53) from concatlines into main
Reviewed-on: #53
Reviewed-by: Oystein Kristoffer Tveit <oysteikt@pvv.ntnu.no>
2024-08-04 02:46:01 +02:00
Peder Bergebakken Sundt d59aa08986 Merge pull request 'shell.nix: remove cc' (!52) from shell-cc into main
Reviewed-on: #52
Reviewed-by: Oystein Kristoffer Tveit <oysteikt@pvv.ntnu.no>
2024-08-04 02:44:52 +02:00
Oystein Kristoffer Tveit 95a5603f27
secrets: run `sops updatekeys` on everything 2024-08-04 02:04:29 +02:00
Peder Bergebakken Sundt 1714681532 `statix fix` 2024-08-04 01:46:00 +02:00
Peder Bergebakken Sundt 314c7960d1 statix: init 2024-08-04 01:45:20 +02:00
Peder Bergebakken Sundt 43d353190c SimpleSamlPHP: use concatLines 2024-08-04 01:42:32 +02:00
Peder Bergebakken Sundt eb74d011db shell.nix: remove cc 2024-08-04 01:30:02 +02:00
Peder Bergebakken Sundt b52de48455 sops: add pederbs 2024-08-04 01:24:54 +02:00
Peder Bergebakken Sundt 510f385f4a direnv: yes 2024-08-04 01:19:22 +02:00
Peder Bergebakken Sundt e25ba96096 users: add pederbs 2024-08-04 00:58:11 +02:00
Oystein Kristoffer Tveit 53040bada1
flake.lock: update pvv-nettsiden 2024-08-04 00:09:32 +02:00
Felix Albrigtsen 2030d4de39 fix-openstack-networking (!47)
Fix networking in Openstack.

This rewrites the systemd-networkd config, fixing both dhcp and manual address/route configurations.
Now, everything should behave predictably, routing NTNU-internal and NTNU-global addresses separately and properly across both ipv4 and ipv6.

Reviewed-on: #47
2024-07-31 11:23:00 +02:00
Felix Albrigtsen c7797bdd04 Merge pull request 'SimpleSAMLPHP/MediaWiki: Update deprecated --replace' (!48) from fix-replace-warn into main
Reviewed-on: #48
Reviewed-by: Oystein Kristoffer Tveit <oysteikt@pvv.ntnu.no>
2024-07-28 23:30:44 +02:00
Felix Albrigtsen 615b5fc1f1 SimpleSAMLPHP/MediaWiki: Update deprecated --replace 2024-07-28 23:28:33 +02:00
Oystein Kristoffer Tveit a0a837e26d Merge pull request 'bekkalokk/gitea: direct non-logged-in users to the explore tab' (!46) from gitea-explore into main
Reviewed-on: #46
Reviewed-by: Felix Albrigtsen <felixalb@pvv.ntnu.no>
Reviewed-by: Oystein Kristoffer Tveit <oysteikt@pvv.ntnu.no>
2024-07-28 23:10:38 +02:00
Daniel Lovbrotte Olsen 8f3013dc00 bekkalokk/gitea: direct non-logged-in users to the explore tab
This is a much more interesting page rather than trying to sell gitea
2024-07-19 21:19:06 +02:00
Daniel Lovbrotte Olsen 78caceddce flake: remove nettsiden from output function scope
This is referred to by inputs anyways
2024-07-18 16:24:42 +02:00
Oystein Kristoffer Tveit 868764e0cd bekkalokk/mediawiki: misc configuration 2024-07-10 19:04:55 +02:00
Oystein Kristoffer Tveit 7c3ff2068d bekkalokk/mediawiki: add some more extensions 2024-07-10 19:04:36 +02:00
Oystein Kristoffer Tveit 9d3f1381bf packages/mediawiki-extensions: refactor 2024-07-10 18:59:16 +02:00
Oystein Kristoffer Tveit f3a29429aa bekkalokk/gitea: set default email notification preference to 'onmention' 2024-07-10 00:18:01 +02:00
Oystein Kristoffer Tveit 1591fdb7cc bekkalokk/mediawiki: re-enable DeleteBatch extension 2024-07-08 19:56:43 +02:00
Oystein Kristoffer Tveit ed28ba28f3 bekkalokk/mediawiki: leave togglable debug flags for future use 2024-07-08 19:55:52 +02:00
Oystein Kristoffer Tveit 52b46667b1 packages/mediawiki-extensions: use fetchgit 2024-07-08 19:54:42 +02:00
Oystein Kristoffer Tveit d0f63b2fc8 packages/mediawiki-extensions: bump all 2024-07-08 16:55:01 +02:00
Oystein Kristoffer Tveit 0301691b1c
gitea: enable notification mails 2024-07-04 20:41:46 +02:00
Oystein Kristoffer Tveit 946555e408
gitea: add subject prefix to mail 2024-07-04 20:36:44 +02:00
Oystein Kristoffer Tveit e02062417a
gitea: move state back to /var/lib 2024-07-04 20:31:51 +02:00
Oystein Kristoffer Tveit b2806d78af
gitea: enable lfs 2024-07-04 20:30:55 +02:00
Oystein Kristoffer Tveit de2c7ea6f1
gitea: install custom images to correct dir 2024-07-04 20:29:50 +02:00
Felix Albrigtsen 106081c967 Merge pull request 'all: Update to nixos-24.05' (!43) from 24.05-for-real into main
Reviewed-on: #43
2024-06-30 01:55:41 +02:00
Felix Albrigtsen ca2deed668 WIP: all: Update to nixos-24.05 2024-06-30 01:55:25 +02:00
Oystein Kristoffer Tveit bb2f7899db Merge pull request 'bekkalokk/gitea: set default licenses and repo units' (!44) from gitea-set-misc-repo-settings into main
Reviewed-on: #44
2024-06-29 23:16:17 +02:00
Oystein Kristoffer Tveit c2b35a7ae4
bekkalokk/gitea: set default licenses and repo units 2024-06-29 23:14:41 +02:00
Felix Albrigtsen c88c3f87e0 buskerud: add libvirtd 2024-06-22 17:36:30 +02:00
Felix Albrigtsen c5bad75edc bekkalokk/nettsiden: Update nettsiden to disable recurring events 2024-06-19 22:15:36 +02:00
113 changed files with 4655 additions and 1173 deletions

10
.editorconfig Normal file
View File

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

1
.envrc Normal file
View File

@ -0,0 +1 @@
use flake

1
.git-blame-ignore-revs Normal file
View File

@ -0,0 +1 @@
e00008da1afe0d760badd34bbeddff36bb08c475

2
.gitignore vendored
View File

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

View File

@ -4,6 +4,9 @@ keys:
- &user_felixalb age1mrnldl334l2nszuta6ywvewng0fswv2dz9l5g4qcwe3nj4yxf92qjskdx6 - &user_felixalb age1mrnldl334l2nszuta6ywvewng0fswv2dz9l5g4qcwe3nj4yxf92qjskdx6
- &user_oysteikt F7D37890228A907440E1FD4846B9228E814A2AAC - &user_oysteikt F7D37890228A907440E1FD4846B9228E814A2AAC
- &user_eirikwit age1ju7rd26llahz3g8tz7cy5ld52swj8gsmg0flrmrxngc0nj0avq3ssh0sn5 - &user_eirikwit age1ju7rd26llahz3g8tz7cy5ld52swj8gsmg0flrmrxngc0nj0avq3ssh0sn5
- &user_pederbs_sopp age1hmpdk4h69wxpwqk9tkud39f66hprhehxtzhgw97r6dvr7v0mx5jscsuhkn
- &user_pederbs_nord age1wrssr4z4g6vl3fd3qme5cewchmmhm0j2xe6wf2meu4r6ycn37anse98mfs
- &user_pederbs_bjarte age1zhxul786an743u0fascv4wtc5xduu7qfy803lfs539yzhgmlq5ds2lznt5
# Hosts # Hosts
- &host_jokum age1gp8ye4g2mmw3may5xg0zsy7mm04glfz3788mmdx9cvcsdxs9hg0s0cc9kt - &host_jokum age1gp8ye4g2mmw3may5xg0zsy7mm04glfz3788mmdx9cvcsdxs9hg0s0cc9kt
@ -20,17 +23,23 @@ creation_rules:
- *user_danio - *user_danio
- *user_felixalb - *user_felixalb
- *user_eirikwit - *user_eirikwit
- *user_pederbs_sopp
- *user_pederbs_nord
- *user_pederbs_bjarte
pgp: pgp:
- *user_oysteikt - *user_oysteikt
# Host specific secrets # Host specific secrets
- path_regex: secrets/bekkalokk/[^/]+\.yaml$ - path_regex: secrets/bekkalokk/[^/]+\.yaml$
key_groups: key_groups:
- age: - age:
- *host_bekkalokk - *host_bekkalokk
- *user_danio - *user_danio
- *user_felixalb - *user_felixalb
- *user_pederbs_sopp
- *user_pederbs_nord
- *user_pederbs_bjarte
pgp: pgp:
- *user_oysteikt - *user_oysteikt
@ -40,6 +49,9 @@ creation_rules:
- *host_jokum - *host_jokum
- *user_danio - *user_danio
- *user_felixalb - *user_felixalb
- *user_pederbs_sopp
- *user_pederbs_nord
- *user_pederbs_bjarte
pgp: pgp:
- *user_oysteikt - *user_oysteikt
@ -49,14 +61,20 @@ creation_rules:
- *host_ildkule - *host_ildkule
- *user_danio - *user_danio
- *user_felixalb - *user_felixalb
- *user_pederbs_sopp
- *user_pederbs_nord
- *user_pederbs_bjarte
pgp: pgp:
- *user_oysteikt - *user_oysteikt
- path_regex: secrets/bicep/[^/]+\.yaml$ - path_regex: secrets/bicep/[^/]+\.yaml$
key_groups: key_groups:
- age: - age:
- *host_bicep - *host_bicep
- *user_danio - *user_danio
- *user_felixalb - *user_felixalb
- *user_pederbs_sopp
- *user_pederbs_nord
- *user_pederbs_bjarte
pgp: pgp:
- *user_oysteikt - *user_oysteikt

View File

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

133
base.nix
View File

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

60
base/default.nix Normal file
View File

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

13
base/networking.nix Normal file
View File

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

34
base/nix.nix Normal file
View File

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

15
base/services/acme.nix Normal file
View File

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

View File

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

View File

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

View File

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

44
base/services/nginx.nix Normal file
View File

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

21
base/services/openssh.nix Normal file
View File

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

23
base/services/postfix.nix Normal file
View File

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

18
base/services/smartd.nix Normal file
View File

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

View File

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

View File

@ -7,11 +7,11 @@
] ]
}, },
"locked": { "locked": {
"lastModified": 1715445235, "lastModified": 1731746438,
"narHash": "sha256-SUu+oIWn+xqQIOlwfwNfS9Sek4i1HKsrLJchsDReXwA=", "narHash": "sha256-f3SSp1axoOk0NAI7oFdRzbxG2XPBSIXC+/DaAXnvS1A=",
"owner": "nix-community", "owner": "nix-community",
"repo": "disko", "repo": "disko",
"rev": "159d87ea5b95bbdea46f0288a33c5e1570272725", "rev": "cb64993826fa7a477490be6ccb38ba1fa1e18fa8",
"type": "github" "type": "github"
}, },
"original": { "original": {
@ -20,64 +20,25 @@
"type": "github" "type": "github"
} }
}, },
"fix-python": { "greg-ng": {
"inputs": { "inputs": {
"flake-utils": "flake-utils",
"nixpkgs": [ "nixpkgs": [
"grzegorz",
"nixpkgs" "nixpkgs"
] ],
"rust-overlay": "rust-overlay"
}, },
"locked": { "locked": {
"lastModified": 1713887124, "lastModified": 1730249639,
"narHash": "sha256-hGTSm0p9xXUYDgsAAr/ORZICo6T6u33vLfX3tILikaQ=", "narHash": "sha256-G3URSlqCcb+GIvGyki+HHrDM5ZanX/dP9BtppD/SdfI=",
"owner": "GuillaumeDesforges", "ref": "refs/heads/main",
"repo": "fix-python", "rev": "80e0447bcb79adad4f459ada5610f3eae987b4e3",
"rev": "f7f4b33e22414071fc1f9cbf68072c413c3a7fdf", "revCount": 34,
"type": "github" "type": "git",
"url": "https://git.pvv.ntnu.no/Projects/greg-ng.git"
}, },
"original": { "original": {
"owner": "GuillaumeDesforges", "type": "git",
"repo": "fix-python", "url": "https://git.pvv.ntnu.no/Projects/greg-ng.git"
"type": "github"
}
},
"flake-utils": {
"inputs": {
"systems": "systems"
},
"locked": {
"lastModified": 1689068808,
"narHash": "sha256-6ixXo3wt24N/melDWjq70UuHQLxGV8jZvooRanIHXw0=",
"owner": "numtide",
"repo": "flake-utils",
"rev": "919d646de7be200f3bf08cb76ae1f09402b6f9b4",
"type": "github"
},
"original": {
"id": "flake-utils",
"type": "indirect"
}
},
"grzegorz": {
"inputs": {
"fix-python": "fix-python",
"nixpkgs": [
"nixpkgs-unstable"
]
},
"locked": {
"lastModified": 1715364232,
"narHash": "sha256-ZJC3SkanEgbV7p+LFhP+85CviRWOXJNHzZwR/Stb7hE=",
"owner": "Programvareverkstedet",
"repo": "grzegorz",
"rev": "3841cda1cdcac470440b06838d56a2eb2256378c",
"type": "github"
},
"original": {
"owner": "Programvareverkstedet",
"repo": "grzegorz",
"type": "github"
} }
}, },
"grzegorz-clients": { "grzegorz-clients": {
@ -87,17 +48,17 @@
] ]
}, },
"locked": { "locked": {
"lastModified": 1715384651, "lastModified": 1726861934,
"narHash": "sha256-7RhckgUTjqeCjWkhiCc1iB+5CBx9fl80d/3O4Jh+5kM=", "narHash": "sha256-lOzPDwktd+pwszUTbpUdQg6iCzInS11fHLfkjmnvJrM=",
"owner": "Programvareverkstedet", "ref": "refs/heads/master",
"repo": "grzegorz-clients", "rev": "546d921ec46735dbf876e36f4af8df1064d09432",
"rev": "738a4f3dd887f7c3612e4e772b83cbfa3cde5693", "revCount": 78,
"type": "github" "type": "git",
"url": "https://git.pvv.ntnu.no/Projects/grzegorz-clients.git"
}, },
"original": { "original": {
"owner": "Programvareverkstedet", "type": "git",
"repo": "grzegorz-clients", "url": "https://git.pvv.ntnu.no/Projects/grzegorz-clients.git"
"type": "github"
} }
}, },
"matrix-next": { "matrix-next": {
@ -107,19 +68,35 @@
] ]
}, },
"locked": { "locked": {
"lastModified": 1710311999, "lastModified": 1727410897,
"narHash": "sha256-s0pT1NyrMgeolUojXXcnXQDymN7m80GTF7itCv0ZH20=", "narHash": "sha256-tWsyxvf421ieWUJYgjV7m1eTdr2ZkO3vId7vmtvfFpQ=",
"owner": "dali99", "owner": "dali99",
"repo": "nixos-matrix-modules", "repo": "nixos-matrix-modules",
"rev": "6c9b67974b839740e2a738958512c7a704481157", "rev": "ff787d410cba17882cd7b6e2e22cc88d4064193c",
"type": "github" "type": "github"
}, },
"original": { "original": {
"owner": "dali99", "owner": "dali99",
"ref": "v0.6.1",
"repo": "nixos-matrix-modules", "repo": "nixos-matrix-modules",
"type": "github" "type": "github"
} }
}, },
"minecraft-data": {
"locked": {
"lastModified": 1725277886,
"narHash": "sha256-Fw4VbbE3EfypQWSgPDFfvVH47BHeg3ptsO715NlUM8Q=",
"ref": "refs/heads/master",
"rev": "1b4087bd3322a2e2ba84271c8fcc013e6b641a58",
"revCount": 2,
"type": "git",
"url": "https://git.pvv.ntnu.no/Drift/minecraft-data.git"
},
"original": {
"type": "git",
"url": "https://git.pvv.ntnu.no/Drift/minecraft-data.git"
}
},
"nix-gitea-themes": { "nix-gitea-themes": {
"inputs": { "inputs": {
"nixpkgs": [ "nixpkgs": [
@ -142,48 +119,50 @@
}, },
"nixpkgs": { "nixpkgs": {
"locked": { "locked": {
"lastModified": 1715410392, "lastModified": 1731663789,
"narHash": "sha256-ltp1jQps9tym0uWNl/lTniHSQngCtNIyzlymu+ZSyts=", "narHash": "sha256-x07g4NcqGP6mQn6AISXJaks9sQYDjZmTMBlKIvajvyc=",
"owner": "NixOS", "owner": "NixOS",
"repo": "nixpkgs", "repo": "nixpkgs",
"rev": "9f8bf7503bd85d5208575f4bd81c8b1fc999a468", "rev": "035d434d48f4375ac5d3a620954cf5fda7dd7c36",
"type": "github" "type": "github"
}, },
"original": { "original": {
"id": "nixpkgs", "owner": "NixOS",
"ref": "nixos-23.11-small", "ref": "nixos-24.05-small",
"type": "indirect" "repo": "nixpkgs",
"type": "github"
} }
}, },
"nixpkgs-stable": { "nixpkgs-stable": {
"locked": { "locked": {
"lastModified": 1714858427, "lastModified": 1730602179,
"narHash": "sha256-tCxeDP4C1pWe2rYY3IIhdA40Ujz32Ufd4tcrHPSKx2M=", "narHash": "sha256-efgLzQAWSzJuCLiCaQUCDu4NudNlHdg2NzGLX5GYaEY=",
"owner": "NixOS", "owner": "NixOS",
"repo": "nixpkgs", "repo": "nixpkgs",
"rev": "b980b91038fc4b09067ef97bbe5ad07eecca1e76", "rev": "3c2f1c4ca372622cb2f9de8016c9a0b1cbd0f37c",
"type": "github" "type": "github"
}, },
"original": { "original": {
"owner": "NixOS", "owner": "NixOS",
"ref": "release-23.11", "ref": "release-24.05",
"repo": "nixpkgs", "repo": "nixpkgs",
"type": "github" "type": "github"
} }
}, },
"nixpkgs-unstable": { "nixpkgs-unstable": {
"locked": { "locked": {
"lastModified": 1715435713, "lastModified": 1731745710,
"narHash": "sha256-lb2HqDQGfTdnCCpc1pgF6fkdgIOuBQ0nP8jjVSfLFqg=", "narHash": "sha256-SVeiClbgqL071JpAspOu0gCkPSAL51kSIRwo4C/pghA=",
"owner": "NixOS", "owner": "NixOS",
"repo": "nixpkgs", "repo": "nixpkgs",
"rev": "52b40f6c4be12742b1504ca2eb4527e597bf2526", "rev": "dfaa4cb76c2d450d8f396bb6b9f43cede3ade129",
"type": "github" "type": "github"
}, },
"original": { "original": {
"id": "nixpkgs", "owner": "NixOS",
"ref": "nixos-unstable-small", "ref": "nixos-unstable-small",
"type": "indirect" "repo": "nixpkgs",
"type": "github"
} }
}, },
"pvv-calendar-bot": { "pvv-calendar-bot": {
@ -193,11 +172,11 @@
] ]
}, },
"locked": { "locked": {
"lastModified": 1693136143, "lastModified": 1723850344,
"narHash": "sha256-amHprjftc3y/bg8yf4hITCLa+ez5HIi0yGfR7TU6UIc=", "narHash": "sha256-aT37O9l9eclWEnqxASVNBL1dKwDHZUOqdbA4VO9DJvw=",
"ref": "refs/heads/main", "ref": "refs/heads/main",
"rev": "a32894b305f042d561500f5799226afd1faf5abb", "rev": "38b66677ab8c01aee10cd59e745af9ce3ea88092",
"revCount": 9, "revCount": 19,
"type": "git", "type": "git",
"url": "https://git.pvv.ntnu.no/Projects/calendar-bot.git" "url": "https://git.pvv.ntnu.no/Projects/calendar-bot.git"
}, },
@ -213,11 +192,11 @@
] ]
}, },
"locked": { "locked": {
"lastModified": 1716150352, "lastModified": 1725212759,
"narHash": "sha256-c13lzYbLmbrcbEdPTYZYtlX2Qsz1W+2sLsIMGShPgwo=", "narHash": "sha256-yZBsefIarFUEhFRj+rCGMp9Zvag3MCafqV/JfGVRVwc=",
"ref": "refs/heads/master", "ref": "refs/heads/master",
"rev": "2cab4df4b119e08a1f90ea1c944652cd78b4d478", "rev": "e7b66b4bc6a89bab74bac45b87e9434f5165355f",
"revCount": 459, "revCount": 473,
"type": "git", "type": "git",
"url": "https://git.pvv.ntnu.no/Projects/nettsiden.git" "url": "https://git.pvv.ntnu.no/Projects/nettsiden.git"
}, },
@ -229,9 +208,10 @@
"root": { "root": {
"inputs": { "inputs": {
"disko": "disko", "disko": "disko",
"grzegorz": "grzegorz", "greg-ng": "greg-ng",
"grzegorz-clients": "grzegorz-clients", "grzegorz-clients": "grzegorz-clients",
"matrix-next": "matrix-next", "matrix-next": "matrix-next",
"minecraft-data": "minecraft-data",
"nix-gitea-themes": "nix-gitea-themes", "nix-gitea-themes": "nix-gitea-themes",
"nixpkgs": "nixpkgs", "nixpkgs": "nixpkgs",
"nixpkgs-unstable": "nixpkgs-unstable", "nixpkgs-unstable": "nixpkgs-unstable",
@ -240,6 +220,27 @@
"sops-nix": "sops-nix" "sops-nix": "sops-nix"
} }
}, },
"rust-overlay": {
"inputs": {
"nixpkgs": [
"greg-ng",
"nixpkgs"
]
},
"locked": {
"lastModified": 1729391507,
"narHash": "sha256-as0I9xieJUHf7kiK2a9znDsVZQTFWhM1pLivII43Gi0=",
"owner": "oxalica",
"repo": "rust-overlay",
"rev": "784981a9feeba406de38c1c9a3decf966d853cca",
"type": "github"
},
"original": {
"owner": "oxalica",
"repo": "rust-overlay",
"type": "github"
}
},
"sops-nix": { "sops-nix": {
"inputs": { "inputs": {
"nixpkgs": [ "nixpkgs": [
@ -248,11 +249,11 @@
"nixpkgs-stable": "nixpkgs-stable" "nixpkgs-stable": "nixpkgs-stable"
}, },
"locked": { "locked": {
"lastModified": 1715244550, "lastModified": 1731748189,
"narHash": "sha256-ffOZL3eaZz5Y1nQ9muC36wBCWwS1hSRLhUzlA9hV2oI=", "narHash": "sha256-Zd/Uukvpcu26M6YGhpbsgqm6LUSLz+Q8mDZ5LOEGdiE=",
"owner": "Mic92", "owner": "Mic92",
"repo": "sops-nix", "repo": "sops-nix",
"rev": "0dc50257c00ee3c65fef3a255f6564cfbfe6eb7f", "rev": "d2bd7f433b28db6bc7ae03d5eca43564da0af054",
"type": "github" "type": "github"
}, },
"original": { "original": {
@ -260,21 +261,6 @@
"repo": "sops-nix", "repo": "sops-nix",
"type": "github" "type": "github"
} }
},
"systems": {
"locked": {
"lastModified": 1681028828,
"narHash": "sha256-Vy1rq5AaRuLzOxct8nz4T6wlgyUR7zLU309k9mBC768=",
"owner": "nix-systems",
"repo": "default",
"rev": "da67096a3b9bf56a91d16901293e51ba5b49a27e",
"type": "github"
},
"original": {
"owner": "nix-systems",
"repo": "default",
"type": "github"
}
} }
}, },
"root": "root", "root": "root",

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

@ -112,7 +112,7 @@ class PwAuth extends \SimpleSAML\Module\core\Auth\UserPassBase
array_shift($groups); array_shift($groups);
array_shift($groups); array_shift($groups);
array_pop($groups); array_pop($groups);
$info = posix_getpwnam($uid); $info = posix_getpwnam($uid);
$group = $info['gid']; $group = $info['gid'];
if (!in_array($group, $groups)) { if (!in_array($group, $groups)) {

View File

@ -58,7 +58,7 @@ $config = [
/* /*
* The following settings are *filesystem paths* which define where * The following settings are *filesystem paths* which define where
* SimpleSAMLphp can find or write the following things: * SimpleSAMLphp can find or write the following things:
* - 'cachedir': Where SimpleSAMLphp can write its cache. * - 'cachedir': Where SimpleSAMLphp can write its cache.
* - 'loggingdir': Where to write logs. MUST be set to NULL when using a logging * - 'loggingdir': Where to write logs. MUST be set to NULL when using a logging
* handler other than `file`. * handler other than `file`.
* - 'datadir': Storage of general data. * - 'datadir': Storage of general data.

View File

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

View File

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

View File

@ -879,15 +879,15 @@ let
inherit (pkgs) pam_krb5 pam_ccreds; inherit (pkgs) pam_krb5 pam_ccreds;
use_ldap = (config.users.ldap.enable && config.users.ldap.loginPam); use_ldap = config.users.ldap.enable && config.users.ldap.loginPam;
pam_ldap = if config.users.ldap.daemon.enable then pkgs.nss_pam_ldapd else pkgs.pam_ldap; pam_ldap = if config.users.ldap.daemon.enable then pkgs.nss_pam_ldapd else pkgs.pam_ldap;
# Create a limits.conf(5) file. # Create a limits.conf(5) file.
makeLimitsConf = limits: makeLimitsConf = limits:
pkgs.writeText "limits.conf" pkgs.writeText "limits.conf"
(concatMapStrings ({ domain, type, item, value }: (concatMapStrings ({ domain, type, item, value }:
"${domain} ${type} ${item} ${toString value}\n") "${domain} ${type} ${item} ${toString value}\n")
limits); limits);
limitsType = with lib.types; listOf (submodule ({ ... }: { limitsType = with lib.types; listOf (submodule ({ ... }: {
options = { options = {
@ -935,8 +935,8 @@ let
})); }));
motd = if config.users.motdFile == null motd = if config.users.motdFile == null
then pkgs.writeText "motd" config.users.motd then pkgs.writeText "motd" config.users.motd
else config.users.motdFile; else config.users.motdFile;
makePAMService = name: service: makePAMService = name: service:
{ name = "pam.d/${name}"; { name = "pam.d/${name}";
@ -976,20 +976,20 @@ in
item = "maxlogins"; item = "maxlogins";
value = "4"; value = "4";
} }
]; ];
description = lib.mdDoc '' description = lib.mdDoc ''
Define resource limits that should apply to users or groups. Define resource limits that should apply to users or groups.
Each item in the list should be an attribute set with a Each item in the list should be an attribute set with a
{var}`domain`, {var}`type`, {var}`domain`, {var}`type`,
{var}`item`, and {var}`value` {var}`item`, and {var}`value`
attribute. The syntax and semantics of these attributes attribute. The syntax and semantics of these attributes
must be that described in {manpage}`limits.conf(5)`. must be that described in {manpage}`limits.conf(5)`.
Note that these limits do not apply to systemd services, Note that these limits do not apply to systemd services,
whose limits can be changed via {option}`systemd.extraConfig` whose limits can be changed via {option}`systemd.extraConfig`
instead. instead.
''; '';
}; };
security.pam.services = mkOption { security.pam.services = mkOption {
@ -1507,10 +1507,10 @@ in
runuser = { rootOK = true; unixAuth = false; setEnvironment = false; }; runuser = { rootOK = true; unixAuth = false; setEnvironment = false; };
/* FIXME: should runuser -l start a systemd session? Currently /* FIXME: should runuser -l start a systemd session? Currently
it complains "Cannot create session: Already running in a it complains "Cannot create session: Already running in a
session". */ session". */
runuser-l = { rootOK = true; unixAuth = false; }; runuser-l = { rootOK = true; unixAuth = false; };
} // optionalAttrs (config.security.pam.enableFscrypt) { } // optionalAttrs config.security.pam.enableFscrypt {
# Allow fscrypt to verify login passphrase # Allow fscrypt to verify login passphrase
fscrypt = {}; fscrypt = {};
}; };

View File

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

View File

@ -58,7 +58,7 @@ $config = [
/* /*
* The following settings are *filesystem paths* which define where * The following settings are *filesystem paths* which define where
* SimpleSAMLphp can find or write the following things: * SimpleSAMLphp can find or write the following things:
* - 'cachedir': Where SimpleSAMLphp can write its cache. * - 'cachedir': Where SimpleSAMLphp can write its cache.
* - 'loggingdir': Where to write logs. MUST be set to NULL when using a logging * - 'loggingdir': Where to write logs. MUST be set to NULL when using a logging
* handler other than `file`. * handler other than `file`.
* - 'datadir': Storage of general data. * - 'datadir': Storage of general data.

View File

@ -1,25 +0,0 @@
{ config, pkgs, lib, ... }:
let
domain = "azul.pvv.ntnu.no";
in
{
services.ozai.enable = true;
services.ozai.host = "0.0.0.0";
services.ozai.port = 8000;
services.ozai-webui = {
enable = true;
port = 8085;
host = "127.0.0.1";
};
services.nginx.virtualHosts."${domain}" = {
forceSSL = true;
enableACME = true;
locations."/" = {
proxyWebsockets = true;
proxyPass = "http://${config.services.ozai.host}:${config.services.ozai.port}";
};
};
}

View File

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

View File

@ -65,4 +65,40 @@ in {
proxyWebsockets = true; proxyWebsockets = true;
}; };
}; };
systemd.services.vaultwarden = lib.mkIf cfg.enable {
serviceConfig = {
AmbientCapabilities = [ "" ];
CapabilityBoundingSet = [ "" ];
DeviceAllow = [ "" ];
LockPersonality = true;
NoNewPrivileges = true;
# MemoryDenyWriteExecute = true;
PrivateMounts = true;
PrivateUsers = true;
ProcSubset = "pid";
ProtectClock = true;
ProtectControlGroups = true;
ProtectHostname = true;
ProtectKernelLogs = true;
ProtectKernelModules = true;
ProtectKernelTunables = true;
ProtectProc = "invisible";
RestrictAddressFamilies = [
"AF_INET"
"AF_INET6"
"AF_UNIX"
];
RemoveIPC = true;
RestrictNamespaces = true;
RestrictRealtime = true;
RestrictSUIDSGID = true;
SystemCallArchitectures = "native";
SystemCallFilter = [
"@system-service"
"~@privileged"
];
UMask = "0007";
};
};
} }

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

@ -1,14 +1,14 @@
{ config, lib, pkgs, secrets, ... }: { config, lib, fp, pkgs, secrets, values, ... }:
{ {
sops.secrets."matrix/synapse/turnconfig" = { sops.secrets."matrix/synapse/turnconfig" = {
sopsFile = ../../../../secrets/bicep/matrix.yaml; sopsFile = fp /secrets/bicep/matrix.yaml;
key = "synapse/turnconfig"; key = "synapse/turnconfig";
owner = config.users.users.matrix-synapse.name; owner = config.users.users.matrix-synapse.name;
group = config.users.users.matrix-synapse.group; group = config.users.users.matrix-synapse.group;
}; };
sops.secrets."matrix/coturn/static-auth-secret" = { sops.secrets."matrix/coturn/static-auth-secret" = {
sopsFile = ../../../../secrets/bicep/matrix.yaml; sopsFile = fp /secrets/bicep/matrix.yaml;
key = "coturn/static-auth-secret"; key = "coturn/static-auth-secret";
owner = config.users.users.turnserver.name; owner = config.users.users.turnserver.name;
group = config.users.users.turnserver.group; group = config.users.users.turnserver.group;
@ -26,7 +26,7 @@
"turns:turn.pvv.ntnu.no:5349?transport=tcp" "turns:turn.pvv.ntnu.no:5349?transport=tcp"
"turns:turn.pvv.ntnu.no:5349?transport=udp" "turns:turn.pvv.ntnu.no:5349?transport=udp"
"turns:turn.pvv.ntnu.no:3478?transport=udp" "turns:turn.pvv.ntnu.no:3478?transport=udp"
"turns:turn.pvv.ntnu.no:3478?transport=tcp" "turns:turn.pvv.ntnu.no:3478?transport=tcp"
"turn:turn.pvv.ntnu.no:3478?transport=udp" "turn:turn.pvv.ntnu.no:3478?transport=udp"
@ -60,16 +60,18 @@
pkey = "${config.security.acme.certs.${realm}.directory}/key.pem"; pkey = "${config.security.acme.certs.${realm}.directory}/key.pem";
use-auth-secret = true; use-auth-secret = true;
# World readable but I dont think it's that bad
static-auth-secret-file = config.sops.secrets."matrix/coturn/static-auth-secret".path; static-auth-secret-file = config.sops.secrets."matrix/coturn/static-auth-secret".path;
secure-stun = true; secure-stun = true;
listening-ips = [ "129.241.210.213" "2001:700:300:1900::213" ]; listening-ips = [
values.services.turn.ipv4
# values.services.turn.ipv6
];
tls-listening-port = 443; tls-listening-port = 443;
alt-tls-listening-port = 5349; alt-tls-listening-port = 5349;
listening-port = 3478; listening-port = 3478;
min-port = 49000; min-port = 49000;
@ -116,7 +118,7 @@
#total-quota=1200 #total-quota=1200
''; '';
}; };
networking.firewall = { networking.firewall = {
interfaces.enp6s0f0 = let interfaces.enp6s0f0 = let
range = with config.services.coturn; [ { range = with config.services.coturn; [ {

View File

@ -10,8 +10,9 @@
./mjolnir.nix ./mjolnir.nix
./discord.nix ./discord.nix
./hookshot
]; ];
} }

View File

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

View File

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

Binary file not shown.

After

Width:  |  Height:  |  Size: 1.1 MiB

View File

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

View File

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

View File

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

View File

@ -15,12 +15,12 @@
mysqld = { mysqld = {
# PVV allows a lot of connections at the same time # PVV allows a lot of connections at the same time
max_connect_errors = 10000; max_connect_errors = 10000;
bind-address = values.services.mysql.ipv4; bind-address = values.services.mysql.ipv4;
skip-networking = 0; skip-networking = 0;
# 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;
}; };
}; };

View File

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

View File

@ -35,10 +35,10 @@
# Workaround for bug https://github.com/NixOS/nixpkgs/issues/162686 # Workaround for bug https://github.com/NixOS/nixpkgs/issues/162686
useHostResolvConf = mkForce false; useHostResolvConf = mkForce false;
}; };
system.stateVersion = "23.11"; system.stateVersion = "23.11";
services.resolved.enable = true; services.resolved.enable = true;
}; };
}; };
}; };

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

File diff suppressed because it is too large Load Diff

View File

@ -23187,4 +23187,4 @@
"uid": "rYdddlPWk", "uid": "rYdddlPWk",
"version": 9, "version": 9,
"weekStart": "" "weekStart": ""
} }

View File

@ -3164,4 +3164,4 @@
"title": "PostgreSQL Database", "title": "PostgreSQL Database",
"uid": "000000039", "uid": "000000039",
"version": 1 "version": 1
} }

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

@ -38,7 +38,7 @@ in {
}; };
systemd.services.prometheus-postgres-exporter-knakelibrak.serviceConfig = let systemd.services.prometheus-postgres-exporter-knakelibrak.serviceConfig = let
localCfg = config.services.prometheus.exporters.postgres; localCfg = config.services.prometheus.exporters.postgres;
in lib.recursiveUpdate config.systemd.services.prometheus-postgres-exporter.serviceConfig { in lib.recursiveUpdate config.systemd.services.prometheus-postgres-exporter.serviceConfig {
EnvironmentFile = config.sops.secrets."keys/postgres/postgres_exporter_knakelibrak_env".path; EnvironmentFile = config.sops.secrets."keys/postgres/postgres_exporter_knakelibrak_env".path;
ExecStart = '' ExecStart = ''

View File

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

View File

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

25
justfile Normal file
View File

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

View File

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

View File

@ -32,7 +32,7 @@
color = "red"; color = "red";
command = "hostname | ${pkgs.toilet}/bin/toilet -f mono9"; command = "hostname | ${pkgs.toilet}/bin/toilet -f mono9";
}; };
service_status = { service_status = {
Accounts = "accounts-daemon"; Accounts = "accounts-daemon";
Cron = "cron"; Cron = "cron";
@ -40,16 +40,16 @@
Matrix = "matrix-synapse"; Matrix = "matrix-synapse";
sshd = "sshd"; sshd = "sshd";
}; };
uptime = { uptime = {
prefix = "Uptime: "; prefix = "Uptime: ";
}; };
# Not relevant for server # Not relevant for server
# user_service_status = { # user_service_status = {
# Gpg-agent = "gpg-agent"; # Gpg-agent = "gpg-agent";
# }; # };
filesystems = let filesystems = let
inherit (lib.attrsets) attrNames listToAttrs nameValuePair; inherit (lib.attrsets) attrNames listToAttrs nameValuePair;
inherit (lib.lists) imap1; inherit (lib.lists) imap1;
@ -61,7 +61,7 @@
getName = i: v: if (v.label != null) then v.label else "<? ${toString i}>"; getName = i: v: if (v.label != null) then v.label else "<? ${toString i}>";
in in
imap1Attrs' (i: n: v: nameValuePair (getName i v) n) fileSystems; imap1Attrs' (i: n: v: nameValuePair (getName i v) n) fileSystems;
memory = { memory = {
swap_pos = "beside"; # or "below" or "none" swap_pos = "beside"; # or "below" or "none"
}; };
@ -70,14 +70,14 @@
inherit (lib.lists) imap1; inherit (lib.lists) imap1;
inherit (lib.attrsets) filterAttrs nameValuePair attrValues listToAttrs; inherit (lib.attrsets) filterAttrs nameValuePair attrValues listToAttrs;
inherit (config.users) users; inherit (config.users) users;
normalUsers = filterAttrs (n: v: v.isNormalUser || n == "root") users; normalUsers = filterAttrs (n: v: v.isNormalUser || n == "root") users;
userNPVs = imap1 (index: user: nameValuePair user.name index) (attrValues normalUsers); userNPVs = imap1 (index: user: nameValuePair user.name index) (attrValues normalUsers);
in listToAttrs userNPVs; in listToAttrs userNPVs;
last_run = {}; last_run = {};
}; };
toml = pkgs.formats.toml {}; toml = pkgs.formats.toml {};
in toml.generate "rust-motd.toml" cfg; in toml.generate "rust-motd.toml" cfg;

View File

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

View File

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

30
packages/bluemap.nix Normal file
View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

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