Restructure and clean up code

This commit is contained in:
Pim Kunis 2024-09-07 13:59:04 +02:00
parent 660191ab42
commit 6dd363a2a8
37 changed files with 17 additions and 1423 deletions

91
modules/backups.nix Normal file
View file

@ -0,0 +1,91 @@
{ pkgs, lib, config, ... }:
let
cfg = config.lab.backups;
borgmaticConfig = pkgs.writeTextFile {
name = "borgmatic-config.yaml";
text = lib.generators.toYAML { } {
source_directories = [ "/mnt/longhorn/persistent/longhorn-backup" ];
repositories = [
{
path = cfg.repoLocation;
label = "nfs";
}
{
path = "ssh://s6969ym3@s6969ym3.repo.borgbase.com/./repo";
label = "borgbase";
}
];
ssh_command = "${pkgs.openssh}/bin/ssh -i ${config.sops.secrets."borg/borgbasePrivateKey".path} -o StrictHostKeychecking=no";
keep_daily = 7;
keep_weekly = 4;
keep_monthly = 12;
keep_yearly = -1;
encryption_passcommand = "${pkgs.coreutils}/bin/cat ${config.sops.secrets."borg/borgPassphrase".path}";
};
};
in
{
options.lab.backups = {
enable = lib.mkOption {
default = false;
type = lib.types.bool;
description = ''
Whether to enable backups of persistent data on this machine.
'';
};
repoLocation = lib.mkOption {
default = "/mnt/longhorn/persistent/nfs.borg";
type = lib.types.str;
description = ''
Location of the Borg repository to back up to.
'';
};
};
config = lib.mkIf cfg.enable {
environment.systemPackages = with pkgs; [ borgbackup ];
# Converted from:
# https://github.com/borgmatic-collective/borgmatic/tree/84823dfb912db650936e3492f6ead7e0e0d32a0f/sample/systemd
systemd.services.borgmatic = {
description = "borgmatic backup";
wants = [ "network-online.target" ];
after = [ "network-online.target" ];
unitConfig.ConditionACPower = true;
preStart = "${pkgs.coreutils}/bin/sleep 10s";
serviceConfig = {
Type = "oneshot";
Nice = 19;
CPUSchedulingPolicy = "batch";
IOSchedulingClass = "best-effort";
IOSchedulingPriority = 7;
IOWeight = 100;
Restart = "no";
LogRateLimitIntervalSec = 0;
Environment = "BORG_PASSPHRASE_FILE=${config.sops.secrets."borg/borgPassphrase".path}";
};
script = "${pkgs.systemd}/bin/systemd-inhibit --who=\"borgmatic\" --what=\"sleep:shutdown\" --why=\"Prevent interrupting scheduled backup\" ${pkgs.borgmatic}/bin/borgmatic --verbosity -2 --syslog-verbosity 1 -c ${borgmaticConfig}";
};
systemd.timers.borgmatic = {
description = "Run borgmatic backup";
wantedBy = [ "timers.target" ];
timerConfig = {
OnCalendar = "*-*-* 3:00:00";
Persistent = true;
RandomizedDelaySec = "1h";
};
};
sops.secrets = {
"borg/borgPassphrase" = { };
"borg/borgbasePrivateKey" = { };
};
};
}

45
modules/data-sharing.nix Normal file
View file

@ -0,0 +1,45 @@
{ lib, config, ... }:
let
cfg = config.lab.data-sharing;
nfsShares = [
"/mnt/longhorn/persistent/media"
"/mnt/longhorn/persistent/media/books"
"/mnt/longhorn/persistent/media/movies"
"/mnt/longhorn/persistent/media/music"
"/mnt/longhorn/persistent/media/shows"
"/mnt/longhorn/persistent/longhorn-backup"
];
nfsExports = lib.strings.concatLines (
builtins.map
(share:
"${share} 192.168.30.0/16(rw,sync,no_subtree_check,no_root_squash) 127.0.0.1/8(rw,sync,no_subtree_check,no_root_squash) 10.0.0.0/8(rw,sync,no_subtree_check,no_root_squash)"
)
nfsShares
);
in
{
options.lab.data-sharing = {
enable = lib.mkOption {
default = false;
type = lib.types.bool;
description = ''
Configure this server to serve our data using NFS and PostgreSQL.
'';
};
};
config = lib.mkIf cfg.enable {
networking.firewall.allowedTCPPorts = [
2049 # NFS
111 # NFS
20048 # NFS
];
services.nfs.server = {
enable = true;
exports = nfsExports;
};
};
}

152
modules/default.nix Normal file
View file

@ -0,0 +1,152 @@
{ self, pkgs, config, lib, inputs, machine, ... }: {
imports = [
./storage.nix
./backups.nix
./networking
./data-sharing.nix
./monitoring
./k3s
./tailscale.nix
machine.nixosModule
inputs.disko.nixosModules.disko
inputs.sops-nix.nixosModules.sops
inputs.nix-snapshotter.nixosModules.nix-snapshotter
] ++ lib.lists.optional (machine.isRaspberryPi) inputs.nixos-hardware.nixosModules.raspberry-pi-4;
config = {
time.timeZone = "Europe/Amsterdam";
hardware.cpu.intel.updateMicrocode = lib.mkIf (! machine.isRaspberryPi) config.hardware.enableRedistributableFirmware;
nixpkgs = {
config.allowUnfree = true;
overlays = [
(final: _prev: {
unstable = import inputs.nixpkgs-unstable {
system = machine.arch;
};
})
];
};
i18n = {
defaultLocale = "en_US.UTF-8";
extraLocaleSettings = let extraLocale = "nl_NL.UTF-8"; in {
LC_ADDRESS = extraLocale;
LC_IDENTIFICATION = extraLocale;
LC_MEASUREMENT = extraLocale;
LC_MONETARY = extraLocale;
LC_NAME = extraLocale;
LC_NUMERIC = extraLocale;
LC_PAPER = extraLocale;
LC_TELEPHONE = extraLocale;
LC_TIME = extraLocale;
};
};
services = {
openssh = {
enable = true;
openFirewall = true;
settings = {
PasswordAuthentication = false;
KbdInteractiveAuthentication = false;
};
};
};
users.users.root.openssh.authorizedKeys.keys = [
"ssh-ed25519 AAAAC3NzaC1lZDI1NTE5AAAAIOodpLr+FDRyKyHjucHizNLVFHZ5AQmE9GmxMnOsSoaw pimkunis@thinkpadpim"
"ssh-ed25519 AAAAC3NzaC1lZDI1NTE5AAAAINUZp4BCxf7uLa1QWonx/Crf8tYZ5MKIZ+EuaBa82LrV user@user-laptop"
];
programs.neovim = {
enable = true;
vimAlias = true;
viAlias = true;
};
environment.systemPackages = with pkgs; [
wget
git
btop
htop
ripgrep
dig
tree
file
tcpdump
lsof
parted
radvd
minicom
socat
pciutils
dmidecode
openssl
nfs-utils
rsync
fio
libva-utils
jq
tmux
fastfetch
];
boot = lib.mkIf (! machine.isRaspberryPi) {
kernelModules = [ "kvm-intel" ];
extraModulePackages = [ ];
kernel.sysctl."fs.inotify.max_user_instances" = 256;
initrd = {
kernelModules = [ ];
availableKernelModules = [
"ahci"
"xhci_pci"
"nvme"
"usbhid"
"usb_storage"
"sd_mod"
"sdhci_pci"
];
};
loader = {
systemd-boot.enable = lib.mkDefault true;
efi.canTouchEfiVariables = true;
};
};
nix = {
package = pkgs.nixFlakes;
extraOptions = ''
experimental-features = nix-command flakes
'';
gc = {
automatic = true;
persistent = true;
dates = "weekly";
options = "--delete-older-than 7d";
};
};
system = {
stateVersion = "23.05";
activationScripts.diff = ''
if [[ -e /run/current-system ]]; then
${pkgs.nix}/bin/nix store diff-closures /run/current-system "$systemConfig"
fi
'';
};
sops = {
age.keyFile = "/root/.config/sops/age/keys.txt";
defaultSopsFile = "${self}/secrets/nixos.yaml";
};
};
}

20
modules/k3s/bootstrap.nix Normal file
View file

@ -0,0 +1,20 @@
{ kubenix, ... }: {
imports = [ kubenix.modules.k8s ];
kubernetes.resources.clusterRoleBindings.cluster-admins = {
roleRef = {
apiGroup = "rbac.authorization.k8s.io";
kind = "ClusterRole";
name = "cluster-admin";
};
subjects = [
{
kind = "User";
name = "pim";
}
{
kind = "User";
name = "niels";
}
];
};
}

225
modules/k3s/default.nix Normal file
View file

