Nginx exception to rewrite rule - nginx

My company is running a webserver with nginx. The configuration is set so that every request on a certain server block are forcefully rewritten to https, using a location block. This is the full configuration for a specific domain:
# HTTP server
server {
listen 80;
server_name www.mydomain.it mydomain.it admin.mydomain.it;
rewrite ^(.*) https://$host$1 permanent;
}
# HTTPS server
server {
listen 443;
server_name www.mydomain.it mydomain.it admin.mydomain.it;
root /usr/share/nginx/html/mydomain_server;
ssl on;
ssl_certificate /etc/certs/mydomain-bundle.crt;
ssl_certificate_key /etc/certs/mydomain.key;
ssl_session_timeout 5m;
ssl_protocols SSLv2 SSLv3 TLSv1;
ssl_ciphers HIGH:!aNULL:!MD5;
ssl_prefer_server_ciphers on;
access_log /var/log/nginx/mydomain.ssl.access.log main;
error_log /var/log/nginx/mydomain.ssl.error.log error;
location / {
try_files $uri $uri/ =404;
}
error_page 404 /404-mydomain.html;
error_page 500 502 503 504 /50x.html;
location ~ \.php$ {
fastcgi_buffer_size 128k;
fastcgi_buffers 4 256k;
fastcgi_busy_buffers_size 256k;
try_files $uri =404;
fastcgi_pass unix:/var/run/php-fpm/php-fpm.sock;
fastcgi_index index.php;
fastcgi_param SCRIPT_FILENAME $document_root$fastcgi_script_name;
include fastcgi_params;
}
}
This domain serves several implementations of the same software to different customers, and works like this:
Customer John: www.domain.com/John
Customer Ada: www.domain.com/Ada
etc...
Obviously, as you can see, all accesses to such URLS are redirected to HTTPS.
Now, there is a particular need for a single customer not this to happen.
I've been reading the official doc here about locations, which tells I can't non-match a particular expression (as stated here too), and I can't find a way to have it work.
I've tried to add another location block matching the customer path before the default one, like this:
server {
listen 80;
server_name www.mydomain.it mydomain.it admin.mydomain.it;
root /usr/share/nginx/html/mydomain_server;
location ^~ /Mole/ {
try_files $uri $uri/ =404;
}
location / {
rewrite ^(.*) https://$host$1 permanent;
try_files $uri $uri/ =404;
}
}
which is not working, as Mole is still being redirected to HTTPS. I've tried using "~", "=" and even simply "location /Mole/", without success. Not a browser cache problem as I've tried already flushing it. What am I missing?

You could try using the map directive to identify customers who prefer to use http:
map $uri $use_https {
default 1;
~^/Mole/ 0; # add other exceptions as needed
}
server {
listen 80;
server_name www.mydomain.it mydomain.it admin.mydomain.it;
root /usr/share/nginx/html/mydomain_server;
location / {
if ($use_https) { # consider using 302 for testing
return 301 https://$host$request_uri;
}
try_files $uri $uri/ =404;
}
}

Related

Nginx yii2 configuration

