at 25.11-pre 10 kB view raw
1{ 2 config, 3 lib, 4 options, 5 pkgs, 6 ... 7}: 8 9let 10 11 inherit (lib) 12 mkDefault 13 mkEnableOption 14 mkPackageOption 15 mkRenamedOptionModule 16 mkForce 17 mkIf 18 mkMerge 19 mkOption 20 types 21 ; 22 inherit (lib) 23 literalExpression 24 mapAttrs 25 optionalString 26 optionals 27 versionAtLeast 28 ; 29 30 cfg = config.services.zabbixWeb; 31 opt = options.services.zabbixWeb; 32 fpm = config.services.phpfpm.pools.zabbix; 33 34 user = "zabbix"; 35 group = "zabbix"; 36 stateDir = "/var/lib/zabbix"; 37 38 zabbixConfig = pkgs.writeText "zabbix.conf.php" '' 39 <?php 40 // Zabbix GUI configuration file. 41 global $DB; 42 $DB['TYPE'] = '${ 43 { 44 mysql = "MYSQL"; 45 pgsql = "POSTGRESQL"; 46 oracle = "ORACLE"; 47 } 48 .${cfg.database.type} 49 }'; 50 $DB['SERVER'] = '${cfg.database.host}'; 51 $DB['PORT'] = '${toString cfg.database.port}'; 52 $DB['DATABASE'] = '${cfg.database.name}'; 53 $DB['USER'] = '${cfg.database.user}'; 54 # NOTE: file_get_contents adds newline at the end of returned string 55 $DB['PASSWORD'] = ${ 56 if cfg.database.passwordFile != null then 57 "trim(file_get_contents('${cfg.database.passwordFile}'), \"\\r\\n\")" 58 else 59 "''" 60 }; 61 // Schema name. Used for IBM DB2 and PostgreSQL. 62 $DB['SCHEMA'] = '''; 63 $ZBX_SERVER = '${cfg.server.address}'; 64 $ZBX_SERVER_PORT = '${toString cfg.server.port}'; 65 $ZBX_SERVER_NAME = '''; 66 $IMAGE_FORMAT_DEFAULT = IMAGE_FORMAT_PNG; 67 68 ${cfg.extraConfig} 69 ''; 70in 71{ 72 imports = [ 73 (mkRenamedOptionModule 74 [ 75 "services" 76 "zabbixWeb" 77 "virtualHost" 78 ] 79 [ 80 "services" 81 "zabbixWeb" 82 "httpd" 83 "virtualHost" 84 ] 85 ) 86 ]; 87 # interface 88 89 options.services = { 90 zabbixWeb = { 91 enable = mkEnableOption "the Zabbix web interface"; 92 93 package = mkPackageOption pkgs [ 94 "zabbix" 95 "web" 96 ] { }; 97 98 server = { 99 port = mkOption { 100 type = types.port; 101 description = "The port of the Zabbix server to connect to."; 102 default = 10051; 103 }; 104 105 address = mkOption { 106 type = types.str; 107 description = "The IP address or hostname of the Zabbix server to connect to."; 108 default = "localhost"; 109 }; 110 }; 111 112 database = { 113 type = mkOption { 114 type = types.enum [ 115 "mysql" 116 "pgsql" 117 "oracle" 118 ]; 119 example = "mysql"; 120 default = "pgsql"; 121 description = "Database engine to use."; 122 }; 123 124 host = mkOption { 125 type = types.str; 126 default = ""; 127 description = "Database host address."; 128 }; 129 130 port = mkOption { 131 type = types.port; 132 default = 133 if cfg.database.type == "mysql" then 134 config.services.mysql.port 135 else if cfg.database.type == "pgsql" then 136 config.services.postgresql.settings.port 137 else 138 1521; 139 defaultText = literalExpression '' 140 if config.${opt.database.type} == "mysql" then config.${options.services.mysql.port} 141 else if config.${opt.database.type} == "pgsql" then config.services.postgresql.settings.port 142 else 1521 143 ''; 144 description = "Database host port."; 145 }; 146 147 name = mkOption { 148 type = types.str; 149 default = "zabbix"; 150 description = "Database name."; 151 }; 152 153 user = mkOption { 154 type = types.str; 155 default = "zabbix"; 156 description = "Database user."; 157 }; 158 159 passwordFile = mkOption { 160 type = types.nullOr types.path; 161 default = null; 162 example = "/run/keys/zabbix-dbpassword"; 163 description = '' 164 A file containing the password corresponding to 165 {option}`database.user`. 166 ''; 167 }; 168 169 socket = mkOption { 170 type = types.nullOr types.path; 171 default = null; 172 example = "/run/postgresql"; 173 description = "Path to the unix socket file to use for authentication."; 174 }; 175 }; 176 177 frontend = mkOption { 178 type = types.enum [ 179 "nginx" 180 "httpd" 181 ]; 182 example = "nginx"; 183 default = "httpd"; 184 description = "Frontend server to use."; 185 }; 186 187 httpd.virtualHost = mkOption { 188 type = types.submodule (import ../web-servers/apache-httpd/vhost-options.nix); 189 example = literalExpression '' 190 { 191 hostName = "zabbix.example.org"; 192 adminAddr = "webmaster@example.org"; 193 forceSSL = true; 194 enableACME = true; 195 } 196 ''; 197 default = { }; 198 description = '' 199 Apache configuration can be done by adapting `services.httpd.virtualHosts.<name>`. 200 See [](#opt-services.httpd.virtualHosts) for further information. 201 ''; 202 }; 203 204 hostname = mkOption { 205 type = types.str; 206 default = "zabbix.local"; 207 description = "Hostname for either nginx or httpd."; 208 }; 209 210 nginx.virtualHost = mkOption { 211 type = types.submodule (import ../web-servers/nginx/vhost-options.nix); 212 example = literalExpression '' 213 { 214 forceSSL = true; 215 sslCertificateKey = "/etc/ssl/zabbix.key"; 216 sslCertificate = "/etc/ssl/zabbix.crt"; 217 } 218 ''; 219 default = { }; 220 description = '' 221 Nginx configuration can be done by adapting `services.nginx.virtualHosts.<name>`. 222 See [](#opt-services.nginx.virtualHosts) for further information. 223 ''; 224 }; 225 226 poolConfig = mkOption { 227 type = 228 with types; 229 attrsOf (oneOf [ 230 str 231 int 232 bool 233 ]); 234 default = { 235 "pm" = "dynamic"; 236 "pm.max_children" = 32; 237 "pm.start_servers" = 2; 238 "pm.min_spare_servers" = 2; 239 "pm.max_spare_servers" = 4; 240 "pm.max_requests" = 500; 241 }; 242 description = '' 243 Options for the Zabbix PHP pool. See the documentation on `php-fpm.conf` for details on configuration directives. 244 ''; 245 }; 246 247 extraConfig = mkOption { 248 type = types.lines; 249 default = ""; 250 description = '' 251 Additional configuration to be copied verbatim into {file}`zabbix.conf.php`. 252 ''; 253 }; 254 }; 255 }; 256 257 # implementation 258 259 config = mkIf cfg.enable { 260 261 services.zabbixWeb.extraConfig = 262 optionalString 263 ( 264 (versionAtLeast config.system.stateVersion "20.09") && (versionAtLeast cfg.package.version "5.0.0") 265 ) 266 '' 267 $DB['DOUBLE_IEEE754'] = 'true'; 268 ''; 269 270 systemd.tmpfiles.rules = 271 [ "d '${stateDir}' 0750 ${user} ${group} - -" ] 272 ++ optionals (cfg.frontend == "httpd") [ 273 "d '${stateDir}/session' 0750 ${user} ${config.services.httpd.group} - -" 274 ] 275 ++ optionals (cfg.frontend == "nginx") [ 276 "d '${stateDir}/session' 0750 ${user} ${config.services.nginx.group} - -" 277 ]; 278 279 services.phpfpm.pools.zabbix = { 280 inherit user; 281 group = config.services.${cfg.frontend}.group; 282 phpOptions = 283 '' 284 # https://www.zabbix.com/documentation/current/manual/installation/install 285 memory_limit = 128M 286 post_max_size = 16M 287 upload_max_filesize = 2M 288 max_execution_time = 300 289 max_input_time = 300 290 session.auto_start = 0 291 mbstring.func_overload = 0 292 always_populate_raw_post_data = -1 293 # https://bbs.archlinux.org/viewtopic.php?pid=1745214#p1745214 294 session.save_path = ${stateDir}/session 295 '' 296 + optionalString (config.time.timeZone != null) '' 297 date.timezone = "${config.time.timeZone}" 298 '' 299 + optionalString (cfg.database.type == "oracle") '' 300 extension=${pkgs.phpPackages.oci8}/lib/php/extensions/oci8.so 301 ''; 302 phpEnv.ZABBIX_CONFIG = "${zabbixConfig}"; 303 settings = { 304 "listen.owner" = 305 if cfg.frontend == "httpd" then config.services.httpd.user else config.services.nginx.user; 306 "listen.group" = 307 if cfg.frontend == "httpd" then config.services.httpd.group else config.services.nginx.group; 308 } // cfg.poolConfig; 309 }; 310 311 services.httpd = mkIf (cfg.frontend == "httpd") { 312 enable = true; 313 adminAddr = mkDefault cfg.httpd.virtualHost.adminAddr; 314 extraModules = [ "proxy_fcgi" ]; 315 virtualHosts.${cfg.hostname} = mkMerge [ 316 cfg.httpd.virtualHost 317 { 318 documentRoot = mkForce "${cfg.package}/share/zabbix"; 319 extraConfig = '' 320 <Directory "${cfg.package}/share/zabbix"> 321 <FilesMatch "\.php$"> 322 <If "-f %{REQUEST_FILENAME}"> 323 SetHandler "proxy:unix:${fpm.socket}|fcgi://localhost/" 324 </If> 325 </FilesMatch> 326 AllowOverride all 327 Options -Indexes 328 DirectoryIndex index.php 329 </Directory> 330 ''; 331 } 332 ]; 333 }; 334 335 services.nginx = mkIf (cfg.frontend == "nginx") { 336 enable = true; 337 virtualHosts.${cfg.hostname} = mkMerge [ 338 cfg.nginx.virtualHost 339 { 340 root = mkForce "${cfg.package}/share/zabbix"; 341 locations."/" = { 342 index = "index.html index.htm index.php"; 343 tryFiles = "$uri $uri/ =404"; 344 }; 345 locations."~ \\.php$".extraConfig = '' 346 fastcgi_pass unix:${fpm.socket}; 347 fastcgi_index index.php; 348 ''; 349 } 350 ]; 351 }; 352 353 users.users.${user} = mapAttrs (name: mkDefault) { 354 description = "Zabbix daemon user"; 355 uid = config.ids.uids.zabbix; 356 inherit group; 357 }; 358 359 users.groups.${group} = mapAttrs (name: mkDefault) { gid = config.ids.gids.zabbix; }; 360 }; 361}