@ -0,0 +1,225 @@
{ self, inputs, pkgs, lib, config, ... }:
let
cfg = config.lab.k3s;
in
{
options.lab.k3s = {
enable = lib.mkOption {
default = false;
type = lib.types.bool;
description = ''
Whether to run k3s on this server.
'';
};
role = lib.mkOption {
default = "server";
type = lib.types.str;
description = ''
Whether to run k3s as a server or an agent.
'';
};
clusterInit = lib.mkOption {
default = false;
type = lib.types.bool;
description = ''
Whether this node should initialize the K8s cluster.
'';
};
serverAddr = lib.mkOption {
default = null;
type = with lib.types; nullOr str;
description = ''
Address of the server whose cluster this server should join.
Leaving this empty will make the server initialize the cluster.
'';
};
};
config = lib.mkIf cfg.enable {
environment.systemPackages = with pkgs; [
k3s
openiscsi # Required for Longhorn
nfs-utils # Required for Longhorn
];
# TODO!!!!!
networking = {
nftables.enable = lib.mkForce false;
firewall.enable = lib.mkForce false;
};
virtualisation.containerd = {
enable = true;
settings = {
version = 2;
proxy_plugins.nix = {
type = "snapshot";
address = "/run/nix-snapshotter/nix-snapshotter.sock";
};
plugins =
let
k3s-cni-plugins = pkgs.buildEnv {
name = "k3s-cni-plugins";
paths = with pkgs; [
cni-plugins
cni-plugin-flannel
];
};
in
{
"io.containerd.grpc.v1.cri" = {
stream_server_address = "127.0.0.1";
stream_server_port = "10010";
enable_selinux = false;
enable_unprivileged_ports = true;
enable_unprivileged_icmp = true;
disable_apparmor = true;
disable_cgroup = true;
restrict_oom_score_adj = true;
sandbox_image = "rancher/mirrored-pause:3.6";
containerd.snapshotter = "nix";
cni = {
conf_dir = "/var/lib/rancher/k3s/agent/etc/cni/net.d/";
bin_dir = "${k3s-cni-plugins}/bin";
};
};
"io.containerd.transfer.v1.local".unpack_config = [{
platform = "linux/amd64";
snapshotter = "nix";
}];
};
};
};
services = {
nix-snapshotter.enable = true;
k3s =
let
serverFlagList = [
"--image-service-endpoint=unix:///run/nix-snapshotter/nix-snapshotter.sock"
"--snapshotter=overlayfs"
"--container-runtime-endpoint=unix:///run/containerd/containerd.sock"
"--tls-san=${config.networking.fqdn}"
"--disable=servicelb"
"--cluster-cidr=10.42.0.0/16,2001:cafe:42::/56"
"--service-cidr=10.43.0.0/16,2001:cafe:43::/112"
];
serverFlags = builtins.concatStringsSep " " serverFlagList;
in
{
enable = true;
role = cfg.role;
tokenFile = config.sops.secrets."k3s/serverToken".path;
extraFlags = lib.mkIf (cfg.role == "server") (lib.mkForce serverFlags);
clusterInit = cfg.clusterInit;
serverAddr = lib.mkIf (! (cfg.serverAddr == null)) cfg.serverAddr;
};
# Required for Longhorn
openiscsi = {
enable = true;
name = "iqn.2016-04.com.open-iscsi:${config.networking.fqdn}";
};
};
# HACK: Symlink binaries to /usr/local/bin such that Longhorn can find them
# when they use nsenter.
# https://github.com/longhorn/longhorn/issues/2166#issuecomment-1740179416
systemd.tmpfiles.rules = [
"L+ /usr/local/bin - - - - /run/current-system/sw/bin/"
];
system.activationScripts = {
k3s-bootstrap = lib.mkIf (cfg.role == "server") {
text = (
let
k3sBootstrapFile = (inputs.kubenix.evalModules.x86_64-linux {
module = import ./bootstrap.nix;
}).config.kubernetes.result;
in
''
mkdir -p /var/lib/rancher/k3s/server/manifests
ln -sf ${k3sBootstrapFile} /var/lib/rancher/k3s/server/manifests/k3s-bootstrap.json
''
);
};
k3s-certs = lib.mkIf (cfg.role == "server") {
text = ''
mkdir -p /var/lib/rancher/k3s/server/tls/etcd
cp -f ${./k3s-ca/server-ca.crt} /var/lib/rancher/k3s/server/tls/server-ca.crt
cp -f ${./k3s-ca/client-ca.crt} /var/lib/rancher/k3s/server/tls/client-ca.crt
cp -f ${./k3s-ca/request-header-ca.crt} /var/lib/rancher/k3s/server/tls/request-header-ca.crt
cp -f ${./k3s-ca/etcd/peer-ca.crt} /var/lib/rancher/k3s/server/tls/etcd/peer-ca.crt
cp -f ${./k3s-ca/etcd/server-ca.crt} /var/lib/rancher/k3s/server/tls/etcd/server-ca.crt
'';
};
docker-images.text =
let
imageDefs = import "${self}/container-images.nix";
setupCommands = [
"rm -rf ${self.globals.imageDir}"
"mkdir -p ${self.globals.imageDir}"
];
getDockerImageConfig = dockerImage:
let
configJson = pkgs.runCommand "config.json"
{
nativeBuildInputs = [ pkgs.skopeo pkgs.jq ];
}
''
skopeo --tmpdir $TMPDIR --insecure-policy inspect docker-archive:${dockerImage} --config | jq '.config' > $out
'';
in
builtins.fromJSON (builtins.readFile configJson);
imageDefToLinkCommand = name: imageDef:
let
dockerImage = pkgs.dockerTools.pullImage imageDef;
nixSnapshotterImage = pkgs.nix-snapshotter.buildImage {
inherit name;
resolvedByNix = true;
fromImage = dockerImage;
config = getDockerImageConfig dockerImage;
};
imageLinkPath = "${self.globals.imageDir}/${name}.tar";
in
"ln -sf ${nixSnapshotterImage} ${imageLinkPath}";
linkCommandList = lib.attrsets.mapAttrsToList imageDefToLinkCommand imageDefs;
# TODO: Creating Docker images like this seems to *explode* in size.
# Doing this for every image we currently have is infeasible.
# I should investigate why the size increases like that.
commandList = setupCommands; # ++ linkCommandList;
in
builtins.concatStringsSep "\n" commandList;
};
sops.secrets =
let
keyPathBase = "/var/lib/rancher/k3s/server/tls";
in
{
"k3s/serverToken" = { };
"k3s/keys/clientCAKey".path = "${keyPathBase}/client-ca.key";
"k3s/keys/requestHeaderCAKey".path = "${keyPathBase}/request-header-ca.key";
"k3s/keys/serverCAKey".path = "${keyPathBase}/server-ca.key";
"k3s/keys/serviceKey".path = "${keyPathBase}/service.key";
"k3s/keys/etcd/peerCAKey".path = "${keyPathBase}/etcd/peer-ca.key";
"k3s/keys/etcd/serverCAKey".path = "${keyPathBase}/etcd/server-ca.key";
};
};
}

View file

