1

I'm trying to get a rewrite rule to work for nginx and Wordpress. After a reboot of nginx, I try the site and get an IS 500 error page. The log file says:

*1 rewrite or internal redirection cycle while internally redirecting to "/index.php"

I'm confused, as this is how they tell you to do it in all the tutorials (and even the Wordpress documentation for setting up rewrite rules with nginx):

    try_files $uri $uri/ /index.php?$args ;

Here is the whole server block:

server {
    listen      178.79.134.35:443 http2;
    listen      [::]:443 http2;
    server_name foo.co.uk www.foo.co.uk cdn.foo.co.uk;
    ssl         on;
    ssl_certificate      /home/test/conf/web/ssl.foo.co.uk.pem;
    ssl_certificate_key  /home/test/conf/web/ssl.foo.co.uk.key;
    error_log  /var/log/apache2/domains/foo.co.uk.error.log error;

    location / {

        # This is cool because no php is touched for static content.
        # include the "?$args" part so non-default permalinks doesn't break when using query string
        try_files $uri $uri/ /index.php?$args ;

        proxy_pass      https://178.79.134.35:8443;
        location ~* ^.+\.(jpg|jpeg|gif|png|ico|svg|css|zip|tgz|gz|rar|bz2|exe|pdf|doc|xls|ppt|txt|odt|ods|odp|odf|tar|bmp|rtf|js|mp3|avi|mpeg|flv|html|htm)$ {
            root           /home/test/web/foo.co.uk/public_html;
            access_log     /var/log/apache2/domains/foo.co.uk.log combined;
            access_log     /var/log/apache2/domains/foo.co.uk.bytes bytes;
            expires        max;
            try_files      $uri @fallback;
        }
    }

    location /error/ {
        alias   /home/test/web/foo.co.uk/document_errors/;
    }

    location @fallback {
        proxy_pass      https://178.79.134.35:8443;
    }

    location ~ /\.ht    {return 404;}
    location ~ /\.svn/  {return 404;}
    location ~ /\.git/  {return 404;}
    location ~ /\.hg/   {return 404;}
    location ~ /\.bzr/  {return 404;}

    include /home/test/conf/web/snginx.foo.co.uk.conf*;
}

Anyone got any suggestions? I even tried something a bit more messy, but get the same error:

    if (!-e $request_filename){
        rewrite ^(.*)$ /index.php?q=$1 last;
        break;
    }

I've tweaked it a bit, so it does a pass to

location / {

    fastcgi_pass 127.0.0.1:9000;
    fastcgi_index index.php;
    fastcgi_param SCRIPT_FILENAME /home/test/web/foo.co.uk/public_shtml$fastcgi_script_name;
    include fastcgi_params;

    try_files $uri $uri/ /index.php?$args ;

    proxy_pass      https://178.79.134.35:8443;

    location ~* ^.+\.(jpg|jpeg|gif|png|ico|svg|css|zip|tgz|gz|rar|bz2|exe|pdf|doc|xls|ppt|txt|odt|ods|odp|odf|tar|bmp|rtf|js|mp3|avi|mpeg|flv|html|htm)$ {
        root           /home/test/web/foo.co.uk/public_shtml;
        access_log     /var/log/apache2/domains/foo.co.uk.log combined;
        access_log     /var/log/apache2/domains/foo.co.uk.bytes bytes;
        expires        max;
        try_files      $uri @fallback;
    }
}

UPDATE 2: As suggested, I know how a location ~ \.php$ { } block wrapped around it. So it looks like:

location / {

    proxy_pass      https://178.79.134.35:8443;

    location ~ \.php$ {
        fastcgi_pass 127.0.0.1:9000;
        fastcgi_index index.php;
        fastcgi_param SCRIPT_FILENAME home/test/web/foo.co.uk/public_shtml$fastcgi_script_name;
        include fastcgi_params;
    }

    location ~* ^.+\.(jpg|jpeg|gif|png|ico|svg|css|zip|tgz|gz|rar|bz2|exe|pdf|doc|xls|ppt|txt|odt|ods|odp|odf|tar|bmp|rtf|js|mp3|avi|mpeg|flv|html|htm)$ {
        root           /home/test/web/foo.co.uk/public_shtml;
        access_log     /var/log/apache2/domains/foo.co.uk.log combined;
        access_log     /var/log/apache2/domains/foo.co.uk.bytes bytes;
        expires        max;
        try_files      $uri @fallback;
    }

    try_files $uri $uri/ /index.php?$args ;
}

