14
votes

QUESTION: What am I missing or doing wrong?

I'm trying to migrate fully functional Zend Framework application from Apache2 with mod_php5 to nginx with php5-fpm. I get this kind of errors:

2012/06/27 12:08:04 [error] 1986#0: *1 open() "/var/www/public/sales/live-trials-json" failed (2: No such file or directory), client: *.*.*.*, server: www.mydomain.com, request: "POST /sales/live-trials-json HTTP/1.1", host: "www.mydomain.com", referrer: "https://www.mydomain.com/sales/live-trials"

Here are my configuration files:

a) /etc/nginx/sites-enabled/www

server {
  listen 80;
  listen 443 default ssl;

  server_name www.mydomain.com;
  root /var/www/public;

  ssl_certificate /etc/nginx/ssl/mydomain.crt;
  ssl_certificate_key /etc/nginx/ssl/mydomain.key;

  access_log /var/log/nginx/access.log;
  error_log /var/log/nginx/error.log error;

  index index.php index.phtml index.html;

  location = /(favicon.ico|robots.txt) {
    access_log off;
    log_not_found off;
  }

  location ~* ^.+.(css|js|jpeg|jpg|gif|png|ico|xml) {
    access_log off;
    expires 30d;
  }

  location / {
    try_files $uri $uri/ /index.php;
  }

  location ~ /\.ht {
    deny all;
  }

  location ~ \.php$ {
    fastcgi_pass 127.0.0.1:9000;
    fastcgi_split_path_info ^(.+\.php)(/.+)$;
    fastcgi_intercept_errors on;
    include /etc/nginx/fastcgi_params;
  }
}

b) /etc/nginx/fastcgi_params

fastcgi_param   QUERY_STRING        $query_string;
fastcgi_param   REQUEST_METHOD      $request_method;
fastcgi_param   CONTENT_TYPE        $content_type;
fastcgi_param   CONTENT_LENGTH      $content_length;
fastcgi_param   SCRIPT_FILENAME     $request_filename;
fastcgi_param   SCRIPT_NAME     $fastcgi_script_name;
fastcgi_param   REQUEST_URI     $request_uri;
fastcgi_param   DOCUMENT_URI        $document_uri;
fastcgi_param   DOCUMENT_ROOT       $document_root;
fastcgi_param   SERVER_PROTOCOL     $server_protocol;
fastcgi_param   GATEWAY_INTERFACE   CGI/1.1;
fastcgi_param   SERVER_SOFTWARE     nginx/$nginx_version;
fastcgi_param   REMOTE_ADDR     $remote_addr;
fastcgi_param   REMOTE_PORT     $remote_port;
fastcgi_param   SERVER_ADDR     $server_addr;
fastcgi_param   SERVER_PORT     $server_port;
fastcgi_param   SERVER_NAME     $server_name;
fastcgi_param   HTTPS           $https;
# PHP only, required if PHP was built with --enable-force-cgi-redirect
fastcgi_param   REDIRECT_STATUS     200;

c) /etc/php5/fpm/pool.d/www.conf

[www]
user = www-data
group = www-data
listen = 127.0.0.1:9000
pm = dynamic
pm.max_children = 20
pm.start_servers = 4
pm.min_spare_servers = 2
pm.max_spare_servers = 6
chdir = /

d) ls -al /var/www

drwxr-xr-x  7 www-data www-data  4096 Jun 27 10:52 application
drwxr-xr-x  5 www-data www-data  4096 Jun 27 10:52 library
drwxr-xr-x 10 www-data www-data  4096 Jun 27 12:05 public

e) nginx -V

nginx version: nginx/1.1.19
TLS SNI support enabled
configure arguments:
  --prefix=/etc/nginx
  --conf-path=/etc/nginx/nginx.conf
  --error-log-path=/var/log/nginx/error.log
  --http-client-body-temp-path=/var/lib/nginx/body
  --http-fastcgi-temp-path=/var/lib/nginx/fastcgi
  --http-log-path=/var/log/nginx/access.log
  --http-proxy-temp-path=/var/lib/nginx/proxy
  --http-scgi-temp-path=/var/lib/nginx/scgi
  --http-uwsgi-temp-path=/var/lib/nginx/uwsgi
  --lock-path=/var/lock/nginx.lock
  --pid-path=/var/run/nginx.pid
  --with-debug
  --with-http_addition_module
  --with-http_dav_module
  --with-http_geoip_module
  --with-http_gzip_static_module
  --with-http_image_filter_module
  --with-http_realip_module
  --with-http_stub_status_module
  --with-http_ssl_module
  --with-http_sub_module
  --with-http_xslt_module
  --with-ipv6
  --with-sha1=/usr/include/openssl
  --with-md5=/usr/include/openssl
  --with-mail
  --with-mail_ssl_module
  --add-module=/build/buildd/nginx-1.1.19/debian/modules/nginx-auth-pam
  --add-module=/build/buildd/nginx-1.1.19/debian/modules/nginx-echo
  --add-module=/build/buildd/nginx-1.1.19/debian/modules/nginx-upstream-fair
  --add-module=/build/buildd/nginx-1.1.19/debian/modules/nginx-dav-ext-module

