2025-01-28 01:22:18 +00:00
|
|
|
{ config, pkgs, lib, ... }:
|
2025-01-25 16:50:54 +00:00
|
|
|
|
2025-02-16 21:18:02 +00:00
|
|
|
let
|
|
|
|
formatPrivateKey = indentLevel: value:
|
|
|
|
let
|
|
|
|
indent = lib.strings.fixedWidthString indentLevel " " "";
|
|
|
|
indentedLines = lib.strings.concatMapStrings
|
|
|
|
(line: "${indent}${line}\n")
|
|
|
|
(lib.strings.splitString "\n" value);
|
|
|
|
in
|
|
|
|
"|\n${indentedLines}";
|
|
|
|
in
|
2025-01-25 16:50:54 +00:00
|
|
|
{
|
2025-01-28 01:22:18 +00:00
|
|
|
# Node Nix Config
|
|
|
|
options = {
|
|
|
|
serverAddr = lib.mkOption {
|
|
|
|
type = lib.types.str;
|
|
|
|
description = "The server to join";
|
|
|
|
default = "";
|
|
|
|
};
|
2025-02-16 21:18:02 +00:00
|
|
|
democraticConfig = lib.mkOption {
|
|
|
|
type = lib.types.submodule {
|
|
|
|
options = {
|
|
|
|
apiKeyFile = lib.mkOption {
|
|
|
|
type = lib.types.path;
|
|
|
|
description = "Path to file containing the TrueNAS API key";
|
|
|
|
};
|
|
|
|
sshKeyFile = lib.mkOption {
|
|
|
|
type = lib.types.path;
|
|
|
|
description = "Path to file containing the TrueNAS User SSH private key";
|
|
|
|
};
|
|
|
|
};
|
|
|
|
};
|
|
|
|
};
|
2025-01-28 01:22:18 +00:00
|
|
|
networkConfig = lib.mkOption {
|
|
|
|
type = lib.types.submodule {
|
|
|
|
options = {
|
|
|
|
interface = lib.mkOption {
|
|
|
|
type = lib.types.str;
|
|
|
|
description = "Network interface name";
|
|
|
|
example = "enp0s3";
|
|
|
|
};
|
|
|
|
address = lib.mkOption {
|
|
|
|
type = lib.types.str;
|
|
|
|
description = "Static IP address";
|
|
|
|
example = "10.0.20.200";
|
|
|
|
};
|
|
|
|
defaultGateway = lib.mkOption {
|
|
|
|
type = lib.types.str;
|
|
|
|
description = "Default gateway IP";
|
|
|
|
example = "10.0.20.254";
|
|
|
|
};
|
|
|
|
nameservers = lib.mkOption {
|
|
|
|
type = lib.types.listOf lib.types.str;
|
|
|
|
description = "List of DNS servers";
|
|
|
|
example = [ "10.0.20.254" "8.8.8.8" ];
|
|
|
|
default = [ "8.8.8.8" "8.8.4.4" ];
|
|
|
|
};
|
|
|
|
};
|
|
|
|
};
|
|
|
|
description = "Network configuration";
|
|
|
|
};
|
2025-01-25 16:50:54 +00:00
|
|
|
};
|
2025-01-28 01:22:18 +00:00
|
|
|
|
|
|
|
config = {
|
|
|
|
# ----------------------------------------
|
|
|
|
# ---------- Base Configuration ----------
|
|
|
|
# ----------------------------------------
|
2025-02-16 21:18:02 +00:00
|
|
|
# Democratic Requirements
|
|
|
|
boot.initrd = {
|
|
|
|
availableKernelModules = [ "xen_blkfront" "xen_netfront" ];
|
|
|
|
kernelModules = [ "xen_netfront" "xen_blkfront" ];
|
|
|
|
supportedFilesystems = [ "ext4" "xenfs" ];
|
|
|
|
};
|
2025-01-28 01:22:18 +00:00
|
|
|
|
|
|
|
boot.kernelModules = [
|
2025-02-16 21:18:02 +00:00
|
|
|
# Xen VM Requirements
|
|
|
|
"xen_netfront"
|
|
|
|
"xen_blkfront"
|
|
|
|
"xenfs"
|
|
|
|
|
|
|
|
# iSCSI & Multipath
|
2025-01-28 01:22:18 +00:00
|
|
|
"iscsi_tcp"
|
2025-02-16 21:18:02 +00:00
|
|
|
"dm_multipath"
|
|
|
|
"dm_round_robin"
|
2025-01-28 01:22:18 +00:00
|
|
|
];
|
|
|
|
|
|
|
|
# Network Configuration
|
|
|
|
networking = {
|
|
|
|
hostName = config.hostName;
|
|
|
|
networkmanager.enable = false;
|
|
|
|
|
|
|
|
# Interface Configuration
|
|
|
|
inherit (config.networkConfig) defaultGateway nameservers;
|
2025-02-16 21:18:02 +00:00
|
|
|
interfaces."${config.networkConfig.interface}" = {
|
|
|
|
mtu = 9000;
|
|
|
|
ipv4.addresses = [{
|
|
|
|
address = config.networkConfig.address;
|
|
|
|
prefixLength = 24;
|
|
|
|
}];
|
|
|
|
};
|
2025-01-28 01:22:18 +00:00
|
|
|
|
|
|
|
firewall = {
|
|
|
|
enable = true;
|
|
|
|
|
|
|
|
allowedTCPPorts = [
|
|
|
|
# RKE2 Ports - https://docs.rke2.io/install/requirements#networking
|
|
|
|
6443 # Kubernetes API
|
|
|
|
9345 # RKE2 supervisor API
|
|
|
|
2379 # etcd Client Port
|
|
|
|
2380 # etcd Peer Port
|
|
|
|
2381 # etcd Metrics Port
|
|
|
|
10250 # kubelet metrics
|
|
|
|
9099 # Canal CNI health checks
|
|
|
|
];
|
|
|
|
|
|
|
|
allowedUDPPorts = [
|
|
|
|
# RKE2 Ports - https://docs.rke2.io/install/requirements#networking
|
|
|
|
8472 # Canal CNI with VXLAN
|
|
|
|
# 51820 # Canal CNI with WireGuard IPv4 (if using encryption)
|
|
|
|
# 51821 # Canal CNI with WireGuard IPv6 (if using encryption)
|
|
|
|
];
|
|
|
|
};
|
|
|
|
};
|
2025-01-25 16:50:54 +00:00
|
|
|
|
2025-01-28 01:22:18 +00:00
|
|
|
# System Packages
|
|
|
|
environment.systemPackages = with pkgs; [
|
|
|
|
htop
|
|
|
|
k9s
|
|
|
|
kubectl
|
|
|
|
kubernetes-helm
|
|
|
|
openiscsi
|
|
|
|
tmux
|
|
|
|
vim
|
|
|
|
];
|
2025-01-25 16:50:54 +00:00
|
|
|
|
2025-01-28 01:22:18 +00:00
|
|
|
# ----------------------------------------
|
|
|
|
# ---------- RKE2 Configuration ----------
|
|
|
|
# ----------------------------------------
|
|
|
|
|
|
|
|
# RKE2 Join Token
|
|
|
|
environment.etc."rancher/rke2/node-token" = lib.mkIf (config.serverAddr != "") {
|
2025-02-16 21:18:02 +00:00
|
|
|
source = ../_scratch/rke2-token;
|
2025-01-28 01:22:18 +00:00
|
|
|
mode = "0600";
|
|
|
|
user = "root";
|
|
|
|
group = "root";
|
2025-01-25 16:50:54 +00:00
|
|
|
};
|
|
|
|
|
2025-01-28 01:22:18 +00:00
|
|
|
# Enable RKE2
|
|
|
|
services.rke2 = {
|
|
|
|
enable = true;
|
|
|
|
role = "server";
|
2025-01-25 16:50:54 +00:00
|
|
|
|
2025-01-28 01:22:18 +00:00
|
|
|
disable = [
|
|
|
|
# Disable - Utilizing Traefik
|
|
|
|
"rke2-ingress-nginx"
|
2025-01-25 19:17:40 +00:00
|
|
|
|
2025-02-16 21:18:02 +00:00
|
|
|
# Disable
|
|
|
|
# "rke2-snapshot-controller"
|
|
|
|
# "rke2-snapshot-controller-crd"
|
|
|
|
# "rke2-snapshot-validation-webhook"
|
2025-01-28 01:22:18 +00:00
|
|
|
];
|
|
|
|
} // lib.optionalAttrs (config.serverAddr != "") {
|
|
|
|
serverAddr = config.serverAddr;
|
|
|
|
tokenFile = "/etc/rancher/rke2/node-token";
|
|
|
|
};
|
2025-01-25 19:17:40 +00:00
|
|
|
|
2025-02-16 21:18:02 +00:00
|
|
|
# Enable Xe Guest Utilities
|
|
|
|
services.xe-guest-utilities.enable = true;
|
|
|
|
|
2025-01-28 01:22:18 +00:00
|
|
|
# Enable OpeniSCSI
|
|
|
|
services.openiscsi = {
|
|
|
|
enable = true;
|
2025-02-16 21:18:02 +00:00
|
|
|
name = "iqn.2025-02.${config.hostName}:initiator";
|
2025-01-28 01:22:18 +00:00
|
|
|
};
|
2025-01-25 16:50:54 +00:00
|
|
|
|
2025-02-16 21:18:02 +00:00
|
|
|
# Enable Multipath
|
|
|
|
services.multipath = {
|
|
|
|
enable = true;
|
|
|
|
defaults = ''
|
|
|
|
defaults {
|
|
|
|
user_friendly_names yes
|
|
|
|
find_multipaths yes
|
|
|
|
}
|
|
|
|
'';
|
|
|
|
pathGroups = [ ];
|
|
|
|
};
|
|
|
|
|
|
|
|
time.timeZone = "UTC";
|
|
|
|
|
|
|
|
# Add Symlinks Expected by Democratic
|
|
|
|
system.activationScripts.add-symlinks = ''
|
|
|
|
mkdir -p /usr/bin
|
|
|
|
ln -sf ${pkgs.openiscsi}/bin/iscsiadm /usr/bin/iscsiadm
|
|
|
|
ln -sf ${pkgs.openiscsi}/bin/iscsid /usr/bin/iscsid
|
|
|
|
'';
|
|
|
|
|
2025-01-28 01:22:18 +00:00
|
|
|
# Bootstrap Kubernetes Manifests
|
|
|
|
system.activationScripts.k8s-manifests = {
|
|
|
|
deps = [ ];
|
|
|
|
text = ''
|
|
|
|
mkdir -p /var/lib/rancher/rke2/server/manifests
|
2025-01-25 16:50:54 +00:00
|
|
|
|
2025-01-28 01:22:18 +00:00
|
|
|
# Base Configs
|
2025-02-16 21:18:02 +00:00
|
|
|
cp ${pkgs.substituteAll {
|
|
|
|
src = ../k8s/democratic.yaml;
|
|
|
|
apiKey = lib.strings.removeSuffix "\n" (builtins.readFile config.democraticConfig.apiKeyFile);
|
|
|
|
privateKey = formatPrivateKey 12 (lib.strings.removeSuffix "\n" (builtins.readFile config.democraticConfig.sshKeyFile));
|
|
|
|
}} /var/lib/rancher/rke2/server/manifests/democratic-base.yaml
|
|
|
|
|
|
|
|
cp ${../k8s/kasten.yaml} /var/lib/rancher/rke2/server/manifests/kasten-base.yaml
|
2025-01-28 01:22:18 +00:00
|
|
|
'';
|
2025-01-25 16:50:54 +00:00
|
|
|
};
|
|
|
|
};
|
|
|
|
}
|