but I now get an error:

111: Connection refused) while connecting to upstream, client: 81.174.134.133, server: foo.co.uk, request: "GET /wp-admin/ HTTP/2.0", upstream: "fastcgi://127.0.0.1:9000"

Looking up on Google, and people suggest testing port 9000:

root@com:/home/# telnet localhost 9000
Trying ::1...
Trying 127.0.0.1...
telnet: Unable to connect to remote host: Connection refused

So it doesn't seem to be able to access it. I'm a bit confused though, as the firewall is setup to allow port 9000:

ACCEPT     tcp  --  anywhere             anywhere             tcp dpt:9000

UPDATE 2: As suggested, I tried:

netstat -nltp|grep 9000

...but it gives no result. If I look though, I can see php-7.0-fpm installed and running (as far as I can tell);

root@com:~# service php7.0-fpm status
â php7.0-fpm.service - The PHP 7.0 FastCGI Process Manager
   Loaded: loaded (/lib/systemd/system/php7.0-fpm.service; enabled; vendor preset: enabled)
   Active: active (running) since Wed 2017-04-12 12:06:48 UTC; 18h ago
  Process: 3560 ExecStartPre=/usr/lib/php/php7.0-fpm-checkconf (code=exited, status=0/SUCCESS)
 Main PID: 3800 (php-fpm7.0)
   Status: "Processes active: 0, idle: 2, Requests: 0, slow: 0, Traffic: 0req/sec"
   CGroup: /system.slice/php7.0-fpm.service
           ââ3800 php-fpm: master process (/etc/php/7.0/fpm/php-fpm.conf)
           ââ3872 php-fpm: pool www
           ââ3882 php-fpm: pool www

Apr 12 12:06:43 com.x.com systemd[1]: Starting The PHP 7.0 FastCGI Process Manager...
Apr 12 12:06:48 com.x.com systemd[1]: Started The PHP 7.0 FastCGI Process Manager.

I looked in /etc/php/7.0/fpm/php-fpm.conf, but don't see any reference to a "listen" port

UPDATE 3: I found a post where they said about editing the www.conf file: https://github.com/serghey-rodin/vesta/issues/1025

So looking for that on my server, I found:

/etc/php/7.0/fpm/pool.d/www.conf

I then commented out:

listen = /run/php/php7.0-fpm.sock

...and added:

listen = 9000

...and then rebooted with:

service php7.0-fpm restart

And now I can see it on the netstat

I then made sure I had this in my config:

    location ~ \.php$ {
        fastcgi_pass 127.0.0.1:9000;
        fastcgi_index index.php;
        fastcgi_param SCRIPT_FILENAME /home/test/web/foo.co.uk/public_shtml$fastcgi_script_name;
        include fastcgi_params;
    }

rebooted nginx, and voila :) It lives!

