vuls: init at 0.27.0
[NixPkgs.git] / nixos / modules / services / monitoring / cockpit.nix
blob64e26ce4e127da2ebd069ec7e0b9164267de9952
1 { pkgs, config, lib, ... }:
3 let
4   cfg = config.services.cockpit;
5   inherit (lib) types mkEnableOption mkOption mkIf literalMD mkPackageOption;
6   settingsFormat = pkgs.formats.ini {};
7 in {
8   options = {
9     services.cockpit = {
10       enable = mkEnableOption "Cockpit";
12       package = mkPackageOption pkgs "Cockpit" {
13         default = [ "cockpit" ];
14       };
16       settings = lib.mkOption {
17         type = settingsFormat.type;
19         default = {};
21         description = ''
22           Settings for cockpit that will be saved in /etc/cockpit/cockpit.conf.
24           See the [documentation](https://cockpit-project.org/guide/latest/cockpit.conf.5.html), that is also available with `man cockpit.conf.5` for details.
25         '';
26       };
28       port = mkOption {
29         description = "Port where cockpit will listen.";
30         type = types.port;
31         default = 9090;
32       };
34       openFirewall = mkOption {
35         description = "Open port for cockpit.";
36         type = types.bool;
37         default = false;
38       };
39     };
40   };
41   config = mkIf cfg.enable {
43     # expose cockpit-bridge system-wide
44     environment.systemPackages = [ cfg.package ];
46     # allow cockpit to find its plugins
47     environment.pathsToLink = [ "/share/cockpit" ];
49     # generate cockpit settings
50     environment.etc."cockpit/cockpit.conf".source = settingsFormat.generate "cockpit.conf" cfg.settings;
52     security.pam.services.cockpit = {};
54     networking.firewall.allowedTCPPorts = mkIf cfg.openFirewall [ cfg.port ];
56     # units are in reverse sort order if you ls $out/lib/systemd/system
57     # all these units are basically verbatim translated from upstream
59     # Translation from $out/lib/systemd/system/systemd-cockpithttps.slice
60     systemd.slices.system-cockpithttps = {
61       description = "Resource limits for all cockpit-ws-https@.service instances";
62       sliceConfig = {
63         TasksMax = 200;
64         MemoryHigh = "75%";
65         MemoryMax = "90%";
66       };
67     };
69     # Translation from $out/lib/systemd/system/cockpit-wsinstance-https@.socket
70     systemd.sockets."cockpit-wsinstance-https@" = {
71       unitConfig = {
72         Description = "Socket for Cockpit Web Service https instance %I";
73         BindsTo = [ "cockpit.service" "cockpit-wsinstance-https@%i.service" ];
74         # clean up the socket after the service exits, to prevent fd leak
75         # this also effectively prevents a DoS by starting arbitrarily many sockets, as
76         # the services are resource-limited by system-cockpithttps.slice
77         Documentation = "man:cockpit-ws(8)";
78       };
79       socketConfig = {
80         ListenStream = "/run/cockpit/wsinstance/https@%i.sock";
81         SocketUser = "root";
82         SocketMode = "0600";
83       };
84     };
86     # Translation from $out/lib/systemd/system/cockpit-wsinstance-https@.service
87     systemd.services."cockpit-wsinstance-https@" = {
88       description = "Cockpit Web Service https instance %I";
89       bindsTo = [ "cockpit.service"];
90       path = [ cfg.package ];
91       documentation = [ "man:cockpit-ws(8)" ];
92       serviceConfig = {
93         Slice = "system-cockpithttps.slice";
94         ExecStart = "${cfg.package}/libexec/cockpit-ws --for-tls-proxy --port=0";
95         User = "root";
96         Group = "";
97       };
98     };
100     # Translation from $out/lib/systemd/system/cockpit-wsinstance-http.socket
101     systemd.sockets.cockpit-wsinstance-http = {
102       unitConfig = {
103         Description = "Socket for Cockpit Web Service http instance";
104         BindsTo = "cockpit.service";
105         Documentation = "man:cockpit-ws(8)";
106       };
107       socketConfig = {
108         ListenStream = "/run/cockpit/wsinstance/http.sock";
109         SocketUser = "root";
110         SocketMode = "0600";
111       };
112     };
114     # Translation from $out/lib/systemd/system/cockpit-wsinstance-https-factory.socket
115     systemd.sockets.cockpit-wsinstance-https-factory = {
116       unitConfig = {
117         Description = "Socket for Cockpit Web Service https instance factory";
118         BindsTo = "cockpit.service";
119         Documentation = "man:cockpit-ws(8)";
120       };
121       socketConfig = {
122         ListenStream = "/run/cockpit/wsinstance/https-factory.sock";
123         Accept = true;
124         SocketUser = "root";
125         SocketMode = "0600";
126       };
127     };
129     # Translation from $out/lib/systemd/system/cockpit-wsinstance-https-factory@.service
130     systemd.services."cockpit-wsinstance-https-factory@" = {
131       description = "Cockpit Web Service https instance factory";
132       documentation = [ "man:cockpit-ws(8)" ];
133       path = [ cfg.package ];
134       serviceConfig = {
135         ExecStart = "${cfg.package}/libexec/cockpit-wsinstance-factory";
136         User = "root";
137       };
138     };
140     # Translation from $out/lib/systemd/system/cockpit-wsinstance-http.service
141     systemd.services."cockpit-wsinstance-http" = {
142       description = "Cockpit Web Service http instance";
143       bindsTo = [ "cockpit.service" ];
144       path = [ cfg.package ];
145       documentation = [ "man:cockpit-ws(8)" ];
146       serviceConfig = {
147         ExecStart = "${cfg.package}/libexec/cockpit-ws --no-tls --port=0";
148         User = "root";
149         Group = "";
150       };
151     };
153     # Translation from $out/lib/systemd/system/cockpit.socket
154     systemd.sockets."cockpit" = {
155       unitConfig = {
156         Description = "Cockpit Web Service Socket";
157         Documentation = "man:cockpit-ws(8)";
158         Wants = "cockpit-motd.service";
159       };
160       socketConfig = {
161         ListenStream = cfg.port;
162         ExecStartPost = [
163           "-${cfg.package}/share/cockpit/motd/update-motd \"\" localhost"
164           "-${pkgs.coreutils}/bin/ln -snf active.motd /run/cockpit/motd"
165         ];
166         ExecStopPost = "-${pkgs.coreutils}/bin/ln -snf inactive.motd /run/cockpit/motd";
167       };
168       wantedBy = [ "sockets.target" ];
169     };
171     # Translation from $out/lib/systemd/system/cockpit.service
172     systemd.services."cockpit" = {
173       description = "Cockpit Web Service";
174       documentation = [ "man:cockpit-ws(8)" ];
175       restartIfChanged = true;
176       path = with pkgs; [ coreutils cfg.package ];
177       requires = [ "cockpit.socket" "cockpit-wsinstance-http.socket" "cockpit-wsinstance-https-factory.socket" ];
178       after = [ "cockpit-wsinstance-http.socket" "cockpit-wsinstance-https-factory.socket" ];
179       environment = {
180         G_MESSAGES_DEBUG = "cockpit-ws,cockpit-bridge";
181       };
182       serviceConfig = {
183         RuntimeDirectory="cockpit/tls";
184         ExecStartPre = [
185           # cockpit-tls runs in a more constrained environment, these + means that these commands
186           # will run with full privilege instead of inside that constrained environment
187           # See https://www.freedesktop.org/software/systemd/man/systemd.service.html#ExecStart= for details
188           "+${cfg.package}/libexec/cockpit-certificate-ensure --for-cockpit-tls"
189         ];
190         ExecStart = "${cfg.package}/libexec/cockpit-tls";
191         User = "root";
192         Group = "";
193         NoNewPrivileges = true;
194         ProtectSystem = "strict";
195         ProtectHome = true;
196         PrivateTmp = true;
197         PrivateDevices = true;
198         ProtectKernelTunables = true;
199         RestrictAddressFamilies = [ "AF_UNIX" "AF_INET" "AF_INET6" ];
200         MemoryDenyWriteExecute = true;
201       };
202     };
204     # Translation from $out/lib/systemd/system/cockpit-motd.service
205     # This part basically implements a motd state machine:
206     # - If cockpit.socket is enabled then /run/cockpit/motd points to /run/cockpit/active.motd
207     # - If cockpit.socket is disabled then /run/cockpit/motd points to /run/cockpit/inactive.motd
208     # - As cockpit.socket is disabled by default, /run/cockpit/motd points to /run/cockpit/inactive.motd
209     # /run/cockpit/active.motd is generated dynamically by cockpit-motd.service
210     systemd.services."cockpit-motd" = {
211       path = with pkgs; [ nettools ];
212       serviceConfig = {
213         Type = "oneshot";
214         ExecStart = "${cfg.package}/share/cockpit/motd/update-motd";
215       };
216       description = "Cockpit motd updater service";
217       documentation = [ "man:cockpit-ws(8)" ];
218       wants = [ "network.target" ];
219       after = [ "network.target" "cockpit.socket" ];
220     };
222     systemd.tmpfiles.rules = [ # From $out/lib/tmpfiles.d/cockpit-tmpfiles.conf
223       "C /run/cockpit/inactive.motd 0640 root root - ${cfg.package}/share/cockpit/motd/inactive.motd"
224       "f /run/cockpit/active.motd   0640 root root -"
225       "L+ /run/cockpit/motd - - - - inactive.motd"
226       "d /etc/cockpit/ws-certs.d 0600 root root 0"
227     ];
228   };
230   meta.maintainers = pkgs.cockpit.meta.maintainers;