I'm trying to set nginx location that will handle various paths and proxy them to my webapp.
Here is my conf:
server {
listen 80;
server_name www.example.org;
#this works fine
location / {
proxy_set_header X-Forwarded-Host $host;
proxy_set_header X-Forwarded-Server $host;
proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;
proxy_pass http://localhost:8081/myApp/;
}
#not working
location ~ ^/(.+)$ {
proxy_pass http://localhost:8081/myApp/$1;
}
}
I would like to access myApp with various paths like: /myApp/ABC, /myApp/DEF, myApp/GEH or /myApp/ZZZ.
Of course these paths are not available in myApp. I want them to point to root of myApp and keep url.
Is that possible to archive with nginx ?
Nginx locations match in order of definition. location / is basically a wildcard location, so it will match everything, and nothing will reach the second location. Reverse the order of the two definitions, and it should work. But actually, now that I look at it more closely, I think both locations are essentially doing the same thing:
/whatever/path/ ->>proxies-to->> http://localhost:8081/myApp/whatever/path/
A very late reply. this might help someone
try proxy_pass /myApp/ /location1 /location2;
Each location separated with space.
You will probably have to do a rewrite followed by a proxy pass, I had the same issue. Check here: How to make a conditional proxy_pass within NGINX
Related
This is my first time posting a question. Kindly let me know if I am missing something that needs to be shared.
I am trying to POST some data into database through my C# APP and API (separately build), but it throws error 404 only for the POST API. All other pages work fine and so does the GET request. The app and API have been deployed on a LINUX machine through NGINX reverse proxy server. Both of them work on HTTP protocol. The feature works for localhost, but not for IP dependent URL.
Here is the content of service file for the app, I do not know what is missing in it. Please take care of the "/" as well where ever it is needed. While performing RnD, I found that the POST request in NGINX gets redirected to GET, I don't know if this will be helpful or not, but felt like sharing.
server {
listen myIP:6002;
server_name attendancepp;
root /home/user/net-core/Publish/AttendanceModule/AttendanceApp;
location /AttendanceApp/{
proxy_set_header Host $host;
proxy_set_header X-Real-IP $remote_addr;
proxy_pass http://myIP:6002/;
proxy_set_header Accept-Encoding "";
proxy_cache_bypass $http_upgrade;
proxy_set_header Upgrade $http_upgrade;
proxy_set_header Connection 'upgrade';
proxy_redirect off;
proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;
}
}
The app works on the URL http://myIP:6002/attendance/allPages . All the pages are accessible without any issue. Just the POST part is not working.
Thank you, in advance.
working fine after commenting
try_files $uri $uri/ =404
cd /etc/nginx/sites-available/
sudo nano default << nginx
edit file then CTR+X and 'y' for yes
sudo systemctl restart nginx
I have different versions of my web application running in Docker containers. And nginx is running on my host machine.
Is it possible to access the desired deployed version of my web application with the help of sub-domain such as v1.myapp.io, v2.myapp.io without reconfiguring and restarting the nginx?
I also want to access future versions in the same way?
Could anyone tell me if there is any way to achieve it?
Please consider me a newbie to Docker/nginx world.
Thanks in Advance.
Yes, although it can be done but its very difficult to achieve with docker only. kubernetes will make this very easy and everything like dns, service mapping is provided out of the box. I will include both docker and kubernetes approach:
Docker approach:
A first draft will look like this, use regex in nginx server_name and set the docker container names with a pattern. Create a /etc/hosts entry for different containers like:
172.16.0.1 v1.docker.container
172.16.0.2 v2.docker.container
And nginx server conf look like:
server {
listen 80;
server_name "~^(?<ns>[a-z]+.+)\.myapp\.io";
resolver 127.0.0.1:53 valid=30s;
# make sure $ns.docker.container is resolved to container IP
set $proxyserver "$ns.docker.container";
location / {
try_files $uri #clusterproxy;
}
location #clusterproxy {
proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;
proxy_set_header X-Forwarded-IP $clientip;
proxy_set_header X-Forwarded-For $clientip;
proxy_set_header X-Real-IP $clientip;
proxy_set_header X-Forwarded-Host $host;
proxy_set_header X-FORWARDED-PROTO 80;
proxy_pass http://$proxyserver:80;
}
}
Kubernetes approach:
Create different service and deployment for different versions in a namespace. Lets say namespace is 'app-namespace'. Service names are self explanatory:
APP version v1: v1-app-service
APP version v2: v2-app-service
To make nginx more flexible you can add the service name as namespace to $proxyserver
Nginx rule:
server {
listen 80;
server_name "~^(?<version>[a-z]+.+)\.myapp\.io";
# you can replace this with kubernetes dns server IP
resolver 127.0.0.1:53 valid=30s;
# make sure $ns.docker.container is resolved to container IP
set $proxyserver "$version.app-namespace.svc.kubernetes";
location / {
try_files $uri #clusterproxy;
}
location #clusterproxy {
proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;
proxy_set_header X-Forwarded-IP $clientip;
proxy_set_header X-Forwarded-For $clientip;
proxy_set_header X-Real-IP $clientip;
proxy_set_header X-Forwarded-Host $host;
proxy_set_header X-FORWARDED-PROTO 80;
proxy_pass http://$proxyserver:80;
}
}
I found another solution to this problem after digging a lot. It can be easily be done with Automated Nginx Reverse Proxy for Docker.
Once docker container for ngninx was up and running on my system.
I spun two docker containers of my webapp(diff versions) with the following command:
docker run -e VIRTUAL_HOST=v1.myapp.io --name versionOne -d myapp.io:v1
docker run -e VIRTUAL_HOST=v2.myapp.io --name versionTwo -d myapp.io:v2
and it worked out for me.
Additional notes:
1. I am using dnsmasq for handling all dns queries
I have two apps: /foo and /bar. In each of those folders I'm starting up passenger. For foo:
passenger start -d -e production -p 4000
And for bar:
passenger start -d -e production -p 4001
I then have nginx configured like so:
server {
listen 80 default_server;
server_name www.server.com;
root /var/www/html;
location /foo/ {
proxy_pass http://0.0.0.0:4000/;
proxy_set_header Host $host;
}
location /bar/ {
proxy_pass http://0.0.0.0:4001/;
proxy_set_header Host $host;
}
}
The apps are getting served up, but none of the links work. A link to the users#index action comes back as '/users' not '/foo/users'.
I've set config.relative_url_root in both apps, that helps with the assets but not the links.
I've tried with both the _url and _path methods, neither work.
This answer is close, but passenger_base_uri isn't a valid directive for stock nginx.
So then I followed the advanced configuration instructions for Passenger's nginx configuration and added passenger_base_uri = '/foo'; to my custom conf file and loaded it like so:
passenger start -d -e production -p 4000 --nginx-config-template nginx.conf.erb
Still no love, and I'm out of ideas. Has anyone done this before? It seems like a common way to deploy multiple apps in production.
More Thoughts (2015-06-05)
Adding passenger_base_uri = '/foo' to my nginx.conf.erb file hosts the application in TWO locations (which is odd to me, but whatever):
localhost:4000/
localhost:4000/foo/
The first doesn't have the correct resource links (i.e. it's just '/users') but has access to its assets.
The second has the correct resource links (e.g. '/foo/users') but doesn't have its assets (this is because it's looking for /foo/assets/* inside of its public folder, not just /assets/*). I believe that this is the way to go though, as I can change my proxy like this to get at the application:
location /foo/ {
proxy_pass http://0.0.0.0:4000/foo/;
proxy_set_header Host $host;
}
Does anyone else have any thoughts though? If I do this, it'll mean I'll have to rake my assets into public/foo for it to work. Not the end of the world, but it still seems weird.
For anyone else looking to do the same thing, here's what it was in the end:
Follow the Advanced Configuration to get a project specific nginx.conf.erb file.
Add a passenger_base_uri directive to that file for your app (e.g. passenger_base_uri = '/foo';)
In your config/environments/production.rb file move the location of the assets: config.assets.prefix = '/foo/assets'.
Start passenger passenger start -d -e production -p SOME_PORT --nginx-config-template nginx.conf.erb
In your nginx proxy configuration add a location directive for your app:
location /foo/ {
proxy_pass http://0.0.0.0:SOME_PORT/foo/;
proxy_buffering off;
proxy_http_version 1.1;
proxy_set_header Connection $connection_upgrade;
proxy_set_header Host $host; # more robust than http_host
proxy_set_header Upgrade $http_upgrade;
proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for; # this ensures your app's env is correct
proxy_set_header X-Forwarded-Host $host;
# proxy_set_header X-Forwarded-Proto https; # add this if you always want the redirects to go to HTTPS
}
After that, (re)start your nginx proxy and you should be good at http://your_proxy/foo/.
I am using nginx in with my Java Application and my problem is that nginx is merging the slashes and I am unable to redirect my website to the correct version.
For instance:
http://goout.cz/cs/koncerty///praha/
is merged to
http://goout.cz/cs/koncerty/praha/
and then I am unable to recognized the malformed URL and perform the redirection.
I tried to set
merge_slashes off;
and then:
rewrite (.*)//(.*) $1/$2 permanent;
But this has no effect and the // stays in the URL.
How can I achieve this?
Try this (untested):
merge_slashes off;
rewrite (.*)//+(.*) $1/$2 permanent;
It might cause multiple redirects if there are multiple groups of slashes though.
Like this:
http://goout.cz/////cs/koncerty///praha/
Might go to:
http://goout.cz/cs/koncerty///praha/
Then finally:
http://goout.cz/cs/koncerty/praha/
This works good, but for my setup adding port_in_redirect off; was necessary.
We encounter the same problem because of mistake, we add two slashes on the URL, and nginx will return 301 error code for the url with two slashes.
The solution for me is:
Add merge_slashes off; to nginx.conf file, and in the location part, add rewrite (.*)//+(.*) $1/$2 break;
The location setting for me is like below:
location / {
rewrite (.*)//+(.*) $1/$2 break;
proxy_pass http://http_urltest;
proxy_http_version 1.1;
proxy_set_header Connection "";
proxy_buffers 4096 32k;
proxy_buffer_size 32K;
proxy_busy_buffers_size 32k;
proxy_set_header Host $host;
proxy_set_header X-Real-IP $remote_addr;
proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;
}
After add these two lines, when I access my url with two slashes, it will return the result with one slash.
Try this(both nginx only and nginx with openresty configuration) you can improve site SEO by doing these 301 redirection
please keep this code inside the server section for your nginx site conf file
server {
........
........
set $test_uri $scheme://$host$request_uri;
if ($test_uri != $scheme://$host$uri$is_args$args) {
rewrite ^ $scheme://$host$uri$is_args$args? permanent;
}
location {
................
................
}
}
its working good for me and am using this code now
example:-
request url- http://www.test.com//test///category/item//value/
result url:- http://www.test.com/test/category/item/value/
301 redirection so that the SEO of the site will not goes down
I am deploying a Rails 2.3 // Spree app with Capistrano/Unicorn/Foreman/Upstart.
The part that I cannot figure out is how to have the /myapp/shared/sockets/unicorn.sock be automatically created by the foreman/upstart process management (at least that I think the unix socket should come from them).
What's responsible for creating the unix socket?
Let's say your configuration is nginx + unicorn . As you probably know , in the config dir you should create a file named unicorn.rb . In this file there is a description how to handle non-static requests , something like this :
upstream unicapd {
server unix:/tmp/capd.sock fail_timeout=0;
}
I've named the upstream differently than stated in tutorials , this gives me ability to host a number different applications on the same host .
Then , in your vhosts dir on the Nginx configuration you put something like this (let's say your host file is 'vhosts/myconf.conf':
location #unicorn1 {
proxy_pass http://unicapd;
proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;
proxy_set_header Host $http_host;
proxy_redirect off;
}
Here you see the instruction to nginx to serve non-static requests from the place , named "http://unicapd" , which is related to your unicorn.rb config file . This configuration is triggered by a file , which is in your init.d (in case you're running Debian) directory .
Summary : When you say bundle exec unicorn --restart , the script in your init.d triggers the code , forming a "special" file /tmp/capd.sock , which serves the dynamic content from you Rails app.
Path to unix-socket configured in unicorn's config:
...
listen "/home/user/app/shared/sockets/unicorn.sock", :backlog => 64
...
Then in nginx.conf:
location / {
try_files $uri #unicorn;
proxy_cache cache;
proxy_cache_valid 10m;
}
location #unicorn {
proxy_set_header Client-Ip $remote_addr;
proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;
proxy_set_header Host $host;
proxy_pass http://unix:/home/user/apps/shared/sockets/unicorn.sock;
}
When application will be started, unicorn create socket-file in setted path (user must have write access to this path)