Andrew Newby
  • 1,102
  • 2
  • 25
  • 58
  • 1
    You are missing any support for PHP. See [this page](https://www.nginx.com/resources/wiki/start/topics/examples/phpfcgi/) for guidance. – Richard Smith Apr 12 '17 at 08:44
  • @RichardSmith - I've added that in, but it doesn't seem to have helped (same error message). I've updated my opening post with the new `location { }` – Andrew Newby Apr 12 '17 at 09:47
  • 1
    You still lack the location that would process PHP. Should be something like `location ~ \.php$ { ... fastcgi_pass unix;/var/run/php5-fpm.sock; ... }` – jollyroger Apr 12 '17 at 10:12
  • @jollyroger - thanks. Can't believe I missed that! I'm still getting a 111 error (see my updated post above). I thought maybe it was the firewall not letting it through, but it seems to be an open port :/ – Andrew Newby Apr 12 '17 at 11:39
  • @jollyroger - is there any way I can just forward the scripts to my Apache install on https://178.79.134.35:8443 ? PHP works fine in Apache, but I can't seem to get this bloomin port opened up and working with nginx :/ – Andrew Newby Apr 12 '17 at 12:14
  • Nginx does not have mod_php as apache does. In order to process PHP scripts it needs a separate process called PHP-FPM. I'd still recommend using php-fpm directly over apache setup. Please check if php-fpm(maybe called php5-fpm or similar, look for `FPM`) is installed/configured/running on your host or at least check if anyone listens on port 9000 (`netstat -nltp|grep 9000`). – jollyroger Apr 13 '17 at 00:26
  • @jollyroger - thanks. That actually didn't give a result, so looks like its not running for some reason. The weird thing, is that I do see it: `root 3671 0.0 0.2 83660 5404 ? Ss Apr12 0:02 php-fpm: master process (/usr/local/vesta/php/etc/php-fpm.conf)`, but its just not listening for some reason – Andrew Newby Apr 13 '17 at 06:18
  • @jollyroger - I just checked, and it looks like php7.0-fpm is running, but just not listening. I've updated my post above – Andrew Newby Apr 13 '17 at 06:30

1 Answers1

2

There are two common ways of using Nginx with PHP projects:

Nginx serves static files, PHP processing is done by PHP-FPM daemon and proxied by Nginx using FastCGI

This is a common scenario to setup a dedicated server to get best performance and you should use it unless your application heavily relies on some Apache's features like .htaccess and you cannot write this once and for all inside Nginx config.

server {
    ...
    root /home/test/web/foo.co.uk/public_html;
    fastcgi_index index.php;

    location / { try_files $uri $uri/ /index.php?$args; }
    location ~ \.php$ {
        include fastcgi_params;
        fastcgi_param SCRIPT_FILENAME $document_root$fastcgi_script_name;
        fastcgi_pass 127.0.0.1:9000;
    }

    location ~* ^.+\.(jpg|jpeg|gif|png|ico|svg|css|zip|tgz|gz|rar|bz2|exe|pdf|doc|xls|ppt|txt|odt|ods|odp|odf|tar|bmp|rtf|js|mp3|avi|mpeg|flv|html|htm)$ {
        access_log     /var/log/apache2/domains/foo.co.uk.log combined;
        access_log     /var/log/apache2/domains/foo.co.uk.bytes bytes;
        expires        max;
    }
}

Nginx serves static files, everything else is proxied to an internal Apache daemon

In this case PHP processing is done by Apaches mod_php module. The setup is something like this:

server {
    ...
    root /home/test/web/foo.co.uk/public_html;
    location / { proxy_pass https://178.79.134.35:8443; }
    location ~* ^.+\.(jpg|jpeg|gif|png|ico|svg|css|zip|tgz|gz|rar|bz2|exe|pdf|doc|xls|ppt|txt|odt|ods|odp|odf|tar|bmp|rtf|js|mp3|avi|mpeg|flv|html|htm)$ {
        access_log     /var/log/apache2/domains/foo.co.uk.log combined;
        access_log     /var/log/apache2/domains/foo.co.uk.bytes bytes;
        expires        max;
    }
}

There is no need in fallback code for static files unless you want your apache to generate a heavy 404 page. This also can be set up in nginx with error_page directive.

Also, in this case please consider connecting to Apache on a loopback interface on a plain HTTP port fo better performance. HTTPS should be set up on the front-end web server only. Proxying to a HTTPS-enabled port on the same host does not really give you any benefit.

UPDATE: I used TCP socket connection to PHP-FPM in my examples just for the sake of example. However there are many benchmarks on the Internet that showed better performance for local UNIX sockets rather than TCP sockets. For Nginx it's fairly easy to use UNIX socket as well:

fastcgi_pass unix:/run/php/php7.0-fpm.sock;

Make sure to check access permissions to that file and corresponding path.

jollyroger
  • 1,650
  • 11
  • 19
  • Thanks for your detailed response :) The issue was actually due to the fact php-fpm was running on a socket, instead of listening on the port. Fixed that up, and it works like a charm now. Maybe add that into your answer so I can accept it? – Andrew Newby Apr 13 '17 at 07:00
  • 1
    I added info on using unix sockets for nginx/php-fpm. This should encourage readers to use correct setup from the start. Hope this suits you as well. – jollyroger Apr 13 '17 at 23:34
  • thanks. I ended up doing it a different way in the end as well :) Instead of an nginx + apache2 setup, I went with nginx + php-fpm, and then have Apache as a backend (purely for my Perl stuff, so I can run it under mod_perl). Seems to be working perfectly now, and even the Wordpress updates stuff works well now – Andrew Newby Apr 14 '17 at 09:41