@ -0,0 +1,81 @@
-----BEGIN CERTIFICATE-----
MIIDZjCCAU6gAwIBAgIIK1UyUU0zJ3cwDQYJKoZIhvcNAQELBQAwKTEnMCUGA1UE
AwweazNzLWludGVybWVkaWF0ZS1jYUAxNzE1MjU3ODEzMB4XDTI0MDUwOTEyMzAy
MFoXDTQ0MDEyNTEyMzAyMFowIzEhMB8GA1UEAwwYazNzLWNsaWVudC1jYUAxNzE1
MjU3ODEzMFkwEwYHKoZIzj0CAQYIKoZIzj0DAQcDQgAEBB8Y6sNAW10pxocoKo71
BTJXo7gwFSxotKxht5rinAmpvVEZnRlIDcjtdRZ0mqTT3I8SXrhGtWjdTP37cmM1
/KNjMGEwHQYDVR0OBBYEFA0aYftOY6QKQhCiWi2U3JEkGfqJMB8GA1UdIwQYMBaA
FPr9VQZaChg8JC0u+mpfJyqQvjdiMA8GA1UdEwEB/wQFMAMBAf8wDgYDVR0PAQH/
BAQDAgKkMA0GCSqGSIb3DQEBCwUAA4ICAQDDGSh4gVbI5zjCrHn4yFt/XdGq1MML
8wJf2UvRCddQULwhuWae21P5i6cGks3v3Yqd9h+uZJ2JKl6heChuq1/vZBQ9Y31G
LuRvaGdJnzgu2S1UQMUbkc39lgJf8j20XMK4NsIOP1N3rU5i5htEzjMsi9MtiabO
yjC9fzYXVW0j5uTi14swYG9ESKPJ7WQ1nETWWRiBrs4IlPRq3jIVOJTBAHxWjMtg
96zfvqK+jgH+rx3QolwiwV7ai0D1RbCvGoOhkoQcy506SztdlNRXfGpAbcXFJ+uP
esw9xLilIjF4o42Ga9uizBGjbk/gyN4r4lZ6ojSXGKDczcQxM6i2bGRvn96KbK/R
o0gbsb56niVt1ZQDCuYdOs3B9JlrQeZaeCUypx/UbAoYnVy1FECj0OcPDI69Es60
wHjyp3EAOTJ/gSiUhdvDjwUYT2klP0d+GvsXWbPAcqJJJS8SuVhXIZZfZW5e7Cbn
+TwO3omtxg6b7Wh7QWTUajWtmLjFSoP0MlOp56u9U5R0rfNDG5mrV4gCh0QTNyzt
+CEIC8fHDUUDAphJnirYLZszzmg14vNQUR2gm3T9/j7XYHtmzrWA7eT2pk6h1HQz
yJwoW2EsGyT6GELjztXQN+lWlBqW05cedkMsGnfym2A4Y06MaUwjNmTA3kiAoUUr
Z6PMef1lNVlmUA==
-----END CERTIFICATE-----
-----BEGIN CERTIFICATE-----
MIIFLzCCAxegAwIBAgIIK1UyUU0zJ3YwDQYJKoZIhvcNAQELBQAwITEfMB0GA1UE
AwwWazNzLXJvb3QtY2FAMTcxNTI1NzgxMzAeFw0yNDA1MDkxMjMwMjBaFw00NDAx
MjUxMjMwMjBaMCkxJzAlBgNVBAMMHmszcy1pbnRlcm1lZGlhdGUtY2FAMTcxNTI1
NzgxMzCCAiIwDQYJKoZIhvcNAQEBBQADggIPADCCAgoCggIBAMZQkDW8ULwu2iUP
ZeXf+v3alHj6MQioEebJqe8ZaCFwyzQuz6VgyJIkxc0qUtvAuan2WVek22+EqLnk
uQfmEgsfuWwHt8n69SGMqZ3SA+sH5eZt+KTGEWUNzyIFZumtNgsRkeJmF+oX5QQ4
yVWqclLrEaYkfPAr0+pf5CPugY51G8v4ezuYU4wFPjXfja4ewZj9Otpmn+X/18OS
TkSMfKG6SoY6hQPoq0rqe/C9BdilWX79C6+2Hw3fs+jzXWPaq7hkRjYEzzBPSzNW
aDl4lYQi/70wZYC85LC0J0VW0NrbrgmxieMmATnTuQAb3Ud4iQGGlqUUV7pgJO/A
vywHNR+V6xyBV2riHloy50jVkQ2ecbdqYlWn89S2Yanca/DvEYm1URWroDvhtTsm
3QPHC/Y5B04+qBaGZif7PayvRWE1WM5h130jpeTEGRRhQ7e1hM+0rvP8gyBEMiFE
HhyYGFBJ4SmZu5kbSGVQNXwS9/F9Tm47yEFEKuMQ0eFw5OASVXX4sglT/5kn8/h0
N6EyrFMgXAo4wyCJ/m3q8ngG9VLcz+vcbSBMtt8cWxs5LyhDvK06oPsy+aGq74Pb
ripTJHysnueCqG51jC/My/vL1TAXQH8kAsz2hHFnqi5LqvY2dpeHqPa4N/9oi7i5
IN7hw1+9kD5zO6mYMnaEQnEiYLVRAgMBAAGjYzBhMB0GA1UdDgQWBBT6/VUGWgoY
PCQtLvpqXycqkL43YjAfBgNVHSMEGDAWgBTLIkPmeEX9fvysxUa/HvlxbPKG2TAP
BgNVHRMBAf8EBTADAQH/MA4GA1UdDwEB/wQEAwICpDANBgkqhkiG9w0BAQsFAAOC
AgEAE4Z9is2j6K6Kk7BvDbDjW83Gew7TIIP8kTC0jZIu1loV2K8YOnmhKjer7XN5
VpcABZ2GOzKw0syN+Z+l54az/dnp1m81MlFhUoZCiNdIDjNwSOJuF/PuBszpODcy
P6LapwD52T0WH7HyUC1Grm84Bvmzwf87rpt29PBgRyt1ZPRgOCD96RvCH9v8/jWx
KkxrtjYpsje7SIagepWEsu4w+ZXMSCsJejj4bqH/mFpkUNGDSu+kgiHh2RXHSqTx
W1ZLHoz243vFyv1wrH1hFpZfEaOxa17zGEn8kdOXcRqkPMOEokKVrbjmv334SeE6
36eWyFtcbrFLWES6wKw4/KLWEzBAuGWz+ujoy9G7ahpylJGTMk74+/njqLbgrOcR
dQom/UAoynkUY+U0Rj7bW1rYpxcjimpTPGyXsJ9AGz4nYtOwQEpQ441/nPxH6hAY
i7tODC4YSbP+HH8aGIkb+oSMExVnHLeypjUcbQWPLQ940p0bLIUu378yl62N9dOC
1JYW68PslezrIN/YViAF9aW7CxxI9mJQeGZlO8+4gpUTLkHX7vLws9GK2giCbvEY
JXnrtd3C2sY8BmP5Ps6hQKd//NyT0D+mIhOmoNXaTufvWSdRdWjgClcdNtEqk88E
XPWn6g0sW7r1usZQCms+bDSmO88ZZ0SDOg+Yw76pBHRAkAo=
-----END CERTIFICATE-----
-----BEGIN CERTIFICATE-----
MIIFMzCCAxugAwIBAgIUVmq/U/xnr7TE0GqtUK9fdm6ClgAwDQYJKoZIhvcNAQEL
BQAwITEfMB0GA1UEAwwWazNzLXJvb3QtY2FAMTcxNTI1NzgxMzAeFw0yNDA1MDkx
MjMwMThaFw00NDA1MDQxMjMwMThaMCExHzAdBgNVBAMMFmszcy1yb290LWNhQDE3
MTUyNTc4MTMwggIiMA0GCSqGSIb3DQEBAQUAA4ICDwAwggIKAoICAQDAcIqRzsAP
tWnAxd3nkSyVutRe1gYGe4cqYExgwn6JLi34/ENZ8PTkUTA7crZ9okm66vn8Wcot
RCIrIQV/4FoQBKnTQgCv0TRaA59TyvLiES1W9EaFOpggrIz5TKx06DN+UhxhEOeQ
OaYpBfigVzODv3qw5+7V10a/9QErpy4PDv915zAO3fu6n/9Y3OJxpzb3vVwfQpLd
6vMl4o13gZq3Tp17DJ3pbs3RT1TMYiECCLEhuEgML9dXVFdW5HNcdiGx9mepzwcw
qyrlD4BufIJ9K6PPu3Ppp1311y0acvTLgYuRUBl9qOlrsMv0rS/7XcNEG6b9Vg+T
1s38y9FJIbtIwvLBlKPonfMatem2bkGcijlf7LHlkDmCd0GLsQtvklwzGPPa2lg9
bCB909ivzRWtSW1ba0kLaQUbCJG7yRH/nqE+fA72IlUzxN01AvXUFtq7Hi3cw2Yc
zyyVk8IRRJLYq9EjFy8+14e1QAWCP4M4RbGLSRb53aVcOWm22KFyczaDg+NnnHtB
ASS6ODfYEeAujVj7tq90IPspT6ewPaZ91qRSanr2lABkEEEaX58ErQ6G2g4yuQLQ
8pzXX9v1crCIWGsclx77a5CV599loKcZOIIxT4e1u7Dhy0EQD0yX1tru3XaVkdP/
TyidJLH2GS5MJ1vLuY7ezrocZJUrkSZOIwIDAQABo2MwYTAdBgNVHQ4EFgQUyyJD
5nhF/X78rMVGvx75cWzyhtkwHwYDVR0jBBgwFoAUyyJD5nhF/X78rMVGvx75cWzy
htkwDwYDVR0TAQH/BAUwAwEB/zAOBgNVHQ8BAf8EBAMCAqQwDQYJKoZIhvcNAQEL
BQADggIBAEM7KOB7myKORjA+smmMHXeHrfWMtS5R1mlp+JFeEZaMks6ktsicynRQ
PdD49F8Kk35XtB97sfNeM0/csIngq9ES0xhRvDbfEq68edFUUD/WpyPYIFjd1MGf
MiIbOYZSVG60xOJSFgE7f+ymK6XTwd61PRojNyIvb+2lVASKT//aWMlHU1ox+2rx
kihi0YJHH8yKhFyps4oJQyW7f+0NFfy2rknvLP55EIKiLCFPHmh636vx+bJ8AbUY
j96VEN96KqZE6YTygqHmYz5n/Vl9FibOBN1hQmHwyBy6mJI8Q0RxS4PMsxSEwKoE
H5RdpAdYPF4F23gsN0rbIFzEmgwXMnJkKPgGEIMniTHcKIEjSPTPnLWScQynqRu0
jpNXpgJ9N22sRFAzJWAaB+67YSwymClOzzAe18A7lwBrQRFZldR+GYjpywBNVI0R
G8WVmyOcQCqNeycwED+z2UvRJcGR1yxkZFDhJjcV/kLbvQQj9zNRpS8cEHWyqXZ0
RYqQMvYebLwydDkmZ9e73NaJPFTtWciFUzzxfDid9Ql6C1sMFURl4XxBthUXNH6+
09T9IIivtoyHV+EWPo/9yr3cO+4B18PXJv3vlmFf1PGOGjpzNLnOxiPU+fDEmAhm
KasQJscK9c2FT6/6XnJjdOnyvgTBlLM7UrZ+9M0icf8vQSVjDudq
-----END CERTIFICATE-----

View file

