Nginx - How to serve a static file to a particular user agent? - nginx

I am trying to restrict access to a particular json file for a certain user-agent using the configuration files in Nginx.
server {
listen 80;
server_name localhost;
location / {
root /usr/share/nginx/html;
try_files $uri$args $uri$args/ /index.html;
}
location /v1/ {
proxy_pass http://127.0.0.1:8118;
proxy_pass_header Server;
proxy_http_version 1.1;
proxy_set_header Upgrade $http_upgrade;
proxy_set_header Connection "upgrade";
}
location = /v1/apischema {
root /usr/share/nginx/json;
if ($http_user_agent ~ useragentname) {
try_files /openapi.json;
break;
}
}
}
The idea is to restrict access to openapi.json for an internal user.
Please let me know where I am going wrong.

try_files can be used in a server or location block. See Context: in this document.
There are a number of ways to achieve this.
Using if:
location = /v1/apischema {
if ($http_user_agent ~ useragentname) {
rewrite ^ /openapi.json last;
}
}
location = /openapi.json {
internal;
root /usr/share/nginx/json;
}
The internal directive prevents this URI being accessed directly. See this caution on the use of if.
Or using map with try_files:
map $http_user_agent $apischema {
~useragentname /openapi.json;
default /nonexistant;
}
server {
...
location = /v1/apischema {
root /usr/share/nginx/json;
try_files $apischema =404;
}
}
See this document for details.

Related

problem using variable in nginx location directive

good evening. i have a question regarding nginx and it is related to the location directive. i currently have this configuration in nginx
server {
server_name ~^(?<account>.+)\.domain\.com$;
root /var/www/html/folder-frontend/;
index index.html;
error_log /var/log/nginx/$account-access.log;
access_log /var/log/nginx/$account-access.log;
location / {
try_files $uri /index.html;
}
location /$account-backend/ {
proxy_pass http://service-backend/;
proxy_set_header HOST $account-backend.domain.co;
proxy_http_version 1.1;
}
}
this means that I have several domains with the ending tenant.domain.com(app1.domain.com, app2.domain.com). with the expression (?.+) I am getting part of the string in the url that interests me and then in the location directive use it to make a proxypass and redirect the requests. but this is not working, I know because when I put in the location what interests me (in this case would be location /app1-backend/) if redirects to the backend service that I have listening in another nginx.
My doubt is, can I use a variable in the location directive of nginx? I tried it that way specified and it does not work.
No, you can't use a variable as location directive argument, even in a regex matching ones. You can try a workaround like
server {
server_name ~^(?<account>.+)\.domain\.com$;
root /var/www/html/folder-frontend/;
index index.html;
error_log /var/log/nginx/$account-access.log;
access_log /var/log/nginx/$account-access.log;
location / {
try_files $uri /index.html;
}
location ~ ^/(?<prefix>[^.]+)-backend(?<suffix>/.*) {
if ($prefix != $account) {
return 404;
}
proxy_pass http://service-backend$suffix$is_args$args;
proxy_set_header HOST $prefix-backend.domain.co;
proxy_http_version 1.1;
}
}

Serving one static file with nginx and auth_request

I am trying to server a static file for a location. It's returning 404 and I don't know why.
Here is my config (censored a bit)
root /home/git/website/prod/;
location = /login {
index login.html;
}
location / {
auth_request /auth;
try_files $uri $uri/index.html;
}
location = /auth {
internal;
proxy_pass http://127.0.0.1:5000/api/auth/logged_in;
proxy_pass_request_body off;
proxy_set_header Content-Length "";
proxy_set_header X-Original-URI $request_uri;
}
location /api {
proxy_pass http://127.0.0.1:5000;
}
When I try to access /login it returns 404. Why?
Assuming your login.html is in root folder (/home/git/website/prod/), you could probably use:
location = /login {
try_files /login.html =404;
}
Or replace =404 with /index.html. That part is basically telling nginx what to try if /login.html is not found on the server.

Serve both static website & SPA (node.js) with NGINX

