I am trying to setup nginx to try files in the following order:
1) See if file exists directly on server
2) See if file exists as part of wordpress
3) Fallback to external server if neither 1 or 2 exist.
I have the following setup:
location / {
try_files $uri $uri/ /index.php?q=$uri&$args #proxy;
}
location #proxy {
proxy_pass https://external.website.com;
}
This doesn't work for wordpress, and nginx's try_files documentation is pretty unhelpful. I can see that whichever arg is last is the fallback, so I tried flipping the last two args, and that caused wordpress to work, but then the reverse proxy didn't work.
I think I solved it. Technically this checks the proxy first, but that's okay for what I want to do. If anyone solves the correct way, I will choose them.
location / {
try_files $uri $uri/ #proxy;
}
location #proxy {
proxy_pass https://external.website.com;
proxy_intercept_errors on;
recursive_error_pages on;
error_page 404 = #wordpress;
}
location #wordpress{
try_files $uri /index.php?q=$uri&$args;
}
location ~ \.php$ {
try_files $uri =404;
fastcgi_split_path_info ^(.+\.php)(/.+)$;
fastcgi_pass unix:/var/run/php5-fpm.sock;
fastcgi_index index.php;
include fastcgi_params;
}
Related
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.
Let's say I have a file named careers.php, how do I serve this file when they click a link that goes to http://example.com/careers without the file extension for both .html and .php files with nginx?
Please note that the solution has to account for query strings. For instance, the URL may be http://example.com/careers?lang=fr.
Also, I'd like the solution to also try subdirectories as well. For instance; if my folder structure on the server is /views/careers.php, I want http://example.com/careers to still serve /views/careers.php.
My current configuration looks like the following:
server {
listen 80 default_server;
root /usr/share/nginx/landing-page;
index index.php index.html;
server_name example.com;
location / {
try_files $uri $uri/ =404;
}
error_page 404 /404.html;
error_page 500 502 503 504 /50x.html;
location ~ \.php$ {
try_files $uri =404;
fastcgi_split_path_info ^(.+\.php)(/.+)$;
fastcgi_pass unix:/var/run/php5-fpm.sock;
fastcgi_index index.php;
fastcgi_param SCRIPT_FILENAME $document_root$fastcgi_script_name;
include fastcgi_params;
}
}
A common solution uses try_files with a named location. The existing location ~ \.php$ block is used to process .php files. Also avoid any if statements.
location / {
try_files $uri $uri/ #rewrite;
}
location #rewrite {
rewrite ^ $uri.php last;
}
location ~ \.php$ {
try_files $uri =404;
...
}
You can use try_files:
try_files $uri $uri.php $uri/ =404;
I know that this is an old post, but I feel like this was never perfectly explained or explained using the most simple solution.
Here is an example of how I accomplished this for a React Application served using nginx for my Portfolio Website hosted on Digital Ocean.
When simplified it's super easy to accomplish. The location block should look like this.
//Originally my location block was set up like this
location /chatgpt-homepage.html {
root /var/www/myportfoliowebsite.com/html/chatgpt-app-homepage/build;
}
//What needs to happen is you need to remove the .html from your location
//and
//Add try_files $uri $uri.html $uri/ =404; underneath your root section of code
//New Location Block example below
location /chatgpt-homepage {
root /var/www/myportfoliowebsite.com/html/chatgpt-app-homepage/build;
try_files $uri $uri.html $uri/ =404;
}
I am using the following setup to run 2 applications on the same domain. If the first application returns 404 it tries the other one (wordpress on /blog).
location /blog {
root /var/www/blog;
index index.html index.htm index.php;
try_files $uri $uri/ /blog/index.php?$args;
location ~ \.php$ {
try_files $uri =404;
fastcgi_split_path_info ^(.+\.php)(/.+)$;
fastcgi_pass unix:/var/run/php5-fpm.sock;
fastcgi_index index.php;
include fastcgi_params;
}
}
location / {
# ...
proxy_intercept_errors on;
recursive_error_pages on;
error_page 404 =200 /blog/$uri;
}
Every page loads as expected and assets return 200 and the correct content.
But css and most images of those assets are not applied to the page, while a few work just fine.
The following is included:
include /etc/nginx/mime.types;
I understand that this is probably a bad configuration anyway but in my understanding it should still work.
Is there another configuration to achieve something similar?
EDITED:
The wordpress installation is located in /var/www/blog/blog/
I can't exactly understand the problem but I suggest you bring out that php block outside and remove blog and $args after index.php uri.
Try this one instead, let me know if this works out. :)
location /blog {
root /var/www/blog;
index index.html index.htm index.php;
try_files $uri $uri/ /index.php;
}
location ~ \.php$ {
try_files $uri =404;
fastcgi_split_path_info ^(.+\.php)(/.+)$;
fastcgi_pass unix:/var/run/php5-fpm.sock;
fastcgi_index index.php;
include fastcgi_params;
}
location / {
# ...
proxy_intercept_errors on;
recursive_error_pages on;
error_page 404 =200 /blog/$uri;
}
I've read a moderate amount of the documentation for location blocks, but I dont have much experience with RegEx so I am a bit lost on how to pull off what I am trying to do. The following nginx config will probably explain what I want to do better than I can word it:
server {
server_name example.com www.example.com;
root /var/www/;
index index.php;
location /blog/ {
try_files $uri $uri/ /index.php?$args;
}
location ~ \.php$ {
try_files $uri =404;
include fastcgi_params;
fastcgi_pass unix:/var/run/php5-fpm.sock;
}
location / {
try_files $uri #uwsgi;
}
location #uwsgi {
include uwsgi_params;
uwsgi_pass unix:/tmp/uwsgi.sock;
}
}
example.com/ is being served by a bottle app through uwsgi, and so all things under this location should be routed to the bottle app and handled there. This is working fine as expected, however I am lost on how to add an 'exception' to the location rule so that example.com/blog, and everything under it ../sub1/sub2 etc. are not directed to the bottle app, but infact handled by wordpress and its PHP magic.
This seems like it should be very simple to set up, but it's proving very difficult to google simple solutions to these sort of problems, as everyone seems to bloat thier 'tutorial' configurations with tons of non-essentials that confuse a beginner.
This may need some tweaks, but you should probably use a nested location block:
server {
server_name example.com www.example.com;
root /var/www;
index index.php;
location /blog/ {
try_files $uri $uri/ /blog/index.php?$args;
location ~ \.php$ {
try_files $uri =404;
include fastcgi_params;
fastcgi_pass unix:/var/run/php5-fpm.sock;
}
}
location / {
try_files $uri #uwsgi;
}
location #uwsgi {
include uwsgi_params;
uwsgi_pass unix:/tmp/uwsgi.sock;
}
}
Notice that the default URI is changed to /blog/index.php which is hopefully where all of your WordPress files are located.
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;
}