I'm trying to rewriting /assets/* -> to /theme/theme_1/*.
The rewrite url works with all files except .php-files.
Example file structure:
/theme/theme_1/images/image.jpg
/theme/theme_1/images/user.jpg
/theme/theme_1/ajax/register.php
/theme/theme_1/ajax/read.php
The problem is the PHP-files, I get a 404 with this url:
wget http://example.com/assets/ajax/read.php.
File is found (200) using full path http://example.com/theme/theme_1/ajax/read.php
All other file works fine (200):
wget http://example.com/assets/images/image.jpg
nginx config:
server {
listen 80 default_server;
root /var/www/html;
index index.php index.html
server_name mysite.com;
location ~ \.php$ {
include snippets/fastcgi-php.conf;
fastcgi_pass 127.0.0.1:9000;
fastcgi_param SCRIPT_FILENAME $document_root$fastcgi_script_name;
}
location /assets {
rewrite ^/assets/(.*) /theme/theme_1/$1 break;
}
location / {
try_files $uri $uri/ /index.php?$args;
}
}
Okie you should try this
location /assets/ {
alias /var/www/html/theme/theme_1/;
}
If that doesn't work then try
location /assets/ {
alias /var/www/html/theme/theme_1/;
try_files $uri $uri/ /index.php?$args;
}
Edit-1
On second look I realize the previous answer won't work as ~ \.php { block will catch everything with php extension and the other assets block can never get called. So the solution is to nest the rewrite inside the php block. So use
location ~ \.php$ {
rewrite ^/assets/(.*)$ /theme/theme_1/$1;
include snippets/fastcgi-php.conf;
fastcgi_pass 127.0.0.1:9000;
fastcgi_param SCRIPT_FILENAME $document_root$fastcgi_script_name;
}
Related
I have two directories, /home/php/www/public/ and /home/php/www/private/ and I would like to serve which one depending on the first part of the uri.
I would like /foo/ to act 'normally' in that it should serve which ever file is in the location, for example mysite.com/about would serve /public/about.php. However /private/ would always serve a single file no matter the request, for example mysite.com/private/foo, mysite.com/private/bar and mysite.com/private/foo/test would all serve /private/app.php.
I am probably in the 100s of different variations from what I have seen here and in other googles but being very new to all of this can't seem to piece together exactly what I need. After a few days of trial and error I am close to what I am after, mysite.com/about serves /public/about.php correctly and mysite.com/private/whatever gets /private/app.php but it doesn't execute it, it serves it as a download instead.
Here is what I have so far:
server {
listen 80;
listen [::]:80;
root /home/php/www/public;
index index.php;
server_name mysite.com;
location /private/ {
alias /home/php/www/private;
try_files /app.php =404;
location ~ [^/]\.php(/|$) {
# location ~ \.php$ {
# fastcgi_split_path_info ^(.+\.php)(/.+)$;
include snippets/fastcgi-php.conf;
fastcgi_pass unix:/run/php/php7.2-fpm.sock;
# fastcgi_index app.php;
# fastcgi_param SCRIPT_FILENAME $document_root$fastcgi_script_name;
# include fastcgi_params;
# return 302 https://google.com;
}
}
location / {
try_files $uri $uri.html $uri/ #extensionless-php;
}
location ~ \.php$ {
include snippets/fastcgi-php.conf;
fastcgi_pass unix:/run/php/php7.2-fpm.sock;
}
location #extensionless-php {
rewrite ^(.*)$ $1.php last;
}
location ~ /\.ht {
deny all;
}
}
If I replace everything inside the location /private/ block with just return 302 https://google.com it redirects successfully to google.com, so I know this location block is being returned but putting the same thing inside the location ~ \.php$ inside location /private/ nothing happens so to me it looks like it is not hitting this block, what am I missing? There aren't any errors in /var/log/nginx/error.log relating to this.
Try:
location /private/ {
root /home/php/www/private;
try_files /app.php =404;
include snippets/fastcgi-php.conf;
fastcgi_pass unix:/run/php/php7.2-fpm.sock;
}
Use root rather than alias as you are not trying to alias the original request. The file was downloaded because of the unnecessary nested location block.
I'm trying to serve my frontend app under /, but have requests for /oauth2 pass off to a php backend. Here is my latest nginx config attempt:
upstream dockerphp {
server backendphp:9000;
}
server {
listen 80;
server_name localhost;
index index.html;
root /application/frontend/build;
location /oauth2 {
root /application/public;
index index.php;
try_files $uri $uri/ /index.php$is_args$args;
#try_files /index.php$is_args$args =404;
location ~ \.php$ {
include /etc/nginx/fastcgi_params;
fastcgi_split_path_info ^(.+\.php)(/.+)$;
fastcgi_param SCRIPT_FILENAME $document_root$fastcgi_script_name;
fastcgi_param PATH_INFO $fastcgi_path_info;
fastcgi_pass dockerphp;
fastcgi_index index.php;
}
}
location / {
try_files $uri $uri/ /index.html;
}
}
I've tried just about every combination of config I can think of and just can't get it to work. Most of the time I end up with 404s.
Both my nginx and php docker containers have the same /application directory mounted.
With the above config, any requests to /oauth2/blah are being picked up by the location block at the bottom and therefore back to my frontend. This is probably my biggest problem - the /oauth2 location block to my mind is more "specific" so why isn't it "winning"?
I tried the commented out try_files line instead (to see whether index.php being the "fallback" value had an effect on specificity), and nginx just started downloading the index.php file rather than passing on the request. Help?
This is the approach that I use:
attempt to serve js / static pages first
if 1.) fails, pass to PHP backend
define a location for handling .php
upstream dockerphp {
server backendphp:9000;
}
server {
listen 80;
server_name localhost;
index index.html;
root /application/frontend/build;
location / {
try_files $uri $uri/ #php;
}
location #php {
root /application/public;
index index.php;
try_files $uri $document_root/index.php?$query_string;
# $document_root/index.php is the important part due to how root and alias directives work
}
location ~ \.php$ {
include /etc/nginx/fastcgi_params;
fastcgi_split_path_info ^(.+\.php)(/.+)$;
fastcgi_param SCRIPT_FILENAME $document_root$fastcgi_script_name;
fastcgi_param PATH_INFO $fastcgi_path_info;
fastcgi_pass dockerphp;
fastcgi_index index.php;
}
}
The location /oauth2 only wins when the URL you try is exactly website.com/oauth2. Add ^~ and the route will win all of the URLs starting with /oauth2, like this:
location ^~ /oauth2 {
For reference I eventually found a simple working solution (below).
upstream dockerphp {
server backendphp:9000;
}
server {
listen 80;
server_name localhost;
index index.html;
root /application/frontend/build;
location / {
try_files $uri $uri/ /index.html;
}
location /oauth2 {
try_files $uri $uri/ #php;
}
location #php {
include /etc/nginx/fastcgi_params;
fastcgi_pass dockerphp;
fastcgi_param SCRIPT_FILENAME /application/public/index.php;
}
}
I try to enable PHP for only one subdirectory (the laravel directory) but I didn't manage to get this working. NGINX is always saying 404 File not found or php says "no input file specifed". What am I doing wrong?
This is my location config:
location /laravel {
root html/laravel/public;
index index.php index.html index.html;
try_files $uri $uri/ /index.php?$query_string;
location ~ \.php$ {
root html/laravel/public;
fastcgi_pass 127.0.0.1:9000;
fastcgi_split_path_info ^(.+\.php)(/.+)$;
fastcgi_index index.php;
fastcgi_param SCRIPT_FILENAME document_root$fastcgi_script_name;
#include fastcgi_params;
include fastcgi.conf;
}
}
UDPATE 1: It seems that nginx does not properly evaluate my location expressions:
2018/09/12 16:30:44 [error] 26476#24408: *1 CreateFile() "C:/Server/nginx/html/index.php" failed (2: The system cannot find the file specified), client: 127.0.0.1, server: localhost, request: "GET /laravel/ HTTP/1.1", host: "localhost"
This is the wrong path and at least the root of the / location:
location / {
root C:/Server/nginx/html;
index index.html index.htm index.php;
}
I tried to move the block but nothing changes.
UPDATE 2:
It seems that nginx is very buggy. The documentation states:
Checks the existence of files in the specified order and uses the first found file for request processing; the processing is performed in the current context. The path to a file is constructed from the file parameter according to the root and alias directives. It is possible to check directory’s existence by specifying a slash at the end of a name, e.g. “$uri/”. If none of the files were found, an internal redirect to the uri specified in the last parameter is made.
As my error log shows, The try_files directive does not respect the root path because it trys to open the file relative to another location block.
As #Richard pointed out in the linked Stackoverflow Thread, this seems to be a bug of nginx. For me this solution works with nginx:
location /laravel {
alias html/laravel/public;
index index.php index.html index.html;
try_files $uri $uri/ #nested;
location ~ \.php$ {
fastcgi_pass 127.0.0.1:9000;
#fastcgi_split_path_info ^(.+\.php)(/.+)$;
include fastcgi.conf;
fastcgi_index index.php;
fastcgi_param SCRIPT_FILENAME $request_filename;
#include fastcgi_params;
}
}
location #nested {
rewrite /laravel/(.*)$ /laravel/index.php?/$1 last;
}
Source: https://serversforhackers.com/c/nginx-php-in-subdirectory
may be some changes and updates you need to apply:
If you want to put your laravel project in a subfolder on a server with ngnix-ubuntu 16-php.7.2, so here is update ngnix config :
1) your nested(subfolder) isn't inside your main folder
/var/www/main:
/var/www/nested:
then your config :
location /nested {
alias /var/www/nested/public;
try_files $uri $uri/ #nested;
location ~ \.php$ {
include fastcgi_params;
fastcgi_param SCRIPT_FILENAME $request_filename;
fastcgi_pass unix:/run/php/php7.2-fpm.sock;
}
}
location #nested {
rewrite /nested/(.*)$ /nested/index.php?/$1 last;
}
2) your laravel-test folder (subfolder) inside your main :
/var/www/main:
/var/www/main/nested:
then your config :
location /laravel-test {
alias /var/www/main/laravel-test/public;
try_files $uri $uri/ #laravelTest;
location ~ \.php$ {
include fastcgi_params;
fastcgi_param SCRIPT_FILENAME $request_filename;
fastcgi_pass unix:/run/php/php7.2-fpm.sock;
}
}
location #laravelTest {
rewrite /laravel-test/(.*)$ /laravel-test/index.php?/$1 last;
}
Some details about my setup first:
I am serving a static webapp (HTML + JS) from default Nginx webroot
I have a PHP-FPM server running on localhost:9000
The destination file should be /api/webroot/index.php for FPM (always, no need to try_files etc.)
I need to forward all /api and /api-debug calls to arrive at localhost:9000, and the /app/webroot/index.php should handle all these requests.
I have the following working Nginx configuration:
upstream fastcgi_backend {
server localhost:9000;
keepalive 30;
}
server {
listen 80;
location / {
root /usr/share/nginx/html;
index index.html index.htm;
location ~ ^/(api|api-debug)/ {
root /app/webroot;
index index.php;
try_files $uri /api/index.php$is_args$args;
location ~ \.php$ {
fastcgi_pass fastcgi_backend;
fastcgi_split_path_info ^(?:\/api\/)(.+\.php)(.*)$;
fastcgi_param SCRIPT_FILENAME /app/webroot/$fastcgi_script_name;
include fastcgi_params;
}
}
}
}
I just want to make it more simple and efficient, because as I see it now it's a mess.
I tried to adjust for example
try_files $uri /api/index.php$is_args$args;
to
try_files $uri /api/webroot/index.php$is_args$args;
and it failed... The only reason that it works is that /api/index.php includes /api/webroot/index.php, but I see it's inefficient.
I found debugging nginx config hard, because it's not easy to test.
Thank you very much for your help in advance!
The simplest solution would be to hardwire SCRIPT_FILENAME with a value of /app/webroot/index.php and remove one of your location blocks altogether.
location / {
root /usr/share/nginx/html;
index index.html index.htm;
}
location ~ ^/(api|api-debug)/ {
include fastcgi_params;
fastcgi_param SCRIPT_FILENAME /app/webroot/index.php;
fastcgi_pass fastcgi_backend;
}
Alternatively, to keep the flexibility of specifying a URI with a .php extension, you could simplify the configuration with:
location / {
root /usr/share/nginx/html;
index index.html index.htm;
rewrite ^/(api|api-debug)/ /index.php last;
}
location ~ \.php$ {
include fastcgi_params;
fastcgi_param SCRIPT_FILENAME /app/webroot$uri;
fastcgi_pass fastcgi_backend;
}
I want to serve static HTML files with NGINX, but if the file is missing, it should load a PHP file instead and PHP should handle the content.
I've been testing several combinations of try_files, but I can't get my head around it. I have a dummy PHP app that looks like this:
./
../
dynamic.php
index.php
static/
static/static.html
Then I have a small PHP code on index like this:
<?php
$path = $_SERVER['REQUEST_URI'];
$pattern = '/^\/(.*)\.html$/';
$matches = [];
$results = preg_match($pattern, $path, $matches);
if (count($matches) > 0) {
if ($matches[1] == "dynamic") {
require 'dynamic.php';
} else {
echo "Not found!";
}
} else {
echo "Index page!";
}
The results of browsing to each page should be:
http://foo.bar/ - Loads index.php
http://foo.bar/static.html - Loads static/static.html
http://foo.bar/dynamic.html - Loads index.php & PHP requires dynamic.php
http://foo.bar/baz.html - Loads index.php with "not found" message
This is what I got in the NGINX config file:
server {
listen 80;
server_name .foo.bar *.foo.bar;
access_log /var/log/nginx/foo.access.log;
error_log /var/log/nginx/foo.error.log;
root /var/www/foo;
index index.php;
location / {
# Trying with 'try_files' here. No success.
}
location ~ \.php$ {
try_files $uri =404;
fastcgi_split_path_info ^(.+\.php)(/.+)$;
fastcgi_pass unix:/var/run/php5-fpm-foo.sock;
fastcgi_index index.php;
fastcgi_param SCRIPT_FILENAME $document_root$fastcgi_script_name;
include fastcgi_params;
}
}
I've been trying repeatedly and evidently utterly failing with this line:
try_files $uri $uri/static /index.php;
I am missing something. Help?
I would use your static directory as document root. This ensures that nobody can execute /dynamic.php directly, however, it will be forwarded to your index.php by the named location block #php.
This configuration example is untested!
server {
index index.php;
root /var/www/foo/static;
server_name foo.bar *.foo.bar;
location / {
try_files $uri #php;
}
location #php {
include fastcgi_params;
fastcgi_pass unix:/var/run/php5-fpm-foo.sock;
fastcgi_index index.php;
fastcgi_param SCRIPT_FILENAME /var/www/foo/index.php;
}
}
You don't need the listen directive if it only contains 80 since this is the default.
The server_names should not contain a leading dot.
The $uri always contains the requested URI including the leading slash (e.g. /static.html) and nginx will prefix them with the document root upon invocation of try_files (e.g. /var/www/foo/static.html). Hence, you need to set your static directory before the $uri (e.g. /static$uri becomes /var/www/foo/static/static.html).
You don't need fastcgi_split_path_info because you are not using that feature.
Your try_files in your PHP location makes it impossible for nginx to properly forward things. A request for /dynamic.html does not end on .php, hence, try_files always fails.
There are a number of ways of hiding the static directory from the URL. For example, manipulating root, clever use of try_files or a rewrite.
Possibly the most obvious is this:
root /var/www/foo;
location / {
root /var/www/foo/static;
try_files $uri /index.php;
}
location ~ \.php$ { ... }
so that nginx looks in the static folder for normal files, but the parent folder for .php files.
What you were trying to achieve was something like this:
root /var/www/foo;
location / {
try_files /static$uri /index.php;
}
location ~ \.php$ { ... }
which will prefix /static to any URI before testing for existence. The /index.php must be the last element as it required processing in a different location. See this document for more.
Based on the specific example case you have given, the configuration below will return the results you listed.
server {
listen 80;
server_name .foo.bar *.foo.bar;
access_log /var/log/nginx/foo.access.log;
error_log /var/log/nginx/foo.error.log;
root /var/www/foo;
index index.php;
location ~ \.php$ {
try_files $uri =404;
fastcgi_split_path_info ^(.+\.php)(/.+)$;
fastcgi_pass unix:/var/run/php5-fpm-foo.sock;
fastcgi_index index.php;
fastcgi_param SCRIPT_FILENAME $document_root$fastcgi_script_name;
include fastcgi_params;
}
location ~ /static {
rewrite ^/static\.html$ /static/ last;
index static.html;
}
location ~ / {
rewrite ^ /index.php last;
}
That is ...
http://foo.bar/ - Loads index.php
http://foo.bar/static.html - Loads static/static.html
http://foo.bar/dynamic.html - Loads index.php & PHP requires dynamic.php
http://foo.bar/baz.html - Loads index.php with "not found" message