nginx appears to use rewrite regardless of server_name - nginx

I have the following config file.
server {
listen 80;
server_name web.example.com;
access_log /var/www/example/shared/log/web.access.log;
error_log /var/www/example/shared/log/web.error.log debug;
rewrite ^/(.*)$ http://www.example.net$request_uri; permanent;
}
When I make a request for curl -Ii -H "Host: example.com" http://example.com the above rewrite rule works. (ARGH)..
The server_name explicitly says "web.example.com"
2014/11/18 22:49:20 [notice] 30694#0: 1868 "^/(.)$" matches "/", client: 1.2.3.4, server: web.example.com, request: "HEAD / HTTP/1.1", host: "example.com"
2014/11/18 22:49:20 [notice] 30694#0: *1868 rewritten redirect: "http://www.example.net/", client: 1.2.3.4, server: web.example.com, request: "HEAD / HTTP/1.1", host: "example.com"
Not present here is the other server { } configs. Xavier (below) pointed out that I had set default_server for listen: 443; but not for listen: 80. (argh)

That's not the strict solution to the issue.
What's happening is that you have only one server block and it becomes the default server block for all requests, even the ones not matching the server name. You simply need to add a default server block in your configuration :
server {
listen 80 default_server;
}
By the way, you have a typo (semicolon before permanent) and you don't need a rewrite as you have specific regular expression. Use this instead :
return 301 http://www.example.net$request_uri;

After a while...
I found that I needed the location / { } wrapped around it
server {
listen 80;
server_name web.example.com;
access_log /var/www/example/shared/log/web.access.log;
error_log /var/www/example/shared/log/web.error.log debug;
location / {
rewrite ^/(.*)$ http://www.example.net$request_uri permanent;
}
}

Related

Location directive doesn't seem to be working for some reason

A few days ago I stumbled upon Nginx inside k8s deployment. As I'm relatively new to Nginx I want to understand how it works - so I made my own dev deployment.
The thing is I can't get my nginx.conf to work as I intended:
When you access the /healthz endpoint, return 200 (health check for the k8s)
Redirect any other http trafic to https
Here's my current nginx.conf:
server {
listen 80;
listen [::]:80;
server_name _;
location /healthz {
return 200 "healthy";
}
return 301 https://$host$request_uri;
access_log off;
error_log /usr/share/nginx/web/logs/http_error.log error;
}
server {
listen 443 ssl http2 default_server;
listen [::]:443 ssl http2 default_server;
server_name company.com;
root /usr/share/nginx/web;
index index.html;
access_log off;
error_log /usr/share/nginx/web/logs/ssl_error.log error;
ssl_certificate /usr/share/nginx/web/cert/company.crt;
ssl_certificate_key /usr/share/nginx/web/cert/company.key;
}
Response I'm getting (I've removed the IP adresses):
[error] 28#28: *2 open() "/usr/share/nginx/web/healthz" failed (2: No such file or directory), client: xx.xx.xx.xx, server: company.com, request: "GET /healthz HTTP/2.0", host: "xx.xx.xx.xx", referrer: "http://xx.xx.xx.xx:80/healthz"
Request is on port 80 to /healthz but instead of returning 200, it gets redirected to the https server where it fails
At this point I really don't know why it doesn't work, so please, even if it's some dumb mistake, please feel free to point it out!
What am I doing wrong here?
All the directives processed by ngx_http_rewrite_module from the server context (including return one) are executed before the same directives from location context. You should define two locations to achieve desired behavior:
server {
listen 80;
listen [::]:80;
server_name _;
access_log off;
error_log /usr/share/nginx/web/logs/http_error.log error;
location / {
return 301 https://$host$request_uri;
}
location /healthz {
return 200 "healthy";
}
}

NGINX mirror files uploaded with HTTP PUT