@ -0,0 +1,81 @@
-----BEGIN CERTIFICATE-----
MIIDaTCCAVGgAwIBAgIIK1UyUU0zJ3owDQYJKoZIhvcNAQELBQAwKTEnMCUGA1UE
AwweazNzLWludGVybWVkaWF0ZS1jYUAxNzE1MjU3ODEzMB4XDTI0MDUwOTEyMzAy
MFoXDTQ0MDEyNTEyMzAyMFowJjEkMCIGA1UEAwwbazNzLWV0Y2QtcGVlci1jYUAx
NzE1MjU3ODEzMFkwEwYHKoZIzj0CAQYIKoZIzj0DAQcDQgAEnl/F0abKbhtunsAE
gFB/NapdHORdwEku2AlLLFZuBTWTm7bDPV6aL/QrSlqKOscrh0WqCJMAy+OrC3Uz
MgKgQKNjMGEwHQYDVR0OBBYEFH8weUS7ylk6JshWGj/UTH3vt/L6MB8GA1UdIwQY
MBaAFPr9VQZaChg8JC0u+mpfJyqQvjdiMA8GA1UdEwEB/wQFMAMBAf8wDgYDVR0P
AQH/BAQDAgKkMA0GCSqGSIb3DQEBCwUAA4ICAQASumDCrfrfm9AAjCou3V1YEbZA
bM20GyWfFHIWzZOtCyKJQt0oOr2tXXv8RwsG0qWeVU7C0CeGUEhF8IFe/O01idWT
wv8Fiatugen6gx2ufawyEv4ATW3tPAizt+r4eZz0euYntGevPx2iM1R5xEcaNj01
kRiydyeP/m1C+uEXTCemIcP0vC67UE5OFBntjub7+K5h+iFApt/3MpdAW51GSDZn
t+EgaMa98ozHhTRWpA0QlmbDzQLX8hIALvFvzqyJcUHSoVeJEo0J25IXi7mJKQP3
kTG/1WjEXlZ2LUfWtBRlhfgxjdupLTULdOpHY3E0Zl5K7gBvDayMcrdcGNIgJ0iJ
qMRfB30Qwa1Hypgio5GOi4aOEyE3dNQke+M8UtI1oMXCyPeLTBMoc7rzZii0AnwD
5IuT4Uwx8SMHBuBPlU6TVe4UsChaw+k7kPDAWJ9yULW4x4o/zHQB/opjWMSpQqc0
nrBfFEhgFyUbwYnGutfEczwhxPlDhdICKPK2bO5dh6LEPohvmoXVks6Dp98Ha371
61/1ZLsMqO8spMrzlkONdSjZmoyFSIWiUivzXcnGVyiuSqYEbRokgoKg1mv61c3x
lcw7ChGafWws1odaHV0A6nXf7G5+K3I6wnKW5601GwrAiQVgEba8x290WWun4k8d
USo2/Dqkd9+wVScQHw==
-----END CERTIFICATE-----
-----BEGIN CERTIFICATE-----
MIIFLzCCAxegAwIBAgIIK1UyUU0zJ3YwDQYJKoZIhvcNAQELBQAwITEfMB0GA1UE
AwwWazNzLXJvb3QtY2FAMTcxNTI1NzgxMzAeFw0yNDA1MDkxMjMwMjBaFw00NDAx
MjUxMjMwMjBaMCkxJzAlBgNVBAMMHmszcy1pbnRlcm1lZGlhdGUtY2FAMTcxNTI1
NzgxMzCCAiIwDQYJKoZIhvcNAQEBBQADggIPADCCAgoCggIBAMZQkDW8ULwu2iUP
ZeXf+v3alHj6MQioEebJqe8ZaCFwyzQuz6VgyJIkxc0qUtvAuan2WVek22+EqLnk
uQfmEgsfuWwHt8n69SGMqZ3SA+sH5eZt+KTGEWUNzyIFZumtNgsRkeJmF+oX5QQ4
yVWqclLrEaYkfPAr0+pf5CPugY51G8v4ezuYU4wFPjXfja4ewZj9Otpmn+X/18OS
TkSMfKG6SoY6hQPoq0rqe/C9BdilWX79C6+2Hw3fs+jzXWPaq7hkRjYEzzBPSzNW
aDl4lYQi/70wZYC85LC0J0VW0NrbrgmxieMmATnTuQAb3Ud4iQGGlqUUV7pgJO/A
vywHNR+V6xyBV2riHloy50jVkQ2ecbdqYlWn89S2Yanca/DvEYm1URWroDvhtTsm
3QPHC/Y5B04+qBaGZif7PayvRWE1WM5h130jpeTEGRRhQ7e1hM+0rvP8gyBEMiFE
HhyYGFBJ4SmZu5kbSGVQNXwS9/F9Tm47yEFEKuMQ0eFw5OASVXX4sglT/5kn8/h0
N6EyrFMgXAo4wyCJ/m3q8ngG9VLcz+vcbSBMtt8cWxs5LyhDvK06oPsy+aGq74Pb
ripTJHysnueCqG51jC/My/vL1TAXQH8kAsz2hHFnqi5LqvY2dpeHqPa4N/9oi7i5
IN7hw1+9kD5zO6mYMnaEQnEiYLVRAgMBAAGjYzBhMB0GA1UdDgQWBBT6/VUGWgoY
PCQtLvpqXycqkL43YjAfBgNVHSMEGDAWgBTLIkPmeEX9fvysxUa/HvlxbPKG2TAP
BgNVHRMBAf8EBTADAQH/MA4GA1UdDwEB/wQEAwICpDANBgkqhkiG9w0BAQsFAAOC
AgEAE4Z9is2j6K6Kk7BvDbDjW83Gew7TIIP8kTC0jZIu1loV2K8YOnmhKjer7XN5
VpcABZ2GOzKw0syN+Z+l54az/dnp1m81MlFhUoZCiNdIDjNwSOJuF/PuBszpODcy
P6LapwD52T0WH7HyUC1Grm84Bvmzwf87rpt29PBgRyt1ZPRgOCD96RvCH9v8/jWx
KkxrtjYpsje7SIagepWEsu4w+ZXMSCsJejj4bqH/mFpkUNGDSu+kgiHh2RXHSqTx
W1ZLHoz243vFyv1wrH1hFpZfEaOxa17zGEn8kdOXcRqkPMOEokKVrbjmv334SeE6
36eWyFtcbrFLWES6wKw4/KLWEzBAuGWz+ujoy9G7ahpylJGTMk74+/njqLbgrOcR
dQom/UAoynkUY+U0Rj7bW1rYpxcjimpTPGyXsJ9AGz4nYtOwQEpQ441/nPxH6hAY
i7tODC4YSbP+HH8aGIkb+oSMExVnHLeypjUcbQWPLQ940p0bLIUu378yl62N9dOC
1JYW68PslezrIN/YViAF9aW7CxxI9mJQeGZlO8+4gpUTLkHX7vLws9GK2giCbvEY
JXnrtd3C2sY8BmP5Ps6hQKd//NyT0D+mIhOmoNXaTufvWSdRdWjgClcdNtEqk88E
XPWn6g0sW7r1usZQCms+bDSmO88ZZ0SDOg+Yw76pBHRAkAo=
-----END CERTIFICATE-----
-----BEGIN CERTIFICATE-----
MIIFMzCCAxugAwIBAgIUVmq/U/xnr7TE0GqtUK9fdm6ClgAwDQYJKoZIhvcNAQEL
BQAwITEfMB0GA1UEAwwWazNzLXJvb3QtY2FAMTcxNTI1NzgxMzAeFw0yNDA1MDkx
MjMwMThaFw00NDA1MDQxMjMwMThaMCExHzAdBgNVBAMMFmszcy1yb290LWNhQDE3
MTUyNTc4MTMwggIiMA0GCSqGSIb3DQEBAQUAA4ICDwAwggIKAoICAQDAcIqRzsAP
tWnAxd3nkSyVutRe1gYGe4cqYExgwn6JLi34/ENZ8PTkUTA7crZ9okm66vn8Wcot
RCIrIQV/4FoQBKnTQgCv0TRaA59TyvLiES1W9EaFOpggrIz5TKx06DN+UhxhEOeQ
OaYpBfigVzODv3qw5+7V10a/9QErpy4PDv915zAO3fu6n/9Y3OJxpzb3vVwfQpLd
6vMl4o13gZq3Tp17DJ3pbs3RT1TMYiECCLEhuEgML9dXVFdW5HNcdiGx9mepzwcw
qyrlD4BufIJ9K6PPu3Ppp1311y0acvTLgYuRUBl9qOlrsMv0rS/7XcNEG6b9Vg+T
1s38y9FJIbtIwvLBlKPonfMatem2bkGcijlf7LHlkDmCd0GLsQtvklwzGPPa2lg9
bCB909ivzRWtSW1ba0kLaQUbCJG7yRH/nqE+fA72IlUzxN01AvXUFtq7Hi3cw2Yc
zyyVk8IRRJLYq9EjFy8+14e1QAWCP4M4RbGLSRb53aVcOWm22KFyczaDg+NnnHtB
ASS6ODfYEeAujVj7tq90IPspT6ewPaZ91qRSanr2lABkEEEaX58ErQ6G2g4yuQLQ
8pzXX9v1crCIWGsclx77a5CV599loKcZOIIxT4e1u7Dhy0EQD0yX1tru3XaVkdP/
TyidJLH2GS5MJ1vLuY7ezrocZJUrkSZOIwIDAQABo2MwYTAdBgNVHQ4EFgQUyyJD
5nhF/X78rMVGvx75cWzyhtkwHwYDVR0jBBgwFoAUyyJD5nhF/X78rMVGvx75cWzy
htkwDwYDVR0TAQH/BAUwAwEB/zAOBgNVHQ8BAf8EBAMCAqQwDQYJKoZIhvcNAQEL
BQADggIBAEM7KOB7myKORjA+smmMHXeHrfWMtS5R1mlp+JFeEZaMks6ktsicynRQ
PdD49F8Kk35XtB97sfNeM0/csIngq9ES0xhRvDbfEq68edFUUD/WpyPYIFjd1MGf
MiIbOYZSVG60xOJSFgE7f+ymK6XTwd61PRojNyIvb+2lVASKT//aWMlHU1ox+2rx
kihi0YJHH8yKhFyps4oJQyW7f+0NFfy2rknvLP55EIKiLCFPHmh636vx+bJ8AbUY
j96VEN96KqZE6YTygqHmYz5n/Vl9FibOBN1hQmHwyBy6mJI8Q0RxS4PMsxSEwKoE
H5RdpAdYPF4F23gsN0rbIFzEmgwXMnJkKPgGEIMniTHcKIEjSPTPnLWScQynqRu0
jpNXpgJ9N22sRFAzJWAaB+67YSwymClOzzAe18A7lwBrQRFZldR+GYjpywBNVI0R
G8WVmyOcQCqNeycwED+z2UvRJcGR1yxkZFDhJjcV/kLbvQQj9zNRpS8cEHWyqXZ0
RYqQMvYebLwydDkmZ9e73NaJPFTtWciFUzzxfDid9Ql6C1sMFURl4XxBthUXNH6+
09T9IIivtoyHV+EWPo/9yr3cO+4B18PXJv3vlmFf1PGOGjpzNLnOxiPU+fDEmAhm
KasQJscK9c2FT6/6XnJjdOnyvgTBlLM7UrZ+9M0icf8vQSVjDudq
-----END CERTIFICATE-----

View file

