1# Nagios system/network monitoring daemon.
2{
3 config,
4 lib,
5 pkgs,
6 ...
7}:
8let
9 cfg = config.services.nagios;
10
11 nagiosState = "/var/lib/nagios";
12 nagiosLogDir = "/var/log/nagios";
13 urlPath = "/nagios";
14
15 nagiosObjectDefs = cfg.objectDefs;
16
17 nagiosObjectDefsDir = pkgs.runCommand "nagios-objects" {
18 inherit nagiosObjectDefs;
19 preferLocalBuild = true;
20 } "mkdir -p $out; ln -s $nagiosObjectDefs $out/";
21
22 nagiosCfgFile =
23 let
24 default = {
25 log_file = "${nagiosLogDir}/current";
26 log_archive_path = "${nagiosLogDir}/archive";
27 status_file = "${nagiosState}/status.dat";
28 object_cache_file = "${nagiosState}/objects.cache";
29 temp_file = "${nagiosState}/nagios.tmp";
30 lock_file = "/run/nagios.lock";
31 state_retention_file = "${nagiosState}/retention.dat";
32 query_socket = "${nagiosState}/nagios.qh";
33 check_result_path = "${nagiosState}";
34 command_file = "${nagiosState}/nagios.cmd";
35 cfg_dir = "${nagiosObjectDefsDir}";
36 nagios_user = "nagios";
37 nagios_group = "nagios";
38 illegal_macro_output_chars = "`~$&|'\"<>";
39 retain_state_information = "1";
40 };
41 lines = lib.mapAttrsToList (key: value: "${key}=${value}") (default // cfg.extraConfig);
42 content = lib.concatStringsSep "\n" lines;
43 file = pkgs.writeText "nagios.cfg" content;
44 validated = pkgs.runCommand "nagios-checked.cfg" { preferLocalBuild = true; } ''
45 cp ${file} nagios.cfg
46 # nagios checks the existence of /var/lib/nagios, but
47 # it does not exist in the build sandbox, so we fake it
48 mkdir lib
49 lib=$(readlink -f lib)
50 sed -i s@=${nagiosState}@=$lib@ nagios.cfg
51 ${pkgs.nagios}/bin/nagios -v nagios.cfg && cp ${file} $out
52 '';
53 defaultCfgFile = if cfg.validateConfig then validated else file;
54 in
55 if cfg.mainConfigFile == null then defaultCfgFile else cfg.mainConfigFile;
56
57 # Plain configuration for the Nagios web-interface with no
58 # authentication.
59 nagiosCGICfgFile = pkgs.writeText "nagios.cgi.conf" ''
60 main_config_file=${cfg.mainConfigFile}
61 use_authentication=0
62 url_html_path=${urlPath}
63 '';
64
65 extraHttpdConfig = ''
66 ScriptAlias ${urlPath}/cgi-bin ${pkgs.nagios}/sbin
67
68 <Directory "${pkgs.nagios}/sbin">
69 Options ExecCGI
70 Require all granted
71 SetEnv NAGIOS_CGI_CONFIG ${cfg.cgiConfigFile}
72 </Directory>
73
74 Alias ${urlPath} ${pkgs.nagios}/share
75
76 <Directory "${pkgs.nagios}/share">
77 Options None
78 Require all granted
79 </Directory>
80 '';
81
82in
83{
84 imports = [
85 (lib.mkRemovedOptionModule [
86 "services"
87 "nagios"
88 "urlPath"
89 ] "The urlPath option has been removed as it is hard coded to /nagios in the nagios package.")
90 ];
91
92 meta.maintainers = with lib.maintainers; [ symphorien ];
93
94 options = {
95 services.nagios = {
96 enable = lib.mkEnableOption ''[Nagios](https://www.nagios.org/) to monitor your system or network'';
97
98 objectDefs = lib.mkOption {
99 description = ''
100 A list of Nagios object configuration files that must define
101 the hosts, host groups, services and contacts for the
102 network that you want Nagios to monitor.
103 '';
104 type = lib.types.listOf lib.types.path;
105 example = lib.literalExpression "[ ./objects.cfg ]";
106 };
107
108 plugins = lib.mkOption {
109 type = lib.types.listOf lib.types.package;
110 default = with pkgs; [
111 monitoring-plugins
112 msmtp
113 mailutils
114 ];
115 defaultText = lib.literalExpression "[pkgs.monitoring-plugins pkgs.msmtp pkgs.mailutils]";
116 description = ''
117 Packages to be added to the Nagios {env}`PATH`.
118 Typically used to add plugins, but can be anything.
119 '';
120 };
121
122 mainConfigFile = lib.mkOption {
123 type = lib.types.nullOr lib.types.package;
124 default = null;
125 description = ''
126 If non-null, overrides the main configuration file of Nagios.
127 '';
128 };
129
130 extraConfig = lib.mkOption {
131 type = lib.types.attrsOf lib.types.str;
132 example = {
133 debug_level = "-1";
134 debug_file = "/var/log/nagios/debug.log";
135 };
136 default = { };
137 description = "Configuration to add to /etc/nagios.cfg";
138 };
139
140 validateConfig = lib.mkOption {
141 type = lib.types.bool;
142 default = pkgs.stdenv.hostPlatform == pkgs.stdenv.buildPlatform;
143 defaultText = lib.literalExpression "pkgs.stdenv.hostPlatform == pkgs.stdenv.buildPlatform";
144 description = "if true, the syntax of the nagios configuration file is checked at build time";
145 };
146
147 cgiConfigFile = lib.mkOption {
148 type = lib.types.package;
149 default = nagiosCGICfgFile;
150 defaultText = lib.literalExpression "nagiosCGICfgFile";
151 description = ''
152 Derivation for the configuration file of Nagios CGI scripts
153 that can be used in web servers for running the Nagios web interface.
154 '';
155 };
156
157 enableWebInterface = lib.mkOption {
158 type = lib.types.bool;
159 default = false;
160 description = ''
161 Whether to enable the Nagios web interface. You should also
162 enable Apache ({option}`services.httpd.enable`).
163 '';
164 };
165
166 virtualHost = lib.mkOption {
167 type = lib.types.submodule (import ../web-servers/apache-httpd/vhost-options.nix);
168 example = lib.literalExpression ''
169 { hostName = "example.org";
170 adminAddr = "webmaster@example.org";
171 enableSSL = true;
172 sslServerCert = "/var/lib/acme/example.org/full.pem";
173 sslServerKey = "/var/lib/acme/example.org/key.pem";
174 }
175 '';
176 description = ''
177 Apache configuration can be done by adapting {option}`services.httpd.virtualHosts`.
178 See [](#opt-services.httpd.virtualHosts) for further information.
179 '';
180 };
181 };
182 };
183
184 config = lib.mkIf cfg.enable {
185 users.users.nagios = {
186 description = "Nagios user";
187 uid = config.ids.uids.nagios;
188 home = nagiosState;
189 group = "nagios";
190 };
191
192 users.groups.nagios = { };
193
194 # This isn't needed, it's just so that the user can type "nagiostats
195 # -c /etc/nagios.cfg".
196 environment.etc."nagios.cfg".source = nagiosCfgFile;
197
198 environment.systemPackages = [ pkgs.nagios ];
199 systemd.services.nagios = {
200 description = "Nagios monitoring daemon";
201 path = [ pkgs.nagios ] ++ cfg.plugins;
202 wantedBy = [ "multi-user.target" ];
203 after = [ "network.target" ];
204 restartTriggers = [ nagiosCfgFile ];
205
206 serviceConfig = {
207 User = "nagios";
208 Group = "nagios";
209 Restart = "always";
210 RestartSec = 2;
211 LogsDirectory = "nagios";
212 StateDirectory = "nagios";
213 ExecStart = "${pkgs.nagios}/bin/nagios /etc/nagios.cfg";
214 };
215 };
216
217 services.httpd.virtualHosts = lib.optionalAttrs cfg.enableWebInterface {
218 ${cfg.virtualHost.hostName} = lib.mkMerge [
219 cfg.virtualHost
220 { extraConfig = extraHttpdConfig; }
221 ];
222 };
223 };
224}