nginx invalid URL prefix with rewrite - nginx

I'm using docker and running nginx alongside varnish.
Because I'm running docker, I've set the resolver manually at the top of the nginx configuration (resolver 127.0.0.11 ipv6=off valid=10s;) so that changes to container IPs will be picked up without needing to restart nginx.
This is the relevant part of the config that's giving me trouble:
location ~^/([a-zA-Z0-9/]+)$ {
set $args ''; #clear out the entire query string
set $card_name $1;
set $card_name $card_name_lowercase;
rewrite ^ /cards?card=$card_name break;
proxy_set_header x-cache-key card-type-$card_name;
proxy_set_header X-Real-IP $remote_addr;
proxy_set_header X-Forwarded-For $remote_addr;
proxy_set_header Host $host;
proxy_set_header REQUEST_URI $request_uri;
proxy_http_version 1.1;
set $backend "http://varnish:80";
proxy_pass $backend;
proxy_intercept_errors on;
proxy_connect_timeout 60s;
proxy_send_timeout 86400s;
proxy_read_timeout 86400s;
proxy_buffer_size 128k;
proxy_buffers 4 256k;
proxy_busy_buffers_size 256k;
error_log /var/log/nginx/error.log;
access_log /var/log/nginx/access.log;
error_page 503 /maintenance.html;
}
When I visit a URL for this, e.g. https://example.com/Test, I get 500 internal server error.
In the nginx error log, I see the following:
2022/04/27 23:59:45 [error] 53#53: *1 invalid URL prefix in "", client: 10.211.55.2, server: example.com, request: "GET /Test HTTP/2.0", host: "example.com"
I'm not sure what's causing this issue -- http:// is included in the backend, so it does have a proper prefix.
If I just use proxy_pass http://varnish:80, it works fine, but the backend needs to be a variable in order to force docker to use the resolver.

I've stumble across similar issue. I'm not sure why but defining the
set $backend "http://varnish:80";
outside of location block

Related

Nginx isn't storing cache

I'm trying to allow nginx caching in the simplest form. But for some reason it's not working. I'm currently using nginx with gunicorn and flask on an ec2 instance.
This is my /etc/nginx/nginx.conf file:
user nginx;
...
proxy_cache_path /var/cache/nginx keys_zone=mycache:10m;
proxy_cache_methods GET HEAD POST;
server {
listen 80;
access_log /var/log/nginx/agori.access.log main;
error_log /var/log/nginx/agori.error.log;
location / {
proxy_set_header Host $http_host;
proxy_set_header X-Real-IP $remote_addr;
proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;
proxy_set_header X-Forwarded-Proto $scheme;
proxy_cache mycache;
proxy_cache_valid any 48h;
proxy_buffering on;
proxy_pass http://unix:/home/ec2-user/src/project.sock;
}
}
when check the /var/cache/nginx folder, it's empty. These are the folders permissions:
drwxrwxrwx 2 nginx root 6 May 13 14:03 nginx
This is the request and respond headers:
PS: This is on mobile(ios)
It sounds to me that something in your Nginx config might not be correct (syntax error or not supported by your Nginx version). In most of the case I encountered so far that was the case for me.
You probably know Nginx' reverse proxy example which features the following configuration
http {
proxy_cache_path /data/nginx/cache levels=1:2 keys_zone=STATIC:10m inactive=24h max_size=1g;
server {
location / {
proxy_pass http://1.2.3.4;
proxy_set_header Host $host;
proxy_buffering on;
proxy_cache STATIC;
proxy_cache_valid 200 1d;
proxy_cache_use_stale error timeout invalid_header updating
http_500 http_502 http_503 http_504;
}
}
}
I tried to compare that with your configuration file and I my debugging approach would be:
Does nginx log your requests in access_log?
Try to remove whether the example configuration file works after minimal modifications.
Replace the any with a 200 for a start and see whether that works.
If that works, put in step by step all additional config lines like the proxy_cache_methods line.

NGINX reverse proxy for Jenkins on a Windows 10

