-
Notifications
You must be signed in to change notification settings - Fork 51
feat: add boot.kernel.sysctl and boot.kernelModules #384
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
base: main
Are you sure you want to change the base?
Changes from all commits
bea6b62
81061be
52cdbb1
cdf90b9
083267b
b959c5d
b75f5f1
4013580
7f089f1
7fc6c21
8789957
c03d5c0
File filter
Filter by extension
Conversations
Jump to
Diff view
Diff view
There are no files selected for viewing
| Original file line number | Diff line number | Diff line change |
|---|---|---|
|
|
@@ -2,8 +2,23 @@ | |
| nixosModulesPath, | ||
| lib, | ||
| pkgs, | ||
| config, | ||
| ... | ||
| }: | ||
| let | ||
| modulesTypeDesc = '' | ||
| This can either be a list of modules, or an attrset. In an | ||
| attrset, names that are set to `true` represent modules that will | ||
| be included. Note that setting these names to `false` does not | ||
| prevent the module from being loaded. | ||
| ''; | ||
| kernelModulesConf = pkgs.writeText "system-manager.conf" '' | ||
| ${lib.concatStringsSep "\n" config.boot.kernelModules} | ||
| ''; | ||
| attrNamesToTrue = lib.types.coercedTo (lib.types.listOf lib.types.str) ( | ||
| enabledList: lib.genAttrs enabledList (_attrName: true) | ||
| ) (lib.types.attrsOf lib.types.bool); | ||
| in | ||
| { | ||
| imports = [ | ||
| ./dhparams.nix | ||
|
|
@@ -13,6 +28,7 @@ | |
| ./programs/ssh.nix | ||
| ./security-wrappers.nix | ||
| ./security/sudo.nix | ||
| ./sysctl.nix | ||
| ./userborn.nix | ||
| ./users-groups.nix | ||
| ../sops-nix.nix | ||
|
|
@@ -38,11 +54,27 @@ | |
| options = | ||
| # We need to ignore a bunch of options that are used in NixOS modules but | ||
| # that don't apply to system-manager configs. | ||
| # TODO: can we print an informational message for things like kernel modules | ||
| # to inform users that they need to be enabled in the host system? | ||
| { | ||
| boot = lib.mkOption { | ||
| type = lib.types.raw; | ||
| boot = { | ||
|
Member
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. The problems is that we now implement a subset of the boot options. It doesn't cost us a lot more to stub more of boot options here. Maybe we should just copying the options defined in https://github.com/NixOS/nixpkgs/blob/80bdc1e5ce51f56b19791b52b2901187931f5353/nixos/modules/system/boot/kernel.nix) ? I guess importing that upstream file directly would have been a problem ?
Author
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Yeah, I think importing it directly wouldn't give us much benefit anyway as a lot of those options don't really make sense in our context, and we'd still need to define extra stubs to make everything work properly. |
||
| kernelModules = lib.mkOption { | ||
| type = attrNamesToTrue; | ||
| default = { }; | ||
| description = '' | ||
| The set of kernel modules to be loaded in the second stage of | ||
| the boot process. | ||
|
|
||
| ${modulesTypeDesc} | ||
| ''; | ||
| apply = mods: lib.attrNames (lib.filterAttrs (_: v: v) mods); | ||
| }; | ||
|
|
||
| kernelPackages = lib.mkOption { | ||
| type = lib.types.raw; | ||
| default = { | ||
| kernel.version = "stub"; | ||
| }; | ||
| description = "Stub kernel packages for compatibility; not actively used in system-manager."; | ||
| }; | ||
| }; | ||
|
|
||
| # nixos/modules/services/system/userborn.nix still depends on activation scripts | ||
|
|
@@ -70,4 +102,26 @@ | |
| defaultText = lib.literalExpression "pkgs.glibcLocales"; | ||
| }; | ||
| }; | ||
|
|
||
| config = { | ||
| # Create /etc/modules-load.d/system-manager.conf, which is read by | ||
| # systemd-modules-load.service to load required kernel modules. | ||
| environment.etc = lib.mkIf (config.boot.kernelModules != [ ]) { | ||
| "modules-load.d/system-manager.conf".source = kernelModulesConf; | ||
|
yuxqiu marked this conversation as resolved.
|
||
| }; | ||
|
|
||
| systemd.services = { | ||
| systemd-modules-load = lib.mkIf (config.boot.kernelModules != [ ]) { | ||
| overrideStrategy = "asDropin"; | ||
| wantedBy = [ | ||
| "system-manager.target" | ||
| "multi-user.target" | ||
| ]; | ||
| restartTriggers = [ kernelModulesConf ]; | ||
| serviceConfig = { | ||
| SuccessExitStatus = "0 1"; | ||
| }; | ||
| }; | ||
| }; | ||
| }; | ||
| } | ||
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1,82 @@ | ||
| { | ||
| config, | ||
| lib, | ||
| ... | ||
| }: | ||
| let | ||
|
|
||
| sysctlOption = lib.mkOptionType { | ||
| name = "sysctl option value"; | ||
| check = | ||
| val: | ||
| let | ||
| checkType = x: lib.isBool x || lib.isString x || lib.isInt x || x == null; | ||
| in | ||
| checkType val || (val._type or "" == "override" && checkType val.content); | ||
| merge = loc: defs: lib.mergeOneOption loc defs; | ||
| }; | ||
|
|
||
| in | ||
| { | ||
|
|
||
| options = { | ||
|
|
||
| boot.kernel.sysctl = lib.mkOption { | ||
| type = | ||
| let | ||
| highestValueType = lib.types.ints.unsigned // { | ||
| merge = loc: defs: lib.foldl (a: b: if b.value == null then null else lib.max a b.value) 0 defs; | ||
| }; | ||
| in | ||
| lib.types.submodule { | ||
| freeformType = lib.types.attrsOf sysctlOption; | ||
| options = { | ||
| "net.core.rmem_max" = lib.mkOption { | ||
| type = lib.types.nullOr highestValueType; | ||
| default = null; | ||
| description = "The maximum receive socket buffer size in bytes. In case of conflicting values, the highest will be used."; | ||
| }; | ||
|
|
||
| "net.core.wmem_max" = lib.mkOption { | ||
| type = lib.types.nullOr highestValueType; | ||
| default = null; | ||
| description = "The maximum send socket buffer size in bytes. In case of conflicting values, the highest will be used."; | ||
| }; | ||
| }; | ||
| }; | ||
| default = { }; | ||
| example = lib.literalExpression '' | ||
| { "net.ipv4.tcp_syncookies" = false; "vm.swappiness" = 60; } | ||
| ''; | ||
| description = '' | ||
| Runtime parameters of the Linux kernel, as set by | ||
| {manpage}`sysctl(8)`. Note that sysctl | ||
| parameters names must be enclosed in quotes | ||
| (e.g. `"vm.swappiness"` instead of | ||
| `vm.swappiness`). The value of each | ||
| parameter may be a string, integer, boolean, or null | ||
| (signifying the option will not appear at all). | ||
| ''; | ||
|
|
||
| }; | ||
|
|
||
| }; | ||
|
|
||
| config = { | ||
|
|
||
| environment.etc = lib.mkIf (config.boot.kernel.sysctl != { }) { | ||
| "sysctl.d/60-system-manager.conf".text = lib.concatStrings ( | ||
| lib.mapAttrsToList ( | ||
| n: v: lib.optionalString (v != null) "${n}=${if v == false then "0" else toString v}\n" | ||
| ) config.boot.kernel.sysctl | ||
| ); | ||
| }; | ||
|
|
||
| systemd.services.systemd-sysctl = lib.mkIf (config.boot.kernel.sysctl != { }) { | ||
| overrideStrategy = "asDropin"; | ||
| wantedBy = [ "system-manager.target" ]; | ||
| restartTriggers = [ config.environment.etc."sysctl.d/60-system-manager.conf".source ]; | ||
| }; | ||
|
|
||
| }; | ||
| } |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Thank you for adding that feature ! Could you add an extra container test for that ?
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Yes, for sure. I've pushed a commit that adds an extra test.
That said, to merge this, we might also need to update the documentation. Previously, the docs stated that we define
bootwith typeraw. I'm not sure exactly how it should be rephrased now, so I'll leave that to you if that's alright.