how can I deal with static files in different server - nginx

upstream app_server {
server unix:/tmp/gunicorn.sock fail_timeout=0;
}
upstream another_server {
server 192.168.128.11;
}
server {
server_name test.com;
listen 80;
location / {
proxy_pass http://app_server;
proxy_set_header Host $host;
}
location ~ \.(js|css|jpeg|jpg|png|gif|ico|mp4|json) {
root /www/app;
try_files $uri /$1/$2.$4;
}
location ~ /anotherapp {
proxy_pass http://another_server;
proxy_set_header Host $host;
}
}
I have two server in different machines.I don't know how to deal with the static files in another_server.
When I get the test.com/anotherapp/index.js resoure ,but it return the files in app_server but not in another_app server.
The question is how can I deal with the static files in another_app server

Regular expression location statements are evaluated in order until a matching regular expression is found.
So /anotherapp/index.js matches \.(js|css|jpeg|jpg|png|gif|ico|mp4|json) before it matches /anotherapp.
You have two options:
Either, reverse the order of the regular expression location blocks, so that location ~ /anotherapp is encountered first.
Or, use a prefix location with the ^~ modifier instead (which will always take precedence over any regular expression location), for example:
location ^~ /anotherapp { ... }
See this document for details.

Related

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;
}

Is is possible to define a single nginx location in two separate blocks?

Is is possible to define a single nginx location in two separate blocks?
For example:
server {
listen *:80;
server_name someserver;
location / {
proxy_cache off;
}
location /assets {
proxy_cache mycache;
}
# What do I need to do to get this second root location
# to append to the 1st? If it's even possible.
location / {
proxy_pass http://foo;
}
}
The idea is that the root location then effectively becomes:
location / {
proxy_cache off;
proxy_pass http://foo;
}
If you'd like to know more about the why, read on.
Background:
I'm running a GitLab Omnibus installation. According to the docs, an admin an inject custom nginx config to the GitLab server block.
However, this injection adds things to the end server block rather than a specific location block.
So if I try to inject include my_config.conf;, I'll get:
server {
listen *:80;
server_name someserver;
location / {
proxy_cache off;
}
location /assets {
proxy_cache mycache;
}
include my_config.conf;
}
and if I try to include location ^~ / {\n include my_config.conf;\n }\n I'll get:
server {
listen *:80;
server_name someserver;
location / {
proxy_cache off;
}
location /assets {
proxy_cache mycache;
}
location ^~ / {
include my_config.conf;
}
}
which then causes the nginx config to fail with a duplicate location "/" in /var/opt/gitlab/nginx/conf/gitlab-http.conf:106 error.
Note: my_config.conf contains add_header stuff for CORS, so it needs to be in a location block.
You probably need to understand how nginx processes a request. But location blocks are not additive and must be individually complete. You can place certain statements in the server block and allow individual location blocks to override as required (e.g. proxy_cache).
Assuming that all of your URIs are proxied, you could use something like this:
proxy_cache off;
location / {
proxy_pass http://foo;
}
location /assets {
proxy_cache mycache;
proxy_pass http://foo;
}
Common statements can be offloaded to an include file.

Modify $request_uri in Nginx

I have multiple apps running on the Nginx server:
http://example.com/app1/ctrl/view
http://example.com/app2/ctrl/view
...
I would like to assign these apps DNS like so:
http://app1.example.com
http://app2.example.com
...
For that I've tried the following server block:
server {
listen 80;
server_name app1.example.com;
location / {
proxy_pass http://example.com/app1/$request_uri;
}
}
If a user is not logged in, my app would redirect to URI:
app1/ctrl/user/login?_next=/app/ctrl/view
Essentially $request_uri becomes (Note doubled app1 instance):
app1/app1/ctrl/user/login?_next=/app/ctrl/view
Is there a convenient way to modify $request_uri or a better method to get around this problem?
EDIT1
It seems I've solved my problem with the following server block:
server {
listen 80;
server_name app1.example.com;
location / {
set $new_request_uri $request_uri;
if ($request_uri ~ ^/app1/(.+)$) {
set $new_request_uri $1;
}
proxy_pass http://example.com/app1/$new_request_uri;
}
}
If someone knows a better (or proper "Nginx") way to do this please don't hesitate to post an answer.
EDIT2
Based on the comments I've also tried the following:
server {
listen 80;
server_name app1.example.com;
location / {
proxy_pass http://example.com/app1/;
proxy_redirect /app1/ /;
}
location ~ ^/app1/(.+)$ {
return 301 http://$server_name/$1;
}
}
This one looks better on screen, as it eliminates app1 instance in the $request_uri part completely, but you must have two location blocks.
EDIT3
The most efficient way to solve my problem apparently is as shown in this config:
server {
listen 80;
server_name app1.example.com;
location / {
proxy_pass http://example.com/app1/;
proxy_redirect /app1/ /;
}
location /app1/ {
rewrite ^/app1(.+) $1 permanent;
}
}
This is due to the fact, that Nginx always tries to match the longest prefix first and then (if ^~ modifier is not present) starts sequentially processing regexes until the first regex match is found. Essentially this means that all regexes are processed on every request, regardless if any of these find a match, therefore it's better to have regexes inside location directives.
You don't need to go complex way. Solution is much simpler
server {
listen 80;
server_name app1.example.com;
location / {
proxy_pass http://app1.example.com/app1/;
}
location /app1/ {
proxy_pass http://app1.example.com/app1/;
# or
# rewrite ^/app1(.+) $1 permanent;
}
}
Nginx will take care of adding /app1/ to request and strip it from Location header.
See proxy_redirect directive.

Nginx: cache only specific urls and named location

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.

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