Compare commits

...

139 commits

Author SHA1 Message Date
Raito Bezarius
c0fe0671a8 core-services-01: update secrets on matterbridge
Signed-off-by: Raito Bezarius <masterancpp@gmail.com>
2024-04-29 14:13:54 +02:00
Raito Bezarius
3aa1369056 router(*): add Julien's X2100 laptop to the wgadmin
Signed-off-by: Raito Bezarius <masterancpp@gmail.com>
2024-04-29 14:13:45 +02:00
Raito Bezarius
dfeeb1c4ea router(*): VRRP the admin interface
Now, the Proxmox can be accessed while redeploying one of the router!
2024-01-12 04:36:15 +01:00
Raito Bezarius
bcbfc91a11 router(*): Use unicast rather than multicast
Due to an unfathomable issue where I would need to recompile with full debug keepalived,
keepalived seems to be not seeing the multicast packets on the vrrp-router
and thus we need to fallback to the disgusting unicast solution.

Well, let's move on.
2024-01-12 04:22:34 +01:00
Raito Bezarius
683555e4eb router04: init and add to VRRP group 2024-01-12 04:04:23 +01:00
Raito Bezarius
2555b97680 router03: enable VRRP 2024-01-12 04:04:10 +01:00
Raito Bezarius
fa0ce6b7ef modules/krz-router: support VRRP
This adds VRRP support on a management L2 domain.

All of this is a bit insecure, we should at least aim to share a password or something.
2024-01-12 04:03:57 +01:00
Raito Bezarius
1a6f9ffb8f router03: perfect refactor into a proper NixOS module
We will focus on growing it for KlubRZ usecases first and then grow it into a proper
external project called Hypervisor NixOS routers.
2024-01-12 02:22:05 +01:00
Raito Bezarius
a0681ee841 router03: fix leakage of MWAN traffic
When traffic is coming in, i.e. `To = 45.13.104.25/29`, we were immediately redirecting
it to `swp`, i.e. ENS.

