In the following site config file i am trying to:
Load index.php on the first visit.
Load files as they appear in the /uploads/ directory.
Any other request should still be handled by index.php.
server {
listen 80 default_server;
listen [::]:80 default_server;
root /home/va/www/example;
# Add index.php to the list if you are using PHP
# index index.php;
server_name example.dev;
location ~ .*
{
try_files /dev/null #php;
}
location /uploads/
{
try_files $uri =404;
expires 30d;
}
location #php
{
include snippets/fastcgi-php.conf;
#pretty url
fastcgi_param SCRIPT_FILENAME $document_root/index.php;
fastcgi_pass unix:/var/run/php/php7.4-fpm.sock;
}
}
However, the last part breaks. In other words:
/ works
/?test=test works
/uploads/test.jpeg works
/random_string does not work and returns 404 error
My understanding is that location ~ .* has no choice but to match everything. Where is the 404 error coming from?
Ok. After working on it some more, and completely rewriting the logic, i have gotten a muse from The MediaWiki Nginx guide. The final solution is:
server {
listen 80 default_server;
listen [::]:80 default_server;
root /home/va/www/example;
server_name example.dev;
location = /
{
return 301 /home;
}
location = /index.php
{
include snippets/fastcgi-php.conf;
#pretty url
fastcgi_param SCRIPT_FILENAME $document_root/index.php;
fastcgi_pass unix:/var/run/php/php7.4-fpm.sock;
}
location /uploads/
{
try_files $uri =404;
expires 30d;
}
location /
{
rewrite ^/(?<pagename>.*)$ /index.php;
}
location /classes/ { deny all; }
location /config/ { deny all; }
}
I will then use $_SERVER['REQUEST_URI'] within PHP to route the request. Hopefully this solution will help somebody.
I'm trying to add a PHP app in subdirectory with different root location.
For example, I have a Rails app at root / and I want to add a phpBB forum at /forum location.
I also have a specific need: I want to add a rewrite rule for a file located in forum root directory (e.g. rewrite /forum/foo.php to /forum/bar.php)
I tried multiple configurations with some examples given on stackoverflow but none of the solutions work :(
If there is no solution I will use subdomain instead (e.g. forum.domain.com), but I would like to try with only one domain if possible
upstream railsApp {
server unix:/tmp/puma.sock;
}
server {
listen 80;
server_name domain.com;
return 301 https://$server_name$request_uri;
}
server {
listen 443 ssl http2;
server_name domain.com;
root /var/www/domain.com/railsApp/public;
ssl_certificate /etc/nginx/ssl_certs/domain.com/fullchain.pem;
ssl_certificate_key /etc/nginx/ssl_certs/domain.com/privkey.pem;
client_body_buffer_size 10M;
client_max_body_size 10M;
location / {
try_files $uri #proxy;
}
location #proxy {
include proxy_params;
proxy_pass http://railsApp;
}
# Here I want a PHP app with different root location
# forum is an example
location /forum {
root /var/www/other-location;
index index.html index.php;
include proxy_params;
location ~ \.php$ {
fastcgi_pass unix:/var/run/php/php7.4-fpm.sock;
fastcgi_index index.php;
fastcgi_param SCRIPT_FILENAME $document_root$fastcgi_script_name;
include fastcgi_params;
}
# I also want to add rewrite rule for a specific file name
location ~ /foo {
rewrite ^(.*)$ /bar.php$1 last;
}
}
}
Thanks
I'm looking for an nginx rule that would do this:
input url: http://domain.com/#johndoe
what our backend sees: http://domain.com/users/profile/johndoe
Example: http://medium.com/#stuartkhall
The current rule I'm using (removed things that don't have to do with this question):
server {
listen 80 default_server;
listen [::]:80 default_server ipv6only=on;
server_name _;
root /var/html;
location / {
try_files $uri $uri/ /index.php$is_args$args;
}
location ~ \.php$ {
include fastcgi_params;
fastcgi_pass mainphp;
fastcgi_param SCRIPT_FILENAME $document_root$fastcgi_script_name;
}
}
What kind of rule I can add to my current nginx config? I experimented with a rewrite but wasn't able to get it to work.
Better practice is location + return instead of rewrite, so try this (place before any location):
location ~ ^/#(.*)$ {
return 301 /users/profile/$1;
}
or identical rewrite in case you prefer it
rewrite ^/#(.*)$ /users/profile/$1 last;
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;
}
My problem is following: I use Wordpress on Nginx with "pretty links". I also run 2 other services on ports 88 and 1234 and I want to make a subdomains bugs.mydomain and mail.mydomain. I did the proxypass on location / but it's working only for the main directory, anything that is after the domain/ is falling into Wordpress "pretty links" mechanism. Do you have any idea how to solve this? My config files below:
The server config:
server {
listen <IP>:80;
root /usr/share/nginx/www/domain;
index index.html index.htm index.php;
server_name domain www.domain;
location / {
try_files $uri $uri/ /index.html;
if ( $host ~ "bugs.domain" ) {
proxy_pass http://domain:88;
}
if ( $host ~ "mail.domain" ) {
proxy_pass http://domain:1234;
}
}
location /doc/ {
alias /usr/share/doc/;
autoindex on;
allow 127.0.0.1;
deny all;
}
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 ~ /\.ht {
deny all;
}
include /home/domain/public_html/nginx.conf;
}
the config for specified domain (with Wordpress):
#First there is many rewrites for the W3TC plugin, like minification, caches etc
if ($host ~* ^www\.(.*))
{
set $host_without_www $1;
rewrite ^/(.*)$ $scheme://$host_without_www/$1 permanent;
}
#
# unless the request is for a valid file, send to bootstrap
if (!-e $request_filename)
{
rewrite ^(.+)$ /index.php?q=$1 last;
}
Now, when I enter domain:88 or domain:1234 it works. When I enter bugs.domain the website loads, but no CSS or images works as the url is bugs.domain/somapath and this falls into the Wordpress bootstrap. I run out of the ideas.
why create only 1 server with if's in it, separate the servers
server {
listen 80;
server_name bugs.example.com;
proxy_pass http://example.com:88;
}
server {
listen 80;
server_name mail.example.com;
proxy_pass http://example.com:1234;
}
server {
listen 80;
# the rest of your main server
#
}
So the problem was completely different then I thought. it was failing on this line:
try_files $uri $uri/ /index.html;
The problem was, that file index.html didn't exist, I only had index.php. Changing it solved the problem.