@ -0,0 +1,81 @@
-----BEGIN CERTIFICATE-----
MIIDazCCAVOgAwIBAgIIK1UyUU0zJ3swDQYJKoZIhvcNAQELBQAwKTEnMCUGA1UE
AwweazNzLWludGVybWVkaWF0ZS1jYUAxNzE1MjU3ODEzMB4XDTI0MDUwOTEyMzAy
MFoXDTQ0MDEyNTEyMzAyMFowKDEmMCQGA1UEAwwdazNzLWV0Y2Qtc2VydmVyLWNh
QDE3MTUyNTc4MTMwWTATBgcqhkjOPQIBBggqhkjOPQMBBwNCAARjDMY4U81p+y3C
k+g4MloNceEQ0+TKbnGc0xlGmJBXXKqB6zrolIdv/J9GABZ9eIUGEs8Xw0E4VEPM
l2iFGyoOo2MwYTAdBgNVHQ4EFgQUm/3f0yXxqbgLmU4a+H2QMavLUX0wHwYDVR0j
BBgwFoAU+v1VBloKGDwkLS76al8nKpC+N2IwDwYDVR0TAQH/BAUwAwEB/zAOBgNV
HQ8BAf8EBAMCAqQwDQYJKoZIhvcNAQELBQADggIBADcxOaGyetgWEqo5BqNZd9X6
6Lj3rJZTYBmAJeISscG/Dwnv0MmRWw911zmRhikEu8jmLiGMQZUwFD1KoJ6Z/D2M
0Iqk87Ur4aS+mw2Yc60QatkZ2D1XBhrzk3gMaCtWMQBRiexA4qvaw8qlDkDR2eW9
wyks+WsD6Am1Vb/9k7fIfDR1KkScpl07fAMil73URy+KNDZ6r8hW3xZulvZd5IWp
g2px4A+i4eUbevBU1xljpXjP5lrEqoApk5YQDlHHKARszWlQC9PbvyiRRn8dH69m
mC0cdt5tSWWT49bCRtfigoejeFr8SaYzDuvR4Wb31CgbH+qVZADfgggE1N6pQCsY
w+b8xvoZGAcKEWAlX3J159Rc1mV9HRCEzaGEt5kgJuPFyJUXCjQzrKTADOawFxGb
IYeKcmUJuJG0yDkYb5lNa5fv02PAqXVM+Wz+YpFryHRphKt/gGLlhg1HyqnLVowi
UhlRyPLj9XG8PH1ZRVF6/havkg9H78voMXdFMcotIF34wSP5k/wsDjmgsvuLUIek
ryImLiMuJT5sTM/xVdLT2B9cJrFz4XIAFV209PvIldDDp1ySsh7Tz8fWHdCjvd5o
8FTAcyBW72mpS5WP+FUnq0mgpHp9HrLCC3q4AQ7juJszD1PExGNW710rjMHlnrrF
w4VKyOziEAxsiuA390Ds
-----END CERTIFICATE-----
-----BEGIN CERTIFICATE-----
MIIFLzCCAxegAwIBAgIIK1UyUU0zJ3YwDQYJKoZIhvcNAQELBQAwITEfMB0GA1UE
AwwWazNzLXJvb3QtY2FAMTcxNTI1NzgxMzAeFw0yNDA1MDkxMjMwMjBaFw00NDAx
MjUxMjMwMjBaMCkxJzAlBgNVBAMMHmszcy1pbnRlcm1lZGlhdGUtY2FAMTcxNTI1
NzgxMzCCAiIwDQYJKoZIhvcNAQEBBQADggIPADCCAgoCggIBAMZQkDW8ULwu2iUP
ZeXf+v3alHj6MQioEebJqe8ZaCFwyzQuz6VgyJIkxc0qUtvAuan2WVek22+EqLnk
uQfmEgsfuWwHt8n69SGMqZ3SA+sH5eZt+KTGEWUNzyIFZumtNgsRkeJmF+oX5QQ4
yVWqclLrEaYkfPAr0+pf5CPugY51G8v4ezuYU4wFPjXfja4ewZj9Otpmn+X/18OS
TkSMfKG6SoY6hQPoq0rqe/C9BdilWX79C6+2Hw3fs+jzXWPaq7hkRjYEzzBPSzNW
aDl4lYQi/70wZYC85LC0J0VW0NrbrgmxieMmATnTuQAb3Ud4iQGGlqUUV7pgJO/A
vywHNR+V6xyBV2riHloy50jVkQ2ecbdqYlWn89S2Yanca/DvEYm1URWroDvhtTsm
3QPHC/Y5B04+qBaGZif7PayvRWE1WM5h130jpeTEGRRhQ7e1hM+0rvP8gyBEMiFE
HhyYGFBJ4SmZu5kbSGVQNXwS9/F9Tm47yEFEKuMQ0eFw5OASVXX4sglT/5kn8/h0
N6EyrFMgXAo4wyCJ/m3q8ngG9VLcz+vcbSBMtt8cWxs5LyhDvK06oPsy+aGq74Pb
ripTJHysnueCqG51jC/My/vL1TAXQH8kAsz2hHFnqi5LqvY2dpeHqPa4N/9oi7i5
IN7hw1+9kD5zO6mYMnaEQnEiYLVRAgMBAAGjYzBhMB0GA1UdDgQWBBT6/VUGWgoY
PCQtLvpqXycqkL43YjAfBgNVHSMEGDAWgBTLIkPmeEX9fvysxUa/HvlxbPKG2TAP
BgNVHRMBAf8EBTADAQH/MA4GA1UdDwEB/wQEAwICpDANBgkqhkiG9w0BAQsFAAOC
AgEAE4Z9is2j6K6Kk7BvDbDjW83Gew7TIIP8kTC0jZIu1loV2K8YOnmhKjer7XN5
VpcABZ2GOzKw0syN+Z+l54az/dnp1m81MlFhUoZCiNdIDjNwSOJuF/PuBszpODcy
P6LapwD52T0WH7HyUC1Grm84Bvmzwf87rpt29PBgRyt1ZPRgOCD96RvCH9v8/jWx
KkxrtjYpsje7SIagepWEsu4w+ZXMSCsJejj4bqH/mFpkUNGDSu+kgiHh2RXHSqTx
W1ZLHoz243vFyv1wrH1hFpZfEaOxa17zGEn8kdOXcRqkPMOEokKVrbjmv334SeE6
36eWyFtcbrFLWES6wKw4/KLWEzBAuGWz+ujoy9G7ahpylJGTMk74+/njqLbgrOcR
dQom/UAoynkUY+U0Rj7bW1rYpxcjimpTPGyXsJ9AGz4nYtOwQEpQ441/nPxH6hAY
i7tODC4YSbP+HH8aGIkb+oSMExVnHLeypjUcbQWPLQ940p0bLIUu378yl62N9dOC
1JYW68PslezrIN/YViAF9aW7CxxI9mJQeGZlO8+4gpUTLkHX7vLws9GK2giCbvEY
JXnrtd3C2sY8BmP5Ps6hQKd//NyT0D+mIhOmoNXaTufvWSdRdWjgClcdNtEqk88E
XPWn6g0sW7r1usZQCms+bDSmO88ZZ0SDOg+Yw76pBHRAkAo=
-----END CERTIFICATE-----
-----BEGIN CERTIFICATE-----
MIIFMzCCAxugAwIBAgIUVmq/U/xnr7TE0GqtUK9fdm6ClgAwDQYJKoZIhvcNAQEL
BQAwITEfMB0GA1UEAwwWazNzLXJvb3QtY2FAMTcxNTI1NzgxMzAeFw0yNDA1MDkx
MjMwMThaFw00NDA1MDQxMjMwMThaMCExHzAdBgNVBAMMFmszcy1yb290LWNhQDE3
MTUyNTc4MTMwggIiMA0GCSqGSIb3DQEBAQUAA4ICDwAwggIKAoICAQDAcIqRzsAP
tWnAxd3nkSyVutRe1gYGe4cqYExgwn6JLi34/ENZ8PTkUTA7crZ9okm66vn8Wcot
RCIrIQV/4FoQBKnTQgCv0TRaA59TyvLiES1W9EaFOpggrIz5TKx06DN+UhxhEOeQ
OaYpBfigVzODv3qw5+7V10a/9QErpy4PDv915zAO3fu6n/9Y3OJxpzb3vVwfQpLd
6vMl4o13gZq3Tp17DJ3pbs3RT1TMYiECCLEhuEgML9dXVFdW5HNcdiGx9mepzwcw
qyrlD4BufIJ9K6PPu3Ppp1311y0acvTLgYuRUBl9qOlrsMv0rS/7XcNEG6b9Vg+T
1s38y9FJIbtIwvLBlKPonfMatem2bkGcijlf7LHlkDmCd0GLsQtvklwzGPPa2lg9
bCB909ivzRWtSW1ba0kLaQUbCJG7yRH/nqE+fA72IlUzxN01AvXUFtq7Hi3cw2Yc
zyyVk8IRRJLYq9EjFy8+14e1QAWCP4M4RbGLSRb53aVcOWm22KFyczaDg+NnnHtB
ASS6ODfYEeAujVj7tq90IPspT6ewPaZ91qRSanr2lABkEEEaX58ErQ6G2g4yuQLQ
8pzXX9v1crCIWGsclx77a5CV599loKcZOIIxT4e1u7Dhy0EQD0yX1tru3XaVkdP/
TyidJLH2GS5MJ1vLuY7ezrocZJUrkSZOIwIDAQABo2MwYTAdBgNVHQ4EFgQUyyJD
5nhF/X78rMVGvx75cWzyhtkwHwYDVR0jBBgwFoAUyyJD5nhF/X78rMVGvx75cWzy
htkwDwYDVR0TAQH/BAUwAwEB/zAOBgNVHQ8BAf8EBAMCAqQwDQYJKoZIhvcNAQEL
BQADggIBAEM7KOB7myKORjA+smmMHXeHrfWMtS5R1mlp+JFeEZaMks6ktsicynRQ
PdD49F8Kk35XtB97sfNeM0/csIngq9ES0xhRvDbfEq68edFUUD/WpyPYIFjd1MGf
MiIbOYZSVG60xOJSFgE7f+ymK6XTwd61PRojNyIvb+2lVASKT//aWMlHU1ox+2rx
kihi0YJHH8yKhFyps4oJQyW7f+0NFfy2rknvLP55EIKiLCFPHmh636vx+bJ8AbUY
j96VEN96KqZE6YTygqHmYz5n/Vl9FibOBN1hQmHwyBy6mJI8Q0RxS4PMsxSEwKoE
H5RdpAdYPF4F23gsN0rbIFzEmgwXMnJkKPgGEIMniTHcKIEjSPTPnLWScQynqRu0
jpNXpgJ9N22sRFAzJWAaB+67YSwymClOzzAe18A7lwBrQRFZldR+GYjpywBNVI0R
G8WVmyOcQCqNeycwED+z2UvRJcGR1yxkZFDhJjcV/kLbvQQj9zNRpS8cEHWyqXZ0
RYqQMvYebLwydDkmZ9e73NaJPFTtWciFUzzxfDid9Ql6C1sMFURl4XxBthUXNH6+
09T9IIivtoyHV+EWPo/9yr3cO+4B18PXJv3vlmFf1PGOGjpzNLnOxiPU+fDEmAhm
KasQJscK9c2FT6/6XnJjdOnyvgTBlLM7UrZ+9M0icf8vQSVjDudq
-----END CERTIFICATE-----