By saying that `To` should also consult the MWAN routing table, we are eliminating
the redirection.
2024-01-12 02:02:14 +01:00
Raito Bezarius
94a64b792c router03: init 2024-01-02 00:39:33 +01:00
9236bed612 feat(npins): Update nix-lib 2023-12-22 23:53:55 +01:00
779f3f3d9e core-services-01: fix cname 2023-12-21 15:12:44 +01:00
9fd583a9cc core-services-01: Disable services 2023-12-21 14:32:12 +01:00
9c32d9b838 core-services-01: Update DNS config 2023-12-21 14:31:50 +01:00
Raito Bezarius
3f20242eab remote-builder-01: decommission 2023-12-21 12:28:49 +01:00
Raito Bezarius
49ed2855a5 core-01: redirect most of our services to web01.dmi01.infra.dgnum.eu 2023-12-21 12:27:55 +01:00
41fc60e1eb core-01: Disable netboot-server 2023-07-23 23:56:33 +02:00
29034e6056 krops.nix: Delete 2023-07-23 23:50:10 +02:00
7f88c60cc2 Switch from krops to colmena 2023-07-23 23:36:55 +02:00
6b6470eef9 keys: Move from machines/publickeys 2023-07-23 23:36:06 +02:00
50c17c74bb Add 'CONTRIBUTING.md' 2023-07-23 18:07:44 +02:00
sinavir
6fb8528a99 public-cof: upgrade garage 2023-07-23 18:07:40 +02:00
Raito Bezarius
2ab0cc6885 public-cof: NC25 → NC26
Get us rid of RC4 encryption shenigans.
2023-07-23 17:52:45 +02:00
sinavir
55c7194022 core-01: make it work for 23.05 2023-07-23 17:49:32 +02:00
Raito Bezarius
793e4d2aee public-cof: add some tuning for lychee 2023-07-19 00:22:03 +02:00
Raito Bezarius
42cd2d7b79 public-cof: add thubrecht 2023-07-19 00:21:54 +02:00
Raito Bezarius
b88167f46a deployment: fix it for 23.05… 2023-07-19 00:21:44 +02:00
Raito Bezarius
2fde8ccf15 deployment: upgrade to 23.05 2023-07-19 00:04:42 +02:00
sinavir
deffb8e1fc core-01: fix ipv4 routing issue 2023-02-24 10:56:54 +01:00
3f2e795b0e chore: Rename module options 2023-02-23 23:59:59 +00:00
66c40b1026 feat: Add sinavir's keys to public-cof and remote-builder-01 2023-02-23 23:59:59 +00:00
244c8027aa feat: Add sinavir's keys for core-services-01 2023-02-23 23:59:59 +00:00
461b1e2aa7 Merge pull request 'fix serveur photos' (#24) from serveur_photos_fix into master
Reviewed-on: https://git.rz.ens.wtf/Klub-RZ/infrastructure/pulls/24
2023-01-30 21:35:33 +01:00
sinavir
455fd180d2 pm=dynamic 2023-01-30 21:21:29 +01:00
bd22c63ec4 public-cof: Switch to systemd-network 2023-01-25 16:55:22 +01:00
f410aa4c75 core-services-01: Switch to systemd-network 2023-01-25 15:35:41 +01:00
Raito Bezarius
5138eb930f core-services-01: add hubrecht 2023-01-24 21:14:04 +01:00
sinavir
9a0c9c615c feat: introduce photos.ens.wtf
Co-authored-by: sinavir <sinavir@sinavir.fr>
Reviewed-on: https://git.rz.ens.wtf/Klub-RZ/infrastructure/pulls/15
Co-authored-by: sinavir <maurice.debray@ens.fr>
Co-committed-by: sinavir <maurice.debray@ens.fr>
2022-12-13 22:23:35 +01:00
Ryan Lahfa
ed92c3df99 Merge pull request 'whitelist thejohncrafter' (#14) from mrf-whitelist into master
Reviewed-on: https://git.rz.ens.wtf/Klub-RZ/infrastructure/pulls/14
2022-12-03 22:14:35 +01:00
Julien Marquet
66ae9b2d04 whitelist thejohncrafter 2022-12-03 21:15:40 +01:00
Raito Bezarius
dbd7594d59 mc: whitelist more players 2022-11-14 23:46:55 +01:00
Raito Bezarius
a2c58e4d87 mc: add Clem's friends to whitelist 2022-11-05 15:48:40 +01:00
Raito Bezarius
d1bc89653c public-cof: fix NC encryption 2022-10-29 17:33:05 +02:00
Raito Bezarius
82cfe98dde core01: fix matterbridge for DGNum 2022-10-29 17:32:39 +02:00
Raito Bezarius
555aabb798 krops: bump channel 2022-10-29 17:32:19 +02:00
Raito Bezarius
42a569b41d public-cof: deploy completely Outline and Garage 2022-10-29 17:32:10 +02:00
Raito Bezarius
43d3367e9f core01: DNS for Garage & Outline 2022-10-29 17:31:46 +02:00
Raito Bezarius
b40a49feed feat: add notion.rz.ens.wtf → public-cof 2022-10-28 00:36:57 +02:00
Raito Bezarius
7beba08321 public-cof: nextcloud24 -> nextcloud25 2022-10-27 22:40:43 +02:00
Raito Bezarius
ccf00cdc46 public-cof: nextcloud23 -> nextcloud24 2022-10-27 22:31:55 +02:00
Raito Bezarius
e827b28967 feat: deploy garage on public-cof 2022-10-27 22:31:47 +02:00
Raito Bezarius
570071bb71 feat: bump to 1.19.2 and add clem197 to allow-list 2022-10-13 21:52:40 +02:00
Raito Bezarius
6b02a84975 core01: initialize tunnels setup 2022-10-12 01:29:08 +02:00
Raito Bezarius
964912c3d4 core01: try latest nightly for netdata and disable cloud 2022-10-09 14:43:29 +02:00
Raito Bezarius
4bc4550540 Revert "feat: remove netdata package pin"
This reverts commit 179a628a4d.
2022-10-02 00:21:16 +02:00
Raito Bezarius
179a628a4d feat: remove netdata package pin 2022-10-01 23:04:19 +02:00
Raito Bezarius
124ec3ab73 feat: bridge #dgnum over Merle 2022-10-01 22:49:56 +02:00
Raito Bezarius
893339ba0b feat: fully functional kanboard 2022-09-18 18:40:55 +02:00
Raito Bezarius
5a796ef74f Revert "Networkd ipv6"
This reverts commit 6e94647d8e.
2022-09-17 21:26:56 +02:00
Raito Bezarius
001c9b0136 all: bump to latest nixos-unstable 2022-09-17 21:26:46 +02:00
Raito Bezarius
d2467fe0bd public-cof: add kanboard 2022-09-17 21:26:46 +02:00
Raito Bezarius
a373803629 patch(keycloak): remove crc patch 2022-09-17 21:26:46 +02:00
6e94647d8e Networkd ipv6 2022-09-13 23:59:59 +00:00
Raito Bezarius
9c006a3519 public-cof: fix docs.beta.rz.ens.wtf 2022-09-13 18:49:49 +02:00
Raito Bezarius
9a24316300 core01: add todo.beta.rz.ens.wtf DNS 2022-09-13 18:49:38 +02:00
Raito Bezarius
badae72a29 feat(public-cof): prevent nginx to bind on all IPv4 2022-09-10 16:20:47 +02:00
Raito Bezarius
c25b0f0eee feat(public-cof): ensure that hedgedocs bind on local ipv6 2022-09-10 16:20:47 +02:00
Raito Bezarius
71e5dcc437 feat(public-cof): disable rstudio server 2022-09-10 16:20:47 +02:00
Raito Bezarius
54163ed857 feat(public-cof): add IPv4 → IPv6 proxy 2022-09-10 16:20:47 +02:00
Raito Bezarius
c90e89bc7a feat: add traque.beta.rz.ens.wtf 2022-09-10 15:30:03 +02:00
Raito Bezarius
7284a9a2d6 meta: use root@core01.rz.ens.wtf rather than internal IP 2022-09-06 01:33:26 +02:00
Raito Bezarius
726bc5af0e feat(core01): enable TLS on inventory.rz.ens.wtf and fix secrets perms 2022-09-06 01:33:17 +02:00
Raito Bezarius
dc971eff71 feat(core01): add inventory.rz.ens.wtf → snipe-it instance 2022-09-06 01:06:39 +02:00
Raito Bezarius
86de42442d feat: add rstudio.beta.rz.ens.wtf basic features 2022-08-17 18:06:26 +02:00
Raito Bezarius
7f5f3213ac hotfix: disable student calendar 2022-08-15 13:31:27 +02:00
c5aa20dffa Move pubkeys in ./machines
This is required by the current krops setup.
2022-08-15 23:59:59 +00:00
ba5086a237 Centralize pubkeys 2022-08-15 03:28:40 +02:00
16f4ad94b1 Add public-cof to README.md 2022-08-15 03:19:33 +02:00
85ab8d8071 Install git
Needed for deployments with krops.
2022-08-15 23:59:59 +00:00
4375b29d50 Aarch64 emulation 2022-08-15 03:00:30 +02:00
bb668034b1 Cleanups 2022-08-15 02:59:45 +02:00
122c0deeac DHCP on ens19 and ens18 + set ip on ens18 2022-08-15 23:59:59 +00:00
816e084deb Change rpool layout and disk id 2022-08-15 01:20:35 +02:00
3f10516b6f Add kitty terminfo 2022-08-15 00:20:07 +02:00
f7b6fdf07a Fix remote builder ip address 2022-08-15 00:00:55 +02:00
a5f3e05889 Formatting 2022-08-14 22:27:28 +02:00
5170bdff65 Cleanups 2022-08-14 22:27:15 +02:00
ac0b6ef15b Update networking interface 2022-08-14 22:25:34 +02:00
Raito Bezarius
506e099945 monitoring: move to tiered dbengine with netdata nightly 2022-08-05 18:52:06 +02:00
Raito Bezarius
6b994c8591 gitea: log only from WARN and up 2022-08-05 17:52:28 +02:00
Raito Bezarius
be6e81ad46 monitoring: fix authentication via oauth2_proxy by moving to Keycloak-OIDC + many proxy buffer hacks 2022-08-05 17:52:21 +02:00
Raito Bezarius
9d3381cafb oauth2_proxy: add a cookie specific to *.rz.ens.wtf 2022-08-05 16:34:22 +02:00
Ryan Lahfa
6f5fdb0317 Headscale support (upgrade to latest nixpkgs) (#9)
This adds Headscale support.

It provides also an upgrade to Keycloak 18.0.0 (Quarkus distribution).
It upgrades NextCloud from 22 to 23.

Reviewed-on: https://git.rz.ens.wtf/Klub-RZ/infrastructure/pulls/9
Co-authored-by: Ryan Lahfa <raito@noreply.git.rz.ens.wtf>
Co-committed-by: Ryan Lahfa <raito@noreply.git.rz.ens.wtf>
2022-06-26 23:48:43 +02:00
57b5c931d1 Add CiterinRemy to MC whitelist 2022-05-21 23:59:59 +00:00
Raito Bezarius
f842b30e05 core01: allow *, unfirewall wgmon 2022-05-15 00:08:46 +02:00
Raito Bezarius
5f2a5ff782 core01: generalize monitoring, open up a wgmon for external nodes 2022-05-14 20:21:18 +02:00
544df15eb1 Enable command blocks in the minecraft server 2022-05-11 23:59:59 +00:00
Raito Bezarius
df2b7e819d public-cof: upgrade nextcloud (21 → 22) 2022-04-17 01:34:44 +02:00
6a3af7d165 Add Pollux to MC whitelist 2022-04-13 23:59:59 +00:00
ab9d022b33 Add Cst1 to MC whitelist 2022-04-07 23:59:59 +00:00
Raito Bezarius
dcc0085c41 public-cof: add framagenda.org 2022-03-29 23:04:31 +02:00
e472173bad Update MC server 2022-03-29 23:59:59 +00:00
Raito Bezarius
bacdad33d3 public-cof: improve monitoring of postgresql 2022-03-08 19:47:32 +01:00
Raito Bezarius
4355c00f8e ci: test public-cof configuration 2022-03-06 20:22:09 +01:00
Raito Bezarius
2721ad9b71 public-cof: improve monitoring of system and nextcloud performance 2022-03-06 20:22:03 +01:00
Raito Bezarius
bfdfa5a206 core01: rotate drone key, update swap uuid, bump netdata multihost disk space for 30d of metrics 2022-03-06 20:21:37 +01:00
Raito Bezarius
e03a3f16f8 public-cof: add monitoring, deploy home.beta.rz.ens.wtf properly 2022-03-05 23:17:06 +01:00
Raito Bezarius
e1e8401160 public-cof: update Raito's NUR 2022-03-05 23:17:06 +01:00
Raito Bezarius
e0167f27d3 core01: open up Gitea registration and whitelist @ens.fr emails 2022-03-05 23:17:06 +01:00
Raito Bezarius
b581fbcfc5 core01: fix #6, remove Dex 2022-03-05 23:17:06 +01:00
Julien Marquet
09ad6670ed feat: Matterbridge
je suis fatigué
2022-02-23 01:42:26 +01:00
Raito Bezarius
075cd90fb7 core01: rekey with MrF, add pve01 hypervisor monitoring 2022-02-22 23:25:46 +01:00
e290a918a0 progress on dex... 2022-01-25 23:59:59 +00:00
52d0f1433a Ryan tu me doit 10k 2022-01-25 23:59:59 +00:00
7193ee270a add dex to confifiguration.nix 2022-01-25 23:59:59 +00:00
6535ca50af add dex 2022-01-25 23:59:59 +00:00
Julien Marquet
3670aab583 ipv4 for public-cof 2022-01-25 18:12:54 +01:00
Raito Bezarius
7e11763d74 core01: Add MrF keys for real 2022-01-25 17:52:56 +01:00
Raito Bezarius
cb92be5d72 core01: add MrF key, default gateway, A for acme 2022-01-25 00:37:12 +01:00
Raito Bezarius
067ab1d7cc core01/public-cof: flush changes, router02 → router01 2022-01-24 22:04:43 +01:00
Raito Bezarius
2c321dd0aa core-services: bump dbengine disk size to 4GiB 2021-12-29 17:33:28 +01:00
Raito Bezarius
8ac5d2e4ab core-services: adjust to our changes in IPv4 network for MWAN/local net 2021-12-19 14:51:12 +01:00
Raito Bezarius
916b06ad1f dns: jurisprudens.beta.rz.ens.wtf → public COF with v4 upstream proxy 2021-11-21 11:53:50 +01:00
Raito Bezarius
f3f4431f2c core-services: use jre8 for keycloak, fixes LDAP federation 2021-11-21 11:53:30 +01:00
Raito Bezarius
d8a577b078 public-cof: fix cryptpad 2021-11-20 21:01:42 +01:00
5e24c6c8c7 try simple cryptpad module 2021-11-15 01:06:57 +01:00
b2eb90564d change hedgedoc localhost port 2021-11-15 01:02:47 +01:00
Raito Bezarius
bf2ecf0874 public-cof: add agenix modules 2021-11-15 00:54:27 +01:00
Raito Bezarius
77b86de5c4 public-cof: proxy ws for hedgedoc 2021-11-15 00:48:11 +01:00
Raito Bezarius
885ba660f5 public-cof: get back to default port 2021-11-15 00:36:46 +01:00
Raito Bezarius
f5eafee411 public-cof: secure nextcloud using agenix 2021-11-15 00:36:46 +01:00
bb89a44d87 add RaitoMezarius to the MC whitlist 2021-11-15 00:19:27 +01:00
ea6b47e4bd add mrf keys 2021-11-15 00:16:01 +01:00
71797ad07e start a cryptpad module 2021-11-15 00:09:44 +01:00
d0b0093ba6 make home.beta.rz.ens.wtf the nginx default 2021-11-14 23:57:19 +01:00
10a5cef823 add hedgedoc 2021-11-14 23:56:00 +01:00
ff0a6b450f remove space in MC level name 2021-11-14 01:28:51 +01:00
f8cc9879ef close unused UDP port 2021-11-13 23:54:30 +01:00
gdd
b3da6272e5 Merge pull request 'public-cof' (#5) from public-cof into master 2021-11-13 23:51:16 +01:00
104 changed files with 3220 additions and 442 deletions

View file

@ -19,5 +19,9 @@ steps:
commands:
- "export NIX_PATH=nixpkgs=/var/nixpkgs"
- "echo Building remote-builder-01 && nix-build krops.nix -A test-remote-builder-01 && ./result"
- name: Build public-cof configuration
commands:
- "export NIX_PATH=nixpkgs=/var/nixpkgs"
- "echo Building public-cof && nix-build krops.nix -A test-public-cof && ./result"
...

1
.envrc Normal file
View file

@ -0,0 +1 @@
use nix

1
.gitignore vendored
View file

@ -1 +1,2 @@
result
.direnv

1
CONTRIBUTING.md Normal file
View file

@ -0,0 +1 @@
Maurice écoute les conventions de Ryan

View file

@ -5,7 +5,8 @@
Refer to wiki for details.
- `core-services-01`
- `remote-builder-01`
- `public-cof`
- `remote-builder-01`: **discontinued**.
## How to deploy a machine?

62
hive.nix Normal file
View file

@ -0,0 +1,62 @@
let
sources = import ./npins;
metadata = import ./meta;
lib = import (sources.nix-lib + "/src/trivial.nix");
mkNode = node: { name, nodes, ... }: {
# Import the base configuration for each node
imports = builtins.map (lib.mkRel ./machines/${node}) [
"_configuration.nix"
"_hardware-configuration.nix"
];
# Include default secrets
# dgn-secrets.sources = [ ./machines/${node}/secrets ];
# Deployment config is specified in meta.nodes.${node}.deployment
inherit (metadata.nodes.${node}) deployment;
# Set NIX_PATH to the patched version of nixpkgs
nix.nixPath = [ "nixpkgs=${mkNixpkgs node}" ];
# Use the stateVersion declared in the metadata
system.stateVersion = metadata.nodes.${node}.stateVersion;
};
mkNixpkgs = node:
let version = "nixos-${metadata.nodes.${node}.nixpkgs}"; in
(import sources.${version} { }).applyPatches {
name = "${version}-patched";
src = sources.${version};
patches = (import ./nix-patches).${version} or [ ];
};
mkNixpkgs' = node: import (mkNixpkgs node) { };
mkArgs = node:
let lib' = (mkNixpkgs' node).lib;
in {
lib = import sources.nix-lib {
lib = lib';
keysRoot = ./keys;
};
};
nodes = builtins.attrNames metadata.nodes;
in
{
meta = {
nodeNixpkgs = lib.mapSingleFuse mkNixpkgs' nodes;
specialArgs = { inherit sources; meta = metadata; };
nodeSpecialArgs = lib.mapSingleFuse mkArgs nodes;
};
defaults = { ... }: {
# Import the default modules
imports = [ ./modules ];
};
} // (lib.mapSingleFuse mkNode nodes)

1
keys/hubrecht.keys Normal file
View file

@ -0,0 +1 @@
ssh-ed25519 AAAAC3NzaC1lZDI1NTE5AAAAIIv3iSpIjeUVDf+f89Hb/L++vzMX15Ti/PZTjAAG+tFl

1
keys/mrf.keys Normal file
View file

@ -0,0 +1 @@
ssh-ed25519 AAAAC3NzaC1lZDI1NTE5AAAAIFe4tx0+lNX2w7kG94c9u7U0wHuOc2A6zpHcbyAs+w/d

1
keys/sinavir.keys Normal file
View file

@ -0,0 +1 @@
ssh-ed25519 AAAAC3NzaC1lZDI1NTE5AAAAIEpwF+XD3HgX64kqD42pcEZRNYAWoO4YNiOm5KO4tH6o

View file

@ -1,35 +0,0 @@
let
krops = builtins.fetchGit { url = "https://cgit.krebsco.de/krops/"; };
lib = import "${krops}/lib";
pkgs = import "${krops}/pkgs" { };
source = machine:
lib.evalSource [{
config.file = toString ./machines;
nixos-config.symlink = "config/${machine}/configuration.nix";
nixpkgs.git = {
clean.exclude = [ "/.version-suffix" ];
ref = "973910f5c31b9ba6c171c33a8bd7199990b14c72"; # nixos-21.05
url = "https://github.com/NixOS/nixpkgs";
};
}];
mkTestConfig = hostname: {
name = "test-${hostname}";
value = pkgs.krops.writeTest "test-${hostname}" {
source = source hostname;
target = lib.mkTarget {
host = "localhost";
path = "/tmp/src";
};
force = true; # force create the sentinel file.
};
};
mkTestsConfig = hostnames: builtins.listToAttrs (map mkTestConfig hostnames);
mkDeploy = hostname: target: { ${hostname} = pkgs.krops.writeDeploy "deploy-${hostname}" {
source = source hostname;
inherit target;
}; };
in {}
// mkDeploy "core-services-01" "root@core01.internal.rz.ens.wtf"
// mkDeploy "remote-builder-01" "root@nix01.builders.rz.ens.wtf"
// mkDeploy "public-cof" "root@beta.rz.ens.wtf"
// mkTestsConfig [ "core-services-01" "remote-builder-01" "public-cof" ]

View file

@ -1,31 +1,36 @@
{ config, pkgs, lib, ... }:
{
imports =
[ # Include the results of the hardware scan.
./hardware-configuration.nix
./nur.nix
./rz.nix
./monitoring.nix
./programs.nix
./system.nix
./acme-ssl.nix
./dns.nix
./netboot-server.nix
./qemu.nix
./gitea.nix
./dokuwiki.nix
./nginx.nix
./keycloak.nix
./acme-dns.nix
./backups.nix
./secrets
# TODO push to gitea
# TODO ./gotify.nix
# TODO(Raito): ./backups.nix
# TODO(Raito): ./snmp.nix
# TODO(Raito): ./sflow.nix?
];
imports = [
./acme-dns.nix
./acme-ssl.nix
./backups.nix
# ./dex.nix
./dns.nix
# ./gitea.nix
./headscale.nix
./keycloak.nix
./matterbridge.nix
# ./monitoring.nix
# ./netboot-server.nix
./network.nix
./nginx.nix
./nur.nix
# ./oauth2_proxy.nix
./programs.nix
./qemu.nix
./rz.nix
./secrets
./snipe-it.nix
./system.nix
./tunnels.nix
# TODO push to gitea
# TODO ./gotify.nix
# TODO(Raito): ./backups.nix
# TODO(Raito): ./snmp.nix
# TODO(Raito): ./sflow.nix?
];
# Use the systemd-boot EFI boot loader.
boot.loader.systemd-boot.enable = true;
@ -69,24 +74,11 @@
services.zfs.autoScrub.enable = true;
# Enable the OpenSSH daemon.
services.openssh.enable = true;
users.users.root.openssh.authorizedKeys.keyFiles = [
./pubkeys/gdd.keys
./pubkeys/raito.keys
];
# Open ports in the firewall.
# networking.firewall.allowedTCPPorts = [ ... ];
# networking.firewall.allowedUDPPorts = [ ... ];
# Or disable the firewall altogether.
networking.firewall.enable = false;
# 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 = "20.09"; # Did you read the comment?
system.stateVersion = "22.05";
}

View file

@ -29,7 +29,7 @@
};
swapDevices =
[ { device = "/dev/disk/by-uuid/0fe95042-8197-4969-a549-65565cf70171"; }
[ { device = "/dev/disk/by-uuid/e32235de-f531-48ad-86b1-dc2163be5127"; }
];
}

View file

@ -5,9 +5,9 @@ let
in
{
security.acme.acceptTerms = true;
security.acme.email = my.email;
security.acme.defaults.email = my.email;
security.acme.server =
security.acme.defaults.server =
if my.acmeStaging
then "https://acme-staging-v02.api.letsencrypt.org/directory"
else null;

View file

@ -0,0 +1,31 @@
{ config, ... }:
let
my = config.my;
in
{
services.dex = {
enable = true;
settings = {
issuer = "http://127.0.0.1:5556/dex";
storage = {
type = "sqlite3";
config.file = "gitea/dex.db";
};
enablePasswordDB = true;
web = {
http = "127.0.0.1:5556";
};
connectors = [ {
type = "gitea";
id = "gitea";
name = "Gitea";
config = {
clientID = "Gitea";
clientSecret = "b2a1b7ae-2f31-489d-84c3-4d429085db14";
redirectURL = "http://127.0.0.1:5556/dex/callback";
baseURL = "https://git.${my.subZone}";
};
} ];
};
};
}

View file

@ -12,13 +12,13 @@ in
settings = {
server = {
access-control = [ "127.0.0.0/8 allow" "::1/128 allow" ] ++ map (v: "${v} allow") my.privateRanges;
interface = [ "127.0.0.1" ] ++ my.ipv4;
interface = [ "127.0.0.1" ] ++ my.ipv4Internal;
};
};
};
services.nsd = {
enable = true;
interfaces = my.ipv6.standard;
interfaces = my.ipv6.standard ++ my.ipv4;
zones = {
${my.subZone} = {
data = dns.lib.toString my.subZone (import ./subZone.nix { inherit dns config lib; });

View file

@ -1,33 +0,0 @@
{ config, ... }:
let
my = config.my;
in
{
services.dokuwiki."wiki.${my.subZone}" = {
enable = true;
hostName = "wiki.${my.subZone}";
acl = ''
* @ALL 1
* @admin 16
'';
nginx = {
enableACME = true;
forceSSL = true;
};
};
/*
services.nginx = {
enable = true;
virtualHosts."wiki.${my.subZone}" = {
enableACME = true;
forceSSL = true;
locations."/" = {
proxyPass = "htttp://127.0.0.1:${toString port}";
};
};
};
*/
}

View file

@ -13,4 +13,6 @@ in
];
envFile = config.age.secrets.droneKeyFile.path;
};
systemd.services."drone-exec-runner-nix01".after = [ "gitea.service" ];
}

View file

@ -13,7 +13,23 @@ in
httpAddress = "127.0.0.1";
httpPort = port;
database.type = "postgres";
disableRegistration = true;
settings = {
service.DISABLE_REGISTRATION = false;
log = {
level = "Warn";
};
openid = {
ENABLE_OPENID_SIGNUP = true;
};
oauth2_account = {
ENABLE_AUTO_REGISTRATION = true;
USERNAME = "email";
};
service = {
EMAIL_DOMAIN_WHITELIST = "ens.fr";
ALLOW_ONLY_EXTERNAL_REGISTRATION = true;
};
};
};
services.nginx = {

View file

@ -0,0 +1,8 @@
{ ... }:
{
services.headscale = {
enable = true;
serverUrl = "https://tailscale.rz.ens.wtf";
tls.letsencrypt.hostname = "tailscale.rz.ens.wtf";
};
}

View file

@ -1,27 +1,44 @@
{ config, ... }:
{ config, pkgs, lib, ... }:
let
my = config.my;
port = 8080;
keycloak-protocol-cas = pkgs.callPackage ./keycloak/keycloak-protocol-cas.nix {};
domain = "auth.${my.subZone}";
certs = config.security.acme.certs."${domain}".directory;
in
{
services.keycloak = {
enable = true;
initialAdminPassword = "changemeasap";
database.createLocally = true;
database.passwordFile = config.age.secrets.keycloakDatabasePasswordFile.path;
frontendUrl = "https://auth.${my.subZone}/auth/";
forceBackendUrlToFrontendUrl = true;
httpPort = toString port;
extraConfig = {
"subsystem=undertow"."server=default-server"."http-listener=default".proxy-address-forwarding = true;
plugins = [ pkgs.keycloak.plugins.keycloak-metrics-spi keycloak-protocol-cas ];
database = {
type = "postgresql";
username = "keycloak";
name = "keycloak";
createLocally = true;
passwordFile = "${config.age.secrets.keycloakDatabasePasswordFile.path}";
};
settings = {
hostname-strict-backchannel = true;
http-port = port;
proxy = "edge";
http-relative-path = "/auth";
hostname = domain;
};
};
services.nginx.virtualHosts."auth.${my.subZone}" = {
services.nginx.virtualHosts."${domain}" = {
forceSSL = true;
enableACME = true;
locations."/" = {
proxyPass = "http://127.0.0.1:${toString port}";
extraConfig = ''
# For large authentication-authorization headers
proxy_buffer_size 128k;
proxy_buffers 4 256k;
proxy_busy_buffers_size 256k;
'';
};
};
}

View file

@ -0,0 +1,26 @@
{ stdenv, lib, fetchurl }:
stdenv.mkDerivation rec {
pname = "keycloak-protocol-cas";
version = "18.0.0";
src = fetchurl {
url = "https://github.com/jacekkow/keycloak-protocol-cas/releases/download/${version}/keycloak-protocol-cas-${version}.jar";
sha256 = "sha256-N+IJqD7oQ4T4MI8klt96kfHwFnPJy5l8MK6bq62nBrM=";
};
dontUnpack = true;
dontBuild = true;
installPhase = ''
mkdir -p $out
install "$src" "$out"
'';
meta = with lib; {
homepage = "https://github.com/jacekkow/keycloak-protocol-cas";
description = "Keycloak Service Provider that adds CAS as an authentication protocol";
license = licenses.apsl20;
maintainers = with maintainers; [ raitobezarius ];
};
}

View file

@ -0,0 +1,50 @@
{ config, pkgs, ... }:
let
manageSecrets = conf: secrets: output: keys:
/*
`secrets` are in the form "SECRET_1=secret\nSECRET_2=secre"
For each name in `keys` we search for a line `$NAME=<secret>`,
(`<secret>` is just everything up to the end of the line)
and we substitute `$NAME` by `<secret>` in `conf`, and we print
the result in `output`.
*/
let
check = key: ''
if grep ${key} ${secrets} > /dev/null
then
true
else
echo "Missing ${key} from secrets"
exit 1
fi
'';
get = key: "$(grep '${key}=' ${secrets} | sed 's/^.*=//' | sed -e 's/[\\/&]/\\\\&/g')";
checks = pkgs.lib.concatMapStrings check;
replaces = pkgs.lib.concatMapStrings (key: "s/${key}/${get key}/;");
in pkgs.writeShellScriptBin "preStart" ''
${checks keys}
sed "${replaces keys}" ${conf} > ${output}
'';
startScript = pkgs.writeShellScriptBin "start" ''
${manageSecrets
./matterbridge.toml "$CREDENTIALS_DIRECTORY/secrets" "$RUNTIME_DIRECTORY/conf.toml"
[ "SECRET_MATTERMOST_KLUBRZ_WEBHOOK" "SECRET_MATTERMOST_DGNUM_WEBHOOK" ]}/bin/preStart
${pkgs.matterbridge}/bin/matterbridge -conf $RUNTIME_DIRECTORY/conf.toml
'';
in {
networking.firewall.allowedTCPPorts = [ 52187 ];
systemd.services.matterbridge = {
description = "Chat platform bridge";
wantedBy = [ "multi-user.target" ];
after = [ "network.target" ];
serviceConfig = {
DynamicUser = true;
LoadCredential = "secrets:${config.age.secrets.matterbridge.path}";
ExecStart = "${startScript}/bin/start";
Restart = "always";
RestartSec = "10";
RuntimeDirectory = "matterbridge";
};
};
}

View file

@ -0,0 +1,38 @@
[irc]
[irc.ulminfo]
Server="ens.wtf:6697"
Nick="botte"
UseTLS=true
Charset="utf8"
PrefixMessagesWithNick=true
RemoteNickFormat="<{NICK}> "
[mattermost]
[mattermost.merle_klubrz]
WebhookURL="SECRET_MATTERMOST_KLUBRZ_WEBHOOK"
WebhookBindAddress="0.0.0.0:52187"
PrefixMessagesWithNick=false
RemoteNickFormat="{NICK}"
[mattermost.merle_dgnum]
WebhookURL="SECRET_MATTERMOST_DGNUM_WEBHOOK"
WebhookBindAddress="0.0.0.0:52188"
PrefixMessagesWithNick=false
RemoteNickFormat="{NICK}"
[[gateway]]
name="réseau"
enable=true
[[gateway.inout]]
account="irc.ulminfo"
channel="#réseau"
[[gateway.inout]]
account="mattermost.merle_klubrz"
channel="town-square"
[[gateway]]
name="dgnum"
enable=true
[[gateway.inout]]
account="irc.ulminfo"
channel="#dgnum"
[[gateway.inout]]
account="mattermost.merle_dgnum"
channel="town-square"

View file

@ -1,25 +1,95 @@
{ config, pkgs, ... }:
{ config, pkgs, lib, ... }:
let
my = config.my;
realm = "ClubReseau";
mkChildNode = { uuid, allowFrom }: { ... }@options: ''
[${uuid}]
enabled = yes
default history = 10000
default memory mode = dbengine
health enabled by default = auto
allow from = ${allowFrom}
'';
testClusterHypervisors = lib.attrValues {
pve01 = {
uuid = "ff9a34ec-2bf4-4389-a01a-6e242424e675";
allowFrom = "*";
# allowFrom = "fd85:27e8:0fc9::2";
};
pve02 = {
uuid = "ed393d76-e325-48c4-be90-3d7a1d3066ee";
allowFrom = "*";
# allowFrom = "fd85:27e8:0fc9::3";
};
pve03 = {
uuid = "abeeab1f-d4f4-4ca7-aabb-54ff28031f82";
allowFrom = "*";
# allowFrom = "fd85:27e8:0fc9::4";
};
pve04 = {
uuid = "ee0f7cec-86f8-4fa2-8258-f7bf4172eb4b";
allowFrom = "*";
# allowFrom = "fd85:27e8:0fc9::5";
};
};
in
{
services.netdata.enable = true;
services.netdata = {
enable = true;
#package = pkgs.netdata.overrideAttrs (old: {
# version = "1.36.0-185-nightly";
# src = pkgs.fetchFromGitHub {
# owner = "netdata";
# repo = "netdata";
# rev = "284d5450ec938b667db9985aca6d3cd02b96487f";
# sha256 = "sha256-QRZL1RjspiqpR1cq8TDqY0wDc4ct7BDY0vbddsvlHgc=";
# fetchSubmodules = true;
# };
#});
};
systemd.services.netdata.restartTriggers = map (v: config.environment.etc."netdata/${v}.conf".source) [
"netdata"
"stream"
"health_alarm_notify"
];
systemd.services.netdata.environment."NETDATA_DISABLE_CLOUD" = "1";
environment.etc."netdata/netdata.conf" = {
# Allow WireGuard VPN
networking.firewall.allowedUDPPorts = [ 51820 ];
# Allow access to the raw netdata
networking.firewall.interfaces.wgmon.allowedUDPPorts = [ 19999 ];
networking.firewall.interfaces.wgmon.allowedTCPPorts = [ 19999 ];
networking.wireguard.interfaces.wgmon = {
ips = [ "fd85:27e8:0fc9::1/48" ];
listenPort = 51820;
privateKeyFile = "/etc/secrets/wgmon";
generatePrivateKeyFile = true;
peers = [
{ publicKey = "6IHA4e+UcCSx9+e5BZwLvzeZv5RWwqO1CCLJedN2nU4="; allowedIPs = [ "fd85:27e8:fc9::2/128" ]; }
{ publicKey = "xRdfylDpi8c+BRwDCxenRs6i4XWesdd75keWfKItZFo="; allowedIPs = [ "fd85:27e8:fc9::3/128" ]; }
{ publicKey = "rjodopHTEyD+DyDsNp8xyNC0KeZGH462Ls495NXT1VI="; allowedIPs = [ "fd85:27e8:fc9::4/128" ];}
{ publicKey = "IJRsrhzCRAHpaEHLZRNdPuDp25FXzuAm+CGmZDsRThk="; allowedIPs = [ "fd85:27e8:fc9::5/128" ]; }
{ publicKey = "oYsN1Qy+a7dwVOKapN5s5KJOmhSflLHZqh+GLMeNpHw="; allowedIPs = [ "fd85:27e8:fc9::6/128" ]; }
# { publicKey = ""; allowedIPs = [ "fd85:27e8:fc9::7/128" ]; }
];
};
environment.etc."netdata/netdata.conf" = lib.mkForce {
user = "netdata";
group = "netdata";
mode = "0600";
text = ''
[global]
page cache size = 32
dbengine multihost disk space = 2048
[db]
mode = dbengine
storage tiers = 3
update every = 1
dbengine multihost disk space MB = 23000
dbengine page cache size MB = 384
dbengine tier 1 update every iterations = 60
dbengine tier 1 multihost disk space MB = 10000
dbengine tier 1 page cache size MB = 384
dbengine tier 2 update every iterations = 3600
dbengine tier 2 multihost disk space MB = 5000
dbengine tier 2 page cache size MB = 384
'';
};
@ -27,14 +97,19 @@ in
user = "netdata";
group = "netdata";
mode = "0600";
text = ''
[e245097d-bf52-4f66-9c10-984e8d5ee178]
enabled = yes
default history = 5000
default memory mode = dbengine
health enabled by default = auto
allow from = 10.1.1.10
'';
text = (lib.concatMapStringsSep "\n" (cfg: mkChildNode cfg {})
([
# PVE01 hypervisor
{
uuid = "e245097d-bf52-4f66-9c10-984e8d5ee178";
allowFrom = "10.1.1.10";
}
# Public COF server
{
uuid = "c48e6ef1-5cdf-408d-ae2f-86aadb14e3fe";
allowFrom = "10.1.1.21";
}
] ++ testClusterHypervisors));
};
environment.etc."netdata/health_alarm_notify.conf" = {
@ -43,7 +118,7 @@ in
mode = "0600";
text = ''
# External tools
nc="${pkgs.netcat}/bin/nc"
nc="${pkgs.nmap}/bin/nc --ssl"
# IRC configuration
SEND_IRC="YES"
@ -57,18 +132,25 @@ in
services.oauth2_proxy = {
enable = true;
keyFile = config.age.secrets.oauth2ProxyKeyFile.path;
provider = "keycloak";
provider = "keycloak-oidc";
email.domains = [ "*" ];
cookie = {
name = "_oauth2_proxy_ensrz";
domain = ".rz.ens.wtf";
};
setXauthrequest = true;
scope = "profile";
loginURL = "https://auth.${my.subZone}/auth/realms/${realm}/protocol/openid-connect/auth";
redeemURL = "https://auth.${my.subZone}/auth/realms/${realm}/protocol/openid-connect/token";
profileURL = "https://auth.${my.subZone}/auth/realms/${realm}/protocol/openid-connect/userinfo";
validateURL = "https://auth.${my.subZone}/auth/realms/${realm}/protocol/openid-connect/userinfo";
scope = "openid";
redirectURL = "https://monitoring.${my.subZone}/oauth2/callback";
reverseProxy = true;
passHostHeader = true;
extraConfig = {
whitelist-domain = [ ".rz.ens.wtf" ];
oidc-issuer-url = "https://auth.${my.subZone}/auth/realms/${realm}";
# insecure-oidc-allow-unverified-email = true;
show-debug-on-error = true;
};
nginx = {
virtualHosts = [ "monitoring.${my.subZone}" ];
};
@ -81,7 +163,15 @@ in
enableACME = true;
forceSSL = true;
locations."/".proxyPass = "http://localhost:19999";
locations."/" = {
proxyPass = "http://localhost:19999";
extraConfig = ''
# For large authentication-authorization headers
proxy_buffer_size 128k;
proxy_buffers 4 256k;
proxy_busy_buffers_size 256k;
'';
};
};
};

View file

@ -46,6 +46,20 @@ in
default = map (v: (mkAddress v).address) cfg.ipv4Full;
};
ipv4Internal = mkOption {
description = "Private IPv4 addresses without prefix";
type = listOf str;
example = [ "192.186.1.153" ];
default = map (v: (mkAddress v).address) cfg.ipv4InternalFull;
};
ipv4InternalFull = mkOption {
description = "Private IPv4 addresses with prefix";
type = listOf str;
default = [];
example = [ "192.168.1.153/24" ];
};
ipv4Full = mkOption {
description = "Public IPv4 addresses with prefix";
type = listOf str;
@ -67,7 +81,7 @@ in
};
ipv6.acme = mkOption {
description = "Public IPv6 address for ACME services (acme-dns) without prefi";
description = "Public IPv6 address for ACME services (acme-dns) without prefix";
type = str;
default = (mkAddress cfg.ipv6.acmeFull).address;
example = "2001:470:1f13:21d:f515:b348:cd48:e064/64";
@ -85,11 +99,4 @@ in
example = [ "10.1.0.0/22" ];
};
};
config = {
networking.interfaces.ens19 = {
ipv4.addresses = map mkAddress cfg.ipv4Full;
ipv6.addresses = map mkAddress (cfg.ipv6.standardFull ++ [ cfg.ipv6.acmeFull ]);
};
};
}

View file

@ -13,8 +13,8 @@ let
# Enable sshd wich gets disabled by netboot-minimal.nix
systemd.services.sshd.wantedBy = mkOverride 0 [ "multi-user.target" ];
users.users.root.openssh.authorizedKeys.keyFiles = [
./pubkeys/gdd.keys
./pubkeys/raito.keys
../pubkeys/gdd.keys
../pubkeys/raito.keys
];
programs.mosh.enable = true;

View file

@ -0,0 +1,43 @@
{ config, ... }:
let
inherit (config) my;
in
{
networking.useNetworkd = true;
systemd.network.networks = {
"10-ens18" = {
name = "ens18";
address = my.ipv4Full;
DHCP = "ipv4";
};
"10-ens19" = {
name = "ens19";
address = with my.ipv6; standardFull ++ [ acmeFull ];
networkConfig.IPv6AcceptRA = true;
ipv6AcceptRAConfig = {
UseOnLinkPrefix = false;
UseAutonomousPrefix = false;
};
};
"10-ens20" = {
name = "ens20";
address = my.ipv4InternalFull;
DHCP = "ipv4";
dhcpV4Config.RouteMetric = 2048;
routes = [
{
routeConfig = {
Destination = "10.0.0.0/8";
};
}
];
};
};
}

View file

@ -0,0 +1,5 @@
{ ... }:
{
users.users.oauth2_proxy.group = "oauth2_proxy";
users.groups.oauth2_proxy = {};
}

View file

@ -11,7 +11,8 @@
"2001:470:1f13:187:fd34:80c3:a761:ff2/64"
];
ipv6.acmeFull = "2001:470:1f13:187:a039:c3ff:fe4f:8661/64";
ipv4Full = [ "10.1.1.20/24" ];
ipv4InternalFull = [ "10.1.1.20/22" ];
ipv4Full = [ "45.13.104.26/32" ];
privateRanges = [ "10.1.0.0/22 "];
};

