rewrite or internal redirection cycle while internally redirecting to, in nginx
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.
Related videos on Youtube
Andrew Newby
Updated on September 18, 2022Comments
-
Andrew Newby almost 2 years
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" portUPDATE 3: I found a post where they said about editing the
www.conf
file: https://github.com/serghey-rodin/vesta/issues/1025So 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!
-
Admin about 7 yearsYou are missing any support for PHP. See this page for guidance.
-
Admin about 7 years@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 { }
-
Admin about 7 yearsYou still lack the location that would process PHP. Should be something like
location ~ \.php$ { ... fastcgi_pass unix;/var/run/php5-fpm.sock; ... }
-
Admin about 7 years@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 :/
-
Admin about 7 years@jollyroger - is there any way I can just forward the scripts to my Apache install on 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 :/
-
Admin about 7 yearsNginx 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
). -
Admin about 7 years@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 -
Admin about 7 years@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 about 7 yearsThanks 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?
-
Miguel Diaz Ballesteros about 7 yearsI 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.
-
Andrew Newby about 7 yearsthanks. 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 <G>