NGINX configuration for static and PHP files - php

I am trying to configure nginx to serve static and PHP files. The config I have isn't working. I want the following local folder structure:
src/static/ -> contains HTML, CSS, JS, images etc
src/api/ -> contains PHP files for a small REST service
If I visit http://mysite.local I want to be served files from the /static folder. If I visit http://mysite.local/api I want to be served the API PHP files. I want the requests to the api to be re-written and sent to an index.php file.
Some examples:
http://mysite.local/test.html -> served from src/static/test.html
http://mysite.local/images/something.png -> served from src/static/images/something.png
http://mysite.local/css/style.css -> served from src/static/css/style.css
http://mysite.local/api/users -> served from src/api/index.php?users
http://mysite.local/api/users/bob -> served from src/api/index.php?users/bob
http://mysite.local/api/biscuits/chocolate/10 -> served from src/api/index.php?biscuits/chocolate/10
The below config works for static files but not for the api files. I get a 404 error back if I visit one of the API paths.
server {
listen 80;
server_name mysite.local;
access_log /var/log/nginx/mysite.access.log main;
error_log /var/log/nginx/mysite.error.log debug;
location / {
index index.html;
root /var/www/mysite/src/static;
try_files $uri $uri/ =404;
}
location /api {
index index.php;
root /var/www/mysite/src/api;
try_files $uri $uri/ /index.php?$query_string;
location ~ \.php$ {
try_files $uri = 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 initial problem is the root directive in the location /api block, which should not include the location component as this gets appended as part of the URI, so:
location /api {
root /var/www/mysite/src;
...
}
will result in a local path of /var/www/mysite/src/api/index.php when presented with the URI /api/index.php. See this document for details.
The try_files rule does not rewrite the URI as you specify in your example. If you really need the final path of the URI to be presented as a query string to /api/index.php you will need to use rewrite.
The simplest solution (if you do not need to serve static content from that location) is to replace your try_files with:
location /api {
...
rewrite ^/api/(.*)$ /api/index.php?$1 last;
location ~ \.php$ { ... }
}
Otherwise, use a named location:
location /api {
...
try_files $uri $uri/ #rewrite;
location ~ \.php$ { ... }
}
location #rewrite {
rewrite ^/api/(.*)$ /api/index.php?$1 last;
}
See this and this for details.

Related

Nginx: how to make a single global location block that handle dynamic prefixed path

I need to handle multiple Laravel projects in a single dynamic "location" block in Nginx config (regex):
/var/www/html/
/var/www/html/any1/public
/var/www/html/some2/public
/var/www/html/project3/public
And change the root/alias to a relative public folder, handling the .php files too:
http://localhost/***/route should serve /var/www/html/***/public/index.php/route
and
http://localhost/***/static.css should serve /var/www/html/***/public/static.css
I tried:
set $the_root $document_root;
location ~ /(?<subdir>[^/]+) {
alias $the_root/$subdir/public;
index index.php;
try_files $uri $uri/ /$subdir/public/index.php?$args;
}
and
location ~ ^/\d+[a-zA-Z]+/ {
index index.php index.html;
try_files $uri $uri/ /$1/public/index.php$is_args$args;
}
But it doesn't work, how to do that?

nginx not redirecting to upstream location

I thought I had understood the basics of nginx rewrite rules. How wrong I was.
Can you please let me know what is I am doing so wrong here:
server {
listen 80;
server_name myserver;
index index.php index.html index.htm;
root /apps/user/websites/;
location / {
autoindex on;
}
location ~ myapp {
try_files $uri $uri /office/myapp/api/public/index.php;
}
location ~\.php$ {
try_files $uri $uri /office/fake/index.html;
# include fastcgi.conf;
# fastcgi_pass php-fpm-upstream;
}
}
If I visit http://myserver/office The index.php is accessed, but instead of being caught by the last location (~.php$) as I thought it would, it is processed as a text file and send to the browser.
I was expecting to receive the office/fake/index.html file instead.
Thank you very much,
Andres
Regex matching locations are checked in the same order they are appeared in the config file. Having the
location ~ myapp {
try_files $uri $uri /office/myapp/api/public/index.php;
}
before the
location ~\.php$ {
try_files $uri $uri /office/fake/index.html;
# include fastcgi.conf;
# fastcgi_pass php-fpm-upstream;
}
would give you an endless loop on every URI containing myapp substring (except those that are matching existed files and not ended with .php) because the /office/myapp/api/public/index.php URI matches the myapp regex. You should swap those locations in order to get this configuration workable.

Configuring php with nginx inside a reactjs app

I have a nginx configuration for a react app. I however would also like to include a sitemap.php that I build dynamically with php.
So here is my nginx config:
server {
listen 80;
listen [::]:80;
server_name mysite.com;
index index.html index.htm;
location ~ \.php$ {
include snippets/fastcgi-php.conf;
fastcgi_pass unix:/var/run/php/php7.0-fpm.sock;
}
location /sitemap.xml {
alias /var/www/web-app/public/sitemap.php;
}
location / {
root /var/www/web-app/public;
try_files $uri $uri/ /index.html;
default_type "text/html";
}
}
The snippets file consist of this:
# regex to split $uri to $fastcgi_script_name and $fastcgi_path
fastcgi_split_path_info ^(.+\.php)(/.+)$;
# Check that the PHP script exists before passing it
try_files $fastcgi_script_name =404;
# Bypass the fact that try_files resets $fastcgi_path_info
# see: http://trac.nginx.org/nginx/ticket/321
set $path_info $fastcgi_path_info;
fastcgi_param PATH_INFO $path_info;
fastcgi_index index.php;
include fastcgi.conf;
Also, this is hosted on an Ubuntu 16.04 digitalocean VPS.
My react app still loads fine. It is based on the index.html in my site root (/var/www/web-app/public). If I put test.php in the public folder, I get a 404 error. For my sitemap.xml alias, it forwards correctly to sitemap.php (also in public) but the php does not render.
So my two biggest issues here:
1. Why am I getting a 404 on /mysite.com/test.php?
2. And why is my php not rendering when it does work? (i.e. sitemap.php)
You are missing a root statement for your location ~ \.php$ block, so your PHP files will not be found. As this seems to be a common root with the location / block, simply move the statement up to server block scope:
root /var/www/web-app/public;
location ~ \.php$ {
include snippets/fastcgi-php.conf;
fastcgi_pass unix:/var/run/php/php7.0-fpm.sock;
}
location / {
try_files $uri $uri/ /index.html;
default_type "text/html";
}
There are a number of ways to redirect /sitemap.xml to /sitemap.php, but a rewrite...last will be simplest and invisible to users:
location = /sitemap.xml {
rewrite ^ /sitemap.php last;
}
See this document for location syntax, and this one for the rewrite directive.

Nginx multiple projects in one domain blank page laravel

This is my config here for Nginx. I have a domain named tstdmn and two Laravel projects first tstdmn.com project and second florist project I want to deploy florist project into the tstdmn.com/florist, I set it all but it returns a blank page at tstdmn.com/florist what's my issue here?! And I know the problem is with my Nginx configuration because I switch the florist project to the main project and it works, it's not from my Laravel configurations
root /var/www/html/tstdmn.com/public;
# Add index.php to the list if you are using PHP
index index.html index.php index.htm index.nginx-debian.html;
server_name tstdmn.com www.tstdmn.com;
location / {
# First attempt to serve request as file, then
# as directory, then fall back to displaying a 404.
try_files $uri $uri/ /index.php?$query_string;
}
location ^~ /florist {
alias /var/www/html/florist/florist_backend/public;
try_files $uri $uri/ #laravel1;
location ~ \.php {
fastcgi_pass unix:/var/run/php/php7.1-fpm.sock;
fastcgi_split_path_info ^(.+\.php)(.*)$;
include /etc/nginx/fastcgi_params;
}
}
location #laravel1 {
rewrite /florist/(.*)$ /florist/index.php?/$1 last;
}
location ~ \.php$ {
include snippets/fastcgi-php.conf;
fastcgi_pass unix:/run/php/php7.1-fpm.sock;
}
And so another route of project show's blank like /register
I solved it by someone's solution at laracasts:
using subdomain instead of routing
server { listen 80; listen [::]:80;
root /var/www/html/florist/florist_backend/public;
# Add index.php to the list if you are using PHP
index index.html index.php index.htm index.nginx-debian.html;
server_name florist.tstdmn.com;
location / {
# First attempt to serve request as file, then
# as directory, then fall back to displaying a 404.
try_files $uri $uri/ /index.php?$query_string;
}
..... and some code not related
address of question in laracast https://laracasts.com/discuss/channels/servers/nginx-multiple-projects-in-one-domain-errors

Nginx to serve static page before dynamic

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

Categories