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