Files
nixpkgs/nixos/modules/services/cluster/rancher/rke2.nix
azey ac4abf7f7b nixos/rke2: merge with nixos/k3s
K3s module was moved from `nixos/.../k3s` to `nixos/.../rancher`.

`rke2/default.nix` was moved to `rancher/rke2.nix`, and some options from RKE2 were migrated into the common `default.nix` for backwards compatibility.

Manifest generation was also changed, instead of multi-doc YAML files the module now generates `kind: List` manifests.
2025-10-07 22:45:36 +02:00

161 lines
5.5 KiB
Nix

{
config,
lib,
mkRancherModule,
...
}:
let
cfg = config.services.rke2;
baseModule = mkRancherModule {
name = "rke2";
serviceName = "rke2-${cfg.role}"; # upstream default, used by rke2-killall.sh
extraBinFlags =
(lib.optional (cfg.cni != null) "--cni=${cfg.cni}")
++ (lib.optional cfg.cisHardening "--profile=${
if lib.versionAtLeast cfg.package.version "1.25" then
"cis"
else if lib.versionAtLeast cfg.package.version "1.23" then
"cis-1.23"
else
"cis-1.6"
}");
# RKE2 sometimes tries opening YAML manifests on start with O_RDWR, which we can't support
# without ugly workarounds since they're linked from the read-only /nix/store.
# https://github.com/rancher/rke2/blob/fa7ed3a87055830924d05009a1071acfbbfbcc2c/pkg/bootstrap/bootstrap.go#L355
jsonManifests = true;
# see https://github.com/rancher/rke2/issues/224
# not all charts can be base64-encoded into chartContent due to
# https://github.com/k3s-io/helm-controller/issues/267
staticContentPort = 9345;
};
in
{
# interface
options.services.rke2 = lib.recursiveUpdate baseModule.options {
# option overrides
role.description = ''
Whether rke2 should run as a server or agent.
If it's a server:
- By default it also runs workloads as an agent.
- All options can be set.
If it's an agent:
- `serverAddr` is required.
- `token` or `tokenFile` is required.
- `agentToken`, `agentTokenFile`, `disable` and `cni` should not be set.
'';
disable.description = ''
Disable default components, see the [RKE2 documentation](https://docs.rke2.io/install/packaged_components#using-the---disable-flag).
'';
images = {
example = lib.literalExpression ''
[
(pkgs.dockerTools.pullImage {
imageName = "docker.io/bitnami/keycloak";
imageDigest = "sha256:714dfadc66a8e3adea6609bda350345bd3711657b7ef3cf2e8015b526bac2d6b";
hash = "sha256-IM2BLZ0EdKIZcRWOtuFY9TogZJXCpKtPZnMnPsGlq0Y=";
finalImageTag = "21.1.2-debian-11-r0";
})
config.services.rke2.package.images-core-linux-amd64-tar-zst
config.services.rke2.package.images-canal-linux-amd64-tar-zst
]
'';
description = ''
List of derivations that provide container images.
All images are linked to {file}`${baseModule.paths.imageDir}` before rke2 starts and are consequently imported
by the rke2 agent. Consider importing the rke2 core and CNI image archives of the rke2 package in
use, if you want to pre-provision this node with all rke2 container images. For a full list of available airgap images, check the
[source](https://github.com/NixOS/nixpkgs/blob/c8a1939887ee6e5f5aae29ce97321c0d83165f7d/pkgs/applications/networking/cluster/rke2/1_32/images-versions.json).
of the rke2 package in use.
'';
};
# rke2-specific options
cni = lib.mkOption {
type =
with lib.types;
nullOr (enum [
"none"
"canal"
"cilium"
"calico"
"flannel"
]);
description = ''
CNI plugins to deploy, one of `none`, `calico`, `canal`, `cilium` or `flannel`.
All CNI plugins get installed via a helm chart after the main components are up and running
and can be [customized by modifying the helm chart options](https://docs.rke2.io/helm).
[Learn more about RKE2 and CNI plugins](https://docs.rke2.io/networking/basic_network_options)
> **WARNING**: Flannel support in RKE2 is currently experimental.
'';
default = null;
};
cisHardening = lib.mkOption {
type = lib.types.bool;
description = ''
Enable CIS Hardening for RKE2.
The OS-level configuration options required to pass the CIS benchmark are enabled by default.
This option only creates the `etcd` user and group, and passes the `--profile=cis` flag to RKE2.
Learn more about [CIS Hardening for RKE2](https://docs.rke2.io/security/hardening_guide).
'';
default = false;
};
};
# implementation
config = lib.mkIf cfg.enable (
lib.recursiveUpdate baseModule.config {
warnings = (
lib.optional (
cfg.role == "agent" && cfg.cni != null
) "rke2: cni should not be set if role is 'agent'"
);
# Configure NetworkManager to ignore CNI network interfaces.
# See: https://docs.rke2.io/known_issues#networkmanager
environment.etc."NetworkManager/conf.d/rke2-canal.conf" = {
enable = config.networking.networkmanager.enable;
text = ''
[keyfile]
unmanaged-devices=interface-name:flannel*;interface-name:cali*;interface-name:tunl*;interface-name:vxlan.calico;interface-name:vxlan-v6.calico;interface-name:wireguard.cali;interface-name:wg-v6.cali
'';
};
# CIS hardening
# https://docs.rke2.io/security/hardening_guide#kernel-parameters
# https://github.com/rancher/rke2/blob/ef0fc7aa9d3bbaa95ce9b1895972488cbd92e302/bundle/share/rke2/rke2-cis-sysctl.conf
boot.kernel.sysctl = {
"vm.panic_on_oom" = 0;
"vm.overcommit_memory" = 1;
"kernel.panic" = 10;
"kernel.panic_on_oops" = 1;
};
# https://docs.rke2.io/security/hardening_guide#etcd-is-configured-properly
users = lib.mkIf cfg.cisHardening {
users.etcd = {
isSystemUser = true;
group = "etcd";
};
groups.etcd = { };
};
}
);
}