We have a website build with react by a partener. And we want to add a blog on the same domain, in a subdirectory:
example.org => /var/www/example.org/app
example.org/blog => /var/www/example.org/blog
I tried many solutions, but I always got a 404 on example.org/blog
server {
server_name example.org;
root /var/www/project/app/functions/build;
access_log /var/log/nginx/example.org_access.log;
error_log /var/log/nginx/example.org_error.log;
index index.html index.htm;
location ^~ /blog/ {
access_log /var/log/nginx/blog-example.org_access.log;
error_log /var/log/nginx/blog-example.orgm_error.log;
alias /var/www/example.org/blog;
index /index.php;
# Add a trailing slash if missing
if (!-f $request_filename) {
rewrite [^/]$ $uri/ permanent;
}
try_files $uri $uri/ /index.php?$args;
}
location / {
try_files $uri #prerender;
}
location #prerender {
// .. config for react stuff
}
location ~ \.php$ {
try_files $uri =404;
fastcgi_split_path_info ^(.+\.php)(/.+)$;
fastcgi_index index.php;
# Change this to your fpm socket
fastcgi_pass unix:/var/run/php/php7.4-fpm.sock;
fastcgi_param SCRIPT_FILENAME $document_root$fastcgi_script_name;
fastcgi_param PATH_INFO $fastcgi_path_info;
include fastcgi_params;
}
}
I tried to create a subdomain with a separate nginx site conf to test if everything was OK, and it was. So it's my nginx site config above which is not good.
Do you have any idea?
Thanks you!
Solution
Thanks to Ivan Shatsky, I was able to correct my config to make everything works.
My main issue why I always had a 404 was because of my index. I had an extra slash: index /index.php => index index.php
location /blog/ {
access_log /var/log/nginx/blog-example.org_access.log;
error_log /var/log/nginx/blog-example.org_error.log;
root /var/www/example.org;
index index.php;
# Add a trailing slash if missing
if (!-f $request_filename) {
rewrite [^/]$ $uri/ permanent;
}
try_files $uri $uri/ /blog/index.php?$args;
location ~ \.php {
try_files $uri =404;
fastcgi_split_path_info ^(.+\.php)(/.+)$;
fastcgi_index index.php;
# Change this to your fpm socket
fastcgi_pass unix:/var/run/php/php7.4-fpm.sock;
fastcgi_param SCRIPT_FILENAME $document_root$fastcgi_script_name;
fastcgi_param PATH_INFO $fastcgi_path_info;
include fastcgi_params;
}
}
Not sure if this will be an answer, but the errors I already see are:
If your react app doesn't make use of PHP (and I suppose it doesn't) why are you use location ^~ /blog/ { ... } having a PHP handler below this block? This way no request for /blog/any/path/file.php ever reach that PHP handler. Use simple location /blog/ { ... } prefix location or move the PHP handler inside the location ^~ /blog/ { ... } making it nested location (preferred).
If your directory where the WP is located is /var/www/example.org/blog and your URI pefix is /blog/ you'd better use root /var/www/example.org; instead of alias /var/www/example.org/blog;. It those string doesn't match, add the trailing slash at the end of the alias directive argument: alias /var/www/example.org/blog/;
You are using try_files directive incorectly, the last argument supposed to be an URI, so to redirect all the requests to WP index file you should use try_files $uri $uri/ /blog/index.php?$args;
Your PHP handler uses global /var/www/project/app/functions/build root instead of WordPress one (if you'd make the PHP handler nested location, this one would gone automatically).
Not sure that's all, but lets start from fixing these errors.
Update
The final working configuration was added by OP as the original question update.
Related
Having the following nginx configuration I try to load static content if url /intern is requested, but what I try it fails in 404. How can I properly setup nginx for this case?
server {
listen 80;
root /var/www/html/public;
index index.php index.html index.htm;
location / {
try_files $uri $uri/ /index.php?$query_string;
}
location ~ \.php$ {
include fastcgi_params;
#try_files $uri /index.php =404;
fastcgi_split_path_info ^(.+\.php)(/.+)$;
fastcgi_pass php:9000;
fastcgi_index index.php;
fastcgi_param SCRIPT_FILENAME $document_root$fastcgi_script_name;
}
location = /intern {
autoindex on;
root /var/www/html/public/back;
}
}
In case of the root directive, full path is appended to the root including the location part, whereas in case of the alias directive, only the portion of the path NOT including the location part is appended to the alias.
So for:
location = /intern/ {
autoindex on;
root /var/www/html/public/back;
}
nginx will create the final path to be:
/var/www/html/public/back/intern/*
Assuming you don't have the intern directory inside the .../public/back/ directory, this will result in a 404 error.
If that's the case, you should use the alias directive. Where the location path is dropped before looking for the file at the said location.
try this:
location = /intern/ {
autoindex on;
alias /var/www/html/public/back/; # trailing slash is important here
}
This should result in the path:
/var/www/html/public/back/*
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 have a Symfony2 application running alongside WordPress - mysite.com/blog routes to my /var/www/mysite/wordpress/ directory and everything else routes to /var/www/mysite/symfony:
server {
listen 80;
server_name mysite.com
location / {
try_files $uri /app.php$is_args$args;
}
location ~ ^/app\.php(/|$) {
fastcgi_pass 127.0.0.1:9000;
fastcgi_split_path_info ^(.+\.php)(/.*)$;
include fastcgi_params;
fastcgi_param SCRIPT_FILENAME $request_filename;
internal;
}
location /blog {
root /var/www/mysite/wordpress;
rewrite ^/blog/(.+)$ /$1 break;
try_files $uri $uri/ /blog/index.php?q=$uri&$args;
index index.php;
location ~ \.php {
fastcgi_pass 127.0.0.1:9000;
include fastcgi_params;
fastcgi_split_path_info ^(?:\/blog)(.+\.php)(.*);
fastcgi_param SCRIPT_FILENAME $document_root$fastcgi_script_name;
}
}
}
Everything works fine, except the WordPress admin (mysite.com/blog/wp-admin/) gives me a 404 error. Visiting mysite.com/blog/wp-admin/index.php works as expected, so it looks like the index index.php line is not working. What could be the issue here?
You should use alias instead of root directive:
location ^~ /blog {
alias /var/www/mysite/wordpress;
index index.php;
try_files $uri $uri/ /blog/index.php?q=$uri&$args;
location ~ \.php$ {
fastcgi_pass 127.0.0.1:9000;
include fastcgi_params;
fastcgi_split_path_info ^(?:\/blog)(.+\.php)(.*);
fastcgi_param SCRIPT_FILENAME $document_root$fastcgi_script_name;
}
}
You need to edit the nginx server Configuration.
# WordPress single blog rules.
# Designed to be included in any server {} block.
# This order might seem weird - this is attempted to match last if rules below fail.
# http://wiki.nginx.org/HttpCoreModule
location / {
try_files $uri $uri/ /index.php?$args;
}
# Add trailing slash to */wp-admin requests.
rewrite /wp-admin$ $scheme://$host$uri/ permanent;
# Directives to send expires headers and turn off 404 error logging.
location ~* ^.+\.(ogg|ogv|svg|svgz|eot|otf|woff|mp4|ttf|rss|atom|jpg|jpeg|gif|png|ico|zip|tgz|gz|rar|bz2|doc|xls|exe|ppt|tar|mid|midi|wav|bmp|rtf)$ {
access_log off; log_not_found off; expires max;
}
# Uncomment one of the lines below for the appropriate caching plugin (if used).
#include global/wordpress-wp-super-cache.conf;
#include global/wordpress-w3-total-cache.conf;
# Pass all .php files onto a php-fpm/php-fcgi server.
location ~ [^/]\.php(/|$) {
fastcgi_split_path_info ^(.+?\.php)(/.*)$;
if (!-f $document_root$fastcgi_script_name) {
return 404;
}
# This is a robust solution for path info security issue and works with "cgi.fix_pathinfo = 1" in /etc/php.ini (default)
include fastcgi.conf;
fastcgi_index index.php;
# fastcgi_intercept_errors on;
fastcgi_pass php;
}
More about this here:
http://codex.wordpress.org/Nginx#General_WordPress_rules
So, if you allege that /blog/wp-admin/index.php works, but /blog/wp-admin/ doesn't, perhaps just conditionally append index.php, if need be?
+ rewrite ^/blog/wp-admin(/)?$ /wp-admin/index.php break;
rewrite ^/blog/(.+)$ /$1 break;
So, what do the logs say in regards to your 404? I think this might be related to the fact that the index directive causes "an internal redirect", thus I would not be surprised if your 404 ends up being generated through the / instead of the /blog location.
I'm trying to get a clear understanding of what's going on with my nginx configuration file for Symfony2, here it is:
server {
listen 80;
autoindex on;
server_name example.com;
root /var/www/example.com/web;
rewrite ^/app\.php/?(.*)$ /$1 permanent;
location / {
index app.php;
try_files $uri $uri/ #symfony;
}
location #symfony {
rewrite ^(.*)$ /app.php/$1 last;
}
location ~ ^/app\.php(/|$) {
include fastcgi_params;
fastcgi_pass unix:/var/run/php5-fpm.sock;
fastcgi_split_path_info ^(.+\.php)(/.*)$;
fastcgi_param SCRIPT_FILENAME $document_root$fastcgi_script_name;
fastcgi_param SCRIPT_NAME $fastcgi_script_name;
}
}
In short, I'm trying to strip app.php in every possible URI that a user can set e.g. example.com/app.php/demo or just example.com/app.php.
This config actually works for URIs like ones above, but it leads to a redirect loop in case of trying to access "root" URI example.com.
And if I remove $uri/ from try_files and leave only $uri and a fallback #symfony there, everything is working fine except I can't access any directories as they're going to be processed by SF.
I'm out of ideas, did a lot of research on how nginx and rewrites actually work, but as for now it's a dead end for me. If you can find a solution to stay with $uri/ in try_files and get out of a loop at front, please let me know.
This solution from Nginx Tips worked for me. It's almost, but not quite, the same as yours.
server {
server_name domain.tld www.domain.tld;
root /var/www/project/web;
location / {
# try to serve file directly, fallback to rewrite
try_files $uri #rewriteapp;
}
location #rewriteapp {
# rewrite all to app.php
rewrite ^(.*)$ /app.php/$1 last;
}
location ~ ^/(app|app_dev|config).php(/|$) {
fastcgi_pass unix:/var/run/php5-fpm.sock;
fastcgi_split_path_info ^(.+.php)(/.*)$;
include fastcgi_params;
fastcgi_param SCRIPT_FILENAME $document_root$fastcgi_script_name;
fastcgi_param HTTPS off;
}
error_log /var/log/nginx/project_error.log;
}
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;
}