Nginx configuration for two versions of PHP - php

I'm trying to set up an nginx environment where legacy code and new MVC-style code can co-exist, so that I can gradually refactor it page by page. The legacy code needs an older version of PHP (it runs best on 5.3, but I had trouble compiling that, so I went with 5.4 and will fix anything that breaks), but it is easily distinguishable by URL, because it has literal file names like http://sub.domain.com/search.php?category=4, etc. instead of new style like http://sub.domain.com/search/category/4 - the key difference is the presence of .php.
The new code runs fine with the following in the nginx config:
server {
listen 80;
server_name *.myproject.dev;
root /var/www/myproject/public;
index index.php index.html index.htm;
try_files $uri $uri/ #rewrite;
location #rewrite {
rewrite ^/(.*)$ /index.php?_url=/$1;
}
location ~ ^(.+\.php)(/.*)?$ {
fastcgi_param PATH_INFO $fastcgi_path_info;
fastcgi_param PATH_TRANSLATED $document_root$fastcgi_path_info;
fastcgi_param SCRIPT_FILENAME $document_root$fastcgi_script_name;
fastcgi_pass unix:/var/run/php5-fpm.sock;
fastcgi_split_path_info ^(.+\.php)(/.+)$;
include fastcgi_params;
}
}
(I will admit that I don't completely understand all that code - it came from various guides and such.)
With the help of this great tutorial I compiled and installed PHP 5.4 in its own location listening on port 9001. It works fine using a separate domain for the old code, but what I want to do is use a single domain, but call the old code if .php is found in the URL, and do the requisite rewrite on anything else and use the new code. I found this post on ServerFault and tried incorporating its ideas in my situation like this:
server {
listen 80;
server_name *.myproject.dev;
root /var/www/myproject/public;
index index.php index.html index.htm;
try_files $uri $uri/ #rewrite;
location #rewrite {
rewrite ^/(.*)$ /index.php?_url=/$1;
}
location ~ ^(.+\.php)(/.*)?$ {
fastcgi_param PATH_INFO $fastcgi_path_info;
fastcgi_param PATH_TRANSLATED $document_root$fastcgi_path_info;
fastcgi_param SCRIPT_FILENAME $document_root$fastcgi_script_name;
fastcgi_pass unix:/var/run/php5-fpm.sock;
fastcgi_split_path_info ^(.+\.php)(/.+)$;
include fastcgi_params;
# Anything with ".php" is directed to the old codebase
location ~* \.php {
root /var/www/myproject/oldcode;
fastcgi_pass 127.0.0.1:9001;
}
}
}
But the rewrite adds index.php to the new code, so in the end, everything matches the .php test, which is not the intent. I tried putting those final four lines earlier in the file with several variations, but that didn't help (either a blank page or still only going to the old code location, depending on the details). Does someone know enough about nginx config syntax to help me rearrange it so that it does what I want?

If your new code only uses /index.php and without any path_info, you could use a prefix location:
location ^~ /index.php { ... }
location ~* \.php { ... }
The first location takes precedence due to the ^~ operator. Or an exact match (which also takes precedence):
location = /index.php { ... }
location ~* \.php { ... }

Related

How to make assets work with Symfony3 in subdirectory on Nginx