View file

@ -0,0 +1,81 @@
-----BEGIN CERTIFICATE-----
MIIDbjCCAVagAwIBAgIIK1UyUU0zJ3kwDQYJKoZIhvcNAQELBQAwKTEnMCUGA1UE
AwweazNzLWludGVybWVkaWF0ZS1jYUAxNzE1MjU3ODEzMB4XDTI0MDUwOTEyMzAy
MFoXDTQ0MDEyNTEyMzAyMFowKzEpMCcGA1UEAwwgazNzLXJlcXVlc3QtaGVhZGVy
LWNhQDE3MTUyNTc4MTMwWTATBgcqhkjOPQIBBggqhkjOPQMBBwNCAARAACYmLLW4
6vaF9q1cqBefK/FQebhkwoDcuYuG597sjxQPEz8sO/yYVaNnNcVZZPqDsiF4OCOz
i9ge02pJJVXJo2MwYTAdBgNVHQ4EFgQUrVPDbR8zlHplrCIASYmcn8IrbDEwHwYD
VR0jBBgwFoAU+v1VBloKGDwkLS76al8nKpC+N2IwDwYDVR0TAQH/BAUwAwEB/zAO
BgNVHQ8BAf8EBAMCAqQwDQYJKoZIhvcNAQELBQADggIBABlvTQJx7B0LI95sOKjM
zul35QpHoMTJOM4IrtDVUQfRutsRVaJ8z2M/2PXY0OiP8ZURaUTR63fL1lklQOMq
xDM59mcyWTEB50+yTYZNCi0qUrxI7kiOGmsCWJ1JDcRRnXonF2htPdMUr8wIOrzR
CL/HIYObEqasmTZeBlaHMc7clLB+yROveCRG91MeC8iftu/ORoqUIMVhXuR2PEQn
mupksalzL71RdOPLdL7UQzhVaABDRD0JrWsb6F198PLWiGpslwqFumyxucgd4+Xq
lb9AB/Sac/2KJH2GEGUoUMac7tJ+BNNc1T6VQUeyKDCacNRemjKxOa58ilFGvGPK
xKuuPhaN/mdZNBI1EX1m8JbCTByP5naGB7DDsP8ekMg1jvfszU+BDZSZoBgDhMmu
7Hsu/CpS8LWDzZ0KRuBsCLTYwlA1H0rp3C2ZYc/cbBexo8oyHMisMvpzM/5NMkuT
aKCQFt3HOncNG6rTltTrFaJaH9sZJxaaR6Q+pKzTtRGpx3SabZnNQkmu2MoFTKoE
vApW1wYptjOm7k5+o0a7IcWWK8FbqGOwfTAiI+mNYkiwo+qunALY0q/MiX0c7beI
qDzvjAHEt/xuWLCVqXhCy7bsgAmiukICMVflWd1Bg5OlXHa9H6sXqE1hP74Wv2bo
kBKEUETfs+HldaQgT5ontb+T
-----END CERTIFICATE-----
-----BEGIN CERTIFICATE-----
MIIFLzCCAxegAwIBAgIIK1UyUU0zJ3YwDQYJKoZIhvcNAQELBQAwITEfMB0GA1UE
AwwWazNzLXJvb3QtY2FAMTcxNTI1NzgxMzAeFw0yNDA1MDkxMjMwMjBaFw00NDAx
MjUxMjMwMjBaMCkxJzAlBgNVBAMMHmszcy1pbnRlcm1lZGlhdGUtY2FAMTcxNTI1
NzgxMzCCAiIwDQYJKoZIhvcNAQEBBQADggIPADCCAgoCggIBAMZQkDW8ULwu2iUP
ZeXf+v3alHj6MQioEebJqe8ZaCFwyzQuz6VgyJIkxc0qUtvAuan2WVek22+EqLnk
uQfmEgsfuWwHt8n69SGMqZ3SA+sH5eZt+KTGEWUNzyIFZumtNgsRkeJmF+oX5QQ4
yVWqclLrEaYkfPAr0+pf5CPugY51G8v4ezuYU4wFPjXfja4ewZj9Otpmn+X/18OS
TkSMfKG6SoY6hQPoq0rqe/C9BdilWX79C6+2Hw3fs+jzXWPaq7hkRjYEzzBPSzNW
aDl4lYQi/70wZYC85LC0J0VW0NrbrgmxieMmATnTuQAb3Ud4iQGGlqUUV7pgJO/A
vywHNR+V6xyBV2riHloy50jVkQ2ecbdqYlWn89S2Yanca/DvEYm1URWroDvhtTsm
3QPHC/Y5B04+qBaGZif7PayvRWE1WM5h130jpeTEGRRhQ7e1hM+0rvP8gyBEMiFE
HhyYGFBJ4SmZu5kbSGVQNXwS9/F9Tm47yEFEKuMQ0eFw5OASVXX4sglT/5kn8/h0
N6EyrFMgXAo4wyCJ/m3q8ngG9VLcz+vcbSBMtt8cWxs5LyhDvK06oPsy+aGq74Pb
ripTJHysnueCqG51jC/My/vL1TAXQH8kAsz2hHFnqi5LqvY2dpeHqPa4N/9oi7i5
IN7hw1+9kD5zO6mYMnaEQnEiYLVRAgMBAAGjYzBhMB0GA1UdDgQWBBT6/VUGWgoY
PCQtLvpqXycqkL43YjAfBgNVHSMEGDAWgBTLIkPmeEX9fvysxUa/HvlxbPKG2TAP
BgNVHRMBAf8EBTADAQH/MA4GA1UdDwEB/wQEAwICpDANBgkqhkiG9w0BAQsFAAOC
AgEAE4Z9is2j6K6Kk7BvDbDjW83Gew7TIIP8kTC0jZIu1loV2K8YOnmhKjer7XN5
VpcABZ2GOzKw0syN+Z+l54az/dnp1m81MlFhUoZCiNdIDjNwSOJuF/PuBszpODcy
P6LapwD52T0WH7HyUC1Grm84Bvmzwf87rpt29PBgRyt1ZPRgOCD96RvCH9v8/jWx
KkxrtjYpsje7SIagepWEsu4w+ZXMSCsJejj4bqH/mFpkUNGDSu+kgiHh2RXHSqTx
W1ZLHoz243vFyv1wrH1hFpZfEaOxa17zGEn8kdOXcRqkPMOEokKVrbjmv334SeE6
36eWyFtcbrFLWES6wKw4/KLWEzBAuGWz+ujoy9G7ahpylJGTMk74+/njqLbgrOcR
dQom/UAoynkUY+U0Rj7bW1rYpxcjimpTPGyXsJ9AGz4nYtOwQEpQ441/nPxH6hAY
i7tODC4YSbP+HH8aGIkb+oSMExVnHLeypjUcbQWPLQ940p0bLIUu378yl62N9dOC
1JYW68PslezrIN/YViAF9aW7CxxI9mJQeGZlO8+4gpUTLkHX7vLws9GK2giCbvEY
JXnrtd3C2sY8BmP5Ps6hQKd//NyT0D+mIhOmoNXaTufvWSdRdWjgClcdNtEqk88E
XPWn6g0sW7r1usZQCms+bDSmO88ZZ0SDOg+Yw76pBHRAkAo=
-----END CERTIFICATE-----
-----BEGIN CERTIFICATE-----
MIIFMzCCAxugAwIBAgIUVmq/U/xnr7TE0GqtUK9fdm6ClgAwDQYJKoZIhvcNAQEL
BQAwITEfMB0GA1UEAwwWazNzLXJvb3QtY2FAMTcxNTI1NzgxMzAeFw0yNDA1MDkx
MjMwMThaFw00NDA1MDQxMjMwMThaMCExHzAdBgNVBAMMFmszcy1yb290LWNhQDE3
MTUyNTc4MTMwggIiMA0GCSqGSIb3DQEBAQUAA4ICDwAwggIKAoICAQDAcIqRzsAP
tWnAxd3nkSyVutRe1gYGe4cqYExgwn6JLi34/ENZ8PTkUTA7crZ9okm66vn8Wcot
RCIrIQV/4FoQBKnTQgCv0TRaA59TyvLiES1W9EaFOpggrIz5TKx06DN+UhxhEOeQ
OaYpBfigVzODv3qw5+7V10a/9QErpy4PDv915zAO3fu6n/9Y3OJxpzb3vVwfQpLd
6vMl4o13gZq3Tp17DJ3pbs3RT1TMYiECCLEhuEgML9dXVFdW5HNcdiGx9mepzwcw
qyrlD4BufIJ9K6PPu3Ppp1311y0acvTLgYuRUBl9qOlrsMv0rS/7XcNEG6b9Vg+T
1s38y9FJIbtIwvLBlKPonfMatem2bkGcijlf7LHlkDmCd0GLsQtvklwzGPPa2lg9
bCB909ivzRWtSW1ba0kLaQUbCJG7yRH/nqE+fA72IlUzxN01AvXUFtq7Hi3cw2Yc
zyyVk8IRRJLYq9EjFy8+14e1QAWCP4M4RbGLSRb53aVcOWm22KFyczaDg+NnnHtB
ASS6ODfYEeAujVj7tq90IPspT6ewPaZ91qRSanr2lABkEEEaX58ErQ6G2g4yuQLQ
8pzXX9v1crCIWGsclx77a5CV599loKcZOIIxT4e1u7Dhy0EQD0yX1tru3XaVkdP/
TyidJLH2GS5MJ1vLuY7ezrocZJUrkSZOIwIDAQABo2MwYTAdBgNVHQ4EFgQUyyJD
5nhF/X78rMVGvx75cWzyhtkwHwYDVR0jBBgwFoAUyyJD5nhF/X78rMVGvx75cWzy
htkwDwYDVR0TAQH/BAUwAwEB/zAOBgNVHQ8BAf8EBAMCAqQwDQYJKoZIhvcNAQEL
BQADggIBAEM7KOB7myKORjA+smmMHXeHrfWMtS5R1mlp+JFeEZaMks6ktsicynRQ
PdD49F8Kk35XtB97sfNeM0/csIngq9ES0xhRvDbfEq68edFUUD/WpyPYIFjd1MGf
MiIbOYZSVG60xOJSFgE7f+ymK6XTwd61PRojNyIvb+2lVASKT//aWMlHU1ox+2rx
kihi0YJHH8yKhFyps4oJQyW7f+0NFfy2rknvLP55EIKiLCFPHmh636vx+bJ8AbUY
j96VEN96KqZE6YTygqHmYz5n/Vl9FibOBN1hQmHwyBy6mJI8Q0RxS4PMsxSEwKoE
H5RdpAdYPF4F23gsN0rbIFzEmgwXMnJkKPgGEIMniTHcKIEjSPTPnLWScQynqRu0
jpNXpgJ9N22sRFAzJWAaB+67YSwymClOzzAe18A7lwBrQRFZldR+GYjpywBNVI0R
G8WVmyOcQCqNeycwED+z2UvRJcGR1yxkZFDhJjcV/kLbvQQj9zNRpS8cEHWyqXZ0
RYqQMvYebLwydDkmZ9e73NaJPFTtWciFUzzxfDid9Ql6C1sMFURl4XxBthUXNH6+
09T9IIivtoyHV+EWPo/9yr3cO+4B18PXJv3vlmFf1PGOGjpzNLnOxiPU+fDEmAhm
KasQJscK9c2FT6/6XnJjdOnyvgTBlLM7UrZ+9M0icf8vQSVjDudq
-----END CERTIFICATE-----

