diff --git a/nixos/modules/programs/rust-motd.nix b/nixos/modules/programs/rust-motd.nix index d5f1820ba752..4c9b1018596b 100644 --- a/nixos/modules/programs/rust-motd.nix +++ b/nixos/modules/programs/rust-motd.nix @@ -5,6 +5,23 @@ with lib; let cfg = config.programs.rust-motd; format = pkgs.formats.toml { }; + + # Order the sections in the TOML according to the order of sections + # in `cfg.order`. + motdConf = pkgs.runCommand "motd.conf" + { + __structuredAttrs = true; + inherit (cfg) order settings; + nativeBuildInputs = [ pkgs.remarshal pkgs.jq ]; + } + '' + cat "$NIX_ATTRS_JSON_FILE" \ + | jq '.settings as $settings + | .order + | map({ key: ., value: $settings."\(.)" }) + | from_entries' -r \ + | json2toml /dev/stdin "$out" + ''; in { options.programs.rust-motd = { enable = mkEnableOption (lib.mdDoc "rust-motd"); @@ -27,10 +44,43 @@ in { For possible formats, please refer to {manpage}`systemd.time(7)`. ''; }; + order = mkOption { + type = types.listOf types.str; + default = attrNames cfg.settings; + defaultText = literalExpression "attrNames cfg.settings"; + description = mdDoc '' + The order of the sections in [](#opt-programs.rust-motd.settings). + By default they are ordered alphabetically. + + Context: since attribute sets in Nix are always + ordered alphabetically internally this means that + + ```nix + { + uptime = { /* ... */ }; + banner = { /* ... */ }; + } + ``` + + will still have `banner` displayed before `uptime`. + + To work around that, this option can be used to define the order of all keys, + i.e. + + ```nix + { + order = [ + "uptime" + "banner" + ]; + } + ``` + + makes sure that `uptime` is placed before `banner` in the motd. + ''; + }; settings = mkOption { - type = types.submodule { - freeformType = format.type; - }; + type = types.attrsOf format.type; description = mdDoc '' Settings on what to generate. Please read the [upstream documentation](https://github.com/rust-motd/rust-motd/blob/main/README.md#configuration) @@ -45,14 +95,21 @@ in { `programs.rust-motd` is incompatible with `users.motd`! ''; } + { assertion = sort (a: b: a < b) cfg.order == attrNames cfg.settings; + message = '' + Please ensure that every section from `programs.rust-motd.settings` is present in + `programs.rust-motd.order`. + ''; + } ]; systemd.services.rust-motd = { path = with pkgs; [ bash ]; documentation = [ "https://github.com/rust-motd/rust-motd/blob/v${pkgs.rust-motd.version}/README.md" ]; description = "motd generator"; + wantedBy = [ "multi-user.target" ]; serviceConfig = { ExecStart = "${pkgs.writeShellScript "update-motd" '' - ${pkgs.rust-motd}/bin/rust-motd ${format.generate "motd.conf" cfg.settings} > motd + ${pkgs.rust-motd}/bin/rust-motd ${motdConf} > motd ''}"; CapabilityBoundingSet = [ "" ]; LockPersonality = true;