Based on this question How to install symfony2 app in a subdirectory in nginx
I've created symfony3 application that works in subdirectory called bcms4. I've manged to make php work with PHP-FPM but I have probelms with assets. When I want to GET asset it directs the request to app_dev and shows 404 because obviosly the path does not exist.
My question is how to make assets not to be proccesed by app_dev but downloaded as supposed?
So when I enter
test.localhost/s/asdfad -> it runs symfony
test.localhost/asdf -> it runs other app living in main dir
test.localhost/s/assets/css/test.css -> it will show file in directory /var/www/test.localhost/bcms4/web/assets/css/test.css
My nginx config:
server {
listen 80;
root /var/www/test.localhost;
index index.html index.htm index.php;
# Make site accessible from http://localhost/
server_name test.localhost;
location / {
# First attempt to serve request as file, then
# as directory, then fall back to displaying a 404.
try_files $uri $uri/ =404;
# Uncomment to enable naxsi on this location
# include /etc/nginx/naxsi.rules
}
location ~ ^/s(/.*)$ {
try_files /s/web$1 /web$1 #sf2dev =404;
}
location #sf2dev {
expires off;
fastcgi_pass unix:/var/run/php5-fpm.sock;
include fastcgi_params;
fastcgi_param SCRIPT_FILENAME /var/www/test.localhost/bcms4/web/app_dev.php;
fastcgi_param SCRIPT_NAME /s/app_dev.php;
fastcgi_param REQUEST_URI /s$1;
}
location ~ \.php$ {
fastcgi_split_path_info ^(.+\.php)(/.+)$;
# NOTE: You should have "cgi.fix_pathinfo = 0;" in php.ini
# With php5-fpm:
fastcgi_pass unix:/var/run/php5-fpm.sock;
fastcgi_split_path_info ^(.+\.php)(/.*)$;
include fastcgi_params;
fastcgi_param SCRIPT_FILENAME $realpath_root$fastcgi_script_name;
fastcgi_param DOCUMENT_ROOT $realpath_root;
fastcgi_intercept_errors on;
}
}
After hours of trying I've managed to figure it out with little hack.
This is what I've added to my config file
location ~ ^/s(/.*).\w{1,5}$ {
rewrite ^/s(/.*) /bcms4/web$1 break;
return 404;
}
It'll rewrite files that has prefix /s and extension to directory where they are actually.
Maybe it will help someone. I'll leave question open for a while maybe someone has better solution cause it's seems hacky for me.

Nginx to host app in different location [closed]

