I have a PHP script that takes two variables and creates a dynamic image. If I access the script directly in the browser it works perfectly. However, I'm trying to use a rewrite rule to make the url nicer looking. Instead of the script executing, the browser downloads the .php source code. What am I doing wrong?
server {
listen 80;
root /folder/subfolder;
index index.html;
server_name domain.com;
location / {
autoindex on;
try_files $uri $uri/ /index.html /index.php?$args;
rewrite ^/images/(\d+)/(\d+)\.png /_images.php?x=$1&y=$2 last;
}
location ~ ^(.+\.php)(.*)$ {
fastcgi_split_path_info ^(.+\.php)(.*)$;
fastcgi_pass 127.0.0.1:9000;
fastcgi_index index.php;
include /etc/nginx/fastcgi_params;
}
}
Related
I have a React frontend and a Symfony backend I'm trying to serve on the same domain. The React frontend needs to serve assets if they exist otherwise fallback to serve index.html.
I'd like to serve the php Symfony app when /api is in the request uri. Similar to the React app, I need all requests to go to the index.php file.
The frontend is being served correctly but not the api. I get a 404 from nginx when i hit /api in the browser.
I feel like i'm close but for some reason nginx doesn't have the correct $document_root. I'm adding a header(X-script) to test what the variables are and I'm getting the following:
X-script: /usr/share/nginx/html/index.php
Here's my nginx config.
server {
listen 80 default_server;
index index.html index.htm;
access_log /var/log/nginx/my-site.com.log;
error_log /var/log/nginx/my-site.com-error.log error;
charset utf-8;
location /api {
root /var/www/my-site.com/backend;
try_files $uri $uri/ /index.php$is_args$args;
}
location / {
root /var/www/my-site.com/frontend;
try_files $uri /index.html;
}
location ~* \.php$ {
add_header X-script "$document_root$fastcgi_script_name" always;
try_files $fastcgi_script_name =404;
fastcgi_split_path_info ^(.+\.php)(/.+)$;
fastcgi_pass unix:/var/run/php/php7.0-fpm.sock;
fastcgi_index index.php;
include fastcgi_params;
fastcgi_param SCRIPT_FILENAME $document_root$fastcgi_script_name;
fastcgi_param HTTPS off;
}
}
Any help would be much appreciated.
The web root of a Symfony 4 project must include the public subfolder. I am not using NGINX but I think this is the correct configuration:
location /api {
root /var/www/my-site.com/backend/public;
In the following vhost, the most important changes I made are :
commented out index directive in server block : it is handled directly in locations blocks
added a slash after location /api/ and remove unnecessary $uri/ in the same api location block
moved the php_fpm logic to index.php location block : you want all requests to be passed to front controller in Symfony app
For the same reason, moved the 404 logic to a general php block, which will handle any other php file request
server {
listen 80 default_server;
access_log /var/log/nginx/my-site.com.log;
error_log /var/log/nginx/my-site.com-error.log error;
charset utf-8;
location /api/ {
root /var/www/my-site.com/backend;
try_files $uri /index.php$is_args$args;
}
location / {
root /var/www/my-site.com/frontend;
try_files $uri /index.html;
}
location ~ ^/index\.php(/|$) {
fastcgi_pass unix:/var/run/php/php7.0-fpm.sock;
fastcgi_split_path_info ^(.+\.php)(/.+)$;
include fastcgi_params;
fastcgi_param SCRIPT_FILENAME $document_root$fastcgi_script_name;
fastcgi_param DOCUMENT_ROOT $realpath_root;
fastcgi_param HTTPS off;
internal;
}
# return 404 for all other php files not matching the front controller
# this prevents access to other php files you don't want to be accessible.
location ~ \.php$ {
return 404;
}
}
Last, I bet you'll have to add symfony public folder into api location block root directive.
This vhost was tested fine on my localhost with following tree.
api_test
- backend
- index.php
- frontend
- index.html
I can successfully access to
backend/index.php from api_test.dv/api
frontend/index.html from api_test.dv/
Kojos answer is excellent, but to make it completely functional a root directive needs to be added under server or an error message “primary script unknown” will be observed. This is almost always related to a wrongly set SCRIPT_FILENAME in the nginx fastcgi_param directive.
# Nginx configuration
server {
listen 80 default_server;
listen [::]:80 default_server;
server_name ${NGINX_HOST};
root /var/www/html/backend/public;
access_log /var/log/nginx/access_log.log;
error_log /var/log/nginx/error.log error;
charset utf-8;
location / {
root /var/www/html/frontend/build;
try_files $uri /index.html;
}
location /api {
alias /var/www/html/backend/public;
try_files $uri /index.php$is_args$args;
}
location ~ ^/index\.php(/|$) {
fastcgi_pass php-fpm:9000;
fastcgi_split_path_info ^(.+\.php)(/.*)$;
include fastcgi_params;
fastcgi_param SCRIPT_FILENAME $realpath_root$fastcgi_script_name;
fastcgi_param DOCUMENT_ROOT $realpath_root;
internal;
}
# return 404 for all other php files not matching the front controller
# this prevents access to other php files you don't want to be accessible.
location ~ \.php$ {
return 404;
}
}
i want to create routing like a:
hxxp://127.0.0.1/ <-- default with default location /var/www/ without listning directories
hxxp://127.0.0.1/allegro/
How to do it?
If i go to hxxp://127.0.0.1/allegro/scripts/test.php i see a blank page. If i go to hxxp://127.0.0.1/ php scripts excutes normally and i see phpinfo()
My nginx config:
server {
listen 8000 default_server;
listen [::]:8000 default_server;
root /var/www/html;
index index.php index.html index.htm index.nginx-debian.html;
server_name localhost;
location / {
try_files $uri $uri/ =404;
}
location ~ \.php$ {
include snippets/fastcgi-php.conf;
fastcgi_pass unix:/run/php7.0-fpm.sock;
}
location /allegro/ {
alias /var/www/allegro/;
autoindex on;
location ~ \.php$ {
fastcgi_split_path_info ^(.+?\.php)(/.*)?$;
fastcgi_pass unix:/run/php7.0-fpm.sock;
fastcgi_index index.php;
include fastcgi_params;
}
}
}
There are multiple issues with your current configuration. The most important is that the URI /allegro/scripts/test.php is not processed by the nested location block, because regular expression location blocks take precedence (unless a ^~ modifier is used).
location ^~ /allegro/ {
root /var/www;
# autoindex on;
try_files $uri $uri/ =404;
location ~ \.php$ {
try_files $uri =404;
fastcgi_pass unix:/run/php7.0-fpm.sock;
include fastcgi_params;
}
}
The ^~ modifier ensures that this prefix location takes precedence over regular expression locations at the same level. See this document for details.
Note that the root statement is preferred over an alias statement where applicable (see this document for details).
The fastcgi_split_path_info and fastcgi_index directives are unnecessary for location blocks which do not match URIs with path info.
You will need to decide whether include fastcgi_params or include snippets/fastcgi-php.conf is the more appropriate source for FastCGI parameters.
I am trying to use different directory from where to serve the files, but have been unsuccessful. /var/www/site.app/public is where the root, but I want to serve news from /var/www/news/api instead, while having URL http://site.app/news/123, from which I want to remove the news part, because otherwise it would map to /var/www/news/api/news/123.
Judging by the debug logs, it seems that it gets rewritten correctly when first testing all location blocks, but after it is done rewritting, it goes through all of them again, and ends up serving content with location block /.
Here is my configuration file I have.
server {
listen 80;
server_name site.app;
root /var/www/site.app/public;
rewrite_log on;
error_log /var/log/nginx/error.log debug;
index index.php index.html;
location / {
try_files $uri $uri/ index.php?$query_string;
}
location /news/ {
root /var/www/news/api;
rewrite ^/news/(.*) /api.php?_=$1;
index index.php index.html;
}
location ~ \.(hh|php)$ {
try_files $uri /index.php =404;
fastcgi_pass 127.0.0.1:9000;
fastcgi_index index.php;
fastcgi_param SCRIPT_FILENAME $document_root$fastcgi_script_name;
include fastcgi_params;
}
}
The root directive in your /news/ location currently does nothing. You are rewriting the URI to /api.php which then hits your \.(hh|php)$ location, which inherits the root from the parent server container.
You need a distinct location for /api.php, possibly /news/api.php. In which case you can construct a separate location block (possibly nested within /news/) where you can place fastcgi_pass code using the different root.
So this is not ideal solution, but it works. By default it would still allow access to api.php, but I am denying access to it by checking if the URL contains /news/
server {
listen 80;
server_name site.app;
root /var/www/site.app/public;
index index.php index.html;
location / {
try_files $uri $uri/ index.php?$query_string;
}
location = /api.php {
if ($request_uri !~ ^/news/) {
return 444;
}
root /var/www/site.app/news/;
try_files $uri $uri/ /api.php?$query_string =408;
fastcgi_pass 127.0.0.1:9000;
fastcgi_index index.php;
fastcgi_param SCRIPT_FILENAME $document_root$fastcgi_script_name;
include fastcgi_params;
}
location /news/ {
rewrite ^/news/(.*) /api.php?$1;
}
location ~ \.(hh|php)$ {
try_files $uri /index.php =407;
fastcgi_pass 127.0.0.1:9000;
fastcgi_index index.php;
fastcgi_param SCRIPT_FILENAME $document_root$fastcgi_script_name;
include fastcgi_params;
}
}
I've been struggling with a NGINX configuration. I've set up a development environment (local laptop) with a configuration supporting search engine friendly (SEF) urls, but the same configuration doesn't seem to work on my test server.
local configuration:
server {
server_name example;
root /home/arciitek/git/example/public;
client_max_body_size 500M;
location /collection/ {
try_files $uri $uri/ /collection/index.php$args;
index index.php;
}
location / {
index index.html index.htm index.php;
try_files $uri $uri/ /index.php?q=$uri&$args;
}
location ~ \.php$ {
include /etc/nginx/fastcgi_params;
fastcgi_pass unix:/var/run/php5-fpm.sock;
fastcgi_index index.php;
fastcgi_param SCRIPT_FILENAME /home/arciitek/git/example/public/$fastcgi_script_name;
}
}
This works fine. Now on the test environment it looks like this:
{
server_name dev.example.com;
access_log /srv/www/dev.example.com/access.log;
error_log /srv/www/dev.example.com/error.log debug;
root /srv/www/dev.example.com/public;
location /collection/ {
try_files $uri $uri/ /collection/index.php$args;
index index.php;
}
location / {
index index.html index.htm index.php;
try_files $uri $uri/ /index.php?q=$uri&$args;
}
location ~ \.php$ {
include /etc/nginx/fastcgi_params;
fastcgi_pass unix:/var/run/php-fastcgi/php-fastcgi.socket;
fastcgi_index index.php;
fastcgi_param SCRIPT_FILENAME /srv/www/dev.example.com/public$fastcgi_script_name;
}
}
On my development environment everything is fine. But on my test environment, when I call a url in my browser with prettyness added : collection/[brand]/[product]. I get the: No input file specified error. Mind you, if I call a url anding with collection/ everyting works as well..
Can anyone help me with this please? if more info is needed, please let me know..
kind regards,
Erik
After frustrating for a long time, I noticed that it was not the configuration that gave me trouble, but the link to sites-enabled...
There you go... *pads himself on the back...
I has a site host on a NGINX server which used to work fine to remove index.php in nginx site config using try_files.
But now I am going to add a blog on it, where the URL will be www.foo.com/blog, I can access the blog and use index.php?p=.
But, once I use pretty permalink with Nginx Helper, www.foo.com/blog/2013/07/bar, I get 404.
server {
# don't forget to tell on which port this server listens
listen 80;
# listen on the www host
server_name foo.com;
# and redirect to the non-www host (declared below)
return 301 $scheme://www.ultra-case.com$request_uri;
}
server {
# listen 80 default_server deferred; # for Linux
# listen 80 default_server accept_filter=httpready; # for FreeBSD
listen 80;
# The host name to respond to
server_name www.foo.com;
# Path for static files
root /web/foo.com
#index file
index index.php;
#Specify a charset
charset utf-8;
# Custom 404 page
error_page 404 /404.html;
# Uri Rewrite
location /blog {
index index.php;
try_files $uri $uri/ /blog/index.php?$args;
}
location / {
autoindex on;
# This is cool because no php is touched for static content.
# include tihe "?$args" part so non-default permalinks doesn't break when using query string
try_files $uri $uri/ /index.php?$args;
}
location ~ \.php$ {
#NOTE: You should have "cgi.fix_pathinfo = 0;" in php.ini
include fastcgi.conf;
fastcgi_intercept_errors on;
fastcgi_pass 127.0.0.1:9000;
fastcgi_index index.php;
}
# Include the component config parts for h5bp
include conf/h5bp.conf;
}
The accepted answer routes everything through index.php.
This will break certain script includes, the wp-admin script being one of them.
You can use:
location /blog/ {
index index.php;
try_files $uri $uri/ /blog/index.php?$args;
}
Um... Thank you for all comments and answer. But finally I use this method to get it works
location /blog {
index index.php;
rewrite ^/blog/(.*)+$ /blog/index.php?$1; # it finally works
# return 200 $request_uri; # it is for inspect what $request_uri is
# try_files $uri $uri/ /blog/index.php$request_uri$is_args$args; # it gets 500 server error
}
Please point out if current setting has any problems. thank you!
I would suggest the following, to catch any permalinks under subfolder /blog
location /blog {
index index.php;
try_files $uri $uri/ /blog/index.php?$args;
}
Try this, I changed my answer to try to imitate the same behaviour you are using in your rewrite.
location ~ /blog(.*) {
index index.php;
try_files $uri /blog/index.php?$1&$args;
}
Try this
location /api {
# example: http://demo.com/api/channels/dmzb
root /data/webserver/demo.com/api/web;
rewrite ^/api/(.*) /$1 break;
try_files $uri $uri/ /api/index.php?$args;
location ~ ^/api/index\.php {
fastcgi_pass 127.0.0.1:9000;
fastcgi_index index.php;
include fastcgi.conf;
# fix request_uri
set $changed_request_uri $request_uri;
if ($changed_request_uri ~ ^/api(.*)) {
set $changed_request_uri $1;
}
fastcgi_param REQUEST_URI $changed_request_uri;
# fix script_filename
fastcgi_split_path_info ^(?:\/api\/)(.+\.php)(.*);
fastcgi_param SCRIPT_FILENAME $document_root/$fastcgi_script_name;
}
}
Think for php, rewrite is no needed with something like this:
location /app/ {
include fastcgi_params;
fastcgi_param SCRIPT_FILENAME /path/to/your/app/index.php;
fastcgi_pass php;
}
With following fastcgi pass
upstream php {
server unix:/var/run/php5-fpm.sock;
}
A universal solution for pretty URLs in root and one subfolder level:
set $virtualdir "";
set $realdir "";
if ($request_uri ~ ^/([^/]*)/.*$ ) {
set $virtualdir /$1;
}
if (-d "$document_root$virtualdir") {
set $realdir "${virtualdir}";
}
location / {
try_files $uri $uri/ $realdir/index.php?$args;
}
I found that with permalink enabled, I needed a combination of both sets of answers given here, otherwise
With only the rewrite, none of the static files got served
With only the try files, the permalinks did not work
This is working on my set up
location /blog/ {
rewrite ^/blog/(blog/(tag|category|20??)/.*)+$ /blog/index.php?$1;
try_files $uri $uri/ /blog/index.php?$args =404;
}
ip url: 123.123.123/xxxxxxxxxx/
location /xxxxxxxxxx/ {
try_files $uri $uri/ /xxxxxxxxxx/index.php?$query_string;
}
# Rewrite multisite '.../wp-.*' and '.../*.php'.
if (!-e $request_filename) {
rewrite ^(/xxxxxxxxxx/.*)+(/wp-.*) /xxxxxxxxxx/$2 last;
rewrite ^(/xxxxxxxxxx/.*)+.*(/wp-admin/.*\.php)$ /xxxxxxxxxx/$2 last;
rewrite ^(/xxxxxxxxxx/.*)+(/.*\.php)$ /xxxxxxxxxx/$2 last;
}