From mboxrd@z Thu Jan 1 00:00:00 1970 Received: from eggs.gnu.org ([2001:4830:134:3::10]:33340) by lists.gnu.org with esmtp (Exim 4.71) (envelope-from ) id 1eHxru-00060s-QD for guix-patches@gnu.org; Thu, 23 Nov 2017 15:13:10 -0500 Received: from Debian-exim by eggs.gnu.org with spam-scanned (Exim 4.71) (envelope-from ) id 1eHxrq-00085c-Ux for guix-patches@gnu.org; Thu, 23 Nov 2017 15:13:06 -0500 Received: from debbugs.gnu.org ([208.118.235.43]:45501) by eggs.gnu.org with esmtps (TLS1.0:RSA_AES_128_CBC_SHA1:16) (Exim 4.71) (envelope-from ) id 1eHxrq-00084z-Bn for guix-patches@gnu.org; Thu, 23 Nov 2017 15:13:02 -0500 Received: from Debian-debbugs by debbugs.gnu.org with local (Exim 4.84_2) (envelope-from ) id 1eHxrq-00083d-2Q for guix-patches@gnu.org; Thu, 23 Nov 2017 15:13:02 -0500 Subject: [bug#28769] [PATCH] gnu: services: Add php-fpm. Resent-Message-ID: From: nee References: <9fe1701f-d78f-ba3a-37eb-64417337a55b@cock.li> <20171013223729.2605f33c@cbaines.net> <7462cec0-7d33-f2a3-1bd7-92454d690b0b@cock.li> <20171102191708.0cf85810@cbaines.net> Message-ID: <145a6af6-bf20-c6e3-f314-009a17239f89@cock.li> Date: Thu, 23 Nov 2017 21:11:48 +0100 MIME-Version: 1.0 In-Reply-To: <20171102191708.0cf85810@cbaines.net> Content-Type: multipart/mixed; boundary="------------64BC90A7CEF2FF28A82C607A" Content-Language: en-GB List-Id: List-Unsubscribe: , List-Archive: List-Post: List-Help: List-Subscribe: , Errors-To: guix-patches-bounces+kyle=kyleam.com@gnu.org Sender: "Guix-patches" To: Christopher Baines Cc: 28769@debbugs.gnu.org This is a multi-part message in MIME format. --------------64BC90A7CEF2FF28A82C607A Content-Type: text/plain; charset=utf-8 Content-Transfer-Encoding: 8bit Hello sorry about not replying for such a long time, and thank you for reviewing my patches again. Am 02.11.2017 um 20:17 schrieb Christopher Baines: > > I've now attached a system test for php-fpm, that sets it up with > nginx, creates a basic php file, and checks that it can be requested. That's great thanks for saving me a bunch of work with this. ;-) > > This seems to work, which I was a little surprised at, as I was > suspecting problems with the socket permissions. > > I had a look, and while the nginx workers in the test system are not > root, the nginx master process is, so maybe that allows it to work... I don't think that's the reason, because I remember it not working at first when I didn't have the permissions set. >> I renamed the default workers-log-file to php7-fpm.www.log as it is >> usually called. The php-fpm log-file is now called php7-fpm.log. > > What I think I meant to say here was, I'm not sure the php _version_ is > adding much to the log file name (rather than "I'm not sure the php is > adding"). > > The php package version is used in a few places, and while I can > imagine this being consistent with other distributions, it does add a > bit of complexity to the default values in the service, and I'm not > sure what benefit it brings? > If users want to run multiple php versions, they only have to change the version in the php-package and pass that package along all the services. My perception of the php landscape was that the major releases aren't 100% reliably backwards compatible and some applications depend on older stable releases, so that it is not too uncommon to run multiple php versions the same system. Here is a quote from: https://wordpress.org/about/requirements/ """ Why do we support older versions? We strongly recommend the latest versions of PHP and MySQL, but we understand that this isn’t right for everyone, and that sometimes hosts can be slow or hesitant to upgrade their customers since upgrades to PHP and MySQL have historically broken applications. """ An alternative could be to include the php-package hash in the socket name, but I'm not sure if that would work with nginx and it's currently missing reload when a system-reconfigure is done. Or services could be generally more isolated somehow. WDYT? >>>> + (file php-fpm-configuration-file ;#f | file-like >>>> + (default #f))) > > ... > >>>> + (service-extension account-service-type >>>> + php-fpm-accounts))) >>>> + (default-value (php-fpm-configuration)))) >>> >>> Filling in the description (a relatively new field on the service type) >>> would be a great addition here. >>> >> Ah, yes I'm mostly using the web documentation and other services from >> web.scm as reference. Thanks for the update. >> What would be a good value for this field? I just used "The php-fpm >> service-type." for now. > > That is ok, but it could probably be more useful. I think ideally it > would describe more about what the service offers. > > Users might encounter this when searching for services for example: > > → guix system search php > name: php-fpm > location: gnu/services/web.scm:607:2 > extends: shepherd-root activate account > description: The php-fpm service-type. > relevance: 5 I ran `guix sysytem search *` and it seems most descriptions start with 'Run' or 'Provide' I changed it to: "Run `php-fpm' to provide a fastcgi socket for calling php through a webserver." > I've attached a patch containing a couple of copy+paste fixes, and a > system test. > > It would be good to get your opinion on the system test, does it test > the right things? > The tests look good to me. I added another test that adds two numbers and checks for the result in the response to see if php actually did something with the file. > If you like the look of it, I'd suggest including those changes in the > commit that adds the service, and then sending the updated patches. > I've included a changelog in the commit message. > Here are the updated patches. Thank you for your tests! --------------64BC90A7CEF2FF28A82C607A Content-Type: text/x-patch; name="0001-guix-utils-add-version-major.patch" Content-Transfer-Encoding: quoted-printable Content-Disposition: attachment; filename="0001-guix-utils-add-version-major.patch" =46rom 5347b2880b92e055cb8df1ea2c68ece74f506180 Mon Sep 17 00:00:00 2001 From: nee Date: Mon, 9 Oct 2017 23:02:05 +0200 Subject: [PATCH 1/2] guix: utils: add version-major. * guix/utils.scm (version-major): New procedure. --- guix/utils.scm | 5 +++++ 1 file changed, 5 insertions(+) diff --git a/guix/utils.scm b/guix/utils.scm index c0ffed172..bfa5e3a69 100644 --- a/guix/utils.scm +++ b/guix/utils.scm @@ -80,6 +80,7 @@ version>=3D? version-prefix version-major+minor + version-major guile-version>? string-replace-substring arguments-from-environment-variable @@ -492,6 +493,10 @@ For example, (version-prefix \"2.1.47.4.23\" 3) retu= rns \"2.1.47\"" minor version numbers from version-string." (version-prefix version-string 2)) =20 +(define (version-major version-string) + "Return the major version number as string from the version-string." + (version-prefix version-string 1)) + (define (version>? a b) "Return #t when A denotes a version strictly newer than B." (eq? '> (version-compare a b))) --=20 2.14.1 --------------64BC90A7CEF2FF28A82C607A Content-Type: text/x-patch; name="0002-gnu-services-Add-php-fpm.patch" Content-Transfer-Encoding: quoted-printable Content-Disposition: attachment; filename="0002-gnu-services-Add-php-fpm.patch" =46rom a9061ce9dafc1454e5b964e6c9e16c9269356ca5 Mon Sep 17 00:00:00 2001 From: nee Date: Mon, 9 Oct 2017 23:06:05 +0200 Subject: [PATCH 2/2] gnu: services: Add php-fpm. * gnu/services/web.scm (, ): New record types. (php-fpm-configuration?, php-fpm-process-manager-configuration?, php-fpm-service-type, nginx-php-location): New procedures. * doc/guix.texi (Web-Services): Document php-fpm service. * gnu/tests/web.scm: Add php-fpm system test. --- doc/guix.texi | 137 +++++++++++++++++++++++++++- gnu/services/web.scm | 248 +++++++++++++++++++++++++++++++++++++++++++++= +++++- gnu/tests/web.scm | 123 ++++++++++++++++++++++++- 3 files changed, 504 insertions(+), 4 deletions(-) diff --git a/doc/guix.texi b/doc/guix.texi index d4a2a696a..9058c9a23 100644 --- a/doc/guix.texi +++ b/doc/guix.texi @@ -40,7 +40,8 @@ Copyright @copyright{} 2017 Christopher Allan Webber@* Copyright @copyright{} 2017 Marius Bakke@* Copyright @copyright{} 2017 Hartmut Goebel@* Copyright @copyright{} 2017 Maxim Cournoyer@* -Copyright @copyright{} 2017 Tobias Geerinckx-Rice +Copyright @copyright{} 2017 Tobias Geerinckx-Rice@* +Copyright @copyright{} 2017 nee =20 Permission is granted to copy, distribute and/or modify this document under the terms of the GNU Free Documentation License, Version 1.3 or @@ -14942,6 +14943,140 @@ capability also has to be configured on the fro= nt-end as well. @end deftp =20 =20 +@cindex php-fpm +PHP-FPM (FastCGI Process Manager) is an alternative PHP FastCGI implemen= tation +with some additional features useful for sites of any size. + +These features include: +@itemize @bullet +@item Adaptive process spawning +@item Basic statistics (ala Apache's mod_status) +@item Advanced process management with graceful stop/start +@item Ability to start workers with different uid/gid/chroot/environment= +and different php.ini (replaces safe_mode) +@item Stdout & stderr logging +@item Emergency restart in case of accidental opcode cache destruction +@item Accelerated upload support +@item Support for a "slowlog" +@item Enhancements to FastCGI, such as fastcgi_finish_request() - +a special function to finish request & flush all data while continuing t= o do +something time-consuming (video converting, stats processing, etc.) +@end itemize +... and much more. + +@defvr {Scheme Variable} php-fpm-service-type +A Service type for @code{php-fpm}. +@end defvr + +@deftp {Data Type} php-fpm-configuration +Data Type for php-fpm service configuration. +@table @asis +@item @code {socket} (default: @code{(string-append "/var/run/php" (vers= ion-major (package-version php)) "-fpm.sock")}) +The address on which to accept FastCGI requests. Valid syntaxes are: +@table @asis +@item @code{"ip.add.re.ss:port"} +Listen on a TCP socket to a specific address on a specific port. +@item @code{"port"} +Listen on a TCP socket to all addresses on a specific port. +@item @code{"/path/to/unix/socket"} +Listen on a unix socket. +@end table + +@item @code {user} (default: @code{php-fpm}) +User who will own the php worker processes. +@item @code {group} (default: @code{php-fpm}) +Group of the worker processes. +@item @code {socket-user} (default: @code{php-fpm}) +User who can speak to the php-fpm socket. +@item @code {socket-group} (default: @code{php-fpm}) +Group that can speak to the php-fpm socket. +@item @code {pid-file} (default: @code{(string-append "/var/log/php" (ve= rsion-major (package-version php)) "-fpm.pid")}) +The process id of the php-fpm process is written to this file +once the service has started. +@item @code {log-file} (default: @code{(string-append "/var/log/php" (ve= rsion-major (package-version php)) "-fpm.log")}) +Log for the php-fpm master process. +@item @code {process-manager} (default: @code{(php-fpm-dynamic-process-m= anager-configuration)}) +Detailed settings for the php-fpm process manager. +Must be either: +@table @asis +@item @code{} +@item @code{} +@item @code{} +@end table +@item @code {display-errors} (default @code{#f}) +Determines wether php errors and warning should be sent to clients +and displayed in their browsers. +This is useful for local php development, but a security risk for public= sites, +as error messages can reveal passwords and personal data. +@item @code {workers-logfile} (default @code{(string-append "/var/log/ph= p" (version-major (package-version php)) "-fpm.www.log")}) +This file will log the @code{stderr} outputs of php worker processes. +Can be set to @code{#f} to disable logging. +@item @code {file} (default @code{#f}) +An optional override of the whole configuration. +You can use the @code{mixed-text-file} function or an absolute filepath = for it. +@end table +@end deftp + +@deftp {Data type} php-fpm-dynamic-process-manager-configuration +Data Type for the @code{dynamic} php-fpm process manager. +With the @code{dynamic} process manager spare worker processes are kept = around +based on it's configured limits. +@table @asis +@item @code {max-children} (default: @code{5}) +Maximum of worker processes. +@item @code {start-servers} (default: @code{2}) +How many worker processes should be started on start-up. +@item @code {min-spare-servers} (default: @code{1}) +How many spare worker processes should be kept around at minimum. +@item @code {max-spare-servers} (default: @code{3}) +How many spare worker processes should be kept around at maximum. +@end table +@end deftp + +@deftp {Data type} php-fpm-static-process-manager-configuration +Data Type for the @code{static} php-fpm process manager. +With the @code{static} process manager an unchanging number +of worker processes is created. +@table @asis +@item @code {max-children} (default: @code{5}) +Maximum of worker processes. +@end table +@end deftp + +@deftp {Data type} php-fpm-on-demand-process-manager-configuration +Data Type for the @code{on-demand} php-fpm process manager. +With the @code{on-demand} process manager worker processes are only crea= ted +as requests arrive. +@table @asis +@item @code {max-children} (default: @code{5}) +Maximum of worker processes. +@item @code {process-idle-timeout} (default: @code{10}) +The time in seconds after which a process with no requests is killed. +@end table +@end deftp + + +@defvr {Scheme Variable} nginx-php-fpm-location +A helper function to quickly add php to an @code{nginx-server-configurat= ion}. +@end defvr + +A simple services setup for nginx with php can look like this: +@example +(services (cons* (dhcp-client-service) + (service php-fpm-service-type) + (service nginx-service-type + (nginx-server-configuration + (server-name '("example.com")) + (root "/srv/http/") + (locations + (list (nginx-php-location))) + (https-port #f) + (ssl-certificate #f) + (ssl-certificate-key #f))) + %base-services)) +@end example + + @node DNS Services @subsubsection DNS Services @cindex DNS (domain name system) diff --git a/gnu/services/web.scm b/gnu/services/web.scm index 9d713003c..3b3be215a 100644 --- a/gnu/services/web.scm +++ b/gnu/services/web.scm @@ -4,6 +4,7 @@ ;;; Copyright =C2=A9 2016 ng0 ;;; Copyright =C2=A9 2016, 2017 Julien Lepiller ;;; Copyright =C2=A9 2017 Christopher Baines +;;; Copyright =C2=A9 2017 nee ;;; ;;; This file is part of GNU Guix. ;;; @@ -26,8 +27,11 @@ #:use-module (gnu system shadow) #:use-module (gnu packages admin) #:use-module (gnu packages web) + #:use-module (gnu packages php) #:use-module (guix records) #:use-module (guix gexp) + #:use-module ((guix utils) #:select (version-major)) + #:use-module ((guix packages) #:select (package-version)) #:use-module (srfi srfi-1) #:use-module (ice-9 match) #:export ( @@ -76,7 +80,49 @@ =20 fcgiwrap-configuration fcgiwrap-configuration? - fcgiwrap-service-type)) + fcgiwrap-service-type + + + php-fpm-configuration + make-php-fpm-configuration + php-fpm-configuration? + php-fpm-configuration-php + php-fpm-configuration-socket + php-fpm-configuration-user + php-fpm-configuration-group + php-fpm-configuration-socket-user + php-fpm-configuration-socket-group + php-fpm-configuration-pid-file + php-fpm-configuration-log-file + php-fpm-configuration-process-manager + php-fpm-configuration-display-errors + php-fpm-configuration-workers-log-file + php-fpm-configuration-file + =20 + + php-fpm-dynamic-process-manager-configuration + make-php-fpm-dynamic-process-manager-configuration + php-fpm-dynamic-process-manager-configuration? + php-fpm-dynamic-process-manager-configuration-max-children + php-fpm-dynamic-process-manager-configuration-start-servers + php-fpm-dynamic-process-manager-configuration-min-spare-serv= ers + php-fpm-dynamic-process-manager-configuration-max-spare-serv= ers + =20 + + php-fpm-static-process-manager-configuration + make-php-fpm-static-process-manager-configuration + php-fpm-static-process-manager-configuration? + php-fpm-static-process-manager-configuration-max-children + =20 + + php-fpm-on-demand-process-manager-configuration + make-php-fpm-on-demand-process-manager-configuration + php-fpm-on-demand-process-manager-configuration? + php-fpm-on-demand-process-manager-configuration-max-children= + php-fpm-on-demand-process-manager-configuration-process-idle= -timeout + + php-fpm-service-type + nginx-php-location)) =20 ;;; Commentary: ;;; @@ -256,10 +302,12 @@ of index files." "events {}\n"))) =20 (define %nginx-accounts - (list (user-group (name "nginx") (system? #t)) + (list (user-group (name "php-fpm") (system? #t)) + (user-group (name "nginx") (system? #t)) (user-account (name "nginx") (group "nginx") + (supplementary-groups '("php-fpm")) (system? #t) (comment "nginx server user") (home-directory "/var/empty") @@ -385,3 +433,199 @@ of index files." (service-extension account-service-type fcgiwrap-accounts))) (default-value (fcgiwrap-configuration)))) + +(define-record-type* php-fpm-configuration + make-php-fpm-configuration + php-fpm-configuration? + (php php-fpm-configuration-php ; + (default php)) + (socket php-fpm-configuration-socket + (default (string-append "/var/run/php" + (version-major (package-vers= ion php)) + "-fpm.sock"))) + (user php-fpm-configuration-user + (default "php-fpm")) + (group php-fpm-configuration-group + (default "php-fpm")) + (socket-user php-fpm-configuration-socket-user + (default "php-fpm")) + (socket-group php-fpm-configuration-socket-group + (default "php-fpm")) + (pid-file php-fpm-configuration-pid-file + (default (string-append "/var/run/php" + (version-major (package-vers= ion php)) + "-fpm.pid"))) + (log-file php-fpm-configuration-log-file + (default (string-append "/var/log/php" + (version-major (package-vers= ion php)) + "-fpm.log"))) + (process-manager php-fpm-configuration-process-manager + (default (php-fpm-dynamic-process-manager-configurat= ion))) + (display-errors php-fpm-configuration-display-errors + (default #f)) + (workers-log-file php-fpm-configuration-workers-log-file + (default (string-append "/var/log/php" + (version-major (package-vers= ion php)) + "-fpm.www.log"))) + (file php-fpm-configuration-file ;#f | file-like + (default #f))) + +(define-record-type* + php-fpm-dynamic-process-manager-configuration + make-php-fpm-dynamic-process-manager-configuration + php-fpm-dynamic-process-manager-configuration? + (max-children php-fpm-dynamic-process-manager-configuration-ma= x-children + (default 5)) + (start-servers php-fpm-dynamic-process-manager-configuration-st= art-servers + (default 2)) + (min-spare-servers php-fpm-dynamic-process-manager-configuration-mi= n-spare-servers + (default 1)) + (max-spare-servers php-fpm-dynamic-process-manager-configuration-ma= x-spare-servers + (default 3))) + +(define-record-type* + php-fpm-static-process-manager-configuration + make-php-fpm-static-process-manager-configuration + php-fpm-static-process-manager-configuration? + (max-children php-fpm-static-process-manager-configuration-max= -children + (default 5))) + +(define-record-type* + php-fpm-on-demand-process-manager-configuration + make-php-fpm-on-demand-process-manager-configuration + php-fpm-on-demand-process-manager-configuration? + (max-children php-fpm-on-demand-process-manager-configuration-= max-children + (default 5)) + (process-idle-timeout php-fpm-on-demand-process-manager-configuration-= process-idle-timeout + (default 10))) + +(define php-fpm-accounts + (match-lambda + (($ php socket user group socket-user socket= -group _ _ _ _ _ _) + (list + (user-group (name "php-fpm") (system? #t)) + (user-group + (name group) + (system? #t)) + (user-account + (name user) + (group group) + (supplementary-groups '("php-fpm")) + (system? #t) + (comment "php-fpm daemon user") + (home-directory "/var/empty") + (shell (file-append shadow "/sbin/nologin"))))))) + +(define (default-php-fpm-config socket user group socket-user socket-gro= up + pid-file log-file pm display-errors workers-log-file) + (apply mixed-text-file "php-fpm.conf" + (flatten + "[global]\n" + "pid =3D" pid-file "\n" + "error_log =3D" log-file "\n" + "[www]\n" + "user =3D" user "\n" + "group =3D" group "\n" + "listen =3D" socket "\n" + "listen.owner =3D" socket-user "\n" + "listen.group =3D" socket-group "\n" + + (match pm + (($ + pm.max-children + pm.start-servers + pm.min-spare-servers + pm.max-spare-servers) + (list + "pm =3D dynamic\n" + "pm.max_children =3D" (number->string pm.max-children) "\n= " + "pm.start_servers =3D" (number->string pm.start-servers) "= \n" + "pm.min_spare_servers =3D" (number->string pm.min-spare-se= rvers) "\n" + "pm.max_spare_servers =3D" (number->string pm.max-spare-se= rvers) "\n")) + =20 + (($ + pm.max-children) + (list + "pm =3D static\n" + "pm.max_children =3D" (number->string pm.max-children) "\n= ")) + =20 + (($ + pm.max-children + pm.process-idle-timeout) + (list + "pm =3D ondemand\n" + "pm.max_children =3D" (number->string pm.max-children) "\n= " + "pm.process_idle_timeout =3D" (number->string pm.process-i= dle-timeout) "s\n"))) + + + "php_flag[display_errors] =3D " (if display-errors "on" "off")= "\n" + + (if workers-log-file + (list "catch_workers_output =3D yes\n" + "php_admin_value[error_log] =3D" workers-log-file "\= n" + "php_admin_flag[log_errors] =3D on\n") + (list "catch_workers_output =3D no\n"))))) + +(define php-fpm-shepherd-service + (match-lambda + (($ php socket user group socket-user socket= -group + pid-file log-file pm display-errors work= ers-log-file file) + (list (shepherd-service + (provision '(php-fpm)) + (documentation "Run the php-fpm daemon.") + (requirement '(networking)) + (start #~(make-forkexec-constructor + '(#$(file-append php "/sbin/php-fpm") + "--fpm-config" + #$(or file + (default-php-fpm-config socket user group + socket-user socket-group pid-file log-fi= le + pm display-errors workers-log-file))) + #:pid-file #$pid-file)) + (stop #~(make-kill-destructor))))))) + +(define php-fpm-activation + (match-lambda + (($ _ _ user _ _ _ _ log-file _ _ workers-lo= g-file _) + #~(begin + (use-modules (guix build utils)) + (let* ((user (getpwnam #$user)) + (touch (lambda (file-name) + (call-with-output-file file-name (const #t)))) + (init-log-file + (lambda (file-name) + (when #$workers-log-file + (when (not (file-exists? file-name)) + (touch file-name)) + (chown file-name (passwd:uid user) (passwd:gid user= )) + (chmod file-name #o660))))) + (init-log-file #$log-file) + (init-log-file #$workers-log-file)))))) + + +(define php-fpm-service-type + (service-type (name 'php-fpm) + (description "Run `php-fpm' to provide a fastcgi socket = for calling php through a webserver.") + (extensions + (list (service-extension shepherd-root-service-type + php-fpm-shepherd-service) + (service-extension activation-service-type + php-fpm-activation) + (service-extension account-service-type + php-fpm-accounts))) + (default-value (php-fpm-configuration)))) + +(define* (nginx-php-location + #:key + (nginx-package nginx) + (socket (string-append "/var/run/php" + (version-major (package-version php)) + "-fpm.sock"))) + "Return a nginx-location-configuration that makes nginx run .php files= =2E" + (nginx-location-configuration + (uri "~ \\.php$") + (body (list + "fastcgi_split_path_info ^(.+\\.php)(/.+)$;" + (string-append "fastcgi_pass unix:" socket ";") + "fastcgi_index index.php;" + (list "include " nginx-package "/share/nginx/conf/fastcgi.conf= ;"))))) diff --git a/gnu/tests/web.scm b/gnu/tests/web.scm index 3fa272c67..68233af9f 100644 --- a/gnu/tests/web.scm +++ b/gnu/tests/web.scm @@ -1,5 +1,6 @@ ;;; GNU Guix --- Functional package management for GNU ;;; Copyright =C2=A9 2017 Ludovic Court=C3=A8s +;;; Copyright =C2=A9 2017 Christopher Baines ;;; ;;; This file is part of GNU Guix. ;;; @@ -27,7 +28,8 @@ #:use-module (gnu services networking) #:use-module (guix gexp) #:use-module (guix store) - #:export (%test-nginx)) + #:export (%test-nginx + %test-php-fpm)) =20 (define %index.html-contents ;; Contents of the /index.html file served by nginx. @@ -132,3 +134,122 @@ HTTP-PORT." (name "nginx") (description "Connect to a running NGINX server.") (value (run-nginx-test)))) + +=0C +;;; +;;; PHP-FPM +;;; + +(define %make-php-fpm-http-root + ;; Create our server root in /srv. + #~(begin + (mkdir "/srv") + (call-with-output-file "/srv/index.php" + (lambda (port) + (display "\n" port))))) + +(define %php-fpm-nginx-server-blocks + (list (nginx-server-configuration + (root "/srv") + (locations + (list (nginx-php-location))) + (http-port 8042) + (https-port #f) + (ssl-certificate #f) + (ssl-certificate-key #f)))) + +(define %php-fpm-os + ;; Operating system under test. + (simple-operating-system + (dhcp-client-service) + (service php-fpm-service-type) + (service nginx-service-type + (nginx-configuration + (server-blocks %php-fpm-nginx-server-blocks))) + (simple-service 'make-http-root activation-service-type + %make-php-fpm-http-root))) + +(define* (run-php-fpm-test #:optional (http-port 8042)) + "Run tests in %PHP-FPM-OS, which has nginx running and listening on +HTTP-PORT, along with php-fpm." + (define os + (marionette-operating-system + %php-fpm-os + #:imported-modules '((gnu services herd) + (guix combinators)))) + + (define vm + (virtual-machine + (operating-system os) + (port-forwardings `((8080 . ,http-port))))) + + (define test + (with-imported-modules '((gnu build marionette) + (guix build utils)) + #~(begin + (use-modules (srfi srfi-11) (srfi srfi-64) + (gnu build marionette) + (web uri) + (web client) + (web response)) + + (define marionette + (make-marionette (list #$vm))) + + (mkdir #$output) + (chdir #$output) + + (test-begin "php-fpm") + + (test-assert "php-fpm running" + (marionette-eval + '(begin + (use-modules (gnu services herd)) + (match (start-service 'php-fpm) + (#f #f) + (('service response-parts ...) + (match (assq-ref response-parts 'running) + ((pid) (number? pid)))))) + marionette)) + + (test-eq "nginx running" + 'running! + (marionette-eval + '(begin + (use-modules (gnu services herd)) + (start-service 'nginx) + 'running!) + marionette)) + + (test-equal "http-get" + 200 + (let-values (((response text) + (http-get "http://localhost:8080/index.php" + #:decode-body? #t))) + (response-code response))) + + (test-equal "php computed result is sent" + "Computed by php:5" + (let-values (((response text) + (http-get "http://localhost:8080/index.php" + #:decode-body? #t))) + (begin + (use-modules (ice-9 regex)) + (let ((matches (string-match "Computed by php:5" text)))= + (and matches + (match:substring matches 0)))))) + + (test-end) + + (exit (=3D (test-runner-fail-count (test-runner-current)) 0)))= )) + + (gexp->derivation "php-fpm-test" test)) + +(define %test-php-fpm + (system-test + (name "php-fpm") + (description "Test PHP-FPM through nginx.") + (value (run-php-fpm-test)))) --=20 2.14.1 --------------64BC90A7CEF2FF28A82C607A--