Hi there!
I'am trying to configure Nginx for 2 yii projects, frontend for users and admin for admins with only one domain (no sub domain). I need to configure it in a way such that mydomain.com should refer to frontend and mydomain.com/admin to admin. The problem is I'am being able to configure only one of them at a time, meaning I can use frontend or admin not both of them.
What I have tried
front.conf
server {
listen 80;
server_name api.maim.experiments.uz;
return 301 https://$server_name$request_uri;
}
server {
charset utf-8;
client_max_body_size 128M;
listen 443 ssl;
ssl_certificate_key privkey.pem;
ssl_certificate fullchain.pem;
ssl_protocols TLSv1.2;
set $host_path "/home/itschool/inha_dev/frontend";
server_name api.maim.experiments.uz;
root $host_path/web;
set $yii_bootstrap "index.php";
access_log /var/log/nginx/itschool-access.log;
error_log /var/log/nginx/itschool-error.log;
location / {
index index.html $yii_bootstrap;
try_files $uri $uri/ /index.php;
}
location ~ ^/(protected|framework|themes/\w+/views) {
deny all;
}
location ~ \.(js|css|png|jpg|gif|swf|ico|pdf|mov|fla|zip|rar)$ {
try_files $uri =404;
}
location ~ \.php$ {
set $fsn /index.php;
if (-f $document_root$fastcgi_script_name){
set $fsn $fastcgi_script_name;
}
fastcgi_pass 127.0.0.1:9002;
include fastcgi_params;
fastcgi_param SCRIPT_FILENAME $document_root$fsn;
}
location ~ /\.(ht|svn|git) {
deny all;
}
location ~* /\. {
deny all;
access_log off;
log_not_found off;
}
}
back.conf
server {
listen 80;
server_name api.maim.experiments.uz;
return 301 https://$server_name$request_uri;
}
server {
charset utf-8;
client_max_body_size 128M;
listen 443 ssl;
ssl_certificate_key privkey.pem;
ssl_certificate fullchain.pem;
ssl_protocols TLSv1.2;
set $host_path "/home/itschool/inha_dev/backend";
server_name api.maim.experiments.uz;
root $host_path/web;
set $yii_bootstrap "index.php";
access_log /var/log/nginx/itschool-access.log;
error_log /var/log/nginx/itschool-error.log;
location ^~ /admin {
alias /home/itschool/inha_dev/backend/web;
if (!-e $request_filename) { rewrite ^ /admin/index.php last; }
location ~ \.php$ {
if (!-f $request_filename) { return 404; }
include fastcgi_params;
fastcgi_param SCRIPT_FILENAME $request_filename;
fastcgi_pass 127.0.0.1:9002;
}
}
location ~ /\.(ht|svn|git) {
deny all;
}
location ~* /\. {
deny all;
access_log off;
log_not_found off;
}
}
I found some questions with answers but they didn't work for me, please help.
I have recently use similar configuration to support web application / mobile application and admin panel on single domain
I hope this could help you out. Below is the configuration
server {
listen 80;
set $root /var/www/html/application;
#here we go
#if backend not found in url then set root url
if ($uri !~ "^(.*)/(backend)(.*)") {
set $root /var/www/html/application/frontend/web;
}
# when request is coming from mobile then display mobile site
# you don't need this one, I just written in order to explain the mobile application navigation.
if ($http_user_agent ~* "android|blackberry|googlebot-mobile|iemobile|ipad|iphone|ipod|opera mobile|palmos|webos") {
set $root /var/www/html/application/mobile/web;
}
root $root;
index index.php index.html index.htm index.nginx-debian.html;
server_name your_domain;
location ~ \.php$ {
include snippets/fastcgi-php.conf;
fastcgi_pass unix:/var/run/php/php7.0-fpm.sock;
}
location / {
index index.html index.php;
if (!-e $request_filename){
rewrite ^/(.*) /index.php?r=$1 last;
}
}
location ~ /\.ht {
deny all;
}
}
Also have a look in official document of Yii2 to setup yii2-app-advanced on single domain (Apache, Nginx).
CLICK HERE
One more thing that you need to know is if you want to change backend/web to admin then you also have to made some changes in Yii2 application.
One domain will lead all requests to one IP (server). Nginx will use the first server block matching server_name https://nginx.org/en/docs/http/request_processing.html so you need to put all configuration on one file and use location to separate them.
You can move location ^~ /admin at the beginning of the front.conf locations and play with roots;
Or you can create a proxying config file that will contain just a little.
Something like that
location /admin {
proxy_pass http://localhost:8001;
}
location / {
proxy_pass http://localhost:8002;
}
Using the latter one you should change front & back configs to listen to other ports. Also, an SSL certificate was given for a domain, not URL. So you can use it only in the proxying config.
If you follow some of the key instructions from option 1 of Yii2 Single Domain Apache and Nginx you should be able to accomplish what you want.
Per the referenced link, Option 1:
Assuming Linux OS
cd /path/to/project/frontend/web
ln -s ../../backend/web backend
and set your nginx file
server {
charset utf-8;
client_max_body_size 128M;
listen 80; ## listen for ipv4
#listen [::]:80 default_server ipv6only=on; ## listen for ipv6
server_name api.maim.experiments.uz;
root /home/itschool/inha_dev/frontend/web;
index index.php;
access_log /var/log/nginx/itschool-access.log;
error_log /var/log/nginx/itschool-error.log;
location / {
# Redirect everything that isn't a real file to index.php
try_files $uri $uri/ /index.php$is_args$args;
}
# uncomment to avoid processing of calls to non-existing static files by Yii
#location ~ \.(js|css|png|jpg|gif|swf|ico|pdf|mov|fla|zip|rar)$ {
# try_files $uri =404;
#}
#error_page 404 /404.html;
# deny accessing php files for the /assets directory
location ~ ^/assets/.*\.php$ {
deny all;
}
location ~ \.php$ {
include fastcgi_params;
fastcgi_param SCRIPT_FILENAME $document_root$fastcgi_script_name;
fastcgi_pass 127.0.0.1:9000;
#fastcgi_pass unix:/var/run/php5-fpm.sock;
try_files $uri =404;
}
location ~* /\. {
deny all;
}
}
Not: See below link for the Option-2, if the above does not work:
Yii2 Single Domain Apache and Nginx

