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;
}
Related
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;
}
}
Looking through the error.log file of Nginx, we can see requests coming as one of two incorrect patterns:
http://www.example.com/app-contextmoduleA/controller1 -> should be http://www.example.com/app-context/moduleA/controller1
http://www.example.com/app-contextcontroller2 -> should be http://www.example.com/app-context/moduleB/controller2
The current Nginx configuration looks like this:
server {
listen 8080;
location /app-context/ {
proxy_redirect off;
proxy_set_header Host $host;
proxy_pass http://localhost:8888/app-context/;
}
}
The challenge is inserting the missing / after app-context (for the first wrong URL) or missing /moduleB/ (for the second wrong URL). It doesn't look like try_files would support that, and I have not found a way to do it with rewrite.
Is there a way for Nginx to rewrite the URLs for both use cases? In particular, I would prefer not to have to know all the name of the modules or controllers in advance. There are many, so "hard-coding" them in the rewrite rule would be onerous.
These should handle your example case:
location /app-context {
rewrite ^(/app-contextmoduleA)/(.*)$ /app-context/moduleA/$2 permanent;
rewrite ^(/app-contextcontroller2) /app-context/moduleB/controller2 permanent;
...
}
Check the ngx_http_rewrite_module for more info.
Looking through quite a few online resources and through trial and error, I was able to come to a good-enough solution:
location /app-context {
location ~ (moduleA|moduleB) {
# inserts a forward slash after app-context if not there,
# e.g. /app-contextmoduleA/foo/bar to /app-context/moduleA/foo/bar
rewrite ^(/app-context(?!/))(.*) $1/$2 break;
try_files $uri #proxy;
}
# inserts /defaultModule/ after app-context
# e.g. /app-context/controller1 to /app-context/defaultModule/controller1
rewrite ^(/app-context(?!/defaultModule/))(.*) $1/defaultModule/$2 break;
try_files $uri #proxy;
}
location #proxy {
proxy_redirect off;
proxy_set_header Host $host;
proxy_pass http://localhost:8888;
}
I'm creating a nginx reverse proxy to apache. Apache runs on port 8080 and nginx on 80.
I hope to achieve the following;
When I request the page http://server/test.html it should be proxyed to http://server:8080/unknown.html
Later on I'll do some eval stuff on the pages and redirect the users to the right pages, but I can't even get this to work. I get the test.html back as response all the time.
My nginx config:
server {
listen 80;
root /var/www/;
index index.php index.html index.htm;
server_name example.com;
location / {
# try_files $uri $uri/ /index.php;
}
location ~ \.html$ {
proxy_set_header X-Real-IP $remote_addr;
proxy_set_header X-Forwarded-For $remote_addr;
proxy_set_header Host $host;
#rewrite ^/unknown.html;
proxy_pass http://127.0.0.1:8080;
proxy_redirect http://127.0.0.1/test.html http://127.0.0.1:8080/unknown.html;
}
location ~ /\.ht {
deny all;
}
}
I have zero experience yet, but I'm eager to learn how to get this working...
Firstly, the proxy_redirect directive is the opposite of what you need. It is only used to rewrite the Location response headers in 3xx responses from upstream. See this document for details.
You can use a rewrite ... break statement within the location block that performs the proxy_pass, for example:
location ... {
rewrite ^/test.html$ /unknown.html break;
proxy_pass ...;
}
See this document for details.
I have rails application. There are parts of nginx config of it:
upstream app_server {
server unix:/var/www/app/shared/unicorn.sock fail_timeout=0;
}
server {
listen 80;
server_name app hostname;
keepalive_timeout 5;
root /var/www/app/current/public;
try_files $uri/index.html $uri.html $uri #app;
location #app {
proxy_pass http://app_server;
proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;
proxy_set_header Host $http_host;
proxy_redirect off;
proxy_cache off;
}
location ~ /assets/*\.(png|gif|jpg|jpeg|css|js|swf|ico|gz)(\?[0-9]+)?$ {
access_log off;
}
}
I want to cache several pages of my apps (for example all *.json urls). How I can do that?
According to nginx docs I can't:
use nested location in named location
use proxy_cache in if block
You can get away with adding Json to the extensions in the static file block if they are not virtual URLs.
If they are, you need to either setup differently by forwarding everything to your app by default and making exceptions, so you avoid having to use named locations. Or you can set variables based on if statements inside the named location:
location #app {
set $proxy_cache_cfg "off";
if($request_uri ~ \.json$) {
set $proxy_cache_cfg "json_zone";
}
}
Untested, not sure if "off" should be quoted and whether it even would work here. If this won't work, you can always use the reverse approach and set proxy_no_cache based on a variable, since that is in effect for anything non-empty and non-zero.
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;
}
}