View file

@ -3,4 +3,8 @@
age.secrets.keycloakDatabasePasswordFile.file = ./keycloakDatabasePasswordFile.age;
age.secrets.oauth2ProxyKeyFile.file = ./oauth2ProxyKeyFile.age;
age.secrets.droneKeyFile.file = ./droneKeyFile.age;
age.secrets.dexGiteaClientSecret.file = ./dexGiteaClientSecret.age;
age.secrets.matterbridge.file = ./matterbridge.age;
age.secrets.snipeItAppKey.file = ./snipeItAppKey.age;
age.secrets.snipeItOidcClientSecret.file = ./snipeItOidcClientSecret.age;
}

View file

@ -1,26 +1,30 @@
age-encryption.org/v1
-> ssh-ed25519 lHr4YQ FHOLoe1idBzwzFB5v1UqrVIgIjmyVMqhC60F+7bsslY
+4jeqlOONU712hstLOOU59dHgx48CB3+Z4xn1faH8Q0
-> ssh-ed25519 Wu8JLQ hqwTH7IVS1GTep9tNy6vrUUVtPcVXBxDnJj77S+l/Ek
gmnQhE5wnxQgEhyE18RKKemMQr4ewtRkQRt0bJo8O7Y
-> ssh-ed25519 cvTB5g bw+GZVk23ok4lgUF86PqTkZOM7BPNY7foMYYMZSEemU
6BAoCmLYb1oJwPPW3X2AaS3ZOttSxAykOeKIJM/03+k
-> ssh-ed25519 /vwQcQ Kqg5WdWhAuxCxMgWPpXWk77utvbIbBdcZXNSOF+a938
4361sLVjBWOoWqTl7sIktNiulSU4gHnD2Q5gjDkZ2po
-> ssh-ed25519 reTIKw abLB9hwppWQhlkAHx3AiFgePvigajethU03CjTu6SUg
sueQMp1LPmF4h1EPsyGrSDH6RoXVXoWm1i3OISZlyPw
-> ssh-ed25519 85WiGg T6amGqzBiF7BLhnhPrz8BCu/NDikWBDnRv+UL2Y8mXs
xghk5e+D3O4rX4FT4TNu/bowSj7HCn3Wi4E6F7pseiw
-> ssh-rsa krWCLQ
KDsZM/5myCVtb7RL9Mo1F2WUKzBPhwillBvrIONZKH0dh3mCMjeVfyYTto1NxKxp
GsvYltgLbDggo3ittwQedB9s/JXL5z0+f3DroKVJzw82ti6w3SMpvKiCR2x+5DjH
D4Wzt/CQFujxAMOghKQGlFuCM6nVkpmL9ucgUPEp7ApbNWuc4patJgLpvkE0yj7X
Q4ScTPg86Oh5RFf4Qwa3QhG7IdnIoSSJxK+rK5qZb2vPST9zc2OKZKQXOh2h6hBy
tEAhRYBTu6oqprwYlEWL7dCsbBeHjLmBE6Zvovp51PizZhzub1jCh/fuka1VTFSq
f1oWAdTS3Ow5gXWKoH5TkQ
-> +_u~Wjak-grease cU8 ?4 8Y(inxl+
h+7nxip00iflkCYBX2HvbHYc0SjsLvn4WVYUPzhDGjyauwARfA5zCfuIbGnEcxzF
FOWG9QQzr90JDCkonUjGTJ3N+ykLpiYCvLDJgXZB4MVEONyutwM
--- dZ6ca/xXQAOh82oeOyV/EkjTzK+oUj0YgzGTqyzJ8Rs
a™éæ OvF·âŒžúÞñÃúÓÊ
¤¦ÄÃJF¾»ÈÐßjëjŒ+
2Ak0HJ0WoUuCQkjBPjRgrFQmHSBP7Lzhwp8JZ22lSDLO4OzGLuyGnmI6f+x3mhSM
UP4X4fz98ygYaPTKHzgs+ALgoe0ZOzIRcrBYKyAmI92iuVk8QJrGBaFsi2e/quur
oRaQybPXCqbGeaFhLY74RHmtbby5zzbQnw8f5DRKn3oFDYgCUMOKdTPI3vsUDd6t
dLmFCWEhGFMwI9bve7bVeu2yKMWpOIIsVgkabSy9EQ0gEUwoXkrGNpc+QqqR2qbJ
qaLok3zO+giVKrzl6+/Z/tzHQ66mUTIZAD7HmRFMqBRBqo2heCtviGyu7NPXhb/T
vTVzgL7fsrkaYd59O7BCSg
-> ssh-ed25519 85WiGg UgubbGKRmcFV5N/Vyo/HEBtGG0GOvZS5dSDnYoWzeSk
N2CZ/ZJJLRTdwBDCVNrXGp8ic0T7ZHx+DfPcXLeEvXQ
-> ssh-ed25519 reTIKw zl6eZh6NG2Y21AElt+Ag7gzDmtzXP0h1RjhVzaiHUg0
PJU/i8Za/JwrCLXcH0vtG8CDxv3MDHCzEYiNIhperC4
-> ssh-ed25519 /vwQcQ RS4rv5dnajCSAdcFj96HOcMBHySk5yBrmepNdlOcsWg
M+dCeQCP3rl4oT8IrkParBnaaTfUNbWpgvbLou/qSp0
-> ssh-ed25519 cvTB5g ZR5ayyiP10Dec6Tg2HYcl5q0dkLSvOgRxeeVxC1Plj8
aiY/6wY4rmB75NRzcbFPKu7nTLKZhgqOuqAZm+9UnTs
-> ssh-ed25519 Wu8JLQ 4nFItVARcWbkkuyaUcgdesLSOmiomY0Ht2LxXX1/L0A
dK2/4X6OFbn4Y3gVK5zKRV3KySiCHzGnGewhZmqETrE
-> ssh-ed25519 vXYJfA k1ANIqwNaMjipiCobpBWMlhbCyudoy7vpuajDK7mLiQ
uudD1Bk1+EWmL3o7VH6YSbv1WRCw6tsDV0HoQ/zwXwg
-> ssh-ed25519 h6AgbA EvhvmT6dx3HAqioaFvT5u94cTk8okjhGgzyxXZF8LyE
R/xTeW/rJEl50kG8e0n3NOGpX9XI13Ftq7ULYNHVaCM
-> ssh-ed25519 lHr4YQ WyG8hEoGZuNvroTdmC8RST7l/Tu7UUXgeG3AfLA0p2o
qk7YeUkrOsRbqnYXFXZAkiOaW6rvKnSaZGSiBw30b5E
-> V9T>@4JS-grease @h!7BAa9
nPtMdfgbktgg20WlJBrQlhTDMI8/i31JEDnZjF4u7RidDSJ5lxzH8zI+411CQ+K5
exQ
--- YY6c8/qxiWxaK31KW+3QP6240bmnDJZ9EXrG7dnyJcE
NÝÖ|JýÎ
Z·ù…ZŠÔ6ÿÝ#kyHš—ô;ú<>Í ì

Binary file not shown.

View file

@ -1,8 +1,8 @@
let
pkgs = import <nixpkgs> {};
lib = pkgs.lib;
readPubkeys = user: builtins.filter (k: k != "") (lib.splitString "\n" (builtins.readFile (../pubkeys + "/${user}.keys")));
superadmins = (readPubkeys "raito") ++ (readPubkeys "gdd");
readPubkeys = user: builtins.filter (k: k != "") (lib.splitString "\n" (builtins.readFile (../../pubkeys + "/${user}.keys")));
superadmins = (readPubkeys "raito") ++ (readPubkeys "gdd") ++ (readPubkeys "hubrecht") ++ (readPubkeys "mrf");
core-services-01 = "ssh-ed25519 AAAAC3NzaC1lZDI1NTE5AAAAILrnZxP4OUGDzd1uykMghzFNLH0Fg42hH+0qxif6O6oU";
systems = [ core-services-01 ];
in
@ -10,5 +10,9 @@ in
"keycloakDatabasePasswordFile.age".publicKeys = superadmins ++ systems;
"oauth2ProxyKeyFile.age".publicKeys = superadmins ++ systems;
"droneKeyFile.age".publicKeys = superadmins ++ systems;
"dexGiteaClientSecret.age".publicKeys = superadmins ++ systems;
"matterbridge.age".publicKeys = superadmins ++ systems;
"snipeItAppKey.age".publicKeys = superadmins ++ systems;
"snipeItOidcClientSecret.age".publicKeys = superadmins ++ systems;
}

View file

@ -0,0 +1,28 @@
age-encryption.org/v1
-> ssh-rsa krWCLQ
gBB9yfHVs4Zgm30rbXOkQNZjOuQVFt9Mos4gBoM09M2psLLxWzsoQopWVcvbV+sY
oZAThV5F2E+RbOP2e9+o5P+rxCcJa8aAXovtmH2BZvr87jNi8tebH1l0Gjn0I85C
B+vv2/m1KCzisCR3p6yaqBiqyETacWRCuILVxKbpnKfVX5ymb//9U0tRbz3BIFH1
i3bAD8j8H4V/5SC5RmYwVeBhdGqEaNX0Qehh8AhDkxoqMT3Xeie93eIK6tyAZuyO
oQezqkUmozq+uvo6PHZvY/auTYb17QTY0s0xf30NnQoqwtVXnyu6xPx+qlj+M99Q
Y/s8SFF+STLrAgK9MN0i8Q
-> ssh-ed25519 85WiGg zkLuTpJaBr8T0XjuC9i9NTxYUPhix9nLlShohTtgmyA
QwdgD0ihIpJF8D54x2Lg+6CE2yV9nLBZ1oOf/iwUKi4
-> ssh-ed25519 reTIKw wB2xC902eZiPXXU9n+oQSocx6J9h5IK0jU4GqmB1XUI
awLSPDqOAOM2g7Wrg6uCMeDRVljl2cdZ40gHDON4DCU
-> ssh-ed25519 /vwQcQ adFZcuzNWIhLFDhF+FjfnMGTpijt4IKO266M8xpZTHs
WR3ig0R6ZgtYLxhN7bm5SNJ3klYvEkMlLeuC/GBxi0U
-> ssh-ed25519 cvTB5g 8Gl7qbc7VZvkjjHesgfgdvtsCntNCxyUU3hwXMaIJUA
uEJwhJJa87+EjpTE/+3jPnNtgFTHNZkah78URULI1nM
-> ssh-ed25519 Wu8JLQ buWP/UWAYd7nAAdIqJjkKq2q3Kcj/TtTm9MacGkoMh4
g9ngALRdWC96t7FLES79gKQNK34WbKHqdw4OCryGx74
-> ssh-ed25519 vXYJfA KT8pRDwADkV4ySKY6HejWKp57aQUWpor7x67x1Sc3wM
th+47fUL5KOak1tEeHslVg9KSxw5DPIO6T/UtfEK6kY
-> ssh-ed25519 h6AgbA 8kWKdngdG4RbvQHnkHpygz1fhzMXpGafXltQNa64mAU
hZZTmthndfMdMZiaW0bLxfiySzFgnKmd6t4u1PxLG9s
-> ssh-ed25519 lHr4YQ JBCRJtCaEH/Dp2em66/ckqFva6JpyeUAHJidVysAsmw
SGyzp26GIo+D4VQdzJZEBUZYvAhc/SZy6rdd6HXOawY
-> 1-grease
niVrY0FwL41sfeE9fB6hg+z0LWMXwce194f+IIL/F8JMIfTnFB0CRAn1OGQ
--- pMIf8bANx+QsRTqnWxPmnJm6DVMmJBEO+emeOdLeeec
.Aîç±z¢JQ[å)s!´ö´­2m õ¤<bÛ\yÝ^7"J¢k<C2A2>Æ_Õ<½Œéoñ¿{ÿ÷»e­¢ïø© Û8×:˜O%

View file

@ -0,0 +1,30 @@
age-encryption.org/v1
-> ssh-rsa krWCLQ
LCJxUzS4Be2QQABzubSP5M9Ridg3Srytbb6+SLITgnRqb0fT5XkG7z4ae2lLMVxT
zJxrZX1crlg/nyibZychMwZDqNofGGKX/zSKyF6u42hqjAtaDneg6jB/T690sSpD
LcuTHUcPLw53bww4amLU5FmFcnGWMHTjmXj6oQ5lks3t3KO9izA+gDJO5kFIYgQa
Z0kMrlH21m2TdyGW7Er72qAlT0euwCKlWGGc1NAaSWyu/2gimTHJ4p+KCOpi1D7/
cIxMEtXHUoS/vtINi1lZypETVZf9C3xfqZGCnu1xTpFcF8pBLskI/Uz4cxQGLAk3
xd5fKuNVBnLc0Ku+oFR3zA
-> ssh-ed25519 85WiGg N5HOphuKLUksJTA29E/KHZAdyvTelqq0Lai3KtsGNi0
6PilN36eZH8KYzQwqeLPX3wuiW4THuFef+ttoJh0BUo
-> ssh-ed25519 reTIKw epotGRShr91lRc2IKDkgfaDd4EhkDtF1jayFv/YW5nE
mMFKyzH1q8ZsUXfLnqFfHT88iz/i4WXVVuWqe3z9vx4
-> ssh-ed25519 /vwQcQ DvVlWcbAA/xPTgDtpMmSyC2wxrnOM4H/dC1Vhh5Rmhg
JCq1yS057vqOFKZL11YhC4/rxYIRGAUI0y97Uch4tS4
-> ssh-ed25519 cvTB5g EQ/YM5UYYp3+fS+6u+CwZxUn8Sm8vdqj5xHQf0U0MGc
mVhpObNYWSrAlh8kfADzGnhOw9O2r07v2RJH7DZhFkg
-> ssh-ed25519 Wu8JLQ k91dq2XwhgvE2Y75KAJWzFlPLXv+8+kTvH7sELmsViw
gpnxsNgbeuCYBYUt8j3mGm10rOGAoN9NDYVbObE2zXc
-> ssh-ed25519 vXYJfA fOpqzkovWF/hLUrsjrDwFUsKG3Pa7LQQ2QTiYWT4Ux0
AM1EdbC+Sg37PZzXf6vsmeXSMMjXRVQT3mq000cmPw8
-> ssh-ed25519 h6AgbA LWhZtBUJXu15GEIwSyKraXkaO8CO7/TuLSxsnbagQTk
1/It/vtykYe2NzG4r2J53yW+ZS2rgtUVNv8hlWYQnwY
-> ssh-ed25519 lHr4YQ zEMhvSZsUOiM+XEpuTljfKE1MqyxqxuL0yuKTj6E1Vc
J/pYqeaTK9NLIhSKeB0CFSFNLkVeV2C5enKVIRy5+Po
-> #Oj-grease fdq ltL1r ohAHn[aU QF%DKt
G2xXhW58AunOBXwtl1mD/DqdsHRoyjMvVl310MPWNFSSmLhG/UG7pQf3GUNsfThQ
lCvckvUfcYRen/hrEFhtyg
--- zwJ1Ma9A8rDbUQLAFpDNLs+2Iv6RQvEGlDFj9HVDRRg
;>qg4ü*¬ÄbŽˆ~G+x8ÃÞü
Œ,¦5õç!ãŠöž•ê4ñŸÀ¼:Ö<C396>\­g¬Ê‡î<E280A1>ßÐo

View file

@ -0,0 +1,34 @@
{ pkgs, config, ... }:
{
age.secrets.snipeItAppKey = {
owner = config.services.snipe-it.user;
group = config.services.snipe-it.group;
};
age.secrets.snipeItOidcClientSecret = {
owner = config.services.snipe-it.user;
group = config.services.snipe-it.group;
};
services.snipe-it = {
enable = true;
hostName = "inventory.rz.ens.wtf";
database.createLocally = true;
appKeyFile = config.age.secrets.snipeItAppKey.path;
nginx = {
enableACME = true;
forceSSL = true;
};
config = {
AUTH_METHOD = "oidc";
OIDC_NAME = "Keycloak";
OIDC_DISPLAY_NAME_CLAIMS = "name";
OIDC_CLIENT_ID = "snipe-it";
OIDC_CLIENT_SECRET = { _secret = config.age.secrets.snipeItOidcClientSecret.path; };
OIDC_ISSUER = "https://auth.rz.ens.wtf/auth/realms/ClubReseau";
OIDC_ISSUER_DISCOVER = true;
};
};
}

View file