View file

@ -0,0 +1,81 @@
-----BEGIN CERTIFICATE-----
MIIDZjCCAU6gAwIBAgIIK1UyUU0zJ3gwDQYJKoZIhvcNAQELBQAwKTEnMCUGA1UE
AwweazNzLWludGVybWVkaWF0ZS1jYUAxNzE1MjU3ODEzMB4XDTI0MDUwOTEyMzAy
MFoXDTQ0MDEyNTEyMzAyMFowIzEhMB8GA1UEAwwYazNzLXNlcnZlci1jYUAxNzE1
MjU3ODEzMFkwEwYHKoZIzj0CAQYIKoZIzj0DAQcDQgAEDhZobdYwh9+5PmK68/Pi
CETLWdTMftlpf4Kws1c1pu9diaQ2p2uAhgsdMxe8k5Su22HUG9soOsLpMfGn1fwS
dqNjMGEwHQYDVR0OBBYEFH4kXKFZ+MJI3cnwRtm2URRJk4ghMB8GA1UdIwQYMBaA
FPr9VQZaChg8JC0u+mpfJyqQvjdiMA8GA1UdEwEB/wQFMAMBAf8wDgYDVR0PAQH/
BAQDAgKkMA0GCSqGSIb3DQEBCwUAA4ICAQCWi/YtfU0RFX8vZenOolcbrtSiZDYO
yYuUUI3h7U1AW7Hmn3Gk0SYdNxUbJLB2sFt8s8TX+N80M5483prUi8O3CL/DTXxD
Ae4uag2MFGh0710JY0I/7paB9H9GU6T+BAKrjdru2mwlNC+DcUIY7UX5/PrmnG9z
HMt6tSdy6RuKTBu69tr/Mpdb3VZIjrEuJ/d1LrkbxEXXW+12AvBMociBXUW+7ooO
LlKji2LGFJUYvh7yjOXykjB5U75/9oBrRpASFkGqwcXk7c89UEL9RiPDLqAm6u1U
YoE8U9mZtgTV2E4DKUbamdeVRFalJMw1Pp6WrSLsK1wBgWxydEz8djUg8WLf01ml
mRtLH7AKgFy3u5s+fxMQMGSfSmSjzsV3HCKb8bssk8bm0Q4wLznqW1ClKTbBRdDb
lE0BkI0cJqaTkjBkcuPUd9yCEUT3mCFRPIqpiYAqzPwudZ9PynZVd4NfrItpEw1V
7hVFjN2q524LK3moPFd/adfEenZEXbkaUimUloADmnR/fuTjvqkUh0OVCta3SMTd
GjhMBidfBaDPs+b/wpI4oo3JzKL9U0AqDH9/KOsJk2W38VE8z+exgY0eU2E6HOaz
O18nrHF+eMY65Zxird7xLmu+I0h1aF0qp37ejBZnWMxawQwb0km0IcVE4xzixQ9F
NBWX9TfSjd17Tg==
-----END CERTIFICATE-----
-----BEGIN CERTIFICATE-----
MIIFLzCCAxegAwIBAgIIK1UyUU0zJ3YwDQYJKoZIhvcNAQELBQAwITEfMB0GA1UE
AwwWazNzLXJvb3QtY2FAMTcxNTI1NzgxMzAeFw0yNDA1MDkxMjMwMjBaFw00NDAx
MjUxMjMwMjBaMCkxJzAlBgNVBAMMHmszcy1pbnRlcm1lZGlhdGUtY2FAMTcxNTI1
NzgxMzCCAiIwDQYJKoZIhvcNAQEBBQADggIPADCCAgoCggIBAMZQkDW8ULwu2iUP
ZeXf+v3alHj6MQioEebJqe8ZaCFwyzQuz6VgyJIkxc0qUtvAuan2WVek22+EqLnk
uQfmEgsfuWwHt8n69SGMqZ3SA+sH5eZt+KTGEWUNzyIFZumtNgsRkeJmF+oX5QQ4
yVWqclLrEaYkfPAr0+pf5CPugY51G8v4ezuYU4wFPjXfja4ewZj9Otpmn+X/18OS
TkSMfKG6SoY6hQPoq0rqe/C9BdilWX79C6+2Hw3fs+jzXWPaq7hkRjYEzzBPSzNW
aDl4lYQi/70wZYC85LC0J0VW0NrbrgmxieMmATnTuQAb3Ud4iQGGlqUUV7pgJO/A
vywHNR+V6xyBV2riHloy50jVkQ2ecbdqYlWn89S2Yanca/DvEYm1URWroDvhtTsm
3QPHC/Y5B04+qBaGZif7PayvRWE1WM5h130jpeTEGRRhQ7e1hM+0rvP8gyBEMiFE
HhyYGFBJ4SmZu5kbSGVQNXwS9/F9Tm47yEFEKuMQ0eFw5OASVXX4sglT/5kn8/h0
N6EyrFMgXAo4wyCJ/m3q8ngG9VLcz+vcbSBMtt8cWxs5LyhDvK06oPsy+aGq74Pb
ripTJHysnueCqG51jC/My/vL1TAXQH8kAsz2hHFnqi5LqvY2dpeHqPa4N/9oi7i5
IN7hw1+9kD5zO6mYMnaEQnEiYLVRAgMBAAGjYzBhMB0GA1UdDgQWBBT6/VUGWgoY
PCQtLvpqXycqkL43YjAfBgNVHSMEGDAWgBTLIkPmeEX9fvysxUa/HvlxbPKG2TAP
BgNVHRMBAf8EBTADAQH/MA4GA1UdDwEB/wQEAwICpDANBgkqhkiG9w0BAQsFAAOC
AgEAE4Z9is2j6K6Kk7BvDbDjW83Gew7TIIP8kTC0jZIu1loV2K8YOnmhKjer7XN5
VpcABZ2GOzKw0syN+Z+l54az/dnp1m81MlFhUoZCiNdIDjNwSOJuF/PuBszpODcy
P6LapwD52T0WH7HyUC1Grm84Bvmzwf87rpt29PBgRyt1ZPRgOCD96RvCH9v8/jWx
KkxrtjYpsje7SIagepWEsu4w+ZXMSCsJejj4bqH/mFpkUNGDSu+kgiHh2RXHSqTx
W1ZLHoz243vFyv1wrH1hFpZfEaOxa17zGEn8kdOXcRqkPMOEokKVrbjmv334SeE6
36eWyFtcbrFLWES6wKw4/KLWEzBAuGWz+ujoy9G7ahpylJGTMk74+/njqLbgrOcR
dQom/UAoynkUY+U0Rj7bW1rYpxcjimpTPGyXsJ9AGz4nYtOwQEpQ441/nPxH6hAY
i7tODC4YSbP+HH8aGIkb+oSMExVnHLeypjUcbQWPLQ940p0bLIUu378yl62N9dOC
1JYW68PslezrIN/YViAF9aW7CxxI9mJQeGZlO8+4gpUTLkHX7vLws9GK2giCbvEY
JXnrtd3C2sY8BmP5Ps6hQKd//NyT0D+mIhOmoNXaTufvWSdRdWjgClcdNtEqk88E
XPWn6g0sW7r1usZQCms+bDSmO88ZZ0SDOg+Yw76pBHRAkAo=
-----END CERTIFICATE-----
-----BEGIN CERTIFICATE-----
MIIFMzCCAxugAwIBAgIUVmq/U/xnr7TE0GqtUK9fdm6ClgAwDQYJKoZIhvcNAQEL
BQAwITEfMB0GA1UEAwwWazNzLXJvb3QtY2FAMTcxNTI1NzgxMzAeFw0yNDA1MDkx
MjMwMThaFw00NDA1MDQxMjMwMThaMCExHzAdBgNVBAMMFmszcy1yb290LWNhQDE3
MTUyNTc4MTMwggIiMA0GCSqGSIb3DQEBAQUAA4ICDwAwggIKAoICAQDAcIqRzsAP
tWnAxd3nkSyVutRe1gYGe4cqYExgwn6JLi34/ENZ8PTkUTA7crZ9okm66vn8Wcot
RCIrIQV/4FoQBKnTQgCv0TRaA59TyvLiES1W9EaFOpggrIz5TKx06DN+UhxhEOeQ
OaYpBfigVzODv3qw5+7V10a/9QErpy4PDv915zAO3fu6n/9Y3OJxpzb3vVwfQpLd
6vMl4o13gZq3Tp17DJ3pbs3RT1TMYiECCLEhuEgML9dXVFdW5HNcdiGx9mepzwcw
qyrlD4BufIJ9K6PPu3Ppp1311y0acvTLgYuRUBl9qOlrsMv0rS/7XcNEG6b9Vg+T
1s38y9FJIbtIwvLBlKPonfMatem2bkGcijlf7LHlkDmCd0GLsQtvklwzGPPa2lg9
bCB909ivzRWtSW1ba0kLaQUbCJG7yRH/nqE+fA72IlUzxN01AvXUFtq7Hi3cw2Yc
zyyVk8IRRJLYq9EjFy8+14e1QAWCP4M4RbGLSRb53aVcOWm22KFyczaDg+NnnHtB
ASS6ODfYEeAujVj7tq90IPspT6ewPaZ91qRSanr2lABkEEEaX58ErQ6G2g4yuQLQ
8pzXX9v1crCIWGsclx77a5CV599loKcZOIIxT4e1u7Dhy0EQD0yX1tru3XaVkdP/
TyidJLH2GS5MJ1vLuY7ezrocZJUrkSZOIwIDAQABo2MwYTAdBgNVHQ4EFgQUyyJD
5nhF/X78rMVGvx75cWzyhtkwHwYDVR0jBBgwFoAUyyJD5nhF/X78rMVGvx75cWzy
htkwDwYDVR0TAQH/BAUwAwEB/zAOBgNVHQ8BAf8EBAMCAqQwDQYJKoZIhvcNAQEL
BQADggIBAEM7KOB7myKORjA+smmMHXeHrfWMtS5R1mlp+JFeEZaMks6ktsicynRQ
PdD49F8Kk35XtB97sfNeM0/csIngq9ES0xhRvDbfEq68edFUUD/WpyPYIFjd1MGf
MiIbOYZSVG60xOJSFgE7f+ymK6XTwd61PRojNyIvb+2lVASKT//aWMlHU1ox+2rx
kihi0YJHH8yKhFyps4oJQyW7f+0NFfy2rknvLP55EIKiLCFPHmh636vx+bJ8AbUY
j96VEN96KqZE6YTygqHmYz5n/Vl9FibOBN1hQmHwyBy6mJI8Q0RxS4PMsxSEwKoE
H5RdpAdYPF4F23gsN0rbIFzEmgwXMnJkKPgGEIMniTHcKIEjSPTPnLWScQynqRu0
jpNXpgJ9N22sRFAzJWAaB+67YSwymClOzzAe18A7lwBrQRFZldR+GYjpywBNVI0R
G8WVmyOcQCqNeycwED+z2UvRJcGR1yxkZFDhJjcV/kLbvQQj9zNRpS8cEHWyqXZ0
RYqQMvYebLwydDkmZ9e73NaJPFTtWciFUzzxfDid9Ql6C1sMFURl4XxBthUXNH6+
09T9IIivtoyHV+EWPo/9yr3cO+4B18PXJv3vlmFf1PGOGjpzNLnOxiPU+fDEmAhm
KasQJscK9c2FT6/6XnJjdOnyvgTBlLM7UrZ+9M0icf8vQSVjDudq
-----END CERTIFICATE-----