Closed. This question does not meet Stack Overflow guidelines. It is not currently accepting answers.
This question does not appear to be about a specific programming problem, a software algorithm, or software tools primarily used by programmers. If you believe the question would be on-topic on another Stack Exchange site, you can leave a comment to explain where the question may be able to be answered.
Closed 7 years ago.
Improve this question
I'm trying to serve CachetHQ in nginx + php-fpm in a specific location. The docs gives this as example that serves in status.example.com (which works):
server {
listen 80;
server_name status.example.com;
root /var/www/Cachet/public;
index index.php;
location / {
try_files $uri /index.php$is_args$args;
}
location ~ \.php$ {
include fastcgi_params;
fastcgi_pass 127.0.0.1:9000;
fastcgi_param SCRIPT_FILENAME $document_root$fastcgi_script_name;
fastcgi_index index.php;
fastcgi_keep_conn on;
}
}
However, instead of serving in status.example.com, I would like to serve in example.com/status.
I was expecting that this would work, but from error.log I see it's trying /etc/nginx/htmlindex.php, but it should be /mnt/data/site/www-cachet/public/index.php:
location /status/ {
index index.php;
root /mnt/data/site/www-cachet/public;
try_files $uri index.php$is_args$args;
location ~ ^/status/.+\.php$ {
root /mnt/data/site/www-cachet/public;
include fastcgi_params;
fastcgi_pass unix:/tmp/php-fpm.sock;
fastcgi_param SCRIPT_FILENAME $document_root$fastcgi_script_name;
fastcgi_index index.php;
fastcgi_keep_conn on;
}
}
Let me start with the original configuration that you claim works, and try to modify it for your requirements, results below:
location ^~ /status {
alias /var/www/Cachet/public;
index index.php;
location = /status {
return 302 /status/;
}
location / {
try_files $uri /status/index.php$is_args$args;
}
location ~ \.php$ {
include fastcgi_params;
fastcgi_pass 127.0.0.1:9000;
rewrite ^/status/(.*) /$1;
rewrite ^(.*)/ $1/index.php; # who knows what fastcgi_index is for?
fastcgi_param SCRIPT_FILENAME $document_root$uri;
fastcgi_keep_conn on;
}
}
Basically, you want to use alias instead of root here, and probably also have an absolute path in the final try_files as well. I don't think adding extra prefixes within nested locations is needed, but you might want to make sure that the root location is a final match with the ^~ modifier.
The main trick, I guess, is that even with the alias directive things aren't as dandy as with a proper root, so, you have to make sure that the SCRIPT_FILENAME is set correctly. This part doesn't seem to be documented very clearly, and I'm too lazy to test out whether $fastcgi_script_name ngx variable and fastcgi_index directive play nice with alias -- instead of trying to determine how those work (or not), we simply do a couple of rewrite rules as applicable, and construct SCRIPT_FILENAME based on the results of our rewrite rules instead. :-)
However, with that said, I'd think the second rewrite rule (as well as the fastcgi_index it replaces) might as well be a no-op, because how were we supposed to end up in a \.php$ location if $uri didn't end in .php already?
(Likewise, you're free to try to remove the first rewrite rule, too, and replace $uri in SCRIPT_FILENAME with $fastcgi_script_name, and see if things still work, but the internet from 2009 may indicate that they didn't.)
Your try_files is not correct.
You can do it like this:
index index.php;
root /mnt/data/site/www-cachet/public;
location / {
if (!-e $request_filename) {
rewrite ^(.*)$ /index.php?$1 last;
break;
}
}
location ~ ^/status/.+\.php$ {
root /mnt/data/site/www-cachet/public;
include fastcgi_params;
fastcgi_pass unix:/tmp/php-fpm.sock;
fastcgi_param SCRIPT_FILENAME $document_root$fastcgi_script_name;
fastcgi_index index.php;
fastcgi_keep_conn on;
}
After so many hours trying a lot of combinations, the way I got it working was:
location ^~ /status {
alias /mnt/data/site/www-cachet/public;
try_files $uri $uri/ #status;
location = /status/ {
rewrite /status/$ /status/index.php;
}
location ~ ^/status/(.+\.php)$ {
fastcgi_pass unix:/tmp/php-fpm.sock;
fastcgi_index index.php;
fastcgi_param SCRIPT_FILENAME /mnt/data/site/www-cachet/public/$1;
include fastcgi_params;
}
}
location #status {
rewrite /status/(.*)$ /status/index.php?/$1 last;
}
The most important thing was fastcgi_param, I had to set it to an absolute path instead of $document_root$fastcgi_script_name or something like it. I'm not sure if it's a good pratice, but adding alias to the block just doesn't work, and neither nginx or FastCGI show us the path of the file they're trying to read.
Nevertheless I couldn't get CachetHQ to work well. Problem is that all paths in source code are absolute, so they won't point to the subdirectory which our files are hosted. The solution was do something that I was reluctant since beginning: host it in a subdomain.

Laravel 5 - Nginx/PHP config issue

I'm having an issue where when I go to the /public directory it shows the Laravel app as normal, but navigating away to any other page results in it saying
No input file specified.
I am using an Nginx server with PHP 5.5.9 FPM.
I've scoured google for the last 4 hours or so, looking at every tutorial and stackoverflow page for rewriting issues in Laravel however they all yield the same result.
I've even set all the files and folders to 777 so I could see if it was some sort of permissions issue. I've checked the Laravel config and it's all set, I've no idea what is wrong.
Can anyone point me in the right direction?
The last config I tried is below:
server {
listen 80 default_server;
root /usr/share/sites/base;
index index.php
server_name localhost;
location / {
try_files $uri $uri/ /index.php?$args;
}
location ~ \.php$ {
fastcgi_pass unix:/var/run/php5-fpm.sock;
include fastcgi_params;
}
}
I have also tried many others such as:
server {
listen 80;
server_name domain.com;
root /usr/share/sites/base;
index index.php;
location / {
try_files $uri $uri/ /index.php?$query_string;
}
if (!-d $request_filename) {
rewrite ^/(.+)/$ /$1 permanent;
}
location ~* \.php$ {
# Server PHP config.
fastcgi_pass unix:/var/run/php5-fpm.sock;
fastcgi_index index.php;
fastcgi_split_path_info ^(.+\.php)(.*)$;
include /etc/nginx/fastcgi_params;
fastcgi_param SCRIPT_FILENAME $document_root$fastcgi_script_name;
}
location ~ /\.ht {
deny all;
}
}
The error "No input files specified" will nearly always be related to the fact that the wrong path was sent to php.
Looking at your 'last config tried' I can see that fastcgi_param SCRIPT_FILENAMEis not defined in your php location. You should first begin by defining it in the location :
location ~ \.php$ {
fastcgi_pass unix:/var/run/php5-fpm.sock;
include fastcgi_params;
fastcgi_param SCRIPT_FILENAME $document_root$fastcgi_script_name
}
Furthermore you say that you can reach the app so this means that index.php is working but not when you change page. So the problem should also come from /index.php?$args. Indeed, using this line if I try to reach yourserver.com/test and if 'test' is not a file in your root path nginx will then try request /index.php? (I had this probem). You should try only with /index.php.
EDIT : The solution was that root directive should point to the Laravel public folder, in that case /usr/share/sites/base/public.