I need a way to serve both static html website and SPA using NGINX.
https://website.com -> should be the static index.html page.
https://website.com/register -> should point to SPA powered by node.js webserver.
So, if there's an appropriate static html route it should be served with NGINX, any other route should be served by node.js webserver.
e.g.
https://website.com/about -> served by NGINX because there's about.html
https://website.com/register -> served by node.js because there's no appropriate static page for this route (there's no register.html).
I've created the following configuration, but it doesn't seems to work properly.
upstream backend {
server localhost:8080;
}
server {
listen 80;
server_name website.com www.website.com;
root /var/www/website.com;
location = / {
try_files /index.html =404;
}
location = /index {
return 404;
}
location / {
try_files $uri/index.html =404 #backend;
}
location #backend {
proxy_pass http://backend;
proxy_http_version 1.1;
proxy_set_header Upgrade $http_upgrade;
proxy_set_header Connection 'upgrade';
proxy_set_header Host $host;
proxy_cache_bypass $http_upgrade;
proxy_redirect off;
}
}
Your configuration could probably be simplified to this:
root /var/www/example.com;
index index.html;
location / {
try_files $uri $uri/ #backend;
}
location #backend {
...
}
You could try something like
location / {
try_files $uri $uri.html $uri/ #backend;
}
Breaking it down for you. The try_files directive
Checks the existence of files in the specified order and uses the first found file for request processing;
So
$uri - look for the exact file as defined in the path. Useful for static files like css, images, js, etc..
$uri.html look for the exact file with a .html extension. This would get your about.html
$uri/ - looks for it to be a directory then uses the index directive to look for index or index.html
#backend - send to the proxied application would be responsible for returning 404

nginx proxy_pass to all pages

So I am using nginx to reverse proxy to another server. This wasn't serving static files, until I linked them in the location. The location block is super long, but looks similar to the code below. I'm sure that I'm doing this the wrong way, but it works, it's just tedious to write all the paths. I'm wondering if there's a better way.
location / {
proxy_pass www.example.com;
}
location /sytlesheet.css {
proxy_pass www.example.com/stylesheet.css;
}
location /page1 {
proxy_pass www.example.com/page1;
}
#this goes on and on
Is there a way to get everything past the '/' for example 'page1', and pass that to the proxy without manually typing it?
I'm hoping there's something a way to use a variable or something to link all the pages and resources with a single location block:
location / {
proxy_pass www.example.com;
}
location /$variable {
proxy_pass www.example.com/$variable;
}
Thanks!
You should use following code
location / {
# First attempt to serve request as file, then
# as directory, then fall back to proxy
try_files $uri $uri/ #proxy;
}
location #proxy {
proxy_pass www.example.com;
}
Check this out.
location / {
proxy_set_header Host $host;
proxy_set_header X-Real-IP $remote_addr;
proxy_pass http://www.example.com;
}

Nginx resolves the wrong route

I have an nginx-based configuration, where the root of the domain should lead to a static page (a splash page) and anything else should be proxied to an internally accessible machine. The configuration looks roughly as follows:
server {
listen 80;
location = / {
root /var/www;
}
location ~ / {
location /robots.txt {
root /var/www;
}
proxy_pass http://127.0.0.1:9091;
proxy_set_header Host $host;
}
}
The problem is that if the second block of code exists, the first one stops being taken into consideration. In other words, nginx starts looking for an index.html file on the 9091 instance, which does not exist. If the proxy_pass block is commented, then the first part goes into effect.
As far as the documentation is concerned, this should not be the case. If the root of my domain is called, Nginx should stop searching after the first block, since it is explicit. Yet, this is not the case.
What should be done here? I do not want to merge the splash page code, with the rest.
Your config looks very weird, but there is no indication that it shouldn't work as you seem to intend.
Perhaps you could try something like this? Else, please provide your full configuration (perhaps your cut-down example is missing something important that we should know about).
server {
listen 80;
root /var/www;
location = / {
}
location = /index.html {
}
location = /robots.txt {
}
location / {
proxy_pass http://127.0.0.1:9091;
proxy_set_header Host $host;
}
}
Try this:
Replace splash.html to your splash page filename.
# Set root directory for requests
root /var/www;
# Rewrite / to /splash.html
rewrite ^/$ /splash.html break;
location = /splash.html { }
location = /robots.txt { }
location ~* / {
proxy_pass http://127.0.0.1:9091;
proxy_set_header Host $host;
}
I guess you have index directive somewhere and this is how index is works.
It should be noted that using an index file causes an internal redirect, and the request can be processed in a different location.
Your first location matches, but then index module cause internal redirect to /index.html and request ends up in second location block.
I would write something like this:
server {
listen 80;
root /var/www;
location = /index.html {
}
location = /robots.txt {
}
location / {
proxy_pass http://127.0.0.1:9091;
proxy_set_header Host $host;
}
}

Resources