So I have looked at all the tutorials that I could found on this topic, and nothing worked.
I have a JENKINS instance on a windows 10 pro, and a centos with nginx.
I want to use the NGINX as reverse proxy for Jenkins, to have https and make it accessible from internet.
My current configuration is:
server {
listen 80;
listen [::]:80;
server_name build.test.com;
access_log /var/log/nginx/log/build.test.com.access.log main;
error_log /var/log/nginx/log/build.test.com.error.log;
location ^~ /jenkins/ {
proxy_pass http://192.X.X.X:8080/;
proxy_redirect http://192.X.X.X:8080 http://build.test.com;
sendfile off;
proxy_set_header Host $host:$server_port;
proxy_set_header X-Real-IP $remote_addr;
proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;
proxy_max_temp_file_size 0;
#this is the maximum upload size
client_max_body_size 10m;
client_body_buffer_size 128k;
proxy_connect_timeout 90;
proxy_send_timeout 90;
proxy_read_timeout 90;
proxy_temp_file_write_size 64k;
# Required for new HTTP-based CLI
proxy_http_version 1.1;
proxy_request_buffering off;
proxy_buffering off; # Required for HTTP-based CLI to work over SSL
}
}
(I replaced the real url and IPs.)
But this gave me a 502 Bad Gateway.
With the following error:
connect() to 192.X.X.X:8080 failed (13: Permission denied) while connecting to upstream, client: 192.168.5.254, server: build.test.com, request: "GET /jenkins HTTP/1.1", upstream: "http://192.X.X.X:8080/", host: "build.test.com"
But on my local network when I try to access the server with the http://192.X.X.X:8080/ url, it works fine.
Any idea ?
Thanks
Doing a little bit of research indicates that this is most likely an issue within CentOS, and more specifically, SELinux. SELinux could be causing the problem in any number of locations; however, this is probably going to be a good jumping off point: https://stackoverflow.com/a/24830777/8680186
Check the SELinux logs to figure out why it's throwing a hissy fit if the above doesn't help.

Is it possible to serve both "proxied content" and local files from the same domain using Nginx?

I have a Nginx server configured as a reverse-proxy cache server to a remote Apache server. At this point, all is running fine. Here's a part of my configuration (I've left some irrelevant parts out):
server {
listen 443 ssl http2;
server_name www.mywebsite.com mywebsite.com;
location / {
proxy_pass https://123.123.123.123;
proxy_set_header Host $host;
proxy_set_header X-Real-IP $remote_addr;
proxy_set_header X-Forwarded-Host $host;
proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;
proxy_set_header X-Forwarded-Proto $scheme;
proxy_set_header REMOTE_ADDR $remote_addr;
proxy_ignore_headers X-Accel-Expires Expires Vary;
proxy_redirect off;
proxy_cache_revalidate off;
proxy_next_upstream off;
proxy_cache_use_stale error timeout invalid_header updating http_500 http_502 http_503 http_504;
proxy_cache_bypass $bypass $do_not_cache;
proxy_no_cache $do_not_cache;
proxy_cache_valid any 2880m;
proxy_cache_valid 404 1m;
proxy_cache my_cache;
proxy_cache_min_uses 1;
proxy_cache_lock on;
proxy_http_version 1.1;
}
}
Now what I want to do is to serve files from a specific directory from local files stored on the Nginx server. The rest of the content must still be cached from the source server:
//www.mywebsite.com => Serves cached content from //123.123.123.123
//www.mywebsite.com/local => Serves files stored locally on the Nginx server
Is it possible to include another location in the "server" section of the configuration? I tried something like this but it doesn't work:
location /local/ {
root /home/user/public_html/local;
try_files $uri $uri/ =404;
add_header 'Access-Control-Allow-Origin' '*';
add_header 'Access-Control-Allow-Methods' 'GET, POST, OPTIONS';
add_header 'Access-Control-Max-Age' 1728000;
}
Sorry for my english by the way.
You're on the right way, you should define another location with an alias directive:
location /local/ {
alias /home/user/public_html/local;
}
Now, when you request the http://YOUR_DOMAIN/local/page.html, it will serve /home/user/public_html/local/page.html.
Keep in mind that nginx must have read permission in the specified root directory.
Read this for the subtle difference between root and alias directives.

nginx 403 Forbidden error