Need to mirror all newly uploaded files from oroginal server to new one.
Direct file upload (HTTP PUT) to new server works fine. When i upload file to original server, file appers only there. Logs on a new server access log:
10.31.181.61 - - [28/Dec/2018:13:08:30 +0300] "PUT / HTTP/1.0" 409 167 "-" "curl/7.47.0" "-"
error log:
2018/12/28 13:08:30 [error] 28983#0: *23 cannot PUT to a collection, client: 10.31.181.61, server: _, request: "PUT / HTTP/1.0", host: "10.31.181.60"
what does this error mean: cannot PUT to a collection
Is it possible to make this setup?
Thanks
Nginx config on original server
location / {
autoindex on;
mirror /mirror;
mirror_request_body on;
}
location /mirror {
proxy_pass http://newserver/;
proxy_pass_request_body on;
}
Config on new server:
server {
listen 80 default_server;
listen [::]:80 default_server;
server_name _;
root /web;
dav_methods PUT;
location / {
autoindex on;
}
You should also add the filename to the url that you are using with PUT

nginx.conf rewrite not getting triggered

http{
server {
listen 80;
server_name example.com;
rewrite_log on;
root /etc/nginx/html/mysite;
location ^~ /me/ {
rewrite ^/me/(.*)$ /etc/nginx/html/mysite/$1.html;
}
}
}
The above is not working when I make the request http://example.com/me/all
I want it to be served by /etc/nginx/html/mysite/all.html
But the request goes to /etc/nginx/html/mysite/me/all ignoring the rewrite and nothing about a rewrite error in the logs (just a 404 not found).
You are specifying the root of your virtual host to /etc/nginx/html/mysite (line 6). In your rewrite rule you again specify the whole path /etc/nginx/html/mysite/$1.html (line 8). What nginx does is appending the target of your rewrite rule (/etc/nginx/html/mysite/$1.html) to the root of your virtual host (/etc/nginx/html/mysite). In you example this results in searching for the file:
/etc/nginx/html/mysite/etc/nginx/html/mysite/all.html
Such file does not exist and causes the 404.
Correct the rule to make the target a relative path with respect to root, as:
http{
server {
listen 80;
server_name example.com;
rewrite_log on;
root /etc/nginx/html/mysite;
location ^~ /me/ {
rewrite ^/me/(.*)$ /$1.html;
}
}
}
Remember that you can get more information on these errors by reading the nginx error log (by default placed at /var/log/nginx/error.log). In you case it would have stated something like:
"/usr/share/nginx/html/mysite/usr/share/nginx/html/mysite/all.html" failed (2: No such file or directory), client: 127.0.0.1, server: localhost, request: "GET /me/all HTTP/1.1", host: "localhost"

Location block is ignored

I testing out nginx but I bumped into a severe problem. Somehow the location tag doesn't catch my uri's. When the browser, or I manually try to access /favicon.ico on my localhost, it just throws an 404 error. The configuration looks like the following code:
server {
listen 80;
server_name localhost;
root www;
#charset koi8-r;
#access_log logs/host.access.log main;
location / {
index index.html index.php;
}
location = /favicon.ico {
alias alias /assets/images/favicon.ico;
}
... and the error log looks like this:
2014/01/17 00:05:18 [error] 7408#10036: *82 CreateFile() "C:\Users\user\Webb\nginx/www/favicon.ico" failed (2: FormatMessage() error:(15105)), client: 127.0.0.1, server: localhost, request: "GET /favicon.ico HTTP/1.1", host: "localhost"
The log proves then that the location block was ignored, because the path nginx look for the file is not the one alias points to.
AFAIK nginx alias goes like this:
alias <the base path>
means that with it you tell the nginx the part to the left of your first "/" in the URI.
example. suppose I have my images in /var/www/html/images and my application refers to apic.jpg as http://app.com/pictures/apic.jpg , what I do then is this:
location ^/pictures {
alias /var/www/html/images;
}
hope this helps.

Nginx: rewrite rule to redirect to https page

I want to redirect my login page to https so that users do not inadvertently enter their credentials through the unencrypted network. How do I do something like the below?
# nginx.conf
server {
server_name example.org;
rewrite http://*.example.org/login https://example.org/login;
}
This works for http://example.org/login, but it does not work for http://www.example.org/login
Rewrite rule output for
rewrite http://.*\.?example.org/login https://example.org/login;
Rewrite debug output:
*2 "http://.*\.?example.org/login" does not match "/login", client: XXX.XXX.XX.72, server: example.org, request: "GET /user HTTP/1.1", host: "example.org"
I deleted my original answer as it was quite a lot easier. You'll need a location block and an if for this to work, along with a catchall server domain. Structure as follows:
server {
server_name example.org;
server_name *.example.org;
location /login {
if ( $scheme = http ) {
rewrite ^ https://example.org/login last;
}
}
}
As much as I hate using ifs in nginx coming, this time, it's necessary.

Resources