Nginx – Rewrite rule madness

I'm trying to redirect links that look like:
http://example.com/dev/some_project
to their physical location:
http://example.com/dev/some_project/some_project.php
In order to achieve this, I came up with this following rule set:
location / {
try_files $uri $uri/ #folderless-php;
index index.php index.html index.htm;
}
location #folderless-php {
rewrite ^(.*)$ "${uri}/${basename}.php";
}
This, however, will for some reason just invoke an internal server error.
So I tried changing it to:
location / {
set $folderless "${uri}/${basename}.php";
try_files $uri $uri/ $folderless;
index index.php index.html index.htm;
}
This seemed to work with curl, but when I tried this in any browser, I was just offered to download the file that I tried to access, to my astonishment.
What causes this behavior? Is there a way to achieve what I'm trying to do?
You are being given a download as you haven't told Nginx how to handle PHP files. You need to set up the fast-cgi parameters to something like:
location ~ \.php$ {
fastcgi_read_timeout 60000;
fastcgi_pass 127.0.0.1:9000;
fastcgi_index index.php;
fastcgi_param SCRIPT_FILENAME /var/www/site$fastcgi_script_name;
include fastcgi_params;
}

Nginx Rewrite Rule for all .PHP files/requests to be parsed by index.php

Is it any magic rewrite (like it does on Apache) for nginx to be able to rewrite URLs like '/submit.php' to be able to process them from index.php? We have lots of 404 not found errors because of the site structure and all previous URLs were like '/addrate.php', '/my_settings.php', '/profile.php' --> there are over 50 files like this and it would be very unprofessional and code-unwise to create a separate .php file for each of these functions, instead of parsing them all through index.php and using the needed classes like we do with the other rewrites.
Can you please find a solution/give us a suggestion today about this?
I think some info about this is here, but I want the exact reversed result:
http://www.nullis.net/weblog/2011/05/nginx-rewrite-remove-file-extension/
This configuration allow you to handle all URL (non-existing files in file system) with one php script placed in /var/www/example.org/htdocs/index.php
server {
listen 80; ## listen for ipv4
server_name example.org www.example.org;
root /var/www/example.org/htdocs;
access_log /var/log/nginx/example.org.access.log;
error_log /var/log/nginx/example.org.error.log;
location / {
index index.php index.html index.htm;
try_files $uri $uri/ #php;
}
# enable running php files under php fastcgi
location ~ \.php {
fastcgi_pass 127.0.0.1:9000;
fastcgi_index index.php;
fastcgi_param SCRIPT_FILENAME /var/www/example.org/htdocs$fastcgi_script_name;
#fastcgi_param QUERY_STRING $uri;
include fastcgi_params1;
}
location #php {
fastcgi_pass 127.0.0.1:9000;
fastcgi_index index.php;
fastcgi_param SCRIPT_FILENAME /var/www/example.org/htdocs/index.php; # this script catches all non existing URLs
fastcgi_param QUERY_STRING $uri;
include fastcgi_params1;
}
}

Categories