typioca: 2.7.0 -> 2.8.0
[NixPkgs.git] / nixos / modules / programs / rust-motd.nix
blob4c9b1018596b7a2bf0e14736a115935270815e2a
1 { config, lib, pkgs, ... }:
3 with lib;
5 let
6   cfg = config.programs.rust-motd;
7   format = pkgs.formats.toml { };
9   # Order the sections in the TOML according to the order of sections
10   # in `cfg.order`.
11   motdConf = pkgs.runCommand "motd.conf"
12     {
13       __structuredAttrs = true;
14       inherit (cfg) order settings;
15       nativeBuildInputs = [ pkgs.remarshal pkgs.jq ];
16     }
17     ''
18       cat "$NIX_ATTRS_JSON_FILE" \
19         | jq '.settings as $settings
20               | .order
21               | map({ key: ., value: $settings."\(.)" })
22               | from_entries' -r \
23         | json2toml /dev/stdin "$out"
24     '';
25 in {
26   options.programs.rust-motd = {
27     enable = mkEnableOption (lib.mdDoc "rust-motd");
28     enableMotdInSSHD = mkOption {
29       default = true;
30       type = types.bool;
31       description = mdDoc ''
32         Whether to let `openssh` print the
33         result when entering a new `ssh`-session.
34         By default either nothing or a static file defined via
35         [](#opt-users.motd) is printed. Because of that,
36         the latter option is incompatible with this module.
37       '';
38     };
39     refreshInterval = mkOption {
40       default = "*:0/5";
41       type = types.str;
42       description = mdDoc ''
43         Interval in which the {manpage}`motd(5)` file is refreshed.
44         For possible formats, please refer to {manpage}`systemd.time(7)`.
45       '';
46     };
47     order = mkOption {
48       type = types.listOf types.str;
49       default = attrNames cfg.settings;
50       defaultText = literalExpression "attrNames cfg.settings";
51       description = mdDoc ''
52         The order of the sections in [](#opt-programs.rust-motd.settings).
53         By default they are ordered alphabetically.
55         Context: since attribute sets in Nix are always
56         ordered alphabetically internally this means that
58         ```nix
59         {
60           uptime = { /* ... */ };
61           banner = { /* ... */ };
62         }
63         ```
65         will still have `banner` displayed before `uptime`.
67         To work around that, this option can be used to define the order of all keys,
68         i.e.
70         ```nix
71         {
72           order = [
73             "uptime"
74             "banner"
75           ];
76         }
77         ```
79         makes sure that `uptime` is placed before `banner` in the motd.
80       '';
81     };
82     settings = mkOption {
83       type = types.attrsOf format.type;
84       description = mdDoc ''
85         Settings on what to generate. Please read the
86         [upstream documentation](https://github.com/rust-motd/rust-motd/blob/main/README.md#configuration)
87         for further information.
88       '';
89     };
90   };
91   config = mkIf cfg.enable {
92     assertions = [
93       { assertion = config.users.motd == null;
94         message = ''
95           `programs.rust-motd` is incompatible with `users.motd`!
96         '';
97       }
98       { assertion = sort (a: b: a < b) cfg.order == attrNames cfg.settings;
99         message = ''
100           Please ensure that every section from `programs.rust-motd.settings` is present in
101           `programs.rust-motd.order`.
102         '';
103       }
104     ];
105     systemd.services.rust-motd = {
106       path = with pkgs; [ bash ];
107       documentation = [ "https://github.com/rust-motd/rust-motd/blob/v${pkgs.rust-motd.version}/README.md" ];
108       description = "motd generator";
109       wantedBy = [ "multi-user.target" ];
110       serviceConfig = {
111         ExecStart = "${pkgs.writeShellScript "update-motd" ''
112           ${pkgs.rust-motd}/bin/rust-motd ${motdConf} > motd
113         ''}";
114         CapabilityBoundingSet = [ "" ];
115         LockPersonality = true;
116         MemoryDenyWriteExecute = true;
117         NoNewPrivileges = true;
118         PrivateDevices = true;
119         PrivateTmp = true;
120         ProtectClock = true;
121         ProtectControlGroups = true;
122         ProtectHome = true;
123         ProtectHostname = true;
124         ProtectKernelModules = true;
125         ProtectKernelLogs = true;
126         ProtectKernelTunables = true;
127         ProtectSystem = "full";
128         StateDirectory = "rust-motd";
129         RestrictAddressFamilies = [ "AF_UNIX" ];
130         RestrictNamespaces = true;
131         RestrictRealtime = true;
132         RestrictSUIDSGID = true;
133         RemoveIPC = true;
134         WorkingDirectory = "/var/lib/rust-motd";
135       };
136     };
137     systemd.timers.rust-motd = {
138       wantedBy = [ "timers.target" ];
139       timerConfig.OnCalendar = cfg.refreshInterval;
140     };
141     security.pam.services.sshd.text = mkIf cfg.enableMotdInSSHD (mkDefault (mkAfter ''
142       session optional ${pkgs.pam}/lib/security/pam_motd.so motd=/var/lib/rust-motd/motd
143     ''));
144     services.openssh.extraConfig = mkIf (cfg.settings ? last_login && cfg.settings.last_login != {}) ''
145       PrintLastLog no
146     '';
147   };
148   meta.maintainers = with maintainers; [ ma27 ];