Debian 8 nginx configuration

On my Nginx webserver i have several virtual hosts like this:
- api.example.com
- www.example.com
- cv.example.com
But when i am visiting www.example.com/example and this is not an valid path its giving me 404 page of my api.example.com. But why ?
This is my current nginx configuration of www.example.com :
server {
listen 443 ssl;
listen [::]:443 ssl;
access_log /var/log/nginx/www.example.com-access.log timed;
error_log /var/log/nginx/www.example.com-error.log;
root /var/www/wwwexamplecom/html/_site;
server_name example.com www.example.com;
add_header X-Content-Type-Options nosniff;
add_header X-XSS-Protection "1; mode=block";
include snippets/ssl-example.com.conf;
include snippets/ssl-params.conf;
location / {
index index.html index.php;
try_files $uri $uri/ /index.php?q=$uri&$args;
}
location ~ \.php$ {
fastcgi_pass unix:/var/run/php/php7.0-fpm.sock;
fastcgi_param SCRIPT_FILENAME /var/www/example/html/public/index.php;
include fastcgi_params;
}
location ~ /.well-known {
allow all;
}
}
This is the configuration of my api.example.com :
server {
listen 443 ssl;
listen [::]:443 ssl;
access_log /var/log/nginx/api.example.com-access.log timed;
error_log /var/log/nginx/api.example.com-error.log;
root /var/www/apiexamplecom/html/public;
server_name api.example.com;
include snippets/ssl-api.example.com.conf;
include snippets/ssl-params.conf;
location / {
index index.html index.php;
try_files $uri $uri/ /index.php?q=$uri&$args;
}
location ~ \.php$ {
fastcgi_pass unix:/var/run/php/php7.0-fpm.sock;
fastcgi_param SCRIPT_FILENAME /var/www/apiexamplecom/html/public/index.php;
include fastcgi_params;
}
location ~ /.well-known {
allow all;
}
}
I think self its in the / location part but i am not really how i can fix this issue. This is also happening on other virtualhost.
You have to explicitly let nginx know that you want to throw a 404 error if it can't find anything in the location block. Otherwise it will try matching your 'default' server block (which in this case seems to be the api.example.com one because you haven't specified the default). It can't find anything in that server either, THEN it tries the 404.
To explicitly tell nginx to throw a 404 if it can't find anything in your location block, add =404 to the end of your try_files line. This means that if it can't find any files for $uri, $uri/ or any php files, then throw the 404 without trying anything else.
try_files $uri $uri/ /index.php?q=$uri&$args =404;

Nginx returns 404 for some sub domains but not for others

So I'm trying to setup 5 websites, all on the same domain just with diffrent subdomain, etc www. and cdn.
but www. works fine as it should
tho cdn. does not, It got the same files I just copyed them over, all permissions are the same for the folders.
I have each sub domain in their own files etc wwwmydomaincom and cdnmydomaincom and the config is the same, only diffrence is server_name. the file that works got www.mydomain.com the rest got somesubdomain.mydomain.com and they throw 404.
I use Nginx on ubuntu server 16.04.1.
Added
location / {
try_files $uri.html;
}
and the sub domains displays the html pages fine (now their config isent like the one that works)
But.. every asset, css, js, images or other things get 404 so it's a pure html page.
The config under is the exact same config as www.mydomain.com but changed to fit cdn.mydomain.com
server {
listen 80;
server_name cdn.domain.com;
location /.well-known/acme-challenge {
default_type "text/plain";
root /storage/webserver/certbot;
}
#Forces all other requests to HTTPS
location / {
return 301 https://$host$request_uri;
}
}
server {
listen 443 ssl http2;
server_name cdn.domain.com;
ssl_certificate /etc/letsencrypt/live/cdn.domain.com/fullchain.pem;
ssl_certificate_key /etc/letsencrypt/live/cdn.domain.com/privkey.pem;
ssl_dhparam /etc/ssl/certs/dhparam.pem;
ssl_protocols TLSv1.2 TLSv1.1 TLSv1;
ssl_prefer_server_ciphers on;
ssl_ciphers EECDH+ECDSA+AESGCM:EECDH+aRSA+AESGCM:EECDH+ECDSA+SHA512:EECDH+ECDSA+SHA384:EECDH+ECDSA+SHA256:ECDH+AESGCM:ECDH+AES256:DH+AESGCM:DH+AES256:RSA+AESGCM:!aNULL:!eNULL:!LOW:!RC4:!3DES:!MD5:!EXP:!PSK:!SRP:!DSS;
ssl_session_cache shared:TLS:2m;
# OCSP stapling
ssl_stapling on;
ssl_stapling_verify on;
resolver 8.8.8.8;
# Set HSTS to 365 days
add_header Strict-Transport-Security 'max-age=31536000; includeSubDomains';
root /storage/webserver/cdn.domain.com;
index index.html index.php;
location #rewrite {
rewrite ^ $uri.php last;
try_files $uri =404;
}
location ~ \.php$ {
fastcgi_split_path_info ^(.+?\.php)(/.+)$;
fastcgi_pass unix:/run/php/php7.0-fpm.sock;
fastcgi_index index.php;
fastcgi_param SCRIPT_FILENAME $document_root$fastcgi_script_name;
include fastcgi_params;
include fastcgi.conf;
try_files $uri =404;
}
rewrite ^(/.*)\.html(\?.*)?$ $1$2 permanent;
#rewrite ^/(.*)/$ /$1 permanent;
error_page 404 /404.php;
error_page 500 503 502 504 /error/40x.php;
location =/error/40x.html {
internal;
}
}
Ahem, this is why I want to learn this kind of stuff.
You obviosly need to make it look for the files.
so if anyone enters this litte situation, Don't forget to make it look in the root folder.
location / {
try_files $uri $uri/ $uri.html #rewrite;
}

