diff --git a/nixos/modules/module-list.nix b/nixos/modules/module-list.nix index 684850df2aeca..83f9ad1724fe7 100644 --- a/nixos/modules/module-list.nix +++ b/nixos/modules/module-list.nix @@ -123,6 +123,7 @@ ./services/misc/nix-daemon.nix ./services/misc/nix-gc.nix ./services/misc/nixos-manual.nix + ./services/misc/phpfpm.nix ./services/misc/rogue.nix ./services/misc/svnserve.nix ./services/misc/synergy.nix diff --git a/nixos/modules/services/misc/phpfpm.nix b/nixos/modules/services/misc/phpfpm.nix new file mode 100644 index 0000000000000..ff30a8d5fdcd7 --- /dev/null +++ b/nixos/modules/services/misc/phpfpm.nix @@ -0,0 +1,344 @@ +{ config, pkgs, ... }: + +/* + +What does this php-fpm module provide? + +Short intro: php-fpm means running PHP outside of apache, with proper linux +user id/group. The php-fdpm daemon will spawn/kill processes as needed. +Comparison chart: http://php-fpm.org/about/#why + +How does it work? One php-fpm daemon supervises multiple pools. +However some options like xdebug cannot be configured for an individual pool, +thus if you want one project to be debugcgable you have to create a new +config/daemon pair. + +This is what this module is about: +You feed in a list of PHP pool configurations - and the module will group +groupable pools so that they can be supervisd by the same daemon. +Eg if you enable xdebug for one user you'll get two php-fpm services +automatically and everything should just work. + +Now that systemd exists each daemon has +- a name ( .service file) +- many pools (each has a socket clients like apache connect to) + +And that's what the functions daemonIdFun, socketPathFun are about: given a +configuration they derive a name. If you know that you're using one PHP-5.3 +configuration you can return "5.3", however you must ensure that different +daemon configs don't get the same name ! Thus the default implementation is +using a short hash based on the configuration. Downside is that log file names +change if you configure PHP differently. + +Obviously the socket paths are used by the systemd configuration and by the +apache/lighthttpd/nginx web server configurations. + +simple usage example illustrating how you can access the same local web applications +using two different domains php53 and php54 to test both versions, but +debugging is only enable for php 5.3 + + let + + phpfpmPools = + let environment = { + # LOCALE_ARCHIVE="${pkgs.glibcLocales}/lib/locale/locale-archive"; + }; + in { + "php54" = { + daemonCfg.php = pkgs.php5_4fpm; + # daemonCfg.id = "5.4"; # optional + poolItemCfg = { + inherit environment; + user = "user"; + group = "users"; + listen = { owner = config.services.httpd.user; group = config.services.httpd.group; mode = "0700"; }; + slowlog = "/pr/www/slow-log-5.4"; + }; + }; + + "php53" = rec { + daemonCfg.php = pkgs.php5_3fpm; + daemonCfg.xdebug = { enable = true; remote_port = "9000"; }; + daemonCfg.phpIniLines = '' + additional php ini lines + ''; + # daemonCfg.id = "5.3"; # optional + poolItemCfg = { + # inherit environment; + user = "user"; + group = "users"; + listen = { owner = config.services.httpd.user; group = config.services.httpd.group; mode = "0700"; }; + slowlog = "/pr/www/slow-log-5.3"; + }; + }; + + in + + {pkgs , config, ...} : { + + services.phpfpm.pools = lib.attrValues phpfpmPools; + + httpd.extraConfig = '' + FastCGIExternalServer /dev/shm/php5.3.fcgi -socket ${config.services.phpfpm.socketPathFun phpfpmPools.php53} -flush -idle-timeout 300 + FastCGIExternalServer /dev/shm/php5.4.fcgi -socket ${config.services.phpfpm.socketPathFun phpfpmPools.php54} -flush -idle-timeout 300 + ''; + + httpd.virtualHosts = + ( + map (php: let documentRoot = "/pr/www"; in { + enable = true; + documentRoot = documentRoot; + hostName = php.domain; + extraConfig = '' + RewriteEngine On + + AddType application/x-httpd-php .php + AddType application/x-httpd-php .php5 + Action application/x-httpd-php /x/php.fcgi + Alias /x/php.fcgi /dev/shm/php${php.version}.fcgi + + + DirectoryIndex index.php index.html + Options +ExecCGI + Order allow,deny + Allow from all + AllowOverride All + + + ''; + }) [ + { domain = "php53"; version = "5.3"; } + { domain = "php54"; version = "5.4"; } + ] + ); + + } + +*/ + + +let + inherit (builtins) listToAttrs head baseNameOf unsafeDiscardStringContext toString; + inherit (pkgs.lib) mkOption mkIf mkMerge mergeAttrs foldAttrs attrValues + mapAttrs catAttrs fold optionalString; + + cfg = config.services.phpfpm; + + phpIniFile = + {item, phpIniLines ? "", name}: + pkgs.runCommand name { inherit phpIniLines; } + "cat ${item.daemonCfg.php}/etc/php-recommended.ini > $out; echo \"$phpIniLines\" >> $out" + ; + + preparePool = item: # item = item of phpfpm.pools + let + enableXdebug = item.daemonCfg.xdebug.enable or false; + profileDir = item.daemonCfg.xdebug.profileDir or (id: "/tmp/xdebug-profiler-dir-${id}"); + xd = if enableXdebug + then + let remote_host = item.xdebug.remote_host or "127.0.0.1"; + remote_port = builtins.toString item.xdebug.remote_port or 9000; + in { + idAppend = "-xdebug"; + phpIniLines = '' + zend_extension="${item.daemonCfg.php.xdebug}/lib/xdebug.so" + zend_extension_ts="${item.daemonCfg.php.xdebug}/lib/xdebug.so" + zend_extension_debug="${item.daemonCfg.php.xdebug}/lib/xdebug.so" + xdebug.remote_enable=true + xdebug.remote_host=${remote_host} + xdebug.remote_port=${remote_port} + xdebug.remote_handler=dbgp + xdebug.profiler_enable=0 + xdebug.remote_mode=req + ''; + } + else { + idAppend = ""; + phpIniLines = ""; + }; + phpIniLines = + xd.phpIniLines + + (item.daemonCfg.phpIniLines or ""); + + + # using phpIniLines create a cfg-id + iniId = builtins.substring 0 5 (builtins.hashString "sha256" (unsafeDiscardStringContext phpIniLines)) + +xd.idAppend; + + phpIni = (item.daemonCfg.phpIniFile or phpIniFile) { + inherit item; + name = "php-${iniId}.ini"; + phpIniLines = + phpIniLines + + optionalString enableXdebug "\nprofiler_output_dir = \"${item.daemonCfg.xdebug.profiler_output_dir or (profileDir iniId)}\;"; + }; + + # [ID] see daemonIdFun + id = item.daemonCfg.id or "${item.daemonCfg.php.id}-${iniId}"; + phpIniName = baseNameOf (unsafeDiscardStringContext item.phpIni); + in item // { + daemonCfg = item.daemonCfg // { + inherit phpIniName phpIni id; + }; + }; + + + phpFpmDaemons = + + let nv = name: value: listToAttrs [{ inherit name value; }]; + poolsWithIni = map preparePool cfg.pools; + # group pools by common php and php ini config + poolsByPHP = foldAttrs (n: a: [n] ++ a) [] (map (p: nv "${p.daemonCfg.id}" p) poolsWithIni); + toDaemon = name: pools: + let h = head pools; + in h.daemonCfg.php.system_fpm_config + { # daemon config + # TODO make option or such by letting user set these by php.id attr or such + log_level = "notice"; + emergency_restart_threshold = "10"; + emergency_restart_interval = "1m"; + process_control_timeout = "5s"; + inherit (h.daemonCfg) id phpIni phpIniLines; + } + # pools + (map (p: + let socketPath = cfg.socketPathFun p; + in p.poolItemCfg + // { + listen_address = socketPath; + name = builtins.baseNameOf socketPath; + }) + pools); + in attrValues (mapAttrs toDaemon poolsByPHP); + +in { + + imports = []; + + options = { + services.phpfpm = { + + enable = mkOption { + default = true; + description = "Whether to enable the PHP FastCGI Process Manager. With empty pool this should have no effect"; + }; + + stateDir = mkOption { + default = "/var/run/phpfpm"; + description = "State directory with PID and socket files."; + }; + + logDir = mkOption { + default = "/var/log/phpfpm"; + description = "Directory where to put in log files."; + }; + + daemonIdFun = mkOption { + description = "Function returning service name based on php compilation options, php ini file"; + default = pool: (preparePool pool).daemonCfg.id; + }; + + socketPathFun = mkOption { + description = "Function returning socket path by pool to which web servers connect to."; + default = pool: + let pool_h = builtins.substring 0 8 (builtins.hashString "sha256" (builtins.toXML pool.poolItemCfg)); + in "/dev/shm/php-fpm-${cfg.daemonIdFun pool}-${pool_h}"; + }; + + pools = mkOption { + default = []; + example = [ + rec { + + ### php-fpm daemon options: If contents differ multiple daemons will be started + daemonCfg = { + + ### id + # optional: + # An ID based on the PHP configuration is generated automatically, see [ID] and daemonIdFun + # id = "php-5.3" + # this id is used to make the systemd units and the socket paths unique + # see daemonIdFun etc. + + # php version, must support fpm, thus must have a system_fpm_config attr + php = pkgs.php5_2fpm.override {}; + + # optional: append addditional php.ini lines. + + # Please note that most options can be set by using etxraLines in + # the pool configuration like this: + # php_flag[name]=on/off + # php_admin_value[str_option]="127.0.0.1" + # which should be preferred so that less php-fpm daemons have to be started + # These lines are appended to the default configuartion shipping with PHP + # unless phpIniFile is given + # + # phpIniLines appends lines to the default php.ini file shipping with PHP. + # You can override everything by either setting + # - phpIniFile (function returning file, see sample in this file) + # - phpIni (must be a file), eg phpIniFile = pkgs.writeFile ... + phpIniLines = '' + ''; + + # optional: enable xdebug, if set additional phpIniLines will be created + # xdebug can't be configured per pool, see: https://bugs.php.net/bug.php?id=54824 + xdebug = { + enable = true; + # optional names: + # remote_host = "127.0.0.1"; + # remote_port = 9000; + # profileDir = id: "/tmp/xdebug-profiler-dir-${id}"; # setting profiler_output_dir + }; + + }; + + ### php-fpm per pool options + poolItemCfg = { + + # pool config, see system_fpm_config implementation in nixpkgs + slowlog = ""; # must be writeable by the user/group of the php process? + + user = "user"; + group = "group"; + # listen_adress will be set automatically by socketPathFun + listen = { owner = config.services.httpd.user; group = config.services.httpd.group; mode = "0700"; }; + + pm = { + value = "dynamic"; + max_children = 400; + min_spare_servers = 10; + max_spare_servers = 30; + }; + + }; + } + ]; + + description = '' + Specify the pools the FastCGI Process Manager should manage. + For each specific PHP and phpIni derivation combination a new + php-fpm pool has to be created .. + + This is specified by using an attribute set which maps roughly 1:1 + to ini-file syntax, with the exception that the main value of a + namespace has to be specified by an attribute called 'value'. + + In addition, attributes called 'env' or starting with 'php_' are + formatted with square brackets, like for example 'env[TMP] = /tmp', + which corresponds to 'env.TMP = "/tmp"'. + + The php-fpm daemon must run as root, because it must switch user for + worker threads .. + ''; + }; + + }; + }; + + # config = mkIf cfg.enable (mkMerge phpFpmDaemons); + # is too strict, need to evaluate "config", so pick attrs which are used only + config = { + environment.etc = mkMerge (catAttrs "etc" (catAttrs "environment" phpFpmDaemons)); + systemd = mkMerge (catAttrs "systemd" phpFpmDaemons); + }; +} diff --git a/pkgs/development/interpreters/php/5.3.nix b/pkgs/development/interpreters/php/5.3.nix deleted file mode 100644 index f7bb29270c7b3..0000000000000 --- a/pkgs/development/interpreters/php/5.3.nix +++ /dev/null @@ -1,241 +0,0 @@ -{ stdenv, fetchurl, composableDerivation, autoconf, automake, flex, bison -, apacheHttpd, mysql, libxml2, readline, zlib, curl, gd, postgresql, gettext -, openssl, pkgconfig, sqlite, config, libjpeg, libpng, freetype, libxslt -, libmcrypt, bzip2, icu, libssh2, makeWrapper, libiconvOrEmpty, libiconv, uwimap -, pam }: - -let - libmcryptOverride = libmcrypt.override { disablePosixThreads = true; }; -in - -composableDerivation.composableDerivation {} ( fixed : let inherit (fixed.fixed) version; in { - - version = "5.3.28"; - - name = "php-${version}"; - - enableParallelBuilding = true; - - buildInputs - = [ flex bison pkgconfig ] - ++ stdenv.lib.optionals stdenv.isDarwin [ libssh2 makeWrapper ]; - - # need to include the C++ standard library when compiling on darwin - NIX_LDFLAGS = stdenv.lib.optionalString stdenv.isDarwin "-lstdc++"; - - # need to specify where the dylib for icu is stored - DYLD_LIBRARY_PATH = stdenv.lib.optionalString stdenv.isDarwin "${icu}/lib"; - - flags = { - - # much left to do here... - - # SAPI modules: - - apxs2 = { - configureFlags = ["--with-apxs2=${apacheHttpd}/bin/apxs"]; - buildInputs = [apacheHttpd]; - }; - - # Extensions - - curl = { - configureFlags = ["--with-curl=${curl}" "--with-curlwrappers"]; - buildInputs = [curl openssl]; - }; - - pcntl = { - configureFlags = [ "--enable-pcntl" ]; - }; - - zlib = { - configureFlags = ["--with-zlib=${zlib}"]; - buildInputs = [zlib]; - }; - - libxml2 = { - configureFlags - = [ "--with-libxml-dir=${libxml2}" ] - ++ stdenv.lib.optional (libiconvOrEmpty != []) - [ "--with-iconv=${libiconv}" ]; - buildInputs = [ libxml2 ] ++ libiconvOrEmpty; - }; - - readline = { - configureFlags = ["--with-readline=${readline}"]; - buildInputs = [ readline ]; - }; - - sqlite = { - configureFlags = ["--with-pdo-sqlite=${sqlite}"]; - buildInputs = [ sqlite ]; - }; - - postgresql = { - configureFlags = ["--with-pgsql=${postgresql}"]; - buildInputs = [ postgresql ]; - }; - - mysql = { - configureFlags = ["--with-mysql=${mysql}"]; - buildInputs = [ mysql ]; - }; - - mysqli = { - configureFlags = ["--with-mysqli=${mysql}/bin/mysql_config"]; - buildInputs = [ mysql]; - }; - - mysqli_embedded = { - configureFlags = ["--enable-embedded-mysqli"]; - depends = "mysqli"; - assertion = fixed.mysqliSupport; - }; - - pdo_mysql = { - configureFlags = ["--with-pdo-mysql=${mysql}"]; - buildInputs = [ mysql ]; - }; - - bcmath = { - configureFlags = ["--enable-bcmath"]; - }; - - gd = { - configureFlags = [ - "--with-gd=${gd}" - "--with-freetype-dir=${freetype}" - "--with-png-dir=${libpng}" - "--with-jpeg-dir=${libjpeg}" - ]; - buildInputs = [gd libpng libjpeg freetype]; - }; - - soap = { - configureFlags = ["--enable-soap"]; - }; - - sockets = { - configureFlags = ["--enable-sockets"]; - }; - - openssl = { - configureFlags = ["--with-openssl=${openssl}"]; - buildInputs = ["openssl"]; - }; - - mbstring = { - configureFlags = ["--enable-mbstring"]; - }; - - gettext = { - configureFlags = ["--with-gettext=${gettext}"]; - buildInputs = [gettext]; - }; - - imap = { - configureFlags = [ "--with-imap=${uwimap}" "--with-imap-ssl" ] - # uwimap builds with kerberos on darwin - ++ stdenv.lib.optional (stdenv.isDarwin) "--with-kerberos"; - buildInputs = [ uwimap openssl ] - ++ stdenv.lib.optional (!stdenv.isDarwin) pam; - }; - - intl = { - configureFlags = ["--enable-intl"]; - buildInputs = [icu]; - }; - - exif = { - configureFlags = ["--enable-exif"]; - }; - - xsl = { - configureFlags = ["--with-xsl=${libxslt}"]; - buildInputs = [libxslt]; - }; - - mcrypt = { - configureFlags = ["--with-mcrypt=${libmcrypt}"]; - buildInputs = [libmcryptOverride]; - }; - - bz2 = { - configureFlags = ["--with-bz2=${bzip2}"]; - buildInputs = [bzip2]; - }; - - zip = { - configureFlags = ["--enable-zip"]; - }; - - ftp = { - configureFlags = ["--enable-ftp"]; - }; - }; - - cfg = { - apxs2Support = config.php.apxs2 or true; - bcmathSupport = config.php.bcmath or true; - bz2Support = config.php.bz2 or false; - curlSupport = config.php.curl or true; - exifSupport = config.php.exif or true; - ftpSupport = config.php.ftp or true; - gdSupport = config.php.gd or true; - gettextSupport = config.php.gettext or true; - imapSupport = config.php.imap or false; - intlSupport = config.php.intl or true; - libxml2Support = config.php.libxml2 or true; - mbstringSupport = config.php.mbstring or true; - mcryptSupport = config.php.mcrypt or false; - mysqlSupport = config.php.mysql or true; - mysqliSupport = config.php.mysqli or true; - opensslSupport = config.php.openssl or true; - pcntlSupport = config.php.pcntl or true; - pdo_mysqlSupport = config.php.pdo_mysql or true; - postgresqlSupport = config.php.postgresql or true; - readlineSupport = config.php.readline or true; - soapSupport = config.php.soap or true; - socketsSupport = config.php.sockets or true; - sqliteSupport = config.php.sqlite or true; - xslSupport = config.php.xsl or false; - zipSupport = config.php.zip or true; - zlibSupport = config.php.zlib or true; - }; - - configurePhase = '' - iniFile=$out/etc/php-recommended.ini - [[ -z "$libxml2" ]] || export PATH=$PATH:$libxml2/bin - ./configure --with-config-file-scan-dir=/etc --with-config-file-path=$out/etc --prefix=$out $configureFlags - echo configurePhase end - '' + stdenv.lib.optionalString stdenv.isDarwin '' - # don't build php.dSYM as the php binary - sed -i 's/EXEEXT = \.dSYM/EXEEXT =/' Makefile - ''; - - installPhase = '' - unset installPhase; installPhase; - cp php.ini-production $iniFile - '' + ( stdenv.lib.optionalString stdenv.isDarwin '' - for prog in $out/bin/*; do - wrapProgram "$prog" --prefix DYLD_LIBRARY_PATH : "$DYLD_LIBRARY_PATH" - done - '' ); - - src = fetchurl { - url = "http://nl1.php.net/get/php-${version}.tar.bz2/from/this/mirror"; - sha256 = "04w53nn6qacpkd1x381mzd41kqh6k8kjnbyg44yvnkqwcl69db0c"; - name = "php-${version}.tar.bz2"; - }; - - meta = { - description = "The PHP language runtime engine"; - homepage = http://www.php.net/; - license = "PHP-3"; - maintainers = with stdenv.lib.maintainers; [ lovek323 ]; - platforms = stdenv.lib.platforms.unix; - }; - - patches = [./fix.patch]; - -}) diff --git a/pkgs/development/interpreters/php/5.4.nix b/pkgs/development/interpreters/php/5.4.nix deleted file mode 100644 index bf60e90d634a0..0000000000000 --- a/pkgs/development/interpreters/php/5.4.nix +++ /dev/null @@ -1,250 +0,0 @@ -{ stdenv, fetchurl, composableDerivation, autoconf, automake, flex, bison -, apacheHttpd, mysql, libxml2, readline, zlib, curl, gd, postgresql, gettext -, openssl, pkgconfig, sqlite, config, libiconv, libjpeg, libpng, freetype -, libxslt, libmcrypt, bzip2, icu, openldap, cyrus_sasl, libmhash }: - -let - libmcryptOverride = libmcrypt.override { disablePosixThreads = true; }; -in - -composableDerivation.composableDerivation {} ( fixed : let inherit (fixed.fixed) version; in { - - version = "5.4.23"; - - name = "php-${version}"; - - enableParallelBuilding = true; - - buildInputs = ["flex" "bison" "pkgconfig"]; - - flags = { - - # much left to do here... - - # SAPI modules: - - apxs2 = { - configureFlags = ["--with-apxs2=${apacheHttpd}/bin/apxs"]; - buildInputs = [apacheHttpd]; - }; - - # Extensions - - ldap = { - configureFlags = ["--with-ldap=${openldap}"]; - buildInputs = [openldap cyrus_sasl openssl]; - }; - - mhash = { - configureFlags = ["--with-mhash"]; - buildInputs = [libmhash]; - }; - - curl = { - configureFlags = ["--with-curl=${curl}" "--with-curlwrappers"]; - buildInputs = [curl openssl]; - }; - - zlib = { - configureFlags = ["--with-zlib=${zlib}"]; - buildInputs = [zlib]; - }; - - libxml2 = { - configureFlags = [ - "--with-libxml-dir=${libxml2}" - #"--with-iconv-dir=${libiconv}" - ]; - buildInputs = [ libxml2 ]; - }; - - pcntl = { - configureFlags = [ "--enable-pcntl" ]; - }; - - readline = { - configureFlags = ["--with-readline=${readline}"]; - buildInputs = [ readline ]; - }; - - sqlite = { - configureFlags = ["--with-pdo-sqlite=${sqlite}"]; - buildInputs = [ sqlite ]; - }; - - postgresql = { - configureFlags = ["--with-pgsql=${postgresql}"]; - buildInputs = [ postgresql ]; - }; - - mysql = { - configureFlags = ["--with-mysql=${mysql}"]; - buildInputs = [ mysql ]; - }; - - mysqli = { - configureFlags = ["--with-mysqli=${mysql}/bin/mysql_config"]; - buildInputs = [ mysql]; - }; - - mysqli_embedded = { - configureFlags = ["--enable-embedded-mysqli"]; - depends = "mysqli"; - assertion = fixed.mysqliSupport; - }; - - pdo_mysql = { - configureFlags = ["--with-pdo-mysql=${mysql}"]; - buildInputs = [ mysql ]; - }; - - bcmath = { - configureFlags = ["--enable-bcmath"]; - }; - - gd = { - # FIXME: Our own gd package doesn't work, see https://bugs.php.net/bug.php?id=60108. - configureFlags = [ - "--with-gd" - "--with-freetype-dir=${freetype}" - "--with-png-dir=${libpng}" - "--with-jpeg-dir=${libjpeg}" - ]; - buildInputs = [ libpng libjpeg freetype ]; - }; - - soap = { - configureFlags = ["--enable-soap"]; - }; - - sockets = { - configureFlags = ["--enable-sockets"]; - }; - - openssl = { - configureFlags = ["--with-openssl=${openssl}"]; - buildInputs = ["openssl"]; - }; - - mbstring = { - configureFlags = ["--enable-mbstring"]; - }; - - gettext = { - configureFlags = ["--with-gettext=${gettext}"]; - buildInputs = [gettext]; - }; - - intl = { - configureFlags = ["--enable-intl"]; - buildInputs = [icu]; - }; - - exif = { - configureFlags = ["--enable-exif"]; - }; - - xsl = { - configureFlags = ["--with-xsl=${libxslt}"]; - buildInputs = [libxslt]; - }; - - mcrypt = { - configureFlags = ["--with-mcrypt=${libmcrypt}"]; - buildInputs = [libmcryptOverride]; - }; - - bz2 = { - configureFlags = ["--with-bz2=${bzip2}"]; - buildInputs = [bzip2]; - }; - - zip = { - configureFlags = ["--enable-zip"]; - }; - - ftp = { - configureFlags = ["--enable-ftp"]; - }; - - /* - php is build within this derivation in order to add the xdebug lines to the php.ini. - So both Apache and command line php both use xdebug without having to configure anything. - Xdebug could be put in its own derivation. - * / - meta = { - description = "debugging support for PHP"; - homepage = http://xdebug.org; - license = "based on the PHP license - as is"; - }; - */ - }; - - cfg = { - ldapSupport = config.php.ldap or true; - mhashSupport = config.php.mhash or true; - mysqlSupport = config.php.mysql or true; - mysqliSupport = config.php.mysqli or true; - pdo_mysqlSupport = config.php.pdo_mysql or true; - libxml2Support = config.php.libxml2 or true; - apxs2Support = config.php.apxs2 or true; - bcmathSupport = config.php.bcmath or true; - socketsSupport = config.php.sockets or true; - curlSupport = config.php.curl or true; - gettextSupport = config.php.gettext or true; - pcntlSupport = config.php.pcntl or true; - postgresqlSupport = config.php.postgresql or true; - readlineSupport = config.php.readline or true; - sqliteSupport = config.php.sqlite or true; - soapSupport = config.php.soap or true; - zlibSupport = config.php.zlib or true; - opensslSupport = config.php.openssl or true; - mbstringSupport = config.php.mbstring or true; - gdSupport = config.php.gd or true; - intlSupport = config.php.intl or true; - exifSupport = config.php.exif or true; - xslSupport = config.php.xsl or false; - mcryptSupport = config.php.mcrypt or false; - bz2Support = config.php.bz2 or false; - zipSupport = config.php.zip or true; - ftpSupport = config.php.ftp or true; - }; - - configurePhase = '' - # Don't record the configure flags since this causes unnecessary - # runtime dependencies. - for i in main/build-defs.h.in scripts/php-config.in; do - substituteInPlace $i \ - --replace '@CONFIGURE_COMMAND@' '(omitted)' \ - --replace '@CONFIGURE_OPTIONS@' "" \ - --replace '@PHP_LDFLAGS@' "" - done - - iniFile=$out/etc/php-recommended.ini - [[ -z "$libxml2" ]] || export PATH=$PATH:$libxml2/bin - ./configure --with-config-file-scan-dir=/etc --with-config-file-path=$out/etc --prefix=$out $configureFlags - ''; - - installPhase = '' - unset installPhase; installPhase; - cp php.ini-production $iniFile - ''; - - src = fetchurl { - urls = [ - "http://nl1.php.net/get/php-${version}.tar.bz2/from/this/mirror" - "http://se1.php.net/get/php-${version}.tar.bz2/from/this/mirror" - ]; - sha256 = "1k4iplqqcaqkmyq10h6a5qcpkfpkd05r2kclxw9n9qdrm47hfz5f"; - name = "php-${version}.tar.bz2"; - }; - - meta = { - description = "The PHP language runtime engine"; - homepage = http://www.php.net/; - license = "PHP-3"; - }; - - patches = [ ./fix-5.4.patch ]; - -}) diff --git a/pkgs/development/interpreters/php/default.nix b/pkgs/development/interpreters/php/default.nix new file mode 100644 index 0000000000000..3a6a5a0e5aaab --- /dev/null +++ b/pkgs/development/interpreters/php/default.nix @@ -0,0 +1,500 @@ +{ pkgs, stdenv, fetchurl, composableDerivation, autoconf, automake +, flex, bison, apacheHttpd, mysql, libxml2, readline +, zlib, curl, gd, postgresql, openssl, pkgconfig, sqlite, config, libiconv +, libjpeg, libpng, htmlTidy, libmcrypt, fcgi, callPackage, gettext +, freetype, writeText +, openldap, cyrus_sasl, libmhash +, systemd +, version ? "5.3.x" # latest stable +, icu +, libxslt +, bzip2 + +# options + + +, sapi ? "apxs2" # SAPI support: only one can be used at a time ? (PHP >= 5.3) + +# keep *Support args sorted +, bcmathSupport ? true +, curlSupport ? true +, fastcgiSupport ? false +, gdSupport ? true +, gettextSupport ? true +, ldapSupport ? true +, libxml2Support ? true +, mbstringSupport ? true +, mcryptSupport ? true +, mysqlSupport ? true +, mysqliSupport ? true +, opensslSupport ? true +, pcntlSupport ? true +, pdo_mysqlSupport ? true +, postgresqlSupport ? true +, readlineSupport ? true +, soapSupport ? true +, socketsSupport ? true +, sqliteSupport ? true +, tidySupport ? true +, ttfSupport ? true +, zipSupport ? true +, zlibSupport ? true + +, gdShared ? true + +, fpmSystemdSocketActivationPatchSupport ? true + +, idByConfig ? true # if true the php.id value will only depend on php configuration, not on the store path, eg dependencies + +, lessThan53 ? builtins.lessThan (builtins.compareVersions version "5.3") 0 # you're not supposed to pass this +, lessThan54 ? builtins.lessThan (builtins.compareVersions version "5.4") 0 +, lessThan55 ? builtins.lessThan (builtins.compareVersions version "5.5") 0 + +, sendmail ? "/var/setuid-wrappers/sendmail" +}: + +/* version specific notes: + 5.2: no longer maintained - use at your own risk. php-fpm patch requires an + /etc/php-fpm-5.2.conf file. fpm support is experimental - also options + may no longer build + + Yes - we should discussing removing this version- however you never know when + you need it - it still works - and there are customer still running old + code .. + + 5.3, 5.4: maintained officially. Everything which does not work is a bug + + Having all versions in one file can be considered "complicated" - but I feel + more code is shared - so I think its the simplest way - unless configuration + changes dramatically + + The php derivation also has special names: + + apc : PHP cache, might be included in PHP 6 eventually, so you might prefer this over xcache + xcache : another cache implementation + xdebug : module required to debug PHP - seems to build for all PHP versions + system_fpm_config : provides nixos config values providing the same "API" for PHP 5.2 and 5.3 + See nixos module for details + + id : something uniq identifying PHP configure options. Its + used by the nixos module to find out which pools may + be controlled by the same daemon. Eg to reduce security risks you + can have special extensions enabled for some projects only. +*/ + +let + + true_version = if version == "5.3.x" then "5.3.28" + else if version == "5.4.x" then "5.4.23" + else if version == "5.5.x" then "5.5.7" + else version; + + libxml2 = if lessThan53 then pkgs.libxml2.override { version = "2.7.8"; } else pkgs.libxml2; + + # used to calculate php id based on features + options = [ /* sapi */ + # keep sorted + "bcmathSupport" + "curlSupport" + "fastcgiSupport" + "fpmSystemdSocketActivationPatchSupport" + "gdSupport" + "gettextSupport" + "ldapSupport" + "libxml2Support" + "mbstringSupport" + "mcryptSupport" + "mysqlSupport" + "mysqliSupport" + "opensslSupport" + "pdo_mysqlSupport" + "postgresqlSupport" + "pcntlSupport" + "readlineSupport" + "soapSupport" + "socketsSupport" + "sqliteSupport" + "tidySupport" + "ttfSupport" + "zipSupport" + "zlibSupport" + ]; + + # note: this derivation contains a small hack: It contains several PHP + # versions + # If the differences get too large this shoud be split into several files + # At the moment this works fine for me. + # known differences: + # -ini location + # PHP 5.3 does no longer support fastcgi. + # fpm seems to be the replacement. + # There exist patches for 5.2 + # PHP > 5.3 can only build one SAPI module + + inherit (composableDerivation) edf wwf; + + inherit (stdenv) lib; + + php = composableDerivation.composableDerivation { + inherit (stdenv) mkDerivation; + } (fixed: /* let inherit (fixed.fixed) version; in*/ { + # Yes, this isn't properly indented. + + version = true_version; + + name = "php_configurable-${true_version}"; + + buildInputs = [/*flex bison*/ pkgconfig]; + + enableParallelBuilding = ! lessThan53; # php 5.2 fails with job server token error (make) + + flags = { + + mergeAttrBy = { + preConfigure = a: b: "${a}\n${b}"; + }; + # much left to do here... + + # SAPI modules: + + apxs2 = { + configureFlags = ["--with-apxs2=${apacheHttpd}/bin/apxs"]; + buildInputs = [apacheHttpd]; + }; + + + fpmSystemdSocketActivationPatch = lib.optionalAttrs (fixed.fixed.cfg.fpmSupport && !lessThan53) { + preConfigure = '' + export NIX_LDFLAGS="$NIX_LDFLAGS `pkg-config --libs libsystemd-daemon`" + ''; + buildInputs = [systemd]; + patches = [ + # wiki.php.net/rfc/socketactivation (merged both files) + ./systemd-socket-activation.patch + ]; + + }; + + fpm = { + configureFlags = ["--enable-fpm"]; + } // (lib.optionalAttrs (true_version == "5.2.17") { + configureFlags = [ + "--enable-fpm" + "--enable-fastcgi" + "--with-fpm-log=/var/log/php-fpm-5.2" + "--with-fpm-pid=/var/run/php-fpm-5.2.pid" + # "--with-xml-config=/etc/php-fpm-5.2.conf" + ]; + + # experimental + patches = [(fetchurl { + url = http://php-fpm.org/downloads/php-5.2.17-fpm-0.5.14.diff.gz; + sha256 = "1v3fwiifx89y5lnj0kv4sb9yj90b4k27dfd2z3a5nw1qh5c44d2g"; + })]; + + postInstall = '' + mv $out/etc/php-fpm.conf{,.example} + ln -s /etc/php-fpm-5.2.conf $out/etc/php-fpm.conf + ''; + }) + ; + + # Extensions + + ttf = { + configureFlags = ["--enable-gd-native-ttf" "--with-ttf" "--with-freetype-dir=${freetype}"]; + buildInputs = [freetype]; + }; + + curl = { + configureFlags = ["--with-curl=${curl}" "--with-curlwrappers"]; + buildInputs = [curl openssl]; + }; + + ldap = { + configureFlags = ["--with-ldap=${openldap}" "--with-ldap-sasl=${cyrus_sasl}"]; + buildInputs = [openldap cyrus_sasl]; + }; + + mhash = { + # obsoleted by Hash, see http://php.net/manual/de/book.mhash.php ? + configureFlags = ["--with-mhash"]; + buildInputs = [libmhash]; + }; + + zlib = { + configureFlags = ["--with-zlib=${zlib}"]; + buildInputs = [zlib]; + }; + + libxml2 = { + configureFlags = [ + "--with-libxml-dir=${libxml2}" + "--with-iconv-dir=${libiconv}" + ]; + buildInputs = [ libxml2 ]; + }; + + pcntl = { + configureFlags = [ "--enable-pcntl" ]; + }; + + readline = { + configureFlags = ["--with-readline=${readline}"]; + buildInputs = [ readline ]; + }; + + sqlite = { + configureFlags = ["--with-pdo-sqlite=${sqlite}"]; + buildInputs = [ sqlite ]; + }; + + postgresql = { + configureFlags = ["--with-pgsql=${postgresql}"]; + buildInputs = [ postgresql ]; + }; + + mysql = { + configureFlags = ["--with-mysql=${mysql}"]; + buildInputs = [ mysql ]; + }; + + mysqli = { + configureFlags = ["--with-mysqli=${mysql}/bin/mysql_config"]; + buildInputs = [ mysql]; + }; + + mysqli_embedded = { + configureFlags = ["--enable-embedded-mysqli"]; + depends = "mysqli"; + assertion = fixed.mysqliSupport; + }; + + pdo_mysql = { + configureFlags = ["--with-pdo-mysql=${mysql}"]; + buildInputs = [ mysql ]; + }; + + bcmath = { + configureFlags = ["--enable-bcmath"]; + }; + + gd = + let graphicLibraries = "--with-freetype-dir=${freetype} --with-png-dir=${libpng} --with-jpeg-dir=${libjpeg}"; in + { + configureFlags = + if gdShared then + # ok: ["--with-gd=${gd}"]; + # does this work with 5.3? + ["--with-gd=shared " graphicLibraries] + else ["--with-gd" graphicLibraries]; + buildInputs = [gd libpng libjpeg ]; + }; + + soap = { + configureFlags = ["--enable-soap"]; + }; + + sockets = { + configureFlags = ["--enable-sockets"]; + }; + + openssl = { + configureFlags = ["--with-openssl=${openssl}"]; + buildInputs = ["openssl"]; + }; + + mbstring = { + configureFlags = ["--enable-mbstring"]; + }; + + gettext = { + configureFlags = ["--with-gettext=${gettext}"]; + preConfigure = '' + sed -i 's@for i in \$PHP_GETTEXT /usr/local /usr; do@for i in '"$nativeBuildInputs"'; do@' configure + ''; + buildInputs = [gettext stdenv.glibc /* libintl.h */]; + }; + + fastcgi = { + configureFlags = ["--enable-fastcgi"]; + assertion = lessThan53; + }; + + tidy = { + configureFlags = ["--with-tidy=${htmlTidy}"]; + }; + + intl = { + configureFlags = ["--enable-intl"]; + buildInputs = [icu]; + }; + + + exif = { + configureFlags = ["--enable-exif"]; + }; + + + xsl = { + configureFlags = ["--with-xsl=${libxslt}"]; + buildInputs = [libxslt]; + }; + + mcrypt = { + configureFlags = ["--with-mcrypt=${libmcrypt}"]; + buildInputs = [ libmcrypt ]; + }; + + + bz2 = { + configureFlags = ["--with-bz2=${bzip2}"]; + buildInputs = [bzip2]; + }; + + zip = { + configureFlags = ["--enable-zip"]; + }; + /* + php is build within this derivation in order to add the xdebug lines to the php.ini. + So both Apache and command line php both use xdebug without having to configure anything. + Xdebug could be put in its own derivation. + * / + meta = { + description = "debugging support for PHP"; + homepage = http://xdebug.org; + license = "based on the PHP license - as is"; + }; + */ + }; + + cfg = { + fpmSupport = sapi == "fpm"; + apxs2Support = sapi == "apxs2"; + + inherit + bcmathSupport + curlSupport + fastcgiSupport + gdSupport + gettextSupport + libxml2Support + mbstringSupport + mcryptSupport + mysqliSupport + mysqlSupport + opensslSupport + pdo_mysqlSupport + postgresqlSupport + readlineSupport + soapSupport + socketsSupport + sqliteSupport + tidySupport + ttfSupport + zipSupport + zlibSupport + fpmSystemdSocketActivationPatchSupport; + }; + + configurePhase = '' + runHook "preConfigure" + # Don't record the configure flags since this causes unnecessary + # runtime dependencies. + for i in main/build-defs.h.in scripts/php-config.in; do + substituteInPlace $i \ + --replace '@CONFIGURE_COMMAND@' '(omitted)' \ + --replace '@CONFIGURE_OPTIONS@' "" \ + --replace '@PHP_LDFLAGS@' "" + done + + iniFile=$out/etc/php-recommended.ini + [[ -z "$libxml2" ]] || export PATH=$PATH:$libxml2/bin + ./configure --with-config-file-scan-dir=/etc --with-config-file-path=$out/etc --prefix=$out $configureFlags + ''; + + preBuild = '' + sed -i 's@#define PHP_PROG_SENDMAIL ""@#define PHP_PROG_SENDMAIL "${sendmail}"@' main/build-defs.h + ''; + + installPhase = '' + unset installPhase; installPhase; + cp php.ini-${ if lessThan53 + then "recommended" /* < PHP 5.3 */ + else "production" /* >= PHP 5.3 */ + } $iniFile + ''; + + src = fetchurl { + url = "http://de2.php.net/distributions/php-${true_version}.tar.bz2"; + md5 = lib.maybeAttr true_version (throw "unkown php version ${true_version}") { + # "5.5.0RC1" = "0b8eaea490888bc7881f60f54798f1cb"; + # "5.5.5" = "186c330c272d6322d254db9b2d18482a"; + "5.5.7" = "19d1ca0a58e192bcc133f700c7e78037"; + + # does not built, due to patch? + # "5.4.5" = "ffcc7f4dcf2b79d667fe0c110e6cb724"; + # "5.4.7" = "9cd421f1cc8fa8e7f215e44a1b06199f"; + # "5.4.14" = "cfdc044be2c582991a1fe0967898fa38"; + # "5.4.15" = "145ea5e845e910443ff1eddb3dbcf56a"; + # "5.4.19" = "f06f99b9872b503758adab5ba7a7e755"; + # "5.4.21" = "3dcf021e89b039409d0b1c346b936b5f"; + # "5.4.22" = "0a7400d1d7f1f55b2b36285bf1a00762"; + "5.4.23" = "023857598b92ea5c78137543817f4bc5"; + + # those older versions are likely to be buggy - there should be no reason to compile them + # "5.3.3" = "21ceeeb232813c10283a5ca1b4c87b48"; + # "5.3.6" = "2286f5a82a6e8397955a0025c1c2ad98"; + # "5.3.14" = "7caac4f71e2f21426c11ac153e538392"; + # "5.3.15" = "5cfcfd0fa4c4da7576f397073e7993cc"; + # "5.3.17" = "29ee79c941ee85d6c1555c176f12f7ef"; + # "5.3.18" = "52539c19d0f261560af3c030143dfa8f"; + # "5.3.24" = "9820604df98c648297dcd31ffb8214e8"; + # "5.3.25" = "347625ed7fbf2fe1f1c70b0f879fee2a"; + # "5.3.27" = "25ae23a5b9615fe8d33de5b63e1bb788"; + "5.3.28" = "56ff88934e068d142d6c0deefd1f396b"; + + # 5.2 is no longer supported. However PHP 5.2 -> 5.3 has had many + # incompatibilities which is why it may be useful to continue supporting it + # You should use 5.3.x if possible + "5.2.17" = "b27947f3045220faf16e4d9158cbfe13"; + }; + name = "php-${true_version}.tar.bz2"; + }; + + meta = { + description = "The PHP language runtime engine"; + homepage = http://www.php.net/; + license = "PHP-3"; + }; + + patches = + # TODO patch still required? I use php-fpm only + if lessThan54 + then [./fix.patch] + else [./fix-5.4.patch]; + + }); + + php_with_id = php // { + id = + if idByConfig && builtins ? hashString + then # turn options into something hashable: + let opts_s = lib.concatMapStrings (x: if x then "1" else "") (lib.attrVals options php); + # you're never going to use that many php's at the same time, thus use a short hash + in "${php.version}-${builtins.substring 0 5 (builtins.hashString "sha256" opts_s)}" + else # the hash of the store path depending on php version and all configuration details + builtins.baseNameOf (builtins.unsafeDiscardStringContext php); + }; + + in php_with_id // { + xdebug = callPackage ../../interpreters/php-xdebug { php = php_with_id; }; + xcache = callPackage ../../libraries/php-xcache { php = php_with_id; }; + apc = callPackage ../../libraries/php-apc { php = php_with_id; }; + system_fpm_config = + if (sapi == "fpm") then + if lessThan53 + then config: pool: (import ./php-5.2-fpm-system-config.nix) { php = php_with_id; inherit pkgs lib writeText config pool;} + else config: pool: (import ./php-5.3-fpm-system-config.nix) { php = php_with_id; inherit pkgs lib writeText config pool;} + else throw "php built without fpm support. use php.override { sapi = \"fpm\"; }"; + } diff --git a/pkgs/development/interpreters/php/fix-5.4.patch b/pkgs/development/interpreters/php/fix-5.4.patch index 51d98549eee2a..7fcb695f8d3de 100644 --- a/pkgs/development/interpreters/php/fix-5.4.patch +++ b/pkgs/development/interpreters/php/fix-5.4.patch @@ -66,3 +66,4 @@ diff -ru php-5.4.14/configure php-5.4.14-new/configure if test -z "$GETTEXT_DIR"; then { { $as_echo "$as_me:$LINENO: error: Cannot locate header file libintl.h" >&5 + diff --git a/pkgs/development/interpreters/php/php-5.2-fpm-system-config.nix b/pkgs/development/interpreters/php/php-5.2-fpm-system-config.nix new file mode 100644 index 0000000000000..6051cd826af5b --- /dev/null +++ b/pkgs/development/interpreters/php/php-5.2-fpm-system-config.nix @@ -0,0 +1,144 @@ +{pkgs, php, lib, writeText, config, pool}: + +# yes - PHP 5.2 should no longer be used. I know +# note that only one setup (with many pools) can be used +# because only one configuration file is supported. + +let + + inherit (lib) concatStringsSep maybeAttr; + inherit (builtins) getAttr isString isInt isAttrs attrNames; + + # id: a uniq identifier based on php version and fpm-daemon config (php ini) + id = config.id; + name = "php-fpm-${id}"; + +defaultConfig = { + # jobName = .. + pid = "/var/run/${name}.pid"; + error_log = "/var/log/${name}.log"; + log_level = "notice"; + emergency_restart_threshold = "10"; + emergency_restart_interval = "1m"; + process_control_timeout = "5s"; + daemonize = "no"; + listen = { # xml: listen_options + backlog = "-1"; + owner = "nobody"; + group = "nogroup"; + mode = "0777"; + }; + commonPoolConfig = { + }; + }; + + defaultPoolConfig = { + request_terminate_timeout = "305s"; + request_slowlog_timeout = "30s"; + rlimit_files = "1024"; + rlimit_core = "0"; + chroot = ""; + chdir = ""; + catch_workers_output = "yes"; + max_requests = "500"; + allowed_clients = "127.0.0.1"; + environment = { + }; + pm = { + style = "static"; + max_children = "5"; + apache_like = { + StartServers = 20; + MinSpareServers = 5; + MaxSpareServers = 35; + }; + }; + }; + + createPHPFpmConfig52 = config: pool: + let + options = a: names: + concatStringsSep "\n" (map (n: xmlOption n (getAttr n a)) names); + + xmlOption = name: value: + if isString value + then "${value}" + else if isInt value + then "${toString value}" + else + '' + + ${options value (attrNames value)} + + ''; + poolToConfig = poolC: '' +
+ ${options poolC [ "name" "listen_address" ] } + + ${options poolC.listen (attrNames poolC.listen) } + + ${options + poolC [ + "user" "group" + "request_terminate_timeout" + "request_slowlog_timeout" + "slowlog" + "rlimit_files" + "rlimit_core" + "chroot" + "chdir" + "catch_workers_output" + "max_requests" + "allowed_clients" + "environment" + "pm" + ]} +
+ ''; + in + # main config which pools + writeText "php-fpm" '' + + +
+ ${xmlOption "pid_file" config.pid} + ${options config [ + "error_log" "log_level" + "emergency_restart_threshold" "emergency_restart_interval" + "process_control_timeout" "daemonize" + ]}} +
+ + ${lib.concatStringsSep "\n" (map (poolC: poolToConfig (defaultPoolConfig // maybeAttr "commonPoolConfig" {} config // poolC)) pool)} + +
+ ''; + + cfg = defaultConfig // config; + cfgFile = createPHPFpmConfig52 (cfg) (pool); +in { + # must be in /etc .., there is no command line flag for PHP 5.2 + environment.etc."php-fpm-5.2.conf".source = cfgFile; + + systemd.services = + let name = "php-fpm-${id}"; + in builtins.listToAttrs [{ + inherit name; + value = { + description = "The PHP 5.2 FastCGI Process Manager ${id}"; + wantedBy = [ "multi-user.target" ]; + serviceConfig = { + Type = "simple"; + PIDFile = cfg.pid; + ExecStart = "${php}/sbin/php-fpm start"; + ExecReload= "${pkgs.coreutils}/bin/kill -USR2 $MAINPID"; + ExecStop = "${pkgs.coreutils}/bin/kill -9 $MAINPID"; + PrivateTmp=true; + }; + environment = + lib.optionalAttrs (config.phpIni != null) { + PHPRC = config.phpIni; + }; + }; + }]; +} diff --git a/pkgs/development/interpreters/php/php-5.3-fpm-system-config.nix b/pkgs/development/interpreters/php/php-5.3-fpm-system-config.nix new file mode 100644 index 0000000000000..13160a9902075 --- /dev/null +++ b/pkgs/development/interpreters/php/php-5.3-fpm-system-config.nix @@ -0,0 +1,142 @@ +{ php, pkgs, lib, writeText +, config # shared config +, pool # configuration for each pool +}: + +let + + inherit (lib) concatStringsSep maybeAttr; + inherit (builtins) getAttr isInt isString attrNames toString; + + # id: a uniq identifier based on php version and fpm-daemon config (php ini) + id = config.id; + name = "php-fpm-${id}"; + + defaultConfig = { + serviceName = "php-fpm-${id}"; + pid = "/var/run/${name}.pid"; + error_log = "/var/log/${name}.log"; + log_level = "notice"; + emergency_restart_threshold = "10"; + emergency_restart_interval = "1m"; + process_control_timeout = "5s"; + daemonize = "no"; + commonPoolConfig = { + }; + }; + + cfg = defaultConfig // config; + + defaultPoolConfig = { + request_terminate_timeout = "305s"; + # slowlog = .. + request_slowlog_timeout = "30s"; + rlimit_files = "1024"; + rlimit_core = "0"; + chroot = ""; + chdir = ""; + catch_workers_output = "yes"; + allowed_clients = "127.0.0.1"; + # can't use "listen" when using listen attrs + # listen_address = .. # listen setting + # listen = { + # backlog = "-1"; + # owner = "nobody"; + # group = "nogroup"; + # mode = "0777"; + # }; + + environment = { + }; + pm_type = "dynamic"; # pm setting + pm = { + max_children = "5"; + max_requests = "500"; + start_servers = 1; + min_spare_servers = 1; + max_spare_servers = 4; + }; + }; + + createConfig = config: pool: + # listen = 127.0.0.1:${builtins.toString (builtins.add start_port_php_fpm kunde.nr)} + let + options = prefix: a: names: + concatStringsSep "\n" (map (n: option prefix n (getAttr n a)) names); + + option = prefix: name: value: + if isString value + then "${prefix}${name} = ${value}\n" + else if isInt value + then "${prefix}${name} = ${toString value}\n" + else "${options "${name}." value (attrNames value)}\n"; + + poolToConfig = poolC: '' + [${poolC.name}] + ${option "" "listen" (poolC.listen_address)} + ${option "" "pm" (poolC.pm_type)} + ${options + "" + poolC + [ + # attrs + "listen" + "pm" + "environment" + # simple values: + "user" + "group" + "request_terminate_timeout" + "slowlog" + "request_slowlog_timeout" + ] + } + ${maybeAttr "extraLines" "" poolC} + ''; + in + # main config which pools + writeText "php-fpm" '' + [global] + ${options "" config [ + "pid" "error_log" "log_level" "emergency_restart_threshold" + "emergency_restart_interval" "process_control_timeout" "daemonize" + ]} + + ${lib.concatStringsSep "\n" (map (poolC: poolToConfig (defaultPoolConfig // maybeAttr "commonPoolConfig" {} config // poolC)) pool)} + ''; + + configFile = createConfig (cfg) (pool); + +in { + systemd.sockets = + builtins.listToAttrs [{ + inherit name; + + value = { + description="The PHP FastCGI Process Manager ${id} socket"; + wantedBy=["multi-user.target"]; + socketConfig={ + ListenStream = lib.catAttrs "listen_address" pool; + }; + }; + }]; + + systemd.services = builtins.listToAttrs [{ + inherit name; + value = { + description = "The PHP FastCGI Process Manager ${id} service"; + environment = lib.optionalAttrs (config.phpIni != null) { + PHPRC="${config.phpIni}"; + }; + serviceConfig = { + Type = "simple"; + PIDFile=cfg.pid; + ExecStart="${php}/sbin/php-fpm -y ${configFile}"; + # TODO: test this: + ExecReload="${pkgs.coreutils}/bin/kill -USR2 $MAINPID"; + ExecStop="${pkgs.coreutils}/bin/kill -9 $MAINPID"; + PrivateTmp=true; + }; + }; + }]; +} diff --git a/pkgs/development/interpreters/php/systemd-socket-activation.patch b/pkgs/development/interpreters/php/systemd-socket-activation.patch new file mode 100644 index 0000000000000..a2ad93fbe8c86 --- /dev/null +++ b/pkgs/development/interpreters/php/systemd-socket-activation.patch @@ -0,0 +1,163 @@ +diff --git a/sapi/fpm/config.m4 b/sapi/fpm/config.m4 +index ad46717..51d7987 100644 +--- a/sapi/fpm/config.m4 ++++ b/sapi/fpm/config.m4 +@@ -101,6 +101,22 @@ AC_DEFUN([AC_FPM_CLOCK], + fi + ]) + ++AC_DEFUN([AC_FPM_SYSTEMD], ++[ ++ AC_MSG_CHECKING([for systemd]) ++ ++ SAVED_LIBS="$LIBS" ++ LIBS="$LIBS -lsystemd-journal -lsystemd-daemon" ++ ++ AC_TRY_LINK([ #include ], [sd_journal_send("Testing linking to sd-journal.h.");], [ ++ AC_DEFINE([HAVE_SYSTEMD], 1, [do we have systemd?]) ++ AC_MSG_RESULT([yes]) ++ ], [ ++ LIBS="$SAVED_LIBS" ++ AC_MSG_RESULT([no]) ++ ]) ++]) ++ + AC_DEFUN([AC_FPM_TRACE], + [ + have_ptrace=no +@@ -544,6 +560,7 @@ if test "$PHP_FPM" != "no"; then + AC_FPM_STDLIBS + AC_FPM_PRCTL + AC_FPM_CLOCK ++ AC_FPM_SYSTEMD + AC_FPM_TRACE + AC_FPM_BUILTIN_ATOMIC + AC_FPM_LQ + + +diff --git a/sapi/fpm/fpm/fpm_sockets.c b/sapi/fpm/fpm/fpm_sockets.c +index f56b9cf..5027ace 100644 +--- a/sapi/fpm/fpm/fpm_sockets.c ++++ b/sapi/fpm/fpm/fpm_sockets.c +@@ -19,6 +19,8 @@ + #include + #include + #include ++#include ++#include + + #include "zlog.h" + #include "fpm_arrays.h" +@@ -34,6 +36,7 @@ struct listening_socket_s { + int refcount; + int sock; + int type; ++ int preserve; + char *key; + }; + +@@ -73,7 +76,7 @@ static void fpm_sockets_cleanup(int which, void *arg) /* {{{ */ + + for (i = 0; i < sockets_list.used; i++, ls++) { + if (which != FPM_CLEANUP_PARENT_EXEC) { +- close(ls->sock); ++ if (ls->preserve != 1) close(ls->sock); /* avoid close if systemd-provided socket */ + } else { /* on PARENT EXEC we want socket fds to be inherited through environment variable */ + char fd[32]; + sprintf(fd, "%d", ls->sock); +@@ -83,7 +86,7 @@ static void fpm_sockets_cleanup(int which, void *arg) /* {{{ */ + + if (which == FPM_CLEANUP_PARENT_EXIT_MAIN) { + if (ls->type == FPM_AF_UNIX) { +- unlink(ls->key); ++ if (ls->preserve != 1) unlink(ls->key); /* avoid unlink if systemd-provided socket */ + } + } + free(ls->key); +@@ -98,7 +101,7 @@ static void fpm_sockets_cleanup(int which, void *arg) /* {{{ */ + } + /* }}} */ + +-static int fpm_sockets_hash_op(int sock, struct sockaddr *sa, char *key, int type, int op) /* {{{ */ ++static int fpm_sockets_hash_op(int sock, struct sockaddr *sa, char *key, int type, int op, int preserve) /* {{{ */ + { + if (key == NULL) { + switch (type) { +@@ -155,6 +158,7 @@ static int fpm_sockets_hash_op(int sock, struct sockaddr *sa, char *key, int typ + ls->type = type; + ls->sock = sock; + ls->key = strdup(key); ++ ls->preserve = preserve; + + return 0; + } +@@ -221,13 +225,13 @@ static int fpm_sockets_get_listening_socket(struct fpm_worker_pool_s *wp, struct + { + int sock; + +- sock = fpm_sockets_hash_op(0, sa, 0, wp->listen_address_domain, FPM_GET_USE_SOCKET); ++ sock = fpm_sockets_hash_op(0, sa, 0, wp->listen_address_domain, FPM_GET_USE_SOCKET, /* (systemd) preserve= */ 0); + if (sock >= 0) { + return sock; + } + + sock = fpm_sockets_new_listening_socket(wp, sa, socklen); +- fpm_sockets_hash_op(sock, sa, 0, wp->listen_address_domain, FPM_STORE_USE_SOCKET); ++ fpm_sockets_hash_op(sock, sa, 0, wp->listen_address_domain, FPM_STORE_USE_SOCKET, /* (systemd) preserve= */ 0); + + return sock; + } +@@ -301,7 +305,10 @@ static int fpm_socket_af_unix_listening_socket(struct fpm_worker_pool_s *wp) /* + + int fpm_sockets_init_main() /* {{{ */ + { ++ int sd_sock_count; + unsigned i, lq_len; ++ struct sockaddr_un address; ++ socklen_t address_len; + struct fpm_worker_pool_s *wp; + char *inherited = getenv("FPM_SOCKETS"); + struct listening_socket_s *ls; +@@ -310,12 +317,32 @@ int fpm_sockets_init_main() /* {{{ */ + return -1; + } + ++ /* Is systemd providing any sockets? */ ++ sd_sock_count = sd_listen_fds(0); ++ if (sd_sock_count < 0) sd_sock_count = 0; /* can return -errno, so set to zero */ ++ ++ /* For each systemd-provided socket, get type and address and store it */ ++ for (i = SD_LISTEN_FDS_START; i < SD_LISTEN_FDS_START + sd_sock_count; i++) { ++ int type, fd_no; ++ ++ fd_no = i; ++ address_len = sizeof(struct sockaddr_un); ++ if (getsockname(fd_no, (struct sockaddr *)&address, &address_len)) { ++ zlog(ZLOG_ERROR, "error getting sockname from systemd-provided socket: fd=%d", fd_no); ++ continue; ++ } ++ ++ type = fpm_sockets_domain_from_address(((struct sockaddr *)&address)->sa_data); ++ zlog(ZLOG_NOTICE, "using systemd-provided socket fd=%d, \"%s\"", fd_no, ((struct sockaddr *)&address)->sa_data); ++ fpm_sockets_hash_op(fd_no, (struct sockaddr *)&address, 0, type, FPM_STORE_SOCKET, /* (systemd) preserve= */ 1); ++ } ++ + /* import inherited sockets */ + while (inherited && *inherited) { + char *comma = strchr(inherited, ','); + int type, fd_no; + char *eq; +- ++ + if (comma) { + *comma = '\0'; + } +@@ -326,7 +353,7 @@ int fpm_sockets_init_main() /* {{{ */ + fd_no = atoi(eq + 1); + type = fpm_sockets_domain_from_address(inherited); + zlog(ZLOG_NOTICE, "using inherited socket fd=%d, \"%s\"", fd_no, inherited); +- fpm_sockets_hash_op(fd_no, 0, inherited, type, FPM_STORE_SOCKET); ++ fpm_sockets_hash_op(fd_no, 0, inherited, type, FPM_STORE_SOCKET, /* (systemd) preserve= */ 0); + } + + if (comma) { diff --git a/pkgs/development/libraries/libmcrypt/default.nix b/pkgs/development/libraries/libmcrypt/default.nix index afa661617318d..abd5efdbb22b5 100644 --- a/pkgs/development/libraries/libmcrypt/default.nix +++ b/pkgs/development/libraries/libmcrypt/default.nix @@ -18,6 +18,8 @@ stdenv.mkDerivation rec { meta = { description = "Replacement for the old crypt() package and crypt(1) command, with extensions"; homepage = http://mcrypt.sourceforge.net; - license = "GPL"; + license = "GPLv2.1"; + maintainers = [stdenv.lib.maintainers.marcweber]; + platforms = stdenv.lib.platforms.linux; }; } diff --git a/pkgs/development/libraries/libxml2/default.nix b/pkgs/development/libraries/libxml2/default.nix index b86df4969c298..ba37fa88b8d6c 100644 --- a/pkgs/development/libraries/libxml2/default.nix +++ b/pkgs/development/libraries/libxml2/default.nix @@ -1,16 +1,33 @@ -{ stdenv, fetchurl, zlib, xz, python ? null, pythonSupport ? true }: +{ stdenv, fetchurl, zlib, xz, python ? null, pythonSupport ? true +, version ? "2.9.x" +}: assert pythonSupport -> python != null; -#TODO: share most stuff between python and non-python builds, perhaps via multiple-output +stdenv.mkDerivation (stdenv.lib.mergeAttrsByVersion "libxml2" version { + "2.9.x" = rec { + name = "libxml2-2.9.1"; + + src = fetchurl { + url = "ftp://xmlsoft.org/libxml2/${name}.tar.gz"; + sha256 = "1nqgd1qqmg0cg09mch78m2ac9klj9n87blilx4kymi7jcv5n8g7x"; + }; + }; -stdenv.mkDerivation (rec { - name = "libxml2-2.9.1"; + # required to build PHP 5.2 (testing only) + "2.7.8" = rec { + name = "libxml2-2.7.8"; - src = fetchurl { - url = "ftp://xmlsoft.org/libxml2/${name}.tar.gz"; - sha256 = "1nqgd1qqmg0cg09mch78m2ac9klj9n87blilx4kymi7jcv5n8g7x"; + src = fetchurl { + url = ftp://xmlsoft.org/libxml2/libxml2-sources-2.7.8.tar.gz; + sha256 = "6a33c3a2d18b902cd049e0faa25dd39f9b554a5b09a3bb56ee07dd7938b11c54"; + }; }; +} +{ + +#TODO: share most stuff between python and non-python builds, perhaps via multiple-output + buildInputs = stdenv.lib.optional pythonSupport python # Libxml2 has an optional dependency on liblzma. However, on impure @@ -44,4 +61,3 @@ stdenv.mkDerivation (rec { } // stdenv.lib.optionalAttrs (!pythonSupport && stdenv.isFreeBSD) { configureFlags = "--with-python=no"; # otherwise build impurity bites us }) - diff --git a/pkgs/development/libraries/php-apc/default.nix b/pkgs/development/libraries/php-apc/default.nix index 7cfdc9ce30d5c..a598d2ab37646 100644 --- a/pkgs/development/libraries/php-apc/default.nix +++ b/pkgs/development/libraries/php-apc/default.nix @@ -1,12 +1,23 @@ -{stdenv, fetchurl, php, autoconf, automake, libtool }: +{stdenv, fetchurl, php, autoconf, automake, libtool +, version ? "3.1.9" }: -stdenv.mkDerivation rec { - name = "php-apc-3.1.7"; - - src = fetchurl { - url = http://pecl.php.net/get/APC-3.1.7.tgz; - sha256 = "0xlvhw5398sl5zzkjm4rkk1m3fcra30zkq0k4i6fij0ylpd6nlls"; +stdenv.mkDerivation (stdenv.lib.mergeAttrsByVersion "php-apc" version { + "3.1.9" = { + name = "php-apc-3.1.9"; + src = fetchurl { + url = http://pecl.php.net/get/APC-3.1.9.tgz; + sha256 = "0wfnhaj7qzfx1c0svv7b73k4py8ccvb3v6qw3r96h6nsv4cg3pj7"; + }; }; + "3.1.7" = { + name = "php-apc-3.1.7"; + src = fetchurl { + url = http://pecl.php.net/get/APC-3.1.7.tgz; + sha256 = "0xlvhw5398sl5zzkjm4rkk1m3fcra30zkq0k4i6fij0ylpd6nlls"; + }; + }; + } + ( rec { preConfigure = '' phpize @@ -23,4 +34,4 @@ stdenv.mkDerivation rec { homepage = "http://pecl.php.net/package/APC"; license = "PHP+"; }; -} +})) diff --git "a/pkgs/development/libraries/php-opcache/\\" "b/pkgs/development/libraries/php-opcache/\\" new file mode 100644 index 0000000000000..a3a9b32ba7cba --- /dev/null +++ "b/pkgs/development/libraries/php-opcache/\\" @@ -0,0 +1,28 @@ +{stdenv, fetchurl, php, autoconf, automake, libtool, m4 }: + +stdenv.mkDerivation rec { + name = "php-opcache-7.0.2"; + + src = fetchurl { + url = http://pecl.php.net/get/zendopcache-7.0.2.tgz; + md5 = "45086010bc4f82f506c08be1c556941b"; + }; + + preConfigure = '' + phpize + + sed -i 's,^EXTENSION_DIR.*,'EXTENSION_DIR=$out/lib/php/extensions, configure + ''; + + configureFlags = [ + "--with-php-config=${pkgs.php}/bin/php-config" + ]; + + buildInputs = [ php autoconf automake libtool m4 ]; + + meta = { + description = "The Zend OPcache provides faster PHP execution through opcode caching and optimization."; + homepage = http://pecl.php.net/package/ZendOpcache + license = "PHP"; + }; +} diff --git a/pkgs/development/libraries/php-opcache/default.nix b/pkgs/development/libraries/php-opcache/default.nix new file mode 100644 index 0000000000000..a04191d16effc --- /dev/null +++ b/pkgs/development/libraries/php-opcache/default.nix @@ -0,0 +1,29 @@ +{stdenv, pkgs, fetchgit, php5_4, autoconf, automake, libtool, m4 }: + +stdenv.mkDerivation rec { + name = "php-opcache-7.0.2"; + + src = fetchgit { + url = https://github.com/zendtech/ZendOptimizerPlus.git; + rev = "20971cd33d723f2be1b9e2bd5bf0c5ad07c4af81"; + sha256 = "0lpfa4kdpz4f528jwydif6gn6kinv457dmkrjmp1szdsvpf3dlfy"; + }; + + preConfigure = '' + phpize + + sed -i 's,^EXTENSION_DIR.*,'EXTENSION_DIR=$out/lib/php/extensions, configure + ''; + + configureFlags = [ + "--with-php-config=${pkgs.php5_4}/bin/php-config" + ]; + + buildInputs = [ php5_4 autoconf automake libtool m4 ]; + + meta = { + description = "The Zend OPcache provides faster PHP execution through opcode caching and optimization."; + homepage = http://pecl.php.net/package/ZendOpcache; + license = "PHP"; + }; +} diff --git a/pkgs/top-level/all-packages.nix b/pkgs/top-level/all-packages.nix index f0700965114b6..1f9c847f238a1 100644 --- a/pkgs/top-level/all-packages.nix +++ b/pkgs/top-level/all-packages.nix @@ -3282,23 +3282,24 @@ let perl = if system != "i686-cygwin" then perl516 else sysPerl; - php = php54; + php = callPackage ../development/interpreters/php { }; + php5_2 = php.override { version = "5.2.17"; }; + php5_2fpm = php5_3.override { version ="5.2.17"; sapi = "fpm"; }; # experimental patch - php53 = callPackage ../development/interpreters/php/5.3.nix { }; + php5_3 = php.override { version = "5.3.x"; }; + php5_3fpm = php5_3.override { sapi = "fpm"; }; - php54 = callPackage ../development/interpreters/php/5.4.nix { }; + php5_4 = php.override { version = "5.4.x"; }; + php5_4fpm = php5_4.override { sapi = "fpm"; }; - php_apc = callPackage ../development/libraries/php-apc { }; + php5_5 = php.override { version = "5.5.x"; }; + php5_5fpm = php5_4.override { sapi = "fpm"; }; - php_xcache = callPackage ../development/libraries/php-xcache { }; - - phpXdebug_5_3 = lowPrio (callPackage ../development/interpreters/php-xdebug { - php = php53; - }); - - phpXdebug_5_4 = callPackage ../development/interpreters/php-xdebug { }; - - phpXdebug = phpXdebug_5_4; + php_opcache = callPackage ../development/libraries/php-opcache { }; + # use php.apc/xcache/Xdebug instead + # php_apc = callPackage ../development/libraries/php-apc { }; + # php_xcache = callPackage ../development/libraries/php-xcache { }; + # phpXdebug = callPackage ../development/interpreters/php-xdebug { }; picolisp = callPackage ../development/interpreters/picolisp {};