@ -1,45 +1,52 @@
{ config, lib, dns, ... }:
with dns.lib.combinators;
let
my = config.my;
upstream-v4-proxies = [ "51.15.7.181" ]; # kurisu.dual.lahfa.xyz
public-cof-ips = [ "2001:470:1f13:187:c08e:feff:fe4d:f5f5" ];
web01 = {
CNAME = ["web01.dmi01.infra.dgnum.eu."];
};
public-cof-ips = {
A = [ "45.13.104.27" ];
AAAA = [ "2001:470:1f13:187:c08e:feff:fe4d:f5f5" ];
};
delegateACMEDNSChallenge = acme: { _acme-challenge.CNAME = [ acme ]; };
remoteBuilders = {
nix01 = [ "2001:470:1f13:187:1e07:c670:3958:f8f1" ];
mkProxyRecord = AAAA: { inherit AAAA; A = [ "45.13.104.29" ]; };
dualstack = {
A = my.ipv4;
AAAA = my.ipv6.standard;
};
in
with my.ipv6; # contains { standard, acme }
{
dualstack // {
SOA = {
nameServer = "ns1.${my.subZone}.";
adminEmail = my.email;
serial = 2021111301; # Y M D Version
serial = 2023122101; # Y M D Version
};
NS = [
"ns1.${my.subZone}."
];
AAAA = standard;
CAA = letsEncrypt my.email;
subdomains = {
git.AAAA = standard;
drone.AAAA = standard;
wiki.AAAA = standard;
monitoring.AAAA = standard;
auth.AAAA = standard;
push.AAAA = standard;
ns1.AAAA = standard;
beta.A = upstream-v4-proxies;
beta.AAAA = public-cof-ips;
git = web01;
drone = dualstack;
monitoring = dualstack;
auth = dualstack;
push = dualstack;
core01 = dualstack;
ns1 = dualstack;
builders.subdomains = lib.mapAttrs (n: AAAA: { inherit AAAA; }) remoteBuilders;
# Non-beta service
# Outline
notion = web01;
# S3 API
s3 = web01;
# CDN API
cdn = web01;
gdd = {
NS = [ "ns1.gdd.${my.subZone}." ];
@ -49,24 +56,37 @@ with my.ipv6; # contains { standard, acme }
acme = {
NS = [ "acme.${my.subZone}." ];
AAAA = [ acme ];
A = my.ipv4;
AAAA = [ my.ipv6.acme ];
};
beta.subdomains = {
nuage.A = upstream-v4-proxies;
nuage.AAAA = public-cof-ips;
minecraft.AAAA = public-cof-ips;
factorio.AAAA = public-cof-ips;
home.A = upstream-v4-proxies;
home.AAAA = public-cof-ips;
pads.AAAA = public-cof-ips;
docs.AAAA = public-cof-ips;
beta = public-cof-ips // {
subdomains = {
traque = mkProxyRecord [ "2001:470:1f13:187:f053:94ff:fe46:9664" ];
nuage = web01;
todo = web01;
minecraft = web01;
factorio = web01;
home = web01;
pads = web01 // {
subdomains = {
api = web01;
files = web01;
sandbox = web01;
};
};
docs = web01;
jurisprudens = web01;
rstudio = web01;
};
};
internal.subdomains = {
# Routers
router01.A = [ "10.1.1.1" ];
router02.A = [ "10.1.1.2" ];
router02.A = [ "10.1.1.1" ];
router03.A = [ "10.1.1.120" ];
# Hypervisors
pve01 = {

View file

@ -8,7 +8,7 @@
# Auto GC and store optimizations
nix = {
trustedUsers = [ "root" "gab" ];
settings.trusted-users = [ "root" "gab" ];
gc = {
automatic = true;
dates = "weekly";

View file

@ -0,0 +1,19 @@
{ ... }: {
networking.wireguard.interfaces.wgalpha = {
privateKeyFile = "/etc/secrets/wireguard/wgalpha";
listenPort = 9999;
ips = [
"fdee:a536:13fa:53ab::2/128"
];
peers = [
{
publicKey = "yAdQRTHn9Yko2r24j8tlxWBz0nYzHRxryPFq8t44Xw4=";
allowedIPs = [ "fdee:a536:13fa:53ab::1/128" ];
}
];
};
networking.firewall.allowedUDPPorts = [ 9999 ];
}

View file

@ -0,0 +1 @@
ssh-ed25519 AAAAC3NzaC1lZDI1NTE5AAAAIIv3iSpIjeUVDf+f89Hb/L++vzMX15Ti/PZTjAAG+tFl

View file

@ -0,0 +1 @@
ssh-ed25519 AAAAC3NzaC1lZDI1NTE5AAAAIFe4tx0+lNX2w7kG94c9u7U0wHuOc2A6zpHcbyAs+w/d

View file

@ -0,0 +1 @@
ssh-ed25519 AAAAC3NzaC1lZDI1NTE5AAAAIA3hCOyFwuoCLt5W9e9yQSwj9I+VspB0kNNHsoFngbgZ Raito's remote builder key

View file

@ -0,0 +1 @@
ssh-ed25519 AAAAC3NzaC1lZDI1NTE5AAAAIEpwF+XD3HgX64kqD42pcEZRNYAWoO4YNiOm5KO4tH6o

View file

@ -3,21 +3,32 @@
{
imports =
[
./hardware-configuration.nix
./programs.nix
./system.nix
./acme.nix
./networking.nix
./monitoring.nix
./garage.nix
./nextcloud.nix
./outline.nix
./lychee.nix
./minecraft.nix
# ./rstudio-server
./nur.nix
# ./factorio.nix # TODO
./nginx.nix
# ./cryptpad.nix
./hedgedoc.nix
# ./kanboard.nix
./secrets
./v6proxy
# TODO monitoring
];
nixpkgs.config.allowUnfreePredicate = pkg: builtins.elem (lib.getName pkg) [
"minecraft-server"
"factorio-headless"
"outline"
];
boot.loader.systemd-boot.enable = true;
@ -37,12 +48,5 @@
enableSSHSupport = true;
};
# Enable the OpenSSH daemon.
services.openssh.enable = true;
users.users.root.openssh.authorizedKeys.keyFiles = [
./pubkeys/gdd.keys
./pubkeys/raito.keys
];
system.stateVersion = "21.05";
}

View file

@ -1,5 +1,5 @@
{ ... }:
{
security.acme.acceptTerms = true;
security.acme.email = "club-reseau@lists.ens.psl.eu";
security.acme.defaults.email = "club-reseau@lists.ens.psl.eu";
}

View file

@ -0,0 +1,316 @@
/* globals module */
/* DISCLAIMER:
There are two recommended methods of running a CryptPad instance:
1. Using a standalone nodejs server without HTTPS (suitable for local development)
2. Using NGINX to serve static assets and to handle HTTPS for API server's websocket traffic
We do not officially recommend or support Apache, Docker, Kubernetes, Traefik, or any other configuration.
Support requests for such setups should be directed to their authors.
If you're having difficulty difficulty configuring your instance
we suggest that you join the project's IRC/Matrix channel.
If you don't have any difficulty configuring your instance and you'd like to
support us for the work that went into making it pain-free we are quite happy
to accept donations via our opencollective page: https://opencollective.com/cryptpad
*/
module.exports = {
/* CryptPad is designed to serve its content over two domains.
* Account passwords and cryptographic content is handled on the 'main' domain,
* while the user interface is loaded on a 'sandbox' domain
* which can only access information which the main domain willingly shares.
*
* In the event of an XSS vulnerability in the UI (that's bad)
* this system prevents attackers from gaining access to your account (that's good).
*
* Most problems with new instances are related to this system blocking access
* because of incorrectly configured sandboxes. If you only see a white screen
* when you try to load CryptPad, this is probably the cause.
*
* PLEASE READ THE FOLLOWING COMMENTS CAREFULLY.
*
*/
/* httpUnsafeOrigin is the URL that clients will enter to load your instance.
* Any other URL that somehow points to your instance is supposed to be blocked.
* The default provided below assumes you are loading CryptPad from a server
* which is running on the same machine, using port 3000.
*
* In a production instance this should be available ONLY over HTTPS
* using the default port for HTTPS (443) ie. https://cryptpad.fr
* In such a case this should be handled by NGINX, as documented in
* cryptpad/docs/example.nginx.conf (see the $main_domain variable)
*
*/
httpUnsafeOrigin: 'https://pads.beta.rz.ens.wtf/',
/* httpSafeOrigin is the URL that is used for the 'sandbox' described above.
* If you're testing or developing with CryptPad on your local machine then
* it is appropriate to leave this blank. The default behaviour is to serve
* the main domain over port 3000 and to serve the content over port 3001.
*
* This is not appropriate in a production environment where invasive networks
* may filter traffic going over abnormal ports.
* To correctly configure your production instance you must provide a URL
* with a different domain (a subdomain is sufficient).
* It will be used to load the UI in our 'sandbox' system.
*
* This value corresponds to the $sandbox_domain variable
* in the example nginx file.
*
* CUSTOMIZE AND UNCOMMENT THIS FOR PRODUCTION INSTALLATIONS.
*/
httpSafeOrigin: "https://sandbox.pads.beta.rz.ens.wtf",
/* httpAddress specifies the address on which the nodejs server
* should be accessible. By default it will listen on 127.0.0.1
* (IPv4 localhost on most systems). If you want it to listen on
* all addresses, including IPv6, set this to '::'.
*
*/
//httpAddress: '::',
/* httpPort specifies on which port the nodejs server should listen.
* By default it will serve content over port 3000, which is suitable
* for both local development and for use with the provided nginx example,
* which will proxy websocket traffic to your node server.
*
*/
//httpPort: 3000,
/* httpSafePort allows you to specify an alternative port from which
* the node process should serve sandboxed assets. The default value is
* that of your httpPort + 1. You probably don't need to change this.
*
*/
//httpSafePort: 3001,
/* CryptPad will launch a child process for every core available
* in order to perform CPU-intensive tasks in parallel.
* Some host environments may have a very large number of cores available
* or you may want to limit how much computing power CryptPad can take.
* If so, set 'maxWorkers' to a positive integer.
*/
// maxWorkers: 4,
/* =====================
* Admin
* ===================== */
/*
* CryptPad contains an administration panel. Its access is restricted to specific
* users using the following list.
* To give access to the admin panel to a user account, just add their user id,
* which can be found on the settings page for registered users.
* Entries should be strings separated by a comma.
*/
adminKeys: [
"https://pads.beta.rz.ens.wtf/user/#/1/raito/W1vJY5Mq+8+5SveZAYe0wYRthS88jQIV-Fwf0s36uas="
],
/* CryptPad's administration panel includes a "support" tab
* wherein administrators with a secret key can view messages
* sent from users via the encrypted forms on the /support/ page
*
* To enable this functionality:
* run `node ./scripts/generate-admin-keys.js`
* save the public key in your config in the value below
* add the private key via the admin panel
* and back it up in a secure manner
*
*/
// supportMailboxPublicKey: "",
/* We're very proud that CryptPad is available to the public as free software!
* We do, however, still need to pay our bills as we develop the platform.
*
* By default CryptPad will prompt users to consider donating to
* our OpenCollective campaign. We publish the state of our finances periodically
* so you can decide for yourself whether our expenses are reasonable.
*
* You can disable any solicitations for donations by setting 'removeDonateButton' to true,
* but we'd appreciate it if you didn't!
*/
//removeDonateButton: false,
/* CryptPad will display a point of contact for your instance on its contact page
* (/contact.html) if you provide it below.
*/
adminEmail: 'club-reseau@lists.ens.psl.eu',
/*
* By default, CryptPad contacts one of our servers once a day.
* This check-in will also send some very basic information about your instance including its
* version and the adminEmail so we can reach you if we are aware of a serious problem.
* We will never sell it or send you marketing mail.
*
* If you want to block this check-in and remain set 'blockDailyCheck' to true.
*/
//blockDailyCheck: false,
/*
* By default users get 50MB of storage by registering on an instance.
* You can set this value to whatever you want.
*
* hint: 50MB is 50 * 1024 * 1024
*/
defaultStorageLimit: 50 * 1024 * 1024,
/* =====================
* STORAGE
* ===================== */
/* Pads that are not 'pinned' by any registered user can be set to expire
* after a configurable number of days of inactivity (default 90 days).
* The value can be changed or set to false to remove expiration.
* Expired pads can then be removed using a cron job calling the
* `evict-inactive.js` script with node
*
* defaults to 90 days if nothing is provided
*/
//inactiveTime: 90, // days
/* CryptPad archives some data instead of deleting it outright.
* This archived data still takes up space and so you'll probably still want to
* remove these files after a brief period.
*
* cryptpad/scripts/evict-inactive.js is intended to be run daily
* from a crontab or similar scheduling service.
*
* The intent with this feature is to provide a safety net in case of accidental
* deletion. Set this value to the number of days you'd like to retain
* archived data before it's removed permanently.
*
* defaults to 15 days if nothing is provided
*/
//archiveRetentionTime: 15,
/* Max Upload Size (bytes)
* this sets the maximum size of any one file uploaded to the server.
* anything larger than this size will be rejected
* defaults to 20MB if no value is provided
*/
//maxUploadSize: 20 * 1024 * 1024,
/*
* CryptPad allows administrators to give custom limits to their friends.
* add an entry for each friend, identified by their user id,
* which can be found on the settings page. Include a 'limit' (number of bytes),
* a 'plan' (string), and a 'note' (string).
*
* hint: 1GB is 1024 * 1024 * 1024 bytes
*/
/*
customLimits: {
"https://my.awesome.website/user/#/1/cryptpad-user1/YZgXQxKR0Rcb6r6CmxHPdAGLVludrAF2lEnkbx1vVOo=": {
limit: 20 * 1024 * 1024 * 1024,
plan: 'insider',
note: 'storage space donated by my.awesome.website'
},
"https://my.awesome.website/user/#/1/cryptpad-user2/GdflkgdlkjeworijfkldfsdflkjeEAsdlEnkbx1vVOo=": {
limit: 10 * 1024 * 1024 * 1024,
plan: 'insider',
note: 'storage space donated by my.awesome.website'
}
},
*/
/* Users with premium accounts (those with a plan included in their customLimit)
* can benefit from an increased upload size limit. By default they are restricted to the same
* upload size as any other registered user.
*
*/
//premiumUploadSize: 100 * 1024 * 1024,
/* =====================
* DATABASE VOLUMES
* ===================== */
/*
* CryptPad stores each document in an individual file on your hard drive.
* Specify a directory where files should be stored.
* It will be created automatically if it does not already exist.
*/
filePath: './datastore/',
/* CryptPad offers the ability to archive data for a configurable period
* before deleting it, allowing a means of recovering data in the event
* that it was deleted accidentally.
*
* To set the location of this archive directory to a custom value, change
* the path below:
*/
archivePath: './data/archive',
/* CryptPad allows logged in users to request that particular documents be
* stored by the server indefinitely. This is called 'pinning'.
* Pin requests are stored in a pin-store. The location of this store is
* defined here.
*/
pinPath: './data/pins',
/* if you would like the list of scheduled tasks to be stored in
a custom location, change the path below:
*/
taskPath: './data/tasks',
/* if you would like users' authenticated blocks to be stored in
a custom location, change the path below:
*/
blockPath: './block',
/* CryptPad allows logged in users to upload encrypted files. Files/blobs
* are stored in a 'blob-store'. Set its location here.
*/
blobPath: './blob',
/* CryptPad stores incomplete blobs in a 'staging' area until they are
* fully uploaded. Set its location here.
*/
blobStagingPath: './data/blobstage',
/* CryptPad supports logging events directly to the disk in a 'logs' directory
* Set its location here, or set it to false (or nothing) if you'd rather not log
*/
logPath: './data/logs',
/* =====================
* Debugging
* ===================== */
/* CryptPad can log activity to stdout
* This may be useful for debugging
*/
logToStdout: false,
/* CryptPad can be configured to log more or less
* the various settings are listed below by order of importance
*
* silly, verbose, debug, feedback, info, warn, error
*
* Choose the least important level of logging you wish to see.
* For example, a 'silly' logLevel will display everything,
* while 'info' will display 'info', 'warn', and 'error' logs
*
* This will affect both logging to the console and the disk.
*/
logLevel: 'info',
/* clients can use the /settings/ app to opt out of usage feedback
* which informs the server of things like how much each app is being
* used, and whether certain clientside features are supported by
* the client's browser. The intent is to provide feedback to the admin
* such that the service can be improved. Enable this with `true`
* and ignore feedback with `false` or by commenting the attribute
*
* You will need to set your logLevel to include 'feedback'. Set this
* to false if you'd like to exclude feedback from your logs.
*/
logFeedback: false,
/* CryptPad supports verbose logging
* (false by default)
*/
verbose: false,
};

View file

@ -0,0 +1,188 @@
{ pkgs, ... }:
let
subZone = "beta.rz.ens.wtf";
main_domain = "pads.${subZone}";
sandbox_domain = "sandbox.${main_domain}";
# TODO: later
api_domain = "api.${main_domain}";
files_domain = "files.${main_domain}";
port = 3000;
in
{
services.cryptpad = {
enable = true;
configFile = "/etc/cryptpad/config.js";
};
environment.etc."cryptpad/config.js".source = ./cryptpad.js;
systemd.services.nginx = {
serviceConfig.BindReadOnlyPaths = [
"/var/lib/private/cryptpad:/www/cryptpad"
];
};
services.nginx.virtualHosts = {
"${main_domain}" = {
forceSSL = true;
enableACME = true;
serverAliases = [ sandbox_domain ];
extraConfig = ''
root ${pkgs.cryptpad}/lib/node_modules/cryptpad;
index index.html;
# CryptPad serves static assets over these two domains.
# `main_domain` is what users will enter in their address bar.
# Privileged computation such as key management is handled in this scope
# UI content is loaded via the `sandbox_domain`.
# "Content Security Policy" headers prevent content loaded via the sandbox
# from accessing privileged information.
# These variables must be different to take advantage of CryptPad's sandboxing techniques.
# In the event of an XSS vulnerability in CryptPad's front-end code
# this will limit the amount of information accessible to attackers.
set $main_domain ${main_domain};
set $sandbox_domain ${sandbox_domain};
# CryptPad's dynamic content (websocket traffic and encrypted blobs)
# can be served over separate domains. Using dedicated domains (or subdomains)
# for these purposes allows you to move them to a separate machine at a later date
# if you find that a single machine cannot handle all of your users.
# If you don't use dedicated domains, this can be the same as $main_domain
# If you do, they'll be added as exceptions to any rules which block connections to remote domains.
set $api_domain ${main_domain};
set $files_domain ${main_domain};
server_name ${main_domain} ${sandbox_domain};
# CSS can be dynamically set inline, loaded from the same domain, or from $main_domain
set $styleSrc "'unsafe-inline' 'self' ${main_domain}";
# connect-src restricts URLs which can be loaded using script interfaces
set $connectSrc "'self' https://${main_domain} ${main_domain} https://${api_domain} blob: wss://${api_domain} ${api_domain} ${files_domain}";
# fonts can be loaded from data-URLs or the main domain
set $fontSrc "'self' data: ${main_domain}";
# images can be loaded from anywhere, though we'd like to deprecate this as it allows the use of images for tracking
set $imgSrc "'self' data: * blob: ${main_domain}";
# frame-src specifies valid sources for nested browsing contexts.
# this prevents loading any iframes from anywhere other than the sandbox domain
set $frameSrc "'self' ${sandbox_domain} blob:";
# specifies valid sources for loading media using video or audio
set $mediaSrc "'self' data: * blob: ${main_domain}";
# defines valid sources for webworkers and nested browser contexts
# deprecated in favour of worker-src and frame-src
set $childSrc "https://${main_domain}";
# specifies valid sources for Worker, SharedWorker, or ServiceWorker scripts.
# supercedes child-src but is unfortunately not yet universally supported.
set $workerSrc "https://${main_domain}";
# script-src specifies valid sources for javascript, including inline handlers
set $scriptSrc "'self' resource: ${main_domain}";
set $unsafe 0;
# the following assets are loaded via the sandbox domain
# they unfortunately still require exceptions to the sandboxing to work correctly.
if ($uri = "/pad/inner.html") { set $unsafe 1; }
if ($uri = "/sheet/inner.html") { set $unsafe 1; }
if ($uri ~ ^\/common\/onlyoffice\/.*\/index\.html.*$) { set $unsafe 1; }
# everything except the sandbox domain is a privileged scope, as they might be used to handle keys
if ($host != $sandbox_domain) { set $unsafe 0; }
# privileged contexts allow a few more rights than unprivileged contexts, though limits are still applied
if ($unsafe) {
set $scriptSrc "'self' 'unsafe-eval' 'unsafe-inline' resource: ${main_domain}";
}
# The nodejs process can handle all traffic whether accessed over websocket or as static assets
# We prefer to serve static content from nginx directly and to leave the API server to handle
# the dynamic content that only it can manage. This is primarily an optimization
location ^~ /cryptpad_websocket {
proxy_pass http://localhost:${toString port};
proxy_set_header X-Real-IP $remote_addr;
proxy_set_header Host $host;
proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;
# WebSocket support (nginx 1.4)
proxy_http_version 1.1;
proxy_set_header Upgrade $http_upgrade;
proxy_set_header Connection upgrade;
}
location ^~ /customize.dist/ {
# This is needed in order to prevent infinite recursion between /customize/ and the root
}
# try to load customizeable content via /customize/ and fall back to the default content
# located at /customize.dist/
# This is what allows you to override behaviour.
location ^~ /customize/ {
rewrite ^/customize/(.*)$ $1 break;
try_files /customize/$uri /customize.dist/$uri;
}
# /api/config is loaded once per page load and is used to retrieve
# the caching variable which is applied to every other resource
# which is loaded during that session.
location = /api/config {
proxy_pass http://localhost:${toString port};
proxy_set_header X-Real-IP $remote_addr;
proxy_set_header Host $host;
proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;
}
# encrypted blobs are immutable and are thus cached for a year
location ^~ /blob/ {
root /www/cryptpad;
if ($request_method = 'OPTIONS') {
add_header 'Access-Control-Allow-Origin' '*';
add_header 'Access-Control-Allow-Methods' 'GET, POST, OPTIONS';
add_header 'Access-Control-Allow-Headers' 'DNT,X-CustomHeader,Keep-Alive,User-Agent,X-Requested-With,If-Modified-Since,Cache-Control,Content-Type,Content-Range,Range';
add_header 'Access-Control-Max-Age' 1728000;
add_header 'Content-Type' 'application/octet-stream; charset=utf-8';
add_header 'Content-Length' 0;
return 204;
}
add_header 'Access-Control-Allow-Origin' '*';
add_header 'Access-Control-Allow-Methods' 'GET, POST, OPTIONS';
add_header 'Access-Control-Allow-Headers' 'DNT,X-CustomHeader,Keep-Alive,User-Agent,X-Requested-With,If-Modified-Since,Cache-Control,Content-Type,Content-Range,Range';
add_header 'Access-Control-Expose-Headers' 'DNT,X-CustomHeader,Keep-Alive,User-Agent,X-Requested-With,If-Modified-Since,Cache-Control,Content-Type,Content-Range,Range';
try_files $uri =404;
}
# the "block-store" serves encrypted payloads containing users' drive keys
# these payloads are unlocked via login credentials. They are mutable
# and are thus never cached. They're small enough that it doesn't matter, in any case.
location ^~ /block/ {
root /www/cryptpad;
add_header Cache-Control max-age=0;
try_files $uri =404;
}
# This block provides an alternative means of loading content
# otherwise only served via websocket. This is solely for debugging purposes,
# and is thus not allowed by default.
#location ^~ /datastore/ {
#add_header Cache-Control max-age=0;
#try_files $uri =404;
#}
# The nodejs server has some built-in forwarding rules to prevent
# URLs like /pad from resulting in a 404. This simply adds a trailing slash
# to a variety of applications.
location ~ ^/(register|login|settings|user|pad|drive|poll|slide|code|whiteboard|file|media|profile|contacts|todo|filepicker|debug|kanban|sheet|support|admin|notifications|teams)$ {
rewrite ^(.*)$ $1/ redirect;
}
# Finally, serve anything the above exceptions don't govern.
try_files /www/$uri /www/$uri/index.html /customize/$uri;
'';
};
};
networking.firewall.allowedTCPPorts = [ 443 80 ];
}

View file

@ -0,0 +1,47 @@
{ pkgs, ... }:
{
security.acme.certs."cdn.rz.ens.wtf" = {
dnsProvider = "acme-dns";
credentialsFile = pkgs.writeText "acme-dns-env" ''
ACME_DNS_API_BASE=https://acme.rz.ens.wtf
ACME_DNS_STORAGE_PATH=/var/lib/acme/lego-acme-dns-accounts.json
'';
extraDomainNames = [ "*.cdn.rz.ens.wtf" ];
group = "nginx";
};
services.nginx.virtualHosts."s3.rz.ens.wtf" = {
enableACME = true;
forceSSL = true;
locations."/".proxyPass = "http://[::1]:3900";
};
services.nginx.virtualHosts."cdn.rz.ens.wtf" = {
serverAliases = [ "*.cdn.rz.ens.wtf" ];
useACMEHost = "cdn.rz.ens.wtf";
forceSSL = true;
locations."/".proxyPass = "http://[::1]:3902";
};
services.garage = {
enable = true;
package = pkgs.garage_0_8;
settings = {
replication_mode = "none";
compression_level = 7;
rpc_bind_addr = "10.1.1.21:3901";
rpc_public_addr = "10.1.1.21:3901";
rpc_secret = "76c2746530a4a27d188530a6bbf6c4613ccb8d8f129863d8c21462b84d5b998f";
s3_api = {
s3_region = "ens";
api_bind_addr = "[::]:3900";
root_domain = ".s3.rz.ens.wtf";
};
s3_web = {
bind_addr = "[::]:3902";
root_domain = ".cdn.rz.ens.wtf";
index = "index.html";
};
};
};
}

View file

@ -0,0 +1,35 @@
{ ... }:
let
port = 3001;
in
{
services.hedgedoc = {
enable = true;
settings = {
protocolUseSSL = true;
# scp =; # TODO
domain = "docs.beta.rz.ens.wtf";
host = "127.0.0.1";
port = port;
db = {
dialect = "sqlite";
storage = "/var/lib/hedgedoc/db.hedgedoc.sqlite";
};
};
};
services.nginx = {
virtualHosts = {
"docs.beta.rz.ens.wtf" = {
forceSSL = true;
enableACME = true;
locations = {
"/" = {
proxyPass = "http://127.0.0.1:${toString port}";
proxyWebsockets = true;
};
};
};
};
};
}

View file

@ -0,0 +1,281 @@
<?php
/*******************************************************************/
/* Rename this file to config.php if you want to change the values */
/* */
/* Make sure all paths are absolute by using __DIR__ where needed */
/*******************************************************************/
// Require the secret file
require('@secretsPath@');
// Data folder (must be writeable by the web server user and absolute)
define('DATA_DIR', '/var/lib/kanboard/data');
// Enable/Disable debug
define('DEBUG', false);
// Available log drivers: syslog, stderr, stdout, system or file
define('LOG_DRIVER', 'file');
// Log filename if the log driver is "file"
define('LOG_FILE', DATA_DIR.DIRECTORY_SEPARATOR.'debug.log');
// Plugins directory
define('PLUGINS_DIR', '@pluginsDirectory@');
// Plugins directory URL
define('PLUGIN_API_URL', 'https://kanboard.org/plugins.json');
// Enable/Disable plugin installer (Disabled by default for security reasons)
// There is no code review or any approval process to submit a plugin.
// This is up to the Kanboard instance owner to validate if a plugin is legit.
define('PLUGIN_INSTALLER', false);
// Available cache drivers are "file" and "memory"
define('CACHE_DRIVER', 'memory');
// Cache folder to use if cache driver is "file" (must be writeable by the web server user)
define('CACHE_DIR', DATA_DIR.DIRECTORY_SEPARATOR.'cache');
// Folder for uploaded files (must be writeable by the web server user)
define('FILES_DIR', DATA_DIR.DIRECTORY_SEPARATOR.'files');
// Enable/disable email configuration from the user interface
define('MAIL_CONFIGURATION', true);
// E-mail address used for the "From" header (notifications)
define('MAIL_FROM', 'todo@dgnum.eu');
// E-mail address used for the "Bcc" header to send a copy of all notifications
define('MAIL_BCC', '');
// Mail transport available: "smtp", "sendmail", "mail" (PHP mail function), "postmark", "mailgun", "sendgrid"
define('MAIL_TRANSPORT', 'smtp');
// SMTP configuration to use when the "smtp" transport is chosen
define('MAIL_SMTP_HOSTNAME', 'kurisu.lahfa.xyz');
define('MAIL_SMTP_PORT', 587);
define('MAIL_SMTP_USERNAME', 'todo@dgnum.eu');
define('MAIL_SMTP_HELO_NAME', null); // valid: null (default), or FQDN
define('MAIL_SMTP_ENCRYPTION', "tls"); // Valid values are null (not a string "null"), "ssl" or "tls"
// Sendmail command to use when the transport is "sendmail"
define('MAIL_SENDMAIL_COMMAND', '/usr/sbin/sendmail -bs');
// Run automatically database migrations
// If set to false, you will have to run manually the SQL migrations from the CLI during the next Kanboard upgrade
// Do not run the migrations from multiple processes at the same time (example: web page + background worker)
define('DB_RUN_MIGRATIONS', true);
// Database driver: sqlite, mysql or postgres (sqlite by default)
define('DB_DRIVER', 'sqlite');
// Mysql/Postgres username
define('DB_USERNAME', 'root');
// Mysql/Postgres password
define('DB_PASSWORD', '');
// Mysql/Postgres hostname
define('DB_HOSTNAME', 'localhost');
// Mysql/Postgres database name
define('DB_NAME', 'kanboard');
// Mysql/Postgres custom port (null = default port)
define('DB_PORT', null);
// Mysql SSL key
define('DB_SSL_KEY', null);
// Mysql SSL certificate
define('DB_SSL_CERT', null);
// Mysql SSL CA
define('DB_SSL_CA', null);
// Mysql SSL server verification, set to false if you don't want the Mysql driver to validate the certificate CN
define('DB_VERIFY_SERVER_CERT', null);
// Timeout value for PDO attribute
define('DB_TIMEOUT', null);
// Enable LDAP authentication (false by default)
define('LDAP_AUTH', false);
// LDAP server protocol, hostname and port URL (ldap[s]://hostname:port)
define('LDAP_SERVER', '');
// By default, require certificate to be verified for ldaps:// style URL. Set to false to skip the verification
define('LDAP_SSL_VERIFY', true);
// Enable LDAP START_TLS
define('LDAP_START_TLS', false);
// By default Kanboard lowercase the ldap username to avoid duplicate users (the database is case sensitive)
// Set to true if you want to preserve the case
define('LDAP_USERNAME_CASE_SENSITIVE', false);
// LDAP bind type: "anonymous", "user" or "proxy"
define('LDAP_BIND_TYPE', 'anonymous');
// LDAP username to use with proxy mode
// LDAP username pattern to use with user mode
define('LDAP_USERNAME', null);
// LDAP password to use for proxy mode
define('LDAP_PASSWORD', null);
// LDAP DN for users
// Example for ActiveDirectory: CN=Users,DC=kanboard,DC=local
// Example for OpenLDAP: ou=People,dc=example,dc=com
define('LDAP_USER_BASE_DN', '');
// LDAP pattern to use when searching for a user account
// Example for ActiveDirectory: '(&(objectClass=user)(sAMAccountName=%s))'
// Example for OpenLDAP: 'uid=%s'
define('LDAP_USER_FILTER', '');
// LDAP attribute for username
// Example for ActiveDirectory: 'sAMAccountName'
// Example for OpenLDAP: 'uid'
define('LDAP_USER_ATTRIBUTE_USERNAME', 'uid');
// LDAP attribute for user full name
// Example for ActiveDirectory: 'displayname'
// Example for OpenLDAP: 'cn'
define('LDAP_USER_ATTRIBUTE_FULLNAME', 'cn');
// LDAP attribute for user email
define('LDAP_USER_ATTRIBUTE_EMAIL', 'mail');
// LDAP attribute to find groups in user profile
define('LDAP_USER_ATTRIBUTE_GROUPS', 'memberof');
// LDAP attribute for user avatar image: thumbnailPhoto or jpegPhoto
define('LDAP_USER_ATTRIBUTE_PHOTO', '');
// LDAP attribute for user language, example: 'preferredlanguage'
// Put an empty string to disable language sync
define('LDAP_USER_ATTRIBUTE_LANGUAGE', '');
// Automatically create a user profile when a user authenticates via LDAP.
// If set to false, only LDAP users can log in for whom a Kanboard profile already exists.
define('LDAP_USER_CREATION', true);
// Set new user as Manager
define('LDAP_USER_DEFAULT_ROLE_MANAGER', false);
// LDAP DN for administrators
// Example: CN=Kanboard-Admins,CN=Users,DC=kanboard,DC=local
define('LDAP_GROUP_ADMIN_DN', '');
// LDAP DN for managers
// Example: CN=Kanboard Managers,CN=Users,DC=kanboard,DC=local
define('LDAP_GROUP_MANAGER_DN', '');
// Enable LDAP group provider for project permissions
// The end-user will be able to browse LDAP groups from the user interface and allow access to specified projects
define('LDAP_GROUP_PROVIDER', false);
// LDAP Base DN for groups
define('LDAP_GROUP_BASE_DN', '');
// LDAP group filter
// Example for ActiveDirectory: (&(objectClass=group)(sAMAccountName=%s*))
define('LDAP_GROUP_FILTER', '');
// LDAP user group filter
// If this filter is configured, Kanboard will search user groups in LDAP_GROUP_BASE_DN with this filter
// Example for OpenLDAP: (&(objectClass=posixGroup)(memberUid=%s))
define('LDAP_GROUP_USER_FILTER', '');
// LDAP attribute for the user in the group filter
// 'username' or 'dn'
define('LDAP_GROUP_USER_ATTRIBUTE', 'username');
// LDAP attribute for the group name
define('LDAP_GROUP_ATTRIBUTE_NAME', 'cn');
// Enable/Disable groups synchronization when external authentication is used.
define('LDAP_GROUP_SYNC', false);
// Enable/disable the reverse proxy authentication
define('REVERSE_PROXY_AUTH', false);
// Header name to use for the username
define('REVERSE_PROXY_USER_HEADER', 'REMOTE_USER');
// Username of the admin, by default blank
define('REVERSE_PROXY_DEFAULT_ADMIN', '');
// Header name to use for the username
define('REVERSE_PROXY_EMAIL_HEADER', 'REMOTE_EMAIL');
// Default domain to use for setting the email address
define('REVERSE_PROXY_DEFAULT_DOMAIN', '');
// Enable/disable remember me authentication
define('REMEMBER_ME_AUTH', true);
// Enable or disable "Strict-Transport-Security" HTTP header
define('ENABLE_HSTS', true);
// Enable or disable "X-Frame-Options: DENY" HTTP header
define('ENABLE_XFRAME', true);
// Escape html inside markdown text
define('MARKDOWN_ESCAPE_HTML', true);
// API alternative authentication header, the default is HTTP Basic Authentication defined in RFC2617
define('API_AUTHENTICATION_HEADER', '');
// Enable/disable url rewrite
define('ENABLE_URL_REWRITE', false);
// Hide login form, useful if all your users use Google/Github/ReverseProxy authentication
define('HIDE_LOGIN_FORM', false);
// Disabling logout (useful for external SSO authentication)
define('DISABLE_LOGOUT', false);
// Enable captcha after 3 authentication failure
define('BRUTEFORCE_CAPTCHA', 3);
// Lock the account after 6 authentication failure
define('BRUTEFORCE_LOCKDOWN', 6);
// Lock account duration in minute
define('BRUTEFORCE_LOCKDOWN_DURATION', 15);
// Session duration in second (0 = until the browser is closed)
// See http://php.net/manual/en/session.configuration.php#ini.session.cookie-lifetime
define('SESSION_DURATION', 0);
// Session handler: db or php
define('SESSION_HANDLER', 'db');
// HTTP client proxy
define('HTTP_PROXY_HOSTNAME', '');
define('HTTP_PROXY_PORT', '3128');
define('HTTP_PROXY_USERNAME', '');
define('HTTP_PROXY_PASSWORD', '');
define('HTTP_PROXY_EXCLUDE', 'localhost');
// Set to false to allow self-signed certificates
define('HTTP_VERIFY_SSL_CERTIFICATE', true);
// TOTP (2FA) issuer name
define('TOTP_ISSUER', 'Kanboard (DGNum)');
// Comma separated list of fields to not synchronize when using external authentication providers
define('EXTERNAL_AUTH_EXCLUDE_FIELDS', 'username');
// Enable or disable displaying group-memberships in userlist (true by default)
define('SHOW_GROUP_MEMBERSHIPS_IN_USERLIST', true);
// Limit number of groups to display in userlist (The full list of group-memberships is always shown, ...
// ... when hovering the mouse over the group-icon of a given user!)
// If set to 0 ALL group-memberships will be listed (7 by default)
define('SHOW_GROUP_MEMBERSHIPS_IN_USERLIST_WITH_LIMIT', 7);

View file

@ -0,0 +1,85 @@
{ pkgs, lib, config, ... }:
let
mkKanboardPlugin = { name, url, hash ? null }: pkgs.fetchzip {
inherit name url;
sha256 = if hash == null then lib.fakeHash else hash;
};
plugins = map mkKanboardPlugin [
{ name = "Milestone"; url = "https://github.com/oliviermaridat/kanboard-milestone-plugin/releases/download/1.1.2/Milestone-1.1.2.zip"; hash = "sha256-NrkMvk/5NdVokKQTYoZajdNEt5athjEzXVgrSHBdQ4w="; }
{ name = "MarkdownPlus"; url = "https://github.com/creecros/MarkdownPlus/releases/download/1.1.0/MarkdownPlus-1.1.0.zip"; hash = "sha256-BMzEaj47NnLvatEgUbKeibiWf9G+B4EFlVYhDNqk+y4="; }
{ name = "MetaMagik"; url = "https://github.com/creecros/MetaMagik/releases/download/1.5.1/MetaMagik-1.5.1.zip"; hash = "sha256-8y8+YvS5MAzRt4VVECQK0vQk6oA4Jbxn+2jWQ8nP3gU="; }
{ name = "OAuth2"; url = "https://github.com/kanboard/plugin-oauth2/releases/download/v1.0.2/OAuth2-1.0.2.zip"; hash = "sha256-L0df8bwPCxHjVOCNiVp+dqVsqJ0CEuJbHzwv5sYprIU="; }
{ name = "HighlightCodeSyntax"; url = "https://github.com/kenlog/HighlightCodeSyntax/releases/download/v1.0.3/HighlightCodeSyntax-v1.0.3.zip"; hash = "sha256-c4bV1gGVNUjHOJKBI6QxsV72mAzcEgjqv8r62ebpPdU="; }
{ name = "Group_assign"; url = "https://github.com/creecros/Group_assign/releases/download/1.7.12/Group_assign-1.7.12.zip"; hash = "sha256-ijI8nIIqsK8Pr1iEfCBUeUD3dlsIfmkOP0xC39JkIAs="; }
];
pluginsDirectory = pkgs.linkFarmFromDrvs "kanboard-plugins" plugins;
secretsPath = config.age.secrets.kanboard-secrets.path;
kanboardConfig = pkgs.substituteAll {
name = "kanboard-config.php";
src = ./kanboard-config.php;
inherit secretsPath;
inherit pluginsDirectory;
};
package = pkgs.kanboard.overrideAttrs (old: {
installPhase = ''
${(old.installPhase or "")}
runHook postInstall
'';
postInstall = ''
${pkgs.xorg.lndir}/bin/lndir ${pluginsDirectory} $out/share/kanboard/plugins
'';
});
in
{
environment.systemPackages = [
];
services.phpfpm.pools.kanboard = {
user = "kanboard";
group = "kanboard";
settings = {
"listen.group" = "nginx";
"pm" = "static";
"pm.max_children" = 4;
};
};
users.users.kanboard = {
isSystemUser = true;
group = "kanboard";
};
users.groups.kanboard = {};
services.nginx = {
enable = true;
virtualHosts."todo.beta.rz.ens.wtf" = {
enableACME = true;
forceSSL = true;
root = pkgs.buildEnv {
name = "kanboard-configured";
paths = [
(pkgs.runCommand "kanboard-over" {meta.priority = 0;} ''
mkdir -p $out
for f in index.php jsonrpc.php ; do
echo "<?php require('$out/config.php');" > $out/$f
tail -n+2 ${package}/share/kanboard/$f \
| sed 's^__DIR__^"${package}/share/kanboard"^' >> $out/$f
done
ln -s /var/lib/kanboard $out/data
ln -s ${pluginsDirectory} $out/plugins
ln -s ${kanboardConfig} $out/config.php
'')
{ outPath = "${package}/share/kanboard"; meta.priority = 10; }
];
};
locations = {
"/".index = "index.php";
"~ \\.php$" = {
tryFiles = "$uri =404";
extraConfig = ''
fastcgi_pass unix:${config.services.phpfpm.pools.kanboard.socket};
'';
};
};
};
};
}

View file

@ -0,0 +1,17 @@
{ config, pkgs, ... }: {
services.lychee = {
enable = true;
package = pkgs.rz.lychee-gallery;
forceSSL = true;
enableACME = true;
website = "photos.ens.wtf";
settings.APP_URL = "https://${config.services.lychee.website}";
};
services.phpfpm.pools."photos.ens.wtf".settings = {
pm = "dynamic";
"pm.max_children" = 10;
"pm.start_servers" = 3;
"pm.min_spare_servers" = 1;
"pm.max_spare_servers" = 3;
};
}

View file

@ -2,11 +2,11 @@
let
papermc = {
ram = 4; # In GB
version = "1.17.1";
build = 189;
sha256 = "06g2vs8z7k9bl8asjgdz9h8fkd93xam2lbrgmzgamwjp94gvfvrn";
version = "1.19.2";
build = 200;
sha256 = "sha256-fhQ1Kukp0MDF0312y/DR3wS9wKXY2aKUyU5f64ELylM=";
};
port = 43000;
port = 25565;
rconPort = 25575;
in
{
@ -38,6 +38,19 @@ in
whitelist = {
gabriel_dr_dl = "53fced49-da51-4c82-b1d0-37168029db08";
aimie_dodo = "d10be020-a612-47e5-b0d0-938b9a7eb58e";
RaitoMezarius = "a400686e-0f62-43d5-b5c6-4295babcc008";
Sup3Legacy = "575ecb9f-bf28-46cb-bc50-cb6bb340c905";
Pollux3737 = "ffa65818-b022-4830-aa90-7f3211c8ee3d";
CiterinRemy = "2f6a0c0a-4c0e-4e6c-beb4-237600fba849";
clem197 = "7461bfdf-4dca-44c2-b035-b49d5740dfc5";
Clashis = "499fdd85-bbcb-446f-9611-8b6bb9bf6965";
skidijo = "6a72a1f4-7448-4fb7-a252-b6d5ceff2d43";
Tifendyll = "5dc1acf3-b214-4607-a3bd-924665e07c67";
OknShield = "ef12e9cd-121f-4b39-886e-89b5b4bc5f4f";
Allygon = "964a2ee3-3a0d-49c1-b8e9-60b5e69976d3";
CheesyBiggy = "574daaed-ce9a-4b33-a3af-055e39bc32dc";
H3raklio = "576969d4-94e7-49db-ba7e-e9e57ff5a75e";
thejohncrafter = "d3959974-3a05-4ab2-8acb-d8817c140d84";
};
serverProperties = {
@ -51,7 +64,7 @@ in
# Map settings
level-seed = "9058136630944956755";
level-name = "Public COF";
level-name = "Public_COF";
level-type = "default";
spawn-animals = true;
@ -59,7 +72,7 @@ in
spawn-npcs = true;
generate-structures = true;
enable-command-block = false;
enable-command-block = true;
# Whitelist
white-list = true;

View file

@ -0,0 +1,89 @@
{ config, lib, pkgs, ... }:
{
services.nginx.statusPage = true;
services.netdata = {
enable = true;
config = {
global."memory mode" = "none";
web = {
mode = "none";
"accept a streaming request every seconds" = 0;
};
};
python.extraPackages = ps: [
ps.psycopg2
];
};
systemd.services.netdata.serviceConfig.SupplementaryGroups = [ "nginx" ];
systemd.services.netdata.restartTriggers = map (v: config.environment.etc."netdata/${v}.conf".source) [
"stream"
"go.d/phpfpm"
"go.d/nginx"
"python.d/postgres"
];
services.postgresql.settings = {
shared_preload_libraries = "pg_stat_statements";
track_activity_query_size = 2048;
"pg_stat_statements.track" = "all";
};
services.postgresql.initialScript = pkgs.writeText "grant-pgmonitor-to-netdata" ''
GRANT pg_monitor TO netdata;
'';
services.postgresql.ensureUsers = [
{ name = "netdata"; }
];
environment.etc."netdata/python.d/postgres.conf" = {
user = "netdata";
group = "netdata";
mode = "0600";
text = builtins.toJSON (
if config.services.postgresql.enable then
{
name = "socket";
user = "netdata";
database = "postgres";
}
else {}
);
};
environment.etc."netdata/go.d/phpfpm.conf" = {
user = "netdata";
group = "netdata";
mode = "0600";
text = builtins.toJSON {
jobs =
map (pool: { name = "local_socket"; inherit (pool) socket; })
(builtins.attrValues config.services.phpfpm.pools);
};
};
environment.etc."netdata/go.d/nginx.conf" = {
user = "netdata";
group = "netdata";
mode = "0600";
text = builtins.toJSON {
jobs =
if config.services.nginx.statusPage then [ { name = "local"; url = "http://localhost/nginx_status"; } ]
else [];
};
};
environment.etc."netdata/stream.conf" = {
user = "netdata";
group = "netdata";
mode = "0600";
text = ''
[stream]
enabled = yes
destination = 10.1.1.20:19999
api key = c48e6ef1-5cdf-408d-ae2f-86aadb14e3fe
'';
};
}

View file

@ -1,19 +1,38 @@
{ ... }:
{ lib, ... }:
{
networking = {
hostName = "public-cof";
useDHCP = false;
interfaces.ens18 = {
useDHCP = true;
ipv6.addresses = [{
address = "2001:470:1f13:187:c08e:feff:fe4d:f5f5";
prefixLength = 64;
}];
useNetworkd = true;
firewall = { enable = true; allowedTCPPorts = [ 22 ]; };
};
systemd.network.networks = {
"10-ens18" = {
name = "ens18";
address = [ "2001:470:1f13:187:c08e:feff:fe4d:f5f5/64" ];
DHCP = "ipv4";
dhcpV4Config.RouteMetric = 10;
};
firewall.allowedTCPPorts = [ 22 ];
firewall.allowedUDPPorts = [ 22 ];
firewall.enable = true;
"10-ens19" = {
name = "ens19";
address = [ "10.1.1.21/22" ];
DHCP = "ipv4";
};
"10-ens20" = {
name = "ens20";
address = [ "45.13.104.27/32" "45.13.104.29/32" ];
DHCP = "ipv4";
};
};
services.nginx.defaultListenAddresses = [ "[::0]" "45.13.104.27" ];
}

View file

@ -1,21 +1,32 @@
{ ... }:
{ pkgs, config, lib, ... }:
{
services.nextcloud = {
enable = true;
hostName = "nuage.beta.rz.ens.wtf";
https = true;
package = pkgs.nextcloud26;
config = {
overwriteProtocol = "https";
dbtype = "pgsql";
dbhost = "/run/postgresql";
dbpass = "TODO";
adminpass = "TODO";
dbpassFile = config.age.secrets.nextcloudDatabasePassword.path;
adminpassFile = config.age.secrets.nextcloudAdminPassword.path;
defaultPhoneRegion = "FR";
};
poolSettings = {
pm = "dynamic";
"pm.max_children" = 100;
"pm.start_servers" = 16;
"pm.min_spare_servers" = 8;
"pm.max_spare_servers" = 16;
"pm.status_path" = "/status";
};
};
services.nginx = {
@ -23,6 +34,7 @@
"nuage.beta.rz.ens.wtf" = {
forceSSL = true;
enableACME = true;
http2 = true;
};
};
};

View file

@ -1,26 +1,45 @@
{ ... }:
let
mkCloudLocation = { from, cloudHost }: {
name = "/cal/${from}";
value = {
extraConfig = ''
proxy_pass https://${cloudHost}/remote.php/dav/public-calendars/;
proxy_set_header Host ${cloudHost};
'';
};
};
clouds = [
{ from = "klub-reseau"; cloudHost = "nuage.beta.rz.ens.wtf"; }
{ from = "eleves-ens"; cloudHost = "cloud.eleves.ens.fr"; }
{ from = "frama-agenda"; cloudHost = "framagenda.org"; }
];
in
{
services.nginx = {
enable = true;
resolver = {
addresses = [ "1.1.1.1" ];
};
recommendedGzipSettings = true;
recommendedOptimisation = true;
recommendedProxySettings = true;
recommendedTlsSettings = true;
# # Only allow PFS-enabled ciphers with AES256
# sslCiphers = "AES256+EECDH:AES256+EDH:!aNULL";
virtualHosts = {
"home.beta.rz.ens.wtf" = {
serverAliases = [ "beta.rz.ens.wtf" ];
forceSSL = true;
enableACME = true;
root = "/var/public-cof/home";
};
# FIXME: factorize and remove it, it has been superseded by eleves.ens.fr/calendrier
# "home.beta.rz.ens.wtf" = {
# serverAliases = [ "beta.rz.ens.wtf" ];
# default = true;
# forceSSL = true;
# enableACME = true;
# root = "/var/public-cof/home";
# locations = builtins.listToAttrs (map mkCloudLocation clouds);
# };
};
};
networking.firewall.allowedTCPPorts = [ 80 443 ];
networking.firewall.allowedUDPPorts = [ 80 443 ];
}

View file

@ -0,0 +1,56 @@
{
"agenix": {
"branch": "master",
"description": "age-encrypted secrets for NixOS",
"homepage": "",
"owner": "ryantm",
"repo": "agenix",
"rev": "fb00f178b3a49a39cc964049075439b575d36d60",
"sha256": "0rb99dbwnaf8sgjbshwk1bizs51jild3zg61a5yqw3h0vcxalzrp",
"type": "tarball",
"url": "https://github.com/ryantm/agenix/archive/fb00f178b3a49a39cc964049075439b575d36d60.tar.gz",
"url_template": "https://github.com/<owner>/<repo>/archive/<rev>.tar.gz"
},
"klubrz-nur": {
"branch": "main",
"repo": "https://git.rz.ens.wtf/Klub-RZ/nur",
"rev": "bb95bbed09ccb2ae5ab5a8e02537c4c28c46d27e",
"type": "git"
},
"niv": {
"branch": "master",
"description": "Easy dependency management for Nix projects",
"homepage": "https://github.com/nmattia/niv",
"owner": "nmattia",
"repo": "niv",
"rev": "e0ca65c81a2d7a4d82a189f1e23a48d59ad42070",
"sha256": "1pq9nh1d8nn3xvbdny8fafzw87mj7gsmp6pxkdl65w2g18rmcmzx",
"type": "tarball",
"url": "https://github.com/nmattia/niv/archive/e0ca65c81a2d7a4d82a189f1e23a48d59ad42070.tar.gz",
"url_template": "https://github.com/<owner>/<repo>/archive/<rev>.tar.gz"
},
"nixexprs": {
"branch": "master",
"description": "All my Nix expressions",
"homepage": null,
"owner": "RaitoBezarius",
"repo": "nixexprs",
"rev": "5fd6966844be775a272e932375d7982275ba2300",
"sha256": "1l5zgdgqbn7apw2ngqzid0sqrklx0rnj8sjid4ykx9156kdqjan5",
"type": "tarball",
"url": "https://github.com/RaitoBezarius/nixexprs/archive/5fd6966844be775a272e932375d7982275ba2300.tar.gz",
"url_template": "https://github.com/<owner>/<repo>/archive/<rev>.tar.gz"
},
"raito-nur": {
"branch": "master",
"description": "All my Nix expressions",
"homepage": null,
"owner": "RaitoBezarius",
"repo": "nixexprs",
"rev": "ead9a70ae1c15d786ee276e6be51a8d6d27baa88",
"sha256": "1wpk6rxcfgf0rvzvdbd3ay1xjc3mh6ds5mmp2w6mphskrhd9qjpq",
"type": "tarball",
"url": "https://github.com/RaitoBezarius/nixexprs/archive/ead9a70ae1c15d786ee276e6be51a8d6d27baa88.tar.gz",
"url_template": "https://github.com/<owner>/<repo>/archive/<rev>.tar.gz"
}
}

View file

@ -0,0 +1,194 @@
# This file has been generated by Niv.
let
#
# The fetchers. fetch_<type> fetches specs of type <type>.
#
fetch_file = pkgs: name: spec:
let
name' = sanitizeName name + "-src";
in
if spec.builtin or true then
builtins_fetchurl { inherit (spec) url sha256; name = name'; }
else
pkgs.fetchurl { inherit (spec) url sha256; name = name'; };
fetch_tarball = pkgs: name: spec:
let
name' = sanitizeName name + "-src";
in
if spec.builtin or true then
builtins_fetchTarball { name = name'; inherit (spec) url sha256; }
else
pkgs.fetchzip { name = name'; inherit (spec) url sha256; };
fetch_git = name: spec:
let
ref =
if spec ? ref then spec.ref else
if spec ? branch then "refs/heads/${spec.branch}" else
if spec ? tag then "refs/tags/${spec.tag}" else
abort "In git source '${name}': Please specify `ref`, `tag` or `branch`!";
submodules = if spec ? submodules then spec.submodules else false;
submoduleArg =
let
nixSupportsSubmodules = builtins.compareVersions builtins.nixVersion "2.4" >= 0;
emptyArgWithWarning =
if submodules == true
then
builtins.trace
(
"The niv input \"${name}\" uses submodules "
+ "but your nix's (${builtins.nixVersion}) builtins.fetchGit "
+ "does not support them"
)
{}
else {};
in
if nixSupportsSubmodules
then { inherit submodules; }
else emptyArgWithWarning;
in
builtins.fetchGit
({ url = spec.repo; inherit (spec) rev; inherit ref; } // submoduleArg);
fetch_local = spec: spec.path;
fetch_builtin-tarball = name: throw
''[${name}] The niv type "builtin-tarball" is deprecated. You should instead use `builtin = true`.
$ niv modify ${name} -a type=tarball -a builtin=true'';
fetch_builtin-url = name: throw
''[${name}] The niv type "builtin-url" will soon be deprecated. You should instead use `builtin = true`.
$ niv modify ${name} -a type=file -a builtin=true'';
#
# Various helpers
#
# https://github.com/NixOS/nixpkgs/pull/83241/files#diff-c6f540a4f3bfa4b0e8b6bafd4cd54e8bR695
sanitizeName = name:
(
concatMapStrings (s: if builtins.isList s then "-" else s)
(
builtins.split "[^[:alnum:]+._?=-]+"
((x: builtins.elemAt (builtins.match "\\.*(.*)" x) 0) name)
)
);
# The set of packages used when specs are fetched using non-builtins.
mkPkgs = sources: system:
let
sourcesNixpkgs =
import (builtins_fetchTarball { inherit (sources.nixpkgs) url sha256; }) { inherit system; };
hasNixpkgsPath = builtins.any (x: x.prefix == "nixpkgs") builtins.nixPath;
hasThisAsNixpkgsPath = <nixpkgs> == ./.;
in
if builtins.hasAttr "nixpkgs" sources
then sourcesNixpkgs
else if hasNixpkgsPath && ! hasThisAsNixpkgsPath then
import <nixpkgs> {}
else
abort
''
Please specify either <nixpkgs> (through -I or NIX_PATH=nixpkgs=...) or
add a package called "nixpkgs" to your sources.json.
'';
# The actual fetching function.
fetch = pkgs: name: spec:
if ! builtins.hasAttr "type" spec then
abort "ERROR: niv spec ${name} does not have a 'type' attribute"
else if spec.type == "file" then fetch_file pkgs name spec
else if spec.type == "tarball" then fetch_tarball pkgs name spec
else if spec.type == "git" then fetch_git name spec
else if spec.type == "local" then fetch_local spec
else if spec.type == "builtin-tarball" then fetch_builtin-tarball name
else if spec.type == "builtin-url" then fetch_builtin-url name
else
abort "ERROR: niv spec ${name} has unknown type ${builtins.toJSON spec.type}";
# If the environment variable NIV_OVERRIDE_${name} is set, then use
# the path directly as opposed to the fetched source.
replace = name: drv:
let
saneName = stringAsChars (c: if isNull (builtins.match "[a-zA-Z0-9]" c) then "_" else c) name;
ersatz = builtins.getEnv "NIV_OVERRIDE_${saneName}";
in
if ersatz == "" then drv else
# this turns the string into an actual Nix path (for both absolute and
# relative paths)
if builtins.substring 0 1 ersatz == "/" then /. + ersatz else /. + builtins.getEnv "PWD" + "/${ersatz}";
# Ports of functions for older nix versions
# a Nix version of mapAttrs if the built-in doesn't exist
mapAttrs = builtins.mapAttrs or (
f: set: with builtins;
listToAttrs (map (attr: { name = attr; value = f attr set.${attr}; }) (attrNames set))
);
# https://github.com/NixOS/nixpkgs/blob/0258808f5744ca980b9a1f24fe0b1e6f0fecee9c/lib/lists.nix#L295
range = first: last: if first > last then [] else builtins.genList (n: first + n) (last - first + 1);
# https://github.com/NixOS/nixpkgs/blob/0258808f5744ca980b9a1f24fe0b1e6f0fecee9c/lib/strings.nix#L257
stringToCharacters = s: map (p: builtins.substring p 1 s) (range 0 (builtins.stringLength s - 1));
# https://github.com/NixOS/nixpkgs/blob/0258808f5744ca980b9a1f24fe0b1e6f0fecee9c/lib/strings.nix#L269
stringAsChars = f: s: concatStrings (map f (stringToCharacters s));
concatMapStrings = f: list: concatStrings (map f list);
concatStrings = builtins.concatStringsSep "";
# https://github.com/NixOS/nixpkgs/blob/8a9f58a375c401b96da862d969f66429def1d118/lib/attrsets.nix#L331
optionalAttrs = cond: as: if cond then as else {};
# fetchTarball version that is compatible between all the versions of Nix
builtins_fetchTarball = { url, name ? null, sha256 }@attrs:
let
inherit (builtins) lessThan nixVersion fetchTarball;
in
if lessThan nixVersion "1.12" then
fetchTarball ({ inherit url; } // (optionalAttrs (!isNull name) { inherit name; }))
else
fetchTarball attrs;
# fetchurl version that is compatible between all the versions of Nix
builtins_fetchurl = { url, name ? null, sha256 }@attrs:
let
inherit (builtins) lessThan nixVersion fetchurl;
in
if lessThan nixVersion "1.12" then
fetchurl ({ inherit url; } // (optionalAttrs (!isNull name) { inherit name; }))
else
fetchurl attrs;
# Create the final "sources" from the config
mkSources = config:
mapAttrs (
name: spec:
if builtins.hasAttr "outPath" spec
then abort
"The values in sources.json should not have an 'outPath' attribute"
else
spec // { outPath = replace name (fetch config.pkgs name spec); }
) config.sources;
# The "config" used by the fetchers
mkConfig =
{ sourcesFile ? if builtins.pathExists ./sources.json then ./sources.json else null
, sources ? if isNull sourcesFile then {} else builtins.fromJSON (builtins.readFile sourcesFile)
, system ? builtins.currentSystem
, pkgs ? mkPkgs sources system
}: rec {
# The sources, i.e. the attribute set of spec name to spec
inherit sources;
# The "pkgs" (evaluated nixpkgs) to use for e.g. non-builtin fetchers
inherit pkgs;
};
in
mkSources (mkConfig {}) // { __functor = _: settings: mkSources (mkConfig settings); }

View file

@ -0,0 +1,20 @@
{ lib, pkgs, ... }:
let
nivSources = import ./nix/sources.nix;
rz-src = nivSources.klubrz-nur;
rz-no-pkgs = (import nivSources.klubrz-nur {});
raitobezarius-src = nivSources.nixexprs;
raitobezarius-no-pkgs = (import raitobezarius-src {});
in
{
nixpkgs.config.packageOverrides = {
rz = import rz-src { inherit pkgs; };
};
imports = [
"${nivSources.agenix}/modules/age.nix"
raitobezarius-no-pkgs.modules.sniproxy
] ++ lib.attrValues rz-no-pkgs.modules;
nixpkgs.overlays = [];
}

View file

@ -0,0 +1,31 @@
{ pkgs, lib, config, ... }:
{
services.nginx.virtualHosts."notion.rz.ens.wtf" = {
enableACME = true;
forceSSL = true;
locations."/" = {
proxyPass = "http://localhost:3000";
proxyWebsockets = true;
};
};
services.outline = {
enable = true;
publicUrl = "https://notion.rz.ens.wtf";
defaultLanguage = "fr_FR";
storage = {
accessKey = "GK8b32d276b2eafb999a53188a";
secretKeyFile = config.age.secrets.outlineS3Secrets.path;
uploadBucketUrl = "https://s3.rz.ens.wtf";
uploadBucketName = "outline";
region = "ens";
};
oidcAuthentication = {
userinfoUrl = "https://auth.rz.ens.wtf/auth/realms/ClubReseau/protocol/openid-connect/userinfo";
tokenUrl = "https://auth.rz.ens.wtf/auth/realms/ClubReseau/protocol/openid-connect/token";
authUrl = "https://auth.rz.ens.wtf/auth/realms/ClubReseau/protocol/openid-connect/auth";
clientSecretFile = config.age.secrets.outline-oidc-client-secret.path;
displayName = "Club réseau";
clientId = "outline";
};
};
}

View file

@ -0,0 +1,34 @@
{ pkgs, ... }:
let
port = 19000;
in
{
services.rstudio-server = {
enable = true;
rserverExtraConfig = ''
www-port = ${toString port}
'';
package = pkgs.rstudioServerWrapper.override {
packages = with pkgs.rPackages; [
ggplot2
rmarkdown
dplyr
];
};
};
users.users.ruser = {
isNormalUser = true;
hashedPassword = "$6$pTXXVh8NfE.M8VPc$q0fFh3Y7Y0DauLCcZLgJzFciq1wkjoHmO61XpOrZLH3a1M32ZzOMbjx2XMm2QxrUncbx6hGerY/lD8rQ8InS4.";
};
services.nginx.virtualHosts."rstudio.beta.rz.ens.wtf" = {
enableACME = true;
forceSSL = true;
locations."/" = {
proxyPass = "http://localhost:${toString port}";
proxyWebsockets = true;
};
};
}

View file

@ -0,0 +1,31 @@
{ ... }:
{
age.secrets.nextcloudAdminPassword = {
owner = "nextcloud";
group = "nextcloud";
file = ./nextcloudAdminPasswordFile.age;
};
age.secrets.nextcloudDatabasePassword = {
owner = "nextcloud";
group = "nextcloud";
file = ./nextcloudDatabasePasswordFile.age;
};
age.secrets.kanboard-secrets = {
owner = "kanboard";
group = "kanboard";
file = ./kanboard-secrets.age;
};
age.secrets.outlineS3Secrets = {
owner = "outline";
group = "outline";
file = ./outlineS3Secrets.age;
};
age.secrets.outline-oidc-client-secret = {
owner = "outline";
group = "outline";
file = ./outline-oidc-client-secret.age;
};
}

View file

@ -0,0 +1,25 @@
age-encryption.org/v1
-> ssh-rsa krWCLQ
jsay8IXK6RjVULRqpfvgHOr8H3ALxQyJ3BQIkmSfRrLlJXDbYWUKBCztXc7whfb/
XTc3Sa5bybIXXX3wLzYmxCYjUa1CoHgIb1UWAhM3KyTJ4XSw7pVti29VM5p74+ex
tJeb44hXlkD7V7C2yYp6CcBH1IgnvEL8ulVopkis/TBQtWi6QaGJBPX2yxEJ3QDh
uAn5czrrDenBZRsIYTaKrlbgCM/Oeh4mDFSaFKIqfX2g7ClbsC1ejF3PvbsXN6il
pk2YSZ/F5ivNBkvWFmQrNJyLjkcIrxoFvzcXOTk8yM9iu4BFlPbX7NcAMrHpbSIR
3ew59I0cGkbzRAtLI9p97w
-> ssh-ed25519 85WiGg XQK2huU0kqkKbVYf6SJFqcumOL8zDPfOuGwNy78dJm4
aP8CNgS1/wfv2RB7nXZqYnZaXDORk9I5lPZy87FVmRY
-> ssh-ed25519 reTIKw jZ57SfMYyOr9P9eNK/Q2CMAWtYtfjyV/MaTVnqEHxkU
ycPo/pwC9CtYWAcrclo1b26+mPU4Z6pCPecGPMmL3ag
-> ssh-ed25519 /vwQcQ v5bvHTvld6WErGt+Vp0mivpFH5srQPHkbPd0Nk3IDy0
27+ZreTwyaxtb5vrRpD/2C2MUT9onRcX4Yr7KHnTGOo
-> ssh-ed25519 cvTB5g gKxECDYMSja0FTqteAk39iMDsNIM+ox31sIvnY2ityk
pkUZgDWdAzuGCvuRhOE8oeazIRw+kpPhnkksF2zTjxA
-> ssh-ed25519 Wu8JLQ lMgIKw3Qzg/Lw6UtpPZWDrE0WBc71meaprrnmARqDDM
FN/S9xo22u4kMWqrPD3KmfLbDq8L0TxtfDUSBLVq+Tk
-> ssh-ed25519 xbfJnw emSflhzdsItaXULjPXre8jlnXxJuXFAaoLWGVAAej1I
4OS68AuzPr+zwp9Bqb4lYGJHjPwPMSXuprw7+8agOyU
-> Wd-grease
pdSa/JP70fd6VvSgpIJQAk8ZiZfKo8l7UpVwBib59SB9IRNVZdSbHINFUzuIozGu
Z7dyg+x6QQ
--- TjceHicjeIIKz0f7R5u7nLrCtb39MmS/vEK3w0xHbmw
¾ßQ¢ëºZ`? ZvÆ~^è¼Ø$öÒcèt§è2ÓÁÚÔ“y3Ö.+KFÊ2OC_$¤]y£³¬À³~ý¢×l%0ôÐ_ ð Ü»”à R·®EÆM4HÄ°•á™{ÑrÐ$˜çÞ¬™*<2A>1\2FÚ¬BLAK!ÜÜ&Cþ×û_Õ.Oëmœ3¬ÕÍ•©´êµV<ü z'-sø'J

View file

@ -0,0 +1,24 @@
age-encryption.org/v1
-> ssh-ed25519 xbfJnw jGSrM/Yx0LnVlmBml7/7LwZeSL68CPiF7/97OyYnJj0
66yS5TDLDpMXz6ggOeMyOhSDU2jSKDVoW5zvBvdN83I
-> ssh-ed25519 Wu8JLQ BH68DcAZ/Ruudd2QgREQ1I9YhC/JWOnn7dOkgoVdAgE
cJq/valbiW3xYyXxgmTMos9XQm/+SDIhd3cn32vcgxs
-> ssh-ed25519 cvTB5g qXCbgWmzetHsJTo/nnN9M/dRmYLW7HIHuaphMHXFB00
WLVPkAJk2D4dca2+QlGFtCArLFjixypXV/P7VmJuK6g
-> ssh-ed25519 /vwQcQ 0aUZckwIHbXv/Uo3gyeAHGwEIzMQyPSh2Ks+s3QBPU8
zt978+4EwedA6UTLurnjisjbrR/qFZf80IPcAxd3Qxw
-> ssh-ed25519 reTIKw jFGzhLb0YM5dJslCmp7bjRt5JYufGRAJzVmdjMKgdQw
Y9KIYgX2PHCU0/8h4Pn6YLqaZYzvrPUy1pmaLGzY8C4
-> ssh-ed25519 85WiGg aZRVNM5iSL+BpZfundDVSpPs0mhFxssUA/t5POsi1AU
haYzRumOlDno9UdlcCr/GUoAOEqNrf+iPv9SpP76EYM
-> ssh-rsa krWCLQ
pbjqzOfXUuWlunTcCiwjKAqe5ZZdW+6jE86D3yuPz4PheDEFi6oYAnc0pIPoZOnh
9OkTTB6o9wPhoA5O+SOszvCFVOlS33EHwCFKFwy/lg3LwgsU6qon6YQAQfjOMf57
yGlFDJhGfKfzoXzAlWIxpY6KQE15pkI2OAv9/1UWmFmGpw1vWOgcyJn0rbHK9Wtk
uGWOPCAsx7n/K4YukvVdB1pHtNlXyj6odMwRch3MmpKl4UlBMtB10NI2fMpqcWp1
vgCcjsP2JX6zlTTQvu1afV2QMk2R9zfm4iZtk6lqhkFO9hGx12/1WfxFlww6YDyB
HDLu5vZddUtV7Wwm9Wa6Cw
-> H0-z{"-grease bic 5)(&;3`E _&UZCo7 hJ_x
5r9qRqyXOdPxqPPV8uCjaiJveaq0TLioCRMohcBamFx80I2EN/XDkPzeUNSkYyQ/
--- gQnYjgiBjl7W2nLAvdfGcX8UVMr5RCFSysgp7iGWZlc
(þ¾}$è11¯¹E-(»Sþ r¾ÂlGb3`>óKÒ6BŒeé” ÊjÉ“o"{G¦G=F7í¼

View file

@ -0,0 +1,25 @@
age-encryption.org/v1
-> ssh-ed25519 xbfJnw qeyTMwQ+l90wwNiGxLCvKZ+yIzEjehcr8SIlHrHTERQ
3XTb7giFfF9l/+hDq/TlWKt/Gr1qlMxB2agi1Mzn4Bs
-> ssh-ed25519 Wu8JLQ vrqgvKp+dB2TnZrRriOvvJfqxh7vbSpTL2P+u8zORC4
7qTNpJw8j4HpjehzoZeMUqCPDBFZRhu3bhdCVbRAUrU
-> ssh-ed25519 cvTB5g 2R6aXhN56nYrEObDuDJdhmH1kMduXUzoEg22C4QjHRA
sIRV6aTkefsy4wdJ1Ay+O/q0Y0MdTPRFKTjWGHlz5xg
-> ssh-ed25519 /vwQcQ xcSn2vFYBkYESWRZqmeWNiP0EV1zWH3SaiYG+6V8xGY
zv2yiZrBlsskeLrvco5w+QPTDRyRGQ3mjGuHFjWcfGI
-> ssh-ed25519 reTIKw Bdc7/F+nWuCQ5aqiuUPqb6mHlQCMafINyWaqVDQG5y0
Myj64k+s/KIVOfGje3reKeRHrjGL6cE+9knBCsS+rX0
-> ssh-ed25519 85WiGg PKpNCdpcl+aSuTx13I/Hq9annJ5FRXiONQ/4iqwyZUc
CHUHvPtA5ydOkpHfgOXtvuYMOAhM53YfXbexhW7fbJY
-> ssh-rsa krWCLQ
IhI9bg+jq5y32OaYdes7y1iBUkOAkc2dXdFP2FI0/CAthBBOGs9qyCuf39S8i4YT
pHPRniwOYUUuCjThU1zUA6cboBh13Y381mioqTF656/w8tn2ZGFRnOcOwqp9d0v4
vPHgdyZFpmD0MUmFlw1YfTWWWMbFyhDPY6C3r4L3dftGuineY3A/+zC+Y1RuCYBw
+Kl/tbIGUBckX+Cqdt8KokPpGw3ZxkHXWx3lMlNembrPpsM44Mbz88mBiHn77Ys3
auHE7Ff04txLiG9fGo9p3GX6nk2aCz1vT+YJB1cWZErsNSWTSRLILGLHvR37KMMv
daiVtfDwNwoGbEmpw0iVCA
-> ;LK-grease H638S/n
76dNkVvkNr1Y+O2AwEjYyUbmCog7ChnU3U54t/ZyPCAd2Q5vuGSQHe+RxtIh8fux
RvrDH2Qa7jGT0F86FTwrWK7fKQkT
--- r4tKKSFy30F9y4jQzdBB0RjCFJQmy2lFhZDr3enZjeQ
Ž-zÆyl¾ ç§,“˜ ýj>8Ѐ¶ÔØÂÊ%>œM<C593>q<EFBFBD>o±)ÛDi0Èï YªžÇLçÌ©Ñ

View file

@ -0,0 +1,26 @@
age-encryption.org/v1
-> ssh-rsa krWCLQ
HeTVcJxU2zRewuzQVknnxAYjlCU8+GJjBz9joGPo2j934uiM3A6PBsFmoz6I1ZfJ
pg68benaKfV+VI1sN8fMDWoEO0QrFzHYULXT9JCyQTClUzUZSlMpzmDgCmHjLPEc
qB23sbwKzgyFO9SKHsPvOqxZrEyTwAKiNYa33QuSyRxN3S4/9PxVjgJTTqLbTVqf
hhnujxviU3iHV2ACqLAV5jYSbAleiAh53vnBc0k326vXbrumQqFvQtgwcqDn4vDR
2QYzEwsj+yV9BlRrGSBZSnoHZjWtsE/ntrEaIZiItT3Ots1CCVswd7LGb3LspYbf
NheRvY7zUXppGiB0+mjZJg
-> ssh-ed25519 85WiGg tGvDzYdpKP8lql3murRlp95w7jQUhhuodIgVxDk4Lgs
aVV4b71w/nU3nBaYKdzzYjXVaxgN2EpyQiKsjO33GcI
-> ssh-ed25519 reTIKw LJJF7K8fRsSoAFDyndWP9nA5FV4w7cWSqUgGnvdB42I
wI22cL/GuyVou1robDUHzNMfCR7L6NA4UWFSeV73d88
-> ssh-ed25519 /vwQcQ KZQSME50r4yrnyFfH6nwbmCn0UmVUMIBhhfqoicrKVY
xDdBu7/K8ZxGT2BnffAR8UsQIAVlLpSfEvo1m4k87ng
-> ssh-ed25519 cvTB5g HjLQQhFwEekFYHV5sko/x8RwcAsgvl/cCoKakX4B6yE
Ub5TWpDPYA3DSwfRT2hmgPcwoMIhsOhgdhckFuZxQ8s
-> ssh-ed25519 Wu8JLQ L0bnDPmv3Chemi/BKhux9GYXDMMLUjO6H8MQe1REpBA
qtN6IH8M8kLYAQ8a64kYCCaAPhg6VjrojTONdY4MVyA
-> ssh-ed25519 xbfJnw 94xx8KL0EWqs3HIsdY9RFvC6aRsk7cemZxciLIkVCDM
WZnyqSwpCBA8GNnu6VEJSLIRtv8rzOpGFH6e387ohpQ
-> TS-grease
D32P8/tpegDSy/xsspwpuq8EVqwDyZUzJF2Ose+3cqHAx8db4DPWnmt4z4Ch5bXw
KtmO+2eEYTmPyYUZxI+uzr93CQhVq7aFlch6cWLEaqg
--- 6kPR6tdczt01UaY4ps38dncSMFCupa9uZmSWBjm85ps
<18>LnŸÖ4¦K¬z>­Ê(³Ù†°=f¼õ´ˆÊ·œ®PG<50>Þ<hÒçº×ø±uÓÖV³Ø#¸P
ÑÑ&¶

View file

@ -0,0 +1,25 @@
age-encryption.org/v1
-> ssh-rsa krWCLQ
nxiY5l98JhWEwLYN7sWtsgN4faDTIpgo1fiPScxXB8/ljnxIyd1vhMVRt0WCTOQV
CFTQ9MOoTAk90Zj4wjxDjoJjjsXLUBVnjqLdQy76kgR5vAvVrHzuYTYO4Y4k0/qh
S6BEFN655P0n4Gxf9kJtKxi3ipN6B46ydACAjFeyeuOPMkMdBBZq1BOLPEOC9I+O
87p+8BdL+zxkYfaWfEggYgabrE7y91EjiB1VCuT0GFm8T8iBojvThxWQlHQAybBc
gvgTlyGf8YmY82uGhGQR39okrA914mJUkr11JZ9457qL+/t5Au/dha1x6QlwcUoz
Tp5OQJAfXZc02LsICq2I7A
-> ssh-ed25519 85WiGg c6vyT96h0eVL+xZpR0Zk06l5ApUsqENY9ESeYuOG0zY
dJbQVgH41Ti/AM7WAlXCCA501h8wgx2os5yiZt+jxp8
-> ssh-ed25519 reTIKw rVhKDqm51EMuOQnTcsdWmqoBDI/LLnFpkJW93EfcdB0
AAOEQp0tux1vJ0bPIcB1HtLodig/J4poeu6j/Hk8KiA
-> ssh-ed25519 /vwQcQ jGLr83VDSxYd3v42ECOiTpSTDRB5TVSqx3QHRbMgfEk
k2hBCGntsqP0czKV2JvMbf8lAqpjVvnJqSxfdr00A7w
-> ssh-ed25519 cvTB5g BqVT8ytcjINNKrGAtttAtxRMpLs4LJg1Uy3zvDxTvwk
DRDEl+CNZnuT+KE1txjHgaWIYmiSeUTsesnXYq89YNQ
-> ssh-ed25519 Wu8JLQ 731ytp+gu36OvH0QbkeDUwMHj3J4u0JujJnfTUQ2C1A
KPGEKLoV9K1PPdIyla5D1lsmhRt/XUHLrCTeApbqR6c
-> ssh-ed25519 xbfJnw Ojf4cuctALx+Q/qWqSarRcnxvwrHjbAK5r4pnhKUzmo
WHp4Op3N3SeniWS7XhPmvRkTyjDIPDBBGviDaiCNbOc
-> 3P-h|3ru-grease
5icFsPwzKpnImSlgICy/wDq6YJLTcIML3EoDUOgvGOFSs+efH4bWExmd2ktGtqYd
ewEKHYlnpIFNTMtlRs7U7sR3qnLHadq3McnhR/8OlQ
--- iwVp/AYpQfFOIg/OI85nNTgdY/HKlEsCHWiBO0lOtJg
Z=eBÒbÀ£â[3$”Ôkâ„(õ®²2Èöx%0ž—£+18T•,;ÅÛóFÕ¬"Ke³•¶óÃZø*Òè$}ýœCp Ão9æ+À¡‡›|CJ¹-¼

View file

@ -0,0 +1,16 @@
let
pkgs = import <nixpkgs> {};
lib = pkgs.lib;
readPubkeys = user: builtins.filter (k: k != "") (lib.splitString "\n" (builtins.readFile (../../pubkeys + "/${user}.keys")));
superadmins = (readPubkeys "raito") ++ (readPubkeys "gdd") ++ (readPubkeys "hubrecht");
public-cof = "ssh-ed25519 AAAAC3NzaC1lZDI1NTE5AAAAIDUe/w7e3+KIa1YPFH9FGapDWM/sWOvOCcYXNlnIWypg";
systems = [ public-cof ];
in
{
"nextcloudAdminPasswordFile.age".publicKeys = superadmins ++ systems;
"nextcloudDatabasePasswordFile.age".publicKeys = superadmins ++ systems;
"kanboard-secrets.age".publicKeys = superadmins ++ systems;
"outlineS3Secrets.age".publicKeys = superadmins ++ systems;
"outline-oidc-client-secret.age".publicKeys = superadmins ++ systems;
}

View file

@ -8,7 +8,7 @@
# Auto GC and store optimizations
nix = {
trustedUsers = [ "root" ];
settings.trusted-users = [ "root" ];
gc = {
automatic = true;
dates = "weekly";

View file

@ -0,0 +1,30 @@
{ ... }:
let
proxyIPv4 = "45.13.104.29";
in
{
networking.firewall.allowedTCPPorts = [ 443 ];
services.sniproxy = {
enable = true;
resolver = {
mode = "ipv6_first";
};
listeners = [
{
address = "${proxyIPv4}:443";
table = "vhosts";
fallback = null;
}
];
tables.vhosts = [
{
match = "traque.beta.rz.ens.wtf";
dest = "traque.beta.rz.ens.wtf";
}
];
};
}

View file

@ -1,84 +0,0 @@
{ config, pkgs, ... }:
{
imports =
[
./hardware-configuration.nix
./programs.nix
./system.nix
# TODO monitoring
];
# Use the systemd-boot EFI boot loader.
boot.loader.systemd-boot.enable = true;
boot.loader.efi.canTouchEfiVariables = true;
boot.initrd.supportedFilesystems = [ "zfs" ];
boot.supportedFilesystems = [ "zfs" ];
networking.hostName = "remote-builder-01";
networking.hostId = "11894198";
# Set your time zone.
time.timeZone = "Europe/Paris";
# The global useDHCP flag is deprecated, therefore explicitly set to false here.
# Per-interface useDHCP will be mandatory in the future, so this generated config
# replicates the default behaviour.
networking.useDHCP = false;
networking.interfaces.ens18.useDHCP = true;
# Configure network proxy if necessary
# networking.proxy.default = "http://user:password@proxy:port/";
# networking.proxy.noProxy = "127.0.0.1,localhost,internal.domain";
# Select internationalisation properties.
i18n.defaultLocale = "en_US.UTF-8";
console = {
font = "Lat2-Terminus16";
keyMap = "us";
};
# List packages installed in system profile. To search, run:
# $ nix search wget
environment.systemPackages = with pkgs; [
vim
wget
];
# Some programs need SUID wrappers, can be configured further or are
# started in user sessions.
programs.mtr.enable = true;
programs.gnupg.agent = {
enable = true;
enableSSHSupport = true;
};
# List services that you want to enable:
services.zfs.autoScrub.enable = true;
# Enable the OpenSSH daemon.
services.openssh.enable = true;
users.users.root.openssh.authorizedKeys.keyFiles = [
./pubkeys/gdd.keys
./pubkeys/raito.keys
./pubkeys/remote-builders.keys
];
# Open ports in the firewall.
# networking.firewall.allowedTCPPorts = [ ... ];
# networking.firewall.allowedUDPPorts = [ ... ];
# Or disable the firewall altogether.
networking.firewall.enable = false;
# 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 = "21.05"; # Did you read the comment?
}

View file

@ -1,24 +0,0 @@
{ pkgs, ... }:
let pkgsList = with pkgs; [
nix-prefetch-git
dnsutils
unzip
zip
ripgrep
niv
nixfmt
];
in
{
imports = [
./vim.nix
];
programs = {
tmux.enable = true;
mosh.enable = true;
};
environment.systemPackages = pkgsList;
}

View file

@ -1,2 +0,0 @@
ssh-ed25519 AAAAC3NzaC1lZDI1NTE5AAAAICE7TN5NQKGojNGIeTFiHjLHTDQGT8i05JFqX/zLW2zc
ssh-ed25519 AAAAC3NzaC1lZDI1NTE5AAAAIIFbkPWWZzOBaRdx4+7xQUgxDwuncSl2fxAeVuYfVUPZ

View file

@ -1,4 +0,0 @@
ssh-rsa AAAAB3NzaC1yc2EAAAADAQABAAABAQDcEkYM1r8QVNM/G5CxJInEdoBCWjEHHDdHlzDYNSUIdHHsn04QY+XI67AdMCm8w30GZnLUIj5RiJEWXREUApby0GrfxGGcy8otforygfgtmuUKAUEHdU2MMwrQI7RtTZ8oQ0USRGuqvmegxz3l5caVU7qGvBllJ4NUHXrkZSja2/51vq80RF4MKkDGiz7xUTixI2UcBwQBCA/kQedKV9G28EH+1XfvePqmMivZjl+7VyHsgUVj9eRGA1XWFw59UPZG8a7VkxO/Eb3K9NF297HUAcFMcbY6cPFi9AaBgu3VC4eetDnoN/+xT1owiHi7BReQhGAy/6cdf7C/my5ehZwD
ssh-ed25519 AAAAC3NzaC1lZDI1NTE5AAAAIKIIcqryU28FkV+UpiTnGCOfwKO5jFhkdvU7a7Ew2KoZ
ssh-ed25519 AAAAC3NzaC1lZDI1NTE5AAAAIMLf6B8VV//BhOWihYK8Zy1CJ3sg4w2bP0aBO0VPs4hS
ssh-ed25519 AAAAC3NzaC1lZDI1NTE5AAAAIE0xMwWedkKosax9+7D2OlnMxFL/eV4CvFZLsbLptpXr

View file

@ -1,28 +0,0 @@
{ pkgs, ... }:
{
# # Auto upgrades
# system.autoUpgrade = {
# enable = false; # TODO(Ryan): do not enable, it will break deployments.
# allowReboot = false;
# };
# Auto GC and store optimizations
nix = {
trustedUsers = [ "root" "gab" ];
gc = {
automatic = true;
dates = "weekly";
options = "--delete-older-than 90d";
};
optimise.automatic = true;
extraOptions = ''
min-free = ${toString (100 * 1024 * 1024)}
max-free = ${toString (1024 * 1024 * 1024)}
'';
};
services.locate = {
enable = true;
interval = "04:05";
};
}

View file

@ -1,31 +0,0 @@
{ pkgs, ... }:
{
environment.variables = { EDITOR = "vim"; };
environment.systemPackages = with pkgs; [
nixfmt
git
(neovim.override {
vimAlias = true;
configure = {
packages.myPlugins = with pkgs.vimPlugins; {
start = [ vim-lastplace vim-nix ];
opt = [];
};
customRC = ''
set encoding=utf-8
set wildmenu
set nocompatible
set backspace=indent,eol,start
set cursorline
hi CursorLine term=bold cterm=bold ctermbg=darkgrey
set number
set relativenumber
set tabstop=4
set expandtab
'';
};
}
)];
}

View file

@ -0,0 +1,28 @@
# Edit this configuration file to define what should be installed on
# your system. Help is available in the configuration.nix(5) man page
# and in the NixOS manual (accessible by running nixos-help).
{ config, pkgs, ... }:
{
imports =
[
./router.nix
];
# Use the systemd-boot EFI boot loader.
boot.loader.systemd-boot.enable = true;
boot.loader.efi.canTouchEfiVariables = true;
# Set your time zone.
# time.timeZone = "Europe/Amsterdam";
networking.hostName = "router03";
networking.domain = "internal.rz.ens.wtf";
services.getty.autologinUser = "root";
services.openssh.enable = true;
system.stateVersion = "24.05"; # Did you read the comment?
}

View file

@ -8,28 +8,33 @@
[ (modulesPath + "/profiles/qemu-guest.nix")
];
boot.initrd.availableKernelModules = [ "ata_piix" "uhci_hcd" "virtio_pci" "sd_mod" "sr_mod" ];
boot.initrd.availableKernelModules = [ "ata_piix" "uhci_hcd" "virtio_pci" "virtio_scsi" "sd_mod" "sr_mod" ];
boot.initrd.kernelModules = [ ];
boot.kernelModules = [ ];
boot.extraModulePackages = [ ];
boot.initrd.luks.devices.c-disk = {
device = "/dev/disk/by-uuid/9c57dd15-b6e4-4496-84ca-6ffe41a9dd42";
keyFile = "/dev/zero";
keyFileSize = 1;
fallbackToPassword = true;
};
fileSystems."/" =
{ device = "rpool/root/nixos";
fsType = "zfs";
};
fileSystems."/home" =
{ device = "rpool/home";
fsType = "zfs";
{ device = "/dev/disk/by-uuid/a48770a7-87f0-4f95-9458-50f022d20472";
fsType = "ext4";
};
fileSystems."/boot" =
{ device = "/dev/disk/by-uuid/3341-A3B9";
{ device = "/dev/disk/by-uuid/1FD5-AB3E";
fsType = "vfat";
};
swapDevices =
[ { device = "/dev/disk/by-uuid/1f624fe3-1fc5-44f4-9529-812558ffba42"; }
[ { device = "/dev/disk/by-uuid/050ed1a8-60be-47e8-9f96-146362ea5e46"; }
];
hardware.cpu.intel.updateMicrocode = lib.mkDefault config.hardware.enableRedistributableFirmware;
}

View file

@ -0,0 +1,28 @@
{ config, pkgs, lib, ... }:
{
krz-router = {
enable = true;
enablePrimary = true;
routerId = 1;
vip = "129.199.146.230";
rip = "129.199.146.231";
trunkPort.macAddress = "92:E3:9C:CE:EF:14";
virtualNeighbors = [ 2 ];
};
# systemd.services."systemd-networkd".environment.SYSTEMD_LOG_LEVEL = "debug";
environment.systemPackages = [ pkgs.tcpdump pkgs.wireguard-tools ];
# Zone based firewall
# Flow accounting in PostgreSQL.
services.postgresql = {
enable = true;
ensureUsers = [];
};
# services.ulogd = {
# enable = true;
# settings = {
# };
# };
}

View file

@ -0,0 +1,28 @@
# Edit this configuration file to define what should be installed on
# your system. Help is available in the configuration.nix(5) man page
# and in the NixOS manual (accessible by running nixos-help).
{ config, pkgs, ... }:
{
imports =
[
./router.nix
];
# Use the systemd-boot EFI boot loader.
boot.loader.systemd-boot.enable = true;
boot.loader.efi.canTouchEfiVariables = true;
# Set your time zone.
# time.timeZone = "Europe/Amsterdam";
networking.hostName = "router04";
networking.domain = "internal.rz.ens.wtf";
services.getty.autologinUser = "root";
services.openssh.enable = true;
system.stateVersion = "24.05"; # Did you read the comment?
}

View file

@ -0,0 +1,40 @@
# 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 + "/profiles/qemu-guest.nix")
];
boot.initrd.availableKernelModules = [ "ata_piix" "uhci_hcd" "virtio_pci" "virtio_scsi" "sd_mod" "sr_mod" ];
boot.initrd.kernelModules = [ ];
boot.kernelModules = [ ];
boot.extraModulePackages = [ ];
boot.initrd.luks.devices.c-disk = {
device = "/dev/disk/by-uuid/9c57dd15-b6e4-4496-84ca-6ffe41a9dd42";
keyFile = "/dev/zero";
keyFileSize = 1;
fallbackToPassword = true;
};
fileSystems."/" =
{ device = "/dev/disk/by-uuid/a48770a7-87f0-4f95-9458-50f022d20472";
fsType = "ext4";
};
fileSystems."/boot" =
{ device = "/dev/disk/by-uuid/1FD5-AB3E";
fsType = "vfat";
};
swapDevices =
[ { device = "/dev/disk/by-uuid/050ed1a8-60be-47e8-9f96-146362ea5e46"; }
];
hardware.cpu.intel.updateMicrocode = lib.mkDefault config.hardware.enableRedistributableFirmware;
}

View file

@ -0,0 +1,28 @@
{ config, pkgs, lib, ... }:
{
krz-router = {
enable = true;
enablePrimary = false;
routerId = 2;
vip = "129.199.146.230";
rip = "129.199.146.232";
trunkPort.macAddress = "92:E3:9C:CE:EF:15";
virtualNeighbors = [ 1 ];
};
# systemd.services."systemd-networkd".environment.SYSTEMD_LOG_LEVEL = "debug";
environment.systemPackages = [ pkgs.tcpdump pkgs.wireguard-tools ];
# Zone based firewall
# Flow accounting in PostgreSQL.
services.postgresql = {
enable = true;
ensureUsers = [];
};
# services.ulogd = {
# enable = true;
# settings = {
# };
# };
}

5
meta/default.nix Normal file
View file

@ -0,0 +1,5 @@
let
nodes = import ./nodes.nix;
in
{ inherit nodes; }

78
meta/nodes.nix Normal file
View file

@ -0,0 +1,78 @@
###
# File specifying all the deployement options for the nodes administrated by the dgnum.
#
# Node metadata template is:
#
# NODE_NAME = {
# adminGroups = []; # List of groups that have root access
# admins = []; # List of individuals that have root access
# deployment = {}; # Colmena deployment options
# nixpkgs = "unstable" or "22.11"; # nixpkgs version
# }
let
mkNode = _: attrs: {
access = [ ];
deployment = { };
nixpkgs = "23.05";
} // attrs;
in
builtins.mapAttrs mkNode {
core-services-01 = {
admins = [
"gdd"
"hubrecht"
"mrf"
"raito"
"sinavir"
];
deployment.targetHost = "core01.rz.ens.wtf";
stateVersion = "22.05";
};
public-cof = {
admins = [
"gdd"
"hubrecht"
"mrf"
"raito"
"sinavir"
];
deployment.targetHost = "beta.rz.ens.wtf";
stateVersion = "21.05";
};
router03 = {
admins = [
"gdd"
"hubrecht"
"raito"
"sinavir"
];
deployment.targetHost = "129.199.146.231";
stateVersion = "24.05";
};
router04 = {
admins = [
"gdd"
"hubrecht"
"raito"
"sinavir"
];
deployment.targetHost = "129.199.146.232";
stateVersion = "24.05";
};
}

12
modules/default.nix Normal file
View file

@ -0,0 +1,12 @@
{ lib, sources, ... }:
{
imports = (lib.extra.mkImports ./. [
"krz-access-control"
"krz-ssh"
"krz-router"
]) ++ [
# TODO: Switch to global version of agenix via npins
# "${sources.agenix}/modules/age.nix"
];
}

View file

@ -0,0 +1,46 @@
{ config, lib, meta, name, ... }:
let
inherit (lib)
mkDefault
mkEnableOption
mkIf
mkOption
types;
nodeMeta = meta.nodes.${name};
inherit (nodeMeta) admins;
cfg = config.krz-access-control;
in
{
options.krz-access-control = {
enable = mkEnableOption "DGNum access control." // { default = true; };
users = mkOption {
type = with types; attrsOf (listOf str);
default = { };
description = ''
Attribute set describing which member has access to which user on the node.
Members must be declared in `meta/members.nix`.
'';
example = ''
{
user1 = [ "member1" "member2" ];
}
'';
};
};
config = mkIf cfg.enable {
# Admins have root access to the node
krz-access-control.users.root = mkDefault admins;
users.users = builtins.mapAttrs
(u: members: { openssh.authorizedKeys.keys = lib.extra.getAllKeys members; })
cfg.users;
};
}

382
modules/krz-router.nix Normal file
View file

@ -0,0 +1,382 @@
{ config, lib, ... }:
let
inherit (lib)
mkIf mkEnableOption mkOption types;
cfg = config.krz-router;
mkVLAN = name: id: {
netdevConfig = {
Kind = "vlan";
Name = name;
};
vlanConfig.Id = id;
};
mkTunnel = kind: name: { local, remote, mtu ? 1480 }: {
netdevConfig = {
Kind = kind;
Name = name;
MTUBytes = toString mtu;
};
tunnelConfig = {
Local = local;
Remote = remote;
};
};
in
{
options.krz-router = {
enable = mkEnableOption "KlubRZ router";
enablePrimary = mkEnableOption ''primary mode for this router.
This means that this router will assume the primary role by default.
Do not run on the same L2 segment the same router as primary.
'';
enableDebug = mkEnableOption "debug mode for the various subsystems";
trunkPort.macAddress = mkOption {
type = types.str;
description = "MAC address of the trunk port connected to a (virtual) switch";
};
vip = mkOption {
type = types.str;
description = "Highly-available virtual IP address of the router";
};
rip = mkOption {
type = types.str;
description = "Real IP address of the router";
};
routerId = mkOption {
type = types.int;
description = "Router ID for computing automatic IPs";
};
virtualPriority = mkOption {
type = types.int;
description = "Virtual router priority in the election";
# As recommended per RFC.
default = if cfg.enablePrimary then 100 else 50;
};
virtualNeighbors = mkOption {
type = types.listOf types.int;
description = "Virtual router neighbors in terms of router IDs";
default = [ ];
};
};
config = mkIf cfg.enable {
systemd.network.links."10-swp" = {
matchConfig.MACAddress = cfg.trunkPort.macAddress;
linkConfig.Name = "swp";
};
networking.firewall.allowedUDPPorts = [ 25351 ];
systemd.network.enable = true;
networking.dhcpcd.enable = false;
systemd.network = {
config.routeTables = {
he = 100;
mwan = 110;
};
netdevs = {
"05-admin-vpn" = {
netdevConfig = {
Kind = "wireguard";
Name = "wgadmin";
MTUBytes = "1420";
};
wireguardConfig = {
PrivateKeyFile = "/etc/secrets/wireguard/wgadmin";
ListenPort = 25351;
};
wireguardPeers = [
{
wireguardPeerConfig = {
PublicKey = "obsUPq4Y1XGbl3yPUytPKkVcSP+eECpaQX+bV+ocwXg=";
AllowedIPs = [ "fd81:fb3a:50cc::100/128" ];
};
}
{
# Julien Malka, laptop X2100
wireguardPeerConfig = {
PublicKey = "P6yIXwpUtX5WABxN5wZdxjqXyb/9kDwJqhj8VGGtAW4=";
AllowedIPs = [ "fd81:fb3a:50cc::200/128" ];
};
}
];
};
"10-tun-mwan" = mkTunnel "gre" "gre-mwan" {
remote = "80.67.167.30";
local = cfg.vip;
};
"10-tun-he" = mkTunnel "sit" "sit-he" {
remote = "216.66.84.42";
local = cfg.vip;
};
# VLANs
# 401: uplink ENS
# 3500: intranet club réseau, proxy ARP et proxy arp pvlan / 10.1.1.1/22
# 3510: mgmt club réseau (administration network) / fd81:fb3a:50cc::/64
# 3605: MWAN V6 DMZ / 2a0e:e701:1120:b00c::1/64
# 3606: MWAN V4 DMZ / 45.13.104.25/29
# 3607: Club Réseau v6 DMZ (en ASN propre)
# 3608: DN42 DMZ
# 3609: HE V6 DMZ / 2001:470:1f13:187::1/64
# 3610: Free V6 DMZ
# 3620: HE.net IPv6 /48 -> DHCP-PD /60
# 3621: MWAN DMZ /48 PD delivery / 2a0e:e701:1120::1/48
# 3622: Router VRRP link / $to_be_determined.
# "10-uplink-ens" = mkVLAN "uplink-ens" 401; dysfunctional?
"10-intranet-krz" = mkVLAN "intranet-krz" 3500;
"10-admin" = mkVLAN "admin" 3510;
"10-mwan-v6" = mkVLAN "mwan-v6" 3605;
"10-mwan-dual" = mkVLAN "mwan-dual" 3606;
"10-krz-v6" = mkVLAN "krz-v6" 3607;
"10-dn42-dmz" = mkVLAN "dn42-dmz" 3608;
"10-he-dmz" = mkVLAN "he-dmz" 3609;
"10-free-dmz" = mkVLAN "free-dmz" 3610;
"10-he-pd" = mkVLAN "he-v6-pd" 3620;
"10-mwan-pd" = mkVLAN "mwan-v6-pd" 3621;
"10-vrrp-router" = mkVLAN "vrrp-router" 3622;
};
networks = {
"10-admin-vpn" = {
matchConfig.Name = "wgadmin";
networkConfig = {
Description = "VPN d'administration système de l'infrastructure";
Address = [ "fd81:fb3a:50cc::${toString (cfg.routerId + 1)}/64" ];
# Give access to the rest of the network.
IPForward = "ipv6";
ConfigureWithoutCarrier = true;
};
linkConfig.RequiredForOnline = "routable";
};
"15-admin-vlan" = {
matchConfig.Name = "admin";
networkConfig = {
Description = "VLAN d'administration système de l'infrastructure";
Address = [ "fd81:fb3a:50cc:1::${toString (cfg.routerId + 1)}/48" ];
# Give access to the rest of the network.
IPForward = "ipv6";
IPv6ProxyNDP = true;
ConfigureWithoutCarrier = true;
};
linkConfig.RequiredForOnline = "routable";
};
"20-tun-mwan" = {
matchConfig.Name = "gre-mwan";
networkConfig = {
Description = "Tunnel de livraison GRE IPv4/IPv6 de MilkyWAN";
Address = [ "10.1.1.50/30" "2a0b:cbc0:1::216/126" ];
ConfigureWithoutCarrier = true;
};
routes = [
{
routeConfig = {
Gateway = "10.1.1.49";
Table = "mwan";
Scope = "global";
# FIXME(raito): Has no effect? Upstream bug?
Source = "45.13.104.25/29";
};
}
{
routeConfig = {
Destination = "::/0";
Gateway = "2a0b:cbc0:1::215";
Table = "mwan";
Scope = "global";
Source = "2a0e:e701:1120::/48";
};
}
];
routingPolicyRules = [
{
routingPolicyRuleConfig = {
From = "2a0e:e701:1120::/48";
Table = "mwan";
};
}
{
routingPolicyRuleConfig = {
From = "45.13.104.25/29";
Table = "mwan";
};
}
{
routingPolicyRuleConfig = {
To = "45.13.104.25/29";
Table = "mwan";
};
}
];
};
"20-tun-he" = {
matchConfig.Name = "sit-he";
networkConfig = {
Description = "HE.NET IPv6 Tunnel (owned by gdd)";
Address = [ "2001:470:1f12:187::2/64" ];
ConfigureWithoutCarrier = true;
};
routes = [
{
routeConfig = {
Destination = "::/0";
Table = "he";
Scope = "global";
Source = "2001:470:1f13::/48";
};
}
];
routingPolicyRules = [
{
routingPolicyRuleConfig = {
From = "2001:470:1f13::/48";
Table = "he";
};
}
];
};
"10-swp" = {
matchConfig.Name = "swp";
networkConfig = {
Description = "VLAN-aware switch port";
Address = [ "${cfg.rip}/24" ];
Gateway = "129.199.146.254";
LLDP = true;
# Only to the switch we are connected to directly, e.g. the hypervisor or the switch.
EmitLLDP = "nearest-bridge";
# For VRRP.
KeepConfiguration = true;
};
routingPolicyRules = [
{
routingPolicyRuleConfig = {
From = "45.13.104.25/29";
Type = "prohibit";
};
}
];
tunnel = [
"gre-mwan"
"sit-he"
];
vlan = [
# "intranet-krz" - we don't want to keep this.
"admin"
# FIXME: "mwan-v6" - do we want to keep this?
# We can achieve v6-only by enforcing MAC address isolation for IPv4.
"mwan-dual"
# FIXME: legacy-nat-zone.
# FIXME: "krz-v6" - not ready yet.
# FIXME: "dn42-dmz" - revive this if you want.
"he-dmz"
# FIXME: "free-dmz" - not ready yet, abandoned?
# FIXME: "he-v6-pd" - require rework
# FIXME: "mwan-v6-pd" - require rework
"vrrp-router"
];
};
# TODO: SIIT/NAT64/DNS64 component to avoid IPv4 dependency.
"20-mwan-dual" = {
matchConfig.Name = "mwan-dual";
addresses = [
{
addressConfig = {
Address = "2a0e:e701:1120:b00c::1/64";
AddPrefixRoute = false;
};
}
{
addressConfig = {
Address = "45.13.104.25/29";
AddPrefixRoute = false;
};
}
];
routes = [
{
routeConfig = {
Destination = "2a0e:e701:1120:b00c::/64";
Metric = 256;
Table = "mwan";
};
}
{
routeConfig = {
Destination = "45.13.104.25/29";
Metric = 256;
Table = "mwan";
};
}
];
networkConfig = {
Description = "MilkyWAN dual stack public interface";
DHCPServer = true;
IPv6SendRA = true;
IPForward = true;
ConfigureWithoutCarrier = true;
};
};
"20-he-dmz" = {
matchConfig.Name = "he-dmz";
addresses = [
{
addressConfig = {
Address = "2001:470:1f13:187::1/64";
# This will add it in the wrong table.
# TODO: add to systemd a `Table` option here.
AddPrefixRoute = false;
};
}
];
routes = [
{
routeConfig = {
Destination = "2001:470:1f13:187::/64";
Metric = 256;
Table = "he";
};
}
];
networkConfig = {
Description = "Hurricane Electrical's 187 /64 unfirewalled zone";
IPv6SendRA = true;
ConfigureWithoutCarrier = true;
};
};
"20-vrrp-router" = {
matchConfig.Name = "vrrp-router";
networkConfig = {
Description = "VRRP router health network";
Address = [ "10.0.0.${toString cfg.routerId}/24" "fe80::${toString cfg.routerId}/64" ];
KeepConfiguration = true;
};
};
};
};
services.keepalived = {
enable = true;
vrrpInstances.wan = {
interface = "vrrp-router";
state = if cfg.enablePrimary then "MASTER" else "BACKUP";
# We want to start in a stable state.
priority = cfg.virtualPriority;
virtualIps = [{ addr = "${cfg.vip}/24"; dev = "swp"; scope = "global"; }];
virtualRouterId = 50;
noPreempt = !cfg.enablePrimary;
unicastPeers = map (n: "10.0.0.${toString n}") cfg.virtualNeighbors;
};
vrrpInstances.admin = {
interface = "vrrp-router";
state = if cfg.enablePrimary then "MASTER" else "BACKUP";
# We want to start in a stable state.
priority = cfg.virtualPriority;
virtualIps = [
{ addr = "fd81:fb3a:50cc::1/64"; dev = "wgadmin"; }
{ addr = "fd81:fb3a:50cc:1::1/48"; dev = "admin"; }
];
virtualRouterId = 51;
noPreempt = !cfg.enablePrimary;
unicastPeers = map (n: "fe80::${toString n}") cfg.virtualNeighbors;
unicastSrcIp = "fe80::${toString cfg.routerId}";
};
};
};
}

25
modules/krz-ssh.nix Normal file
View file

@ -0,0 +1,25 @@
{ config, lib, ... }:
let
inherit (lib)
mkEnableOption
mkIf;
cfg = config.krz-ssh;
in
{
options.krz-ssh = {
enable = mkEnableOption "ssh default configuration." // { default = true; };
};
config = mkIf cfg.enable {
services.openssh = {
enable = true;
settings.PasswordAuthentication = false;
};
programs.mosh.enable = true;
};
}

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