at 24.11-pre 7.4 kB view raw
1{ config, lib, options, pkgs, ... }: 2 3let 4 5 inherit (lib) mkDefault mkEnableOption mkPackageOption mkForce mkIf mkMerge mkOption types; 6 inherit (lib) literalExpression mapAttrs optionalString versionAtLeast; 7 8 cfg = config.services.zabbixWeb; 9 opt = options.services.zabbixWeb; 10 fpm = config.services.phpfpm.pools.zabbix; 11 12 user = "zabbix"; 13 group = "zabbix"; 14 stateDir = "/var/lib/zabbix"; 15 16 zabbixConfig = pkgs.writeText "zabbix.conf.php" '' 17 <?php 18 // Zabbix GUI configuration file. 19 global $DB; 20 $DB['TYPE'] = '${ { mysql = "MYSQL"; pgsql = "POSTGRESQL"; oracle = "ORACLE"; }.${cfg.database.type} }'; 21 $DB['SERVER'] = '${cfg.database.host}'; 22 $DB['PORT'] = '${toString cfg.database.port}'; 23 $DB['DATABASE'] = '${cfg.database.name}'; 24 $DB['USER'] = '${cfg.database.user}'; 25 # NOTE: file_get_contents adds newline at the end of returned string 26 $DB['PASSWORD'] = ${if cfg.database.passwordFile != null then "trim(file_get_contents('${cfg.database.passwordFile}'), \"\\r\\n\")" else "''"}; 27 // Schema name. Used for IBM DB2 and PostgreSQL. 28 $DB['SCHEMA'] = '''; 29 $ZBX_SERVER = '${cfg.server.address}'; 30 $ZBX_SERVER_PORT = '${toString cfg.server.port}'; 31 $ZBX_SERVER_NAME = '''; 32 $IMAGE_FORMAT_DEFAULT = IMAGE_FORMAT_PNG; 33 34 ${cfg.extraConfig} 35 ''; 36 37in 38{ 39 # interface 40 41 options.services = { 42 zabbixWeb = { 43 enable = mkEnableOption "the Zabbix web interface"; 44 45 package = mkPackageOption pkgs [ "zabbix" "web" ] { }; 46 47 server = { 48 port = mkOption { 49 type = types.port; 50 description = "The port of the Zabbix server to connect to."; 51 default = 10051; 52 }; 53 54 address = mkOption { 55 type = types.str; 56 description = "The IP address or hostname of the Zabbix server to connect to."; 57 default = "localhost"; 58 }; 59 }; 60 61 database = { 62 type = mkOption { 63 type = types.enum [ "mysql" "pgsql" "oracle" ]; 64 example = "mysql"; 65 default = "pgsql"; 66 description = "Database engine to use."; 67 }; 68 69 host = mkOption { 70 type = types.str; 71 default = ""; 72 description = "Database host address."; 73 }; 74 75 port = mkOption { 76 type = types.port; 77 default = 78 if cfg.database.type == "mysql" then config.services.mysql.port 79 else if cfg.database.type == "pgsql" then config.services.postgresql.settings.port 80 else 1521; 81 defaultText = literalExpression '' 82 if config.${opt.database.type} == "mysql" then config.${options.services.mysql.port} 83 else if config.${opt.database.type} == "pgsql" then config.services.postgresql.settings.port 84 else 1521 85 ''; 86 description = "Database host port."; 87 }; 88 89 name = mkOption { 90 type = types.str; 91 default = "zabbix"; 92 description = "Database name."; 93 }; 94 95 user = mkOption { 96 type = types.str; 97 default = "zabbix"; 98 description = "Database user."; 99 }; 100 101 passwordFile = mkOption { 102 type = types.nullOr types.path; 103 default = null; 104 example = "/run/keys/zabbix-dbpassword"; 105 description = '' 106 A file containing the password corresponding to 107 {option}`database.user`. 108 ''; 109 }; 110 111 socket = mkOption { 112 type = types.nullOr types.path; 113 default = null; 114 example = "/run/postgresql"; 115 description = "Path to the unix socket file to use for authentication."; 116 }; 117 }; 118 119 virtualHost = mkOption { 120 type = types.submodule (import ../web-servers/apache-httpd/vhost-options.nix); 121 example = literalExpression '' 122 { 123 hostName = "zabbix.example.org"; 124 adminAddr = "webmaster@example.org"; 125 forceSSL = true; 126 enableACME = true; 127 } 128 ''; 129 description = '' 130 Apache configuration can be done by adapting `services.httpd.virtualHosts.<name>`. 131 See [](#opt-services.httpd.virtualHosts) for further information. 132 ''; 133 }; 134 135 poolConfig = mkOption { 136 type = with types; attrsOf (oneOf [ str int bool ]); 137 default = { 138 "pm" = "dynamic"; 139 "pm.max_children" = 32; 140 "pm.start_servers" = 2; 141 "pm.min_spare_servers" = 2; 142 "pm.max_spare_servers" = 4; 143 "pm.max_requests" = 500; 144 }; 145 description = '' 146 Options for the Zabbix PHP pool. See the documentation on `php-fpm.conf` for details on configuration directives. 147 ''; 148 }; 149 150 extraConfig = mkOption { 151 type = types.lines; 152 default = ""; 153 description = '' 154 Additional configuration to be copied verbatim into {file}`zabbix.conf.php`. 155 ''; 156 }; 157 158 }; 159 }; 160 161 # implementation 162 163 config = mkIf cfg.enable { 164 165 services.zabbixWeb.extraConfig = optionalString ((versionAtLeast config.system.stateVersion "20.09") && (versionAtLeast cfg.package.version "5.0.0")) '' 166 $DB['DOUBLE_IEEE754'] = 'true'; 167 ''; 168 169 systemd.tmpfiles.rules = [ 170 "d '${stateDir}' 0750 ${user} ${group} - -" 171 "d '${stateDir}/session' 0750 ${user} ${config.services.httpd.group} - -" 172 ]; 173 174 services.phpfpm.pools.zabbix = { 175 inherit user; 176 group = config.services.httpd.group; 177 phpOptions = '' 178 # https://www.zabbix.com/documentation/current/manual/installation/install 179 memory_limit = 128M 180 post_max_size = 16M 181 upload_max_filesize = 2M 182 max_execution_time = 300 183 max_input_time = 300 184 session.auto_start = 0 185 mbstring.func_overload = 0 186 always_populate_raw_post_data = -1 187 # https://bbs.archlinux.org/viewtopic.php?pid=1745214#p1745214 188 session.save_path = ${stateDir}/session 189 '' + optionalString (config.time.timeZone != null) '' 190 date.timezone = "${config.time.timeZone}" 191 '' + optionalString (cfg.database.type == "oracle") '' 192 extension=${pkgs.phpPackages.oci8}/lib/php/extensions/oci8.so 193 ''; 194 phpEnv.ZABBIX_CONFIG = "${zabbixConfig}"; 195 settings = { 196 "listen.owner" = config.services.httpd.user; 197 "listen.group" = config.services.httpd.group; 198 } // cfg.poolConfig; 199 }; 200 201 services.httpd = { 202 enable = true; 203 adminAddr = mkDefault cfg.virtualHost.adminAddr; 204 extraModules = [ "proxy_fcgi" ]; 205 virtualHosts.${cfg.virtualHost.hostName} = mkMerge [ cfg.virtualHost { 206 documentRoot = mkForce "${cfg.package}/share/zabbix"; 207 extraConfig = '' 208 <Directory "${cfg.package}/share/zabbix"> 209 <FilesMatch "\.php$"> 210 <If "-f %{REQUEST_FILENAME}"> 211 SetHandler "proxy:unix:${fpm.socket}|fcgi://localhost/" 212 </If> 213 </FilesMatch> 214 AllowOverride all 215 Options -Indexes 216 DirectoryIndex index.php 217 </Directory> 218 ''; 219 } ]; 220 }; 221 222 users.users.${user} = mapAttrs (name: mkDefault) { 223 description = "Zabbix daemon user"; 224 uid = config.ids.uids.zabbix; 225 inherit group; 226 }; 227 228 users.groups.${group} = mapAttrs (name: mkDefault) { 229 gid = config.ids.gids.zabbix; 230 }; 231 232 }; 233}