I'm trying to set up graphite to work with grafana in docker based on this project : https://github.com/kamon-io/docker-grafana-graphite
and when I run my dockerfile I get 403 Forbidden error for nginx.
my configurations for nginx are almost the same as the project's configurations. I run my dockerfiles on a server and test them on my windows machine. So the configurations are not exactly the same ... for example I have :
server {
listen 80 default_server;
server_name _;
location / {
root /src/grafana/dist;
index index.html;
}
location /graphite/ {
proxy_pass http:/myserver:8000/;
proxy_set_header X-Real-IP $remote_addr;
proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;
proxy_set_header X-Forwarded-Proto $scheme;
proxy_set_header X-Forwarded-Server $host;
proxy_set_header X-Forwarded-Host $host;
proxy_set_header Host $host;
client_max_body_size 10m;
client_body_buffer_size 128k;
proxy_connect_timeout 90;
proxy_send_timeout 90;
proxy_read_timeout 90;
proxy_buffer_size 4k;
proxy_buffers 4 32k;
proxy_busy_buffers_size 64k;
proxy_temp_file_write_size 64k;
add_header Access-Control-Allow-Origin "*";
add_header Access-Control-Allow-Methods "GET, OPTIONS";
add_header Access-Control-Allow-Headers "origin, authorization, accept";
}
But I still keep getting 403 forbidden. Checking the error log for nginx says :
directory index of "/src/grafana/dist/" is forbidden
Stopping and running it again it says :
directory index of "/src/grafana/dist/" is forbidden
I'm very new to nginx ... was wondering if there's something in the configurations that I'm misunderstanding.
Thanks in advance.
That's because you are hitting the first location block and the index file is not found.
A request to '/' will look for 'index.html' in '/src/grafana/dist'.
Confirm that:
1. 'index.html' exists.
2. You have the right permissions.
nginx has read-access to the entire directory tree leading up to 'index.html'. That is, it must be able to read directories 'src', 'src/grafana' and 'src/grafana/dist' as well as 'index.html' itself.
A hacky quick-fix to achieve this would be to do 'sudo chmod -R 755 /src', but I don't recommend it.

nginx not serving my error_page

I have a Sinatra application hosted with Unicorn, and nginx in front of it. When the Sinatra application errors out (returns 500), I'd like to serve a static page, rather than the default "Internal Server Error". I have the following nginx configuration:
server {
listen 80 default;
server_name *.example.com;
root /home/deploy/www-frontend/current/public;
location / {
proxy_pass_header Server;
proxy_set_header Host $http_host;
proxy_redirect off;
proxy_set_header X-Real-IP $remote_addr;
proxy_set_header X-Scheme $scheme;
proxy_connect_timeout 5;
proxy_read_timeout 240;
proxy_pass http://127.0.0.1:4701/;
}
error_page 500 502 503 504 /50x.html;
}
The error_page directive is there, and I have sudo'd as www-data (Ubuntu) and verified I can cat the file, thus it's not a permission problem. With the above config file, and service nginx reload, the page I receive on error is still the same "Internal Server Error".
What's my error?
error_page handles errors that are generated by nginx. By default, nginx will return whatever the proxy server returns regardless of http status code.
What you're looking for is proxy_intercept_errors
This directive decides if nginx will intercept responses with HTTP
status codes of 400 and higher.
By default all responses will be sent as-is from the proxied server.
If you set this to on then nginx will intercept status codes that are
explicitly handled by an error_page directive. Responses with status
codes that do not match an error_page directive will be sent as-is
from the proxied server.
You can set proxy_intercept_errors especially for that location
location /some/location {
proxy_pass_header Server;
proxy_set_header Host $http_host;
proxy_redirect off;
proxy_set_header X-Real-IP $remote_addr;
proxy_set_header X-Scheme $scheme;
proxy_connect_timeout 5;
proxy_read_timeout 240;
proxy_pass http://127.0.0.1:4701/;
proxy_intercept_errors on; # see http://nginx.org/en/docs/http/ngx_http_proxy_module.html#proxy_intercept_errors
error_page 400 500 404 ... other statuses ... =200 /your/path/for/custom/errors;
}
and you can set instead 200 other status what you need
People who are using FastCGI as their upstream need this parameter turned on
fastcgi_intercept_errors on;
For my PHP application, I am using it in my upstream configuration block
location ~ .php$ { ## Execute PHP scripts
fastcgi_pass php-upstream;
fastcgi_intercept_errors on;
error_page 500 /500.html;
}
As mentioned by Stephen in this response, using proxy_intercept_errors on; can work.
Though in my case, as seen in this answer, using uwsgi_intercept_errors on; did the trick...

Resources