View file

@ -0,0 +1,76 @@
{ lib, config, machines, ... }:
let
cfg = config.lab.monitoring;
in
{
options = {
lab.monitoring = {
enable = lib.mkOption {
default = true;
type = lib.types.bool;
};
server.enable = lib.mkOption {
default = false;
type = lib.types.bool;
};
};
};
config = lib.mkIf cfg.enable {
networking.firewall.allowedTCPPorts = [ config.services.prometheus.exporters.node.port ]
++ lib.lists.optionals cfg.server.enable [ 80 ];
services.prometheus = {
enable = cfg.server.enable;
exporters = {
node = {
enable = true;
};
};
scrapeConfigs = lib.mkIf cfg.server.enable (
let
generated = lib.attrsets.mapAttrsToList
(name: machine: {
job_name = name;
static_configs = [{
targets = [ "${name}.dmz:${toString config.services.prometheus.exporters.node.port}" ];
}];
})
machines;
pikvm = {
job_name = "pikvm";
metrics_path = "/api/export/prometheus/metrics";
scheme = "https";
tls_config.insecure_skip_verify = true;
# We don't care about security here, it's behind a VPN.
basic_auth = {
username = "admin";
password = "admin";
};
static_configs = [{
targets = [ "pikvm.dmz" ];
}];
};
in
generated ++ [ pikvm ]
);
};
services.nginx = lib.mkIf cfg.server.enable {
enable = true;
virtualHosts."${config.networking.fqdn}" = {
locations."/" = {
proxyPass = "http://127.0.0.1:${toString config.services.prometheus.port}";
recommendedProxySettings = true;
};
};
};
};
}

View file

@ -0,0 +1,36 @@
{ lib, machine, ... }: {
config = {
networking = {
domain = "dmz";
nftables.enable = lib.mkDefault true;
useDHCP = false;
firewall.enable = lib.mkDefault true;
};
systemd.network = {
enable = true;
networks = lib.attrsets.mergeAttrsList [
(lib.optionalAttrs (! machine.isRaspberryPi) {
"30-main-nic" = {
matchConfig.Name = "en*";
networkConfig = {
DHCP = "yes";
};
};
})
(lib.optionalAttrs machine.isRaspberryPi {
"30-main-nic" = {
matchConfig.Name = "end*";
networkConfig = {
IPv6AcceptRA = true;
DHCP = "yes";
};
};
})
];
};
};
}

167
modules/storage.nix Normal file
View file

@ -0,0 +1,167 @@
{ lib, config, ... }:
let
cfg = config.lab.storage;
modules = [
{
config = lib.mkIf (cfg.profile == "pi") {
fileSystems."/" = {
device = "/dev/disk/by-label/NIXOS_SD";
fsType = "ext4";
options = [ "noatime" ];
};
};
}
{
config = lib.mkIf (cfg.profile == "kubernetes") {
disko.devices = {
disk = {
nvme = {
device = "/dev/nvme0n1";
type = "disk";
content = {
type = "gpt";
partitions = {
boot = {
type = "EF00";
size = "500M";
content = {
type = "filesystem";
format = "vfat";
mountpoint = "/boot";
};
};
pv_os = {
size = "79G";
content = {
type = "lvm_pv";
vg = "vg_os";
};
};
pv_nvme_extra = {
size = "100%";
content = {
type = "lvm_pv";
vg = "vg_data";
};
};
};
};
};
sata = {
device = "/dev/sda";
type = "disk";
content = {
type = "gpt";
partitions.pv_sata = {
size = "100%";
content = {
type = "lvm_pv";
vg = "vg_data";
};
};
};
};
};
lvm_vg = {
vg_os = {
type = "lvm_vg";
lvs = {
root = {
size = "75G";
content = {
type = "filesystem";
format = "ext4";
mountpoint = "/";
mountOptions = [ "defaults" ];
};
};
swap = {
size = "100%FREE";
content.type = "swap";
};
};
};
vg_data = {
type = "lvm_vg";
lvs.longhorn = {
size = "100%FREE";
content = {
type = "filesystem";
format = "xfs";
mountpoint = "/mnt/longhorn";
};
};
};
};
};
};
}
{
config = lib.mkIf (cfg.profile == "normal") {
disko.devices = {
disk.sata = {
device = "/dev/sda";
type = "disk";
content = {
type = "gpt";
partitions = {
boot = {
type = "EF00";
size = "500M";
content = {
type = "filesystem";
format = "vfat";
mountpoint = "/boot";
};
};
root = {
size = "100%";
content = {
type = "filesystem";
format = "ext4";
mountpoint = "/";
mountOptions = [ "defaults" ];
};
};
};
};
};
};
};
}
];
in
{
imports = modules;
options.lab.storage = {
profile = lib.mkOption {
type = lib.types.str;
};
};
}

35
modules/tailscale.nix Normal file
View file

@ -0,0 +1,35 @@
{ lib, config, ... }:
let
cfg = config.lab.tailscale;
in
{
options = {
lab.tailscale = {
enable = lib.mkEnableOption "tailscale";
advertiseExitNode = lib.mkOption {
type = lib.types.bool;
default = false;
};
};
};
config = lib.mkIf cfg.enable {
services.tailscale = {
enable = true;
authKeyFile = config.sops.secrets."tailscale/authKey".path;
useRoutingFeatures = "server";
openFirewall = true;
extraUpFlags = [
"--accept-dns=false"
"--hostname=${config.networking.hostName}"
] ++ lib.lists.optional cfg.advertiseExitNode "--advertise-exit-node"
++ lib.lists.optional cfg.advertiseExitNode "--advertise-routes=192.168.30.0/24";
};
sops.secrets."tailscale/authKey" = { };
systemd.network.wait-online.ignoredInterfaces = [ "tailscale0" ];
};
}