f) php -v (this is cli version, but I swear I am running nginx with fpm:)

PHP 5.3.10-1ubuntu3 with Suhosin-Patch (cli) (built: Apr 11 2012 17:25:33) 
Copyright (c) 1997-2012 The PHP Group
Zend Engine v2.3.0, Copyright (c) 1998-2012 Zend Technologies
3
I have also changed in fastcgi_params as people complained in below article and still nothing: forum.nginx.org/read.php?11,214780,215113eistrati
What's the output from ls -l /var/www/public/sales/live-trials-json?sarnold
It doesn't exist, of course. Zend Framework rewrites the rules and runs corresponding controller and action. Check this out: framework.zend.com/manual/en/learning.quickstart.intro.htmleistrati
Ah, good, then you've got a good place to start -- it tried to access that file, so perhaps the rewriting is broken.sarnold
Well, it doesn't make sense, since it's working for all HTTP GET and not working for any HTTP POST. Judging from this point of view, I think rewrite is fine.eistrati

3 Answers

11
votes

Alright, after long and exhausting struggles, I've managed to figure out this madness. So, I've started everything from scratch and here is what I've learned:

Entire weirdness is somewhere in location ~* ... { ... }, so whoever have better experience, please explain why :-) Meanwhile I'll manage assets and caching on application layer.

My functional configuration file looks like this:

server {
  listen 80;
  listen 443 default ssl;

  server_name www.mydomain.com;
  root /var/www/public;

  ssl_certificate /etc/nginx/ssl/mydomain.crt;
  ssl_certificate_key /etc/nginx/ssl/mydomain.key;

  access_log /var/log/nginx/access.log;
  error_log /var/log/nginx/error.log error;

  index index.php index.phtml index.html;

  location / {
    try_files $uri $uri/ /index.php;
  }

  location ~ \.php$ {
    fastcgi_pass 127.0.0.1:9000;
    fastcgi_split_path_info ^(.+\.php)(/.+)$;
    fastcgi_intercept_errors on;
    include /etc/nginx/fastcgi_params;
  }
}

Thanks for trying, especially @sarnold and @sergei-lomakov!

9
votes

Your nginx configuration is little wrong.

Because agree with your rules, nginx tries to access /var/www/public/sales/live-trials-json which doesn't exist.

Because I don't know which endpoints your application use, I suggest you to make two nginx locations. First , for all static files (with regexp) create this location:

location ~* ^.+.(css|js|jpeg|jpg|gif|png|ico|xml) {
    access_log off;
    expires 30d;
  }

All another queries should be proxied to apache:

  location / {
    fastcgi_pass 127.0.0.1:9000;
    fastcgi_split_path_info ^(.+\.php)(/.+)$;
    fastcgi_intercept_errors on;
    include /etc/nginx/fastcgi_params;
  }

Make little change with this rule:

  location ~* ^/(favicon.ico|robots.txt)$ {
    access_log off;
    log_not_found off;
  }

Of course, you can leave ".ht settings" untouched:

  location ~ /\.ht {
    deny all;
  }

So, Final config will be:

server {
  listen 80;
  listen 443 default ssl;

  server_name www.mydomain.com;
  root /var/www/public;

  ssl_certificate /etc/nginx/ssl/mydomain.crt;
  ssl_certificate_key /etc/nginx/ssl/mydomain.key;

  access_log /var/log/nginx/access.log;
  error_log /var/log/nginx/error.log error;

  index index.php index.phtml index.html;

  location ~* ^/(favicon.ico|robots.txt)$ {
    access_log off;
    log_not_found off;
  }

  location ~* ^.+.(css|js|jpeg|jpg|gif|png|ico|xml) {
    access_log off;
    expires 30d;
  }

  location ~ /\.ht {
    deny all;
  }

  location / {
    fastcgi_pass 127.0.0.1:9000;
# I'm not sure that this setting is needed:
#        fastcgi_split_path_info ^(.+\.php)(/.+)$;
    fastcgi_intercept_errors on;
    include /etc/nginx/fastcgi_params;
  }


}
2
votes

As you noted, your problem is with

location ~* ^.+.(css|js|jpeg|jpg|gif|png|ico|xml) {
  access_log off;
  expires 30d;
}

This matches your POST uri of /sales/live-trials-json because it hasn't been anchored to the end of the uri path, and . matches any character. This means that '-js' matches. To fix this, you just need to add a \ (to match a literal '.') and a $ (to anchor the match at the end of the uri path):

location ~* \.(css|js|jpeg|jpg|gif|png|ico|xml)$ {
  access_log off;
  expires 30d;
}