NGINX - rewrite and error 404

my rewrite works.
On the other hand my 404 error redirection does not work anymore.
If I add to my .php link it returns me there is no file.
Similarly when I put in my link an admin / it puts me the opening, the menu and the copiryght.
Example if I put https://mon.domain.com/admin/ it loads me a page while I would like my 404 error page.
What I would like, if the pages does not exist that in any case I come across my error 404
Can you help me?
Here is the configuration of nginx:
upstream www {
server unix:/var/run/php5-fpm.sock;
}
server {
listen 80 default;
server_name no-impact.eu;
return 301 https://my.domain.com;
}
server {
listen 443 ssl;
server_name my.domain.com;
fastcgi_param HTTPS on;
ssl on;
ssl_certificate /etc/letsencrypt/live/my.domain.com/fullchain.pem;
ssl_certificate_key /etc/letsencrypt/live/my.domain.com/privkey.pem;
ssl_session_timeout 5m;
ssl_protocols SSLv2 SSLv3 TLSv1;
ssl_ciphers HIGH:!aNULL:!MD5;
ssl_prefer_server_ciphers on;
root /var/www/my.domain.com/;
index index.php;
error_page 400 401 402 403 404 500 502 503 504 /error.html;
location /.well-known/acme-challenge {
root /var/www/letsencrypt;
}
location = /error.html {
root /var/www/my.domain.com/error/;
index index.html;
}
location / {
index index.php index.html;
try_files $uri $uri/ #rewrite;
}
location #rewrite {
rewrite ^/([\w-]+)-page-(\d+)$ /index.php?id=$1&page=$2 last;
rewrite ^/([\w-]+)-(\d+)$ /index.php?id=$1&id_tutoriel=$2 last;
rewrite ^/(.*)$ /index.php?id=$1 last;
}
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;
}
}
The problem here is that your rewrite tells nginx to redirect everything to the backend, so nginx does not detect a 404 by itself. Your backend then handles the request and sends a 404, which nginx sends back directly to the client.
In order for nginx to intercept the 404 and show its own error page, you need to add the directive fastcgi_intercept_errors on; to your .php-location.

Nginx server only shows default page

I have a problem with Nginx server as it only shows default page. Virtual host and host file seem to be ok. I don't get where is the problem.
Here is my virtual host configuration:
server {
listen 80;
listen [::]:80;
listen 443 default ssl;
server_name marketplace_unirgy;
ssl_certificate /etc/nginx/ssl/nginx.crt;
ssl_certificate_key /etc/nginx/ssl/nginx.key;
root /var/www/html/marketplace_unirgy/;
index index.php;
#location / {
# index index.html index.php;
# autoindex on;
# #If missing pass the URI to Magento's front handler
# try_files $uri $uri/ #handler;
# expires max;
#}
#need it to execute php
location ~ \.php$ {
fastcgi_pass unix:/var/run/php5-fpm.sock;
include fastcgi_params;
include fastcgi.conf;
}
## Magento uses a common front handler
location #handler {
rewrite / /index.php;
}
}
And my host:
127.0.0.1 marketplace_unirgy localhost
My website is in /var/www/html/marketplace_unirgy
You seem to have the default location commented out for some reason. Try enabling it with:
location / {
try_files $uri $uri/ /index.php;
}
See this and this for more.

Resources