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