Friday, 26 June 2015

Getting PHP FastCgi Process Manager (FPM) and nginx working in cygwin

Despite the popularity of nginx and php, I was surprised that it wasn't easiy to find a working configuration for PHP-FPM (fast cgi) with a nginx server in front, running on cygwin.
Once I had the right fragments of settings, it was a case of systematically trying them all out.

/etc/php5/php-fpm.conf:

[global]
pid = /var/run/php-fpm.pid

;note: i create a /var/log/php dir owned by the service user/group
;this allows the permissions to be inherited easily on the filesystem
error_log = /var/log/php/fpm-global.log

; cygwin user default is 256
rlimit_files = 1024

;pool configuration, having a pool config per site means you can easily have a separate log file
[www]
;they have to be set but the cygwin version ignores them
;user=service-user
;group-service-group

; The address on which to accept FastCGI requests.
listen = 127.0.0.1:8001
; or
; listen = tmp/php-cgi.socket
; for socket unset these:
listen.owner=service-user
listen.group=service-group

; this allows the process pool to be queried if it appears to be bogging down
pm.status_path = /status

php_admin_flag[log_errors] = on

/etc/php5/php.ini:

The magic to get the pretty permalinks working is on the wordpress site.
error_reporting = -1
display_errors = On
display_startup_errors = On
log_errors = On
log_errors_max_len = 0

/etc/nginx/nginx.conf:

error_log  /var/log/nginx/error.log;
pid        /var/run/nginx.pid;

events {
    worker_connections  1024;
}


http {
    access_log off;
    
    include       mime.types;
    default_type  application/octet-stream;

    sendfile        on;
    keepalive_timeout  65;

    # Upstream to abstract backend connection(s) for php
    upstream php {
      #server unix:/tmp/php-cgi.socket;
      server 127.0.0.1:8001;
    }

    include site1.conf;
}

/etc/nginx/site1.conf:

server {
  listen       8000;
  server_name  localhost;
  
  ## This should be in your http block and if it is, it's not needed here.
  index index.php;
  root   /cygdrive/c/Projects/site1/wordpress/;
  
  location / {
      try_files $uri $uri/ /index.php?$args;
  }
  rewrite /wp-admin$ $scheme://$host$uri/ permanent;
  
  # pass the PHP scripts to FastCGI server listening on 127.0.0.1:9000
  #
  location ~ [^/]\.php(/|$) {           
    fastcgi_split_path_info ^(.+?\.php)(/.*)$;
    if (!-f $document_root$fastcgi_script_name) {
      return 404;
    }
    # This is a robust solution for path info security issue and works with "cgi.fix_pathinfo = 1" in /etc/php.ini (default)
    
    include fastcgi.conf;
    fastcgi_index index.php;
    fastcgi_pass php;
    
    # fastcgi_intercept_errors on;
    fastcgi_connect_timeout 40s;     

    # set the log file here so each site is different
    fastcgi_param PHP_VALUE "error_log = /var/log/php/php-site1.log";
  }
    
  # pass status page request on
  location ~ ^/(status|ping)$ {
    access_log off;
    allow 127.0.0.1;
    deny all;
    
    include fastcgi.conf;
    fastcgi_pass php;
  }
}

Finally, I had some problems connecting from cygwin php to a windows native mysql. Discovered I just had to use the localhost IP to force it over TCP/IP (instead of trying to use unix sockets).

/var/www/wordpress/wp-config.php:

/** MySQL hostname */
define('DB_HOST', '127.0.0.1');

Update 2015/07/02:

I've hit a few problems using cygwin and it's nearly wholly based around permissioning. I've written up a summary of my ad-hoc solution, mainly because I couldn't easily find sample setups and wasted a lot more time than one should on a popular platform.

The launch scripts themselves are a bit hacky but these are the best I've got so far. The cygrunsrv service launcher directly calls the service so you don't get a shell script (though this could easily be changed). I've found running as the "Local System" account causes too many problems relating to group access so setting up a dedicated user is the easiest.

Here are the 2 service install scripts:


/etc/rc.d/init.d/ngix
/etc/init.d/php-fpm


No comments:

Post a Comment