Nginx configuration issue - getting 404 - nginx

I trying to configure Nginx to serve as a HTTP Load Balancer. Just for sake of prove of concept, I configured my nginx to redirect to ordinary http website (www.nationalrail.co.uk).
This is how my nginx configuration looks like:
http {
upstream stream_backend {
server www.nationalrail.co.uk:80;
}
server {
listen 80;
error_log /home/ubuntu/logs/error.log debug;
location / {
proxy_pass http://stream_backend;
}
}
}
However, when I going to my Nginx url (say, loadbalancer.com) - I receiving "404 - not found" error.
What do I miss?

Have you tried like this ?
http {
server {
server_name loadbalancer.com;
location / {
proxy_pass http://www.nationalrail.co.uk;
proxy_set_header Host $host;
proxy_set_header X-Forwarded-For $remote_addr;
}
}
}

I discovered that the issue was due to http redirects. Redirects shall be explicitly handled inside Nginx, otherwise it doesn't works as expected.

Related

Flask API & nginx alongside each other

I have a server that I'm trying to set up. I have a Flask server that needs to run on api.domain.com, while I have other subdomains pointing to the server. I have one problem. 2/3 subdomains have no problem using nginx. Meanwhile, my script tries to bind to port 80 on the same machine, therefore failing. Is there a way I can bind my Flask REST script to port 80 ONLY for the subdomain 'api'?
My current config is:
server {
server_name api.domain.me;
location / {
error_page 404 /404.html;
proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;
proxy_set_header X-Forwarded-Proto $http_x_forwarded_proto;
proxy_http_version 1.1;
proxy_set_header Upgrade $http_upgrade;
proxy_set_header Connection "upgrade";
proxy_max_temp_file_size 0;
proxy_pass http://127.0.0.1:5050/;
proxy_cache off;
proxy_read_timeout 240s;
}
}
There's a little problem though, nginx likes to turn all POST requests into GET requests, any ideas?
Thanks!
There is no way binding two different applications on port 80 at the same time.
I would set up your api like this:
Bind your Flask API to Port 8080.
On NGINX you can configure you subdomain pointing to your Flask Application
upstream flask_app {
server 127.0.0.1:8080;
}
sever {
listen 80;
server_name api.domain.com;
location / {
proxy_pass http://flask_app/;
proxy_set_header Host $host;
}
}
I actually found out after a bit of diagnosis.
server {
if ($host = api.domain.me) {
return 301 https://$host
}
# managed by Certbot
had to become:
server {
if ($host = api.domain.me) {
return 497 '{"code":"497", "text": "The client has made a HTTP request to a port listening for HTTPS requests"}';
}
Because Certbot tries to upgrade the request to https but the HTTP method gets changed to GET because of the 301 response code.

NGINX Proxy pass to external site that has internal redirect

i'm trying to configure an nginx proxy that hide an internal site via the proxy pass but without success.
the config i used is
location /internal1/ {
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_connect_timeout 15;
proxy_read_timeout 180;
proxy_pass http://internal1/;
}
upstream internal1 {
server a.b.c.d:80;
}
the problem is that when i try to reach the a.b.c.d site it redirect to a login page that sould be http://a.b.c.d/login and after i login it redirect at another page http://a.b.c.d/device/config . with the proxy it redirect to http://mysite/login and http://mysite/device/config
that make the proxy do not work and show me resource not found and i couldn not see any of the pages.
If i change the proxy_pass value to http://a.b.c.d/login/ it show the login page at http://mysite/internal1 and after i login it show no resource found because it try to reach http://mysite/device/config.
someone have some suggestion on how to configure it in the proper way?
thanks for all the answer
EDIT:
sorry for the late answer but i got very busy in the meanwhile, anyway that solution work for 1 device but now all my device connected go only that device "internal" page and i cannot differentiate between more cause nginx do not support the same location in multiple config ( all device have ip/page1 )
location /page1/
{
proxy_pass mysite/internal1/page1;
proxy_redirect off;
proxy_set_header Host $host;
}
EDIT2:
unlucky it's not possible to expose all device to internet directly. the solution i found is:
create a custom DNS subdomain and then create a different nginx server block for every device with his own location and future redirect/proxy ecc...
If you want to expose the web UI of all your devices that live in the internal network to be accessible through Internet - then you will have to create a subdomain (and a corresponding virtual host config) for each device.
Suppose that the domain that points to your nginX is mydevices.net and that you have 2 devices - on 192.168.2.10 and 192.168.2.20
Then your nginX config will look like this:
server {
listen 80;
server_name dev1.mydevices.net;
location / {
proxy_pass internal1;
proxy_redirect default;
}
}
upstream internal1 {
server 192.168.2.10;
}
server {
listen 80;
server_name dev2.mydevices.net;
location / {
proxy_pass internal2;
proxy_redirect default;
}
}
upstream internal2 {
server 192.168.2.20;
}

Nginx Reverse proxy config

I'm having issues with getting a simple config to work with nginx. I have a server that host docker containers so nginx is in a container. So lets call the url foo.com. I would like for the url foo.com/service1 to actually just go to foo.com on another port, so it would actually be pulling foo.com:4321 and foo.com/service2 to be pulling foo.com:5432 and so on. Here is the config I have been having issues with.
http {
server {
listen 0.0.0.0:80;
location /service1/ {
proxy_pass http://192.168.0.2:4321/;
}
location /service2/ {
proxy_pass http://192.168.0.2:5432/;
}
}
}
So the services and nginx live at 192.168.0.2. What is the prefered way to be able to do this? Thank you in advance!
As A side note, this is running in a docker container. Thanks!
I think you should check whether your foo.com is pointing to the right ip address or not first by removing the reverse proxy config. E.g.
http {
server {
listen 80;
server_name foo.com;
location / {
}
}
}
Then, if your ip address already has a service running on port 80 you should specify the server_name for each service like in my example. Nginx can only distinguish which service to respond to which domain by server_name.
*My guess is that you forgot the server_name option.
http {
server {
listen 80;
server_name foo.com;
location /service1/ {
proxy_pass http://192.168.0.2:4321/;
}
location /service2/ {
proxy_pass http://192.168.0.2:5432/;
}
}
}
I have a guess your problem is not related to Nginx per se, but instead it is related to Docker networking. You provided insufficient information to make a detailed conclusion, but here it is a couple of suggestions:
run a simple Docker container at the same host where nginx container is running and try curl from inside that container (I've seen your answer that you are able to call curl from the server running Nginx, but it's not really the same)
for example, if the server running nginx container is OSX or Windows, it may use an intermediate Linux virtual machine with its own network stack, IP addreses, routing, etc.
This is my conf sending to inner glassfish. Check out the use of proxy_redirect off & proxy_set_header X-NginX-Proxy true;
#Glassfish
location /MyService/ {
index index.html;
add_header Access-Control-Allow-Origin $http_origin;
proxy_set_header X-Real-IP $remote_addr;
proxy_set_header X-NginX-Proxy true;
proxy_ssl_session_reuse off;
proxy_set_header Host $http_host;
proxy_redirect off;
proxy_set_header X-Forwarded-Server $host;
proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;
proxy_pass http://127.0.0.1:18000/MyService/;
}

Rewriting redirects to include the port used to access the service

I have a setup like this:
A user working with my Vagrant development environment accesses localhost:8080 on their host machine, which is forwarded into Vagrant to NGINX running at localhost:80 on the guest. Some requests are forwarded into my application server running at localhost:8080 on the guest, and some are static files served from NGINX.
A weird thing happens when I access my site. I have a login page which redirects on success, and the URL is rewritten from http://localhost:8080/login to http://localhost:80/login.
Here's my NGINX configuration for the site:
upstream appserver {
server 127.0.0.1:8080;
}
upstream production {
server www.mysite.com:443;
}
server {
listen 80 default_server;
server_name _;
client_max_body_size 20M;
access_log /var/log/nginx/project.access.log;
error_log /var/log/nginx/project.error.log;
index /index;
location ~ ^(/js/testpage.js) {
alias /vagrant/artifacts/www/js/testpage.js;
}
location ~ ^(/test/js/app.js) {
alias /vagrant/test/js/app.js;
}
location ~ /test/js/app_router.js {
alias /vagrant/test/js/app_router.js;
}
location ~ /test/js/app_layout_controller.js {
alias /vagrant/test/js/app_layout_controller.js;
}
location ~ /test/js/apps/navbar/sections/layout/navbar_layout_controller.js {
alias /vagrant/test/js/apps/navbar/sections/layout/navbar_layout_controller.js;
}
location ~ /test/js/apps/navbar/sections/navbar/navbar_options_view.js {
alias /vagrant/test/js/apps/navbar/sections/navbar/navbar_options_view.js;
}
location ~ /test/js/apps/navbar/sections/navbar_all_views.js {
alias /vagrant/test/js/apps/navbar/sections/navbar_all_views.js;
}
location ~ ^/test/js/apps/(.*/testpage_.*\.js)$ {
alias /vagrant/test/js/apps/$1;
}
location ~ ^/test/js/(.*)$ {
alias /vagrant/js/$1;
}
location ~ ^/build/js/(.*)$ {
alias /vagrant/artifacts/www/js/$1;
}
location ~ ^/build/css/(.*)$ {
alias /vagrant/artifacts/www/css/$1;
}
location ~ ^/(.*main.*)\.[#\-_\/\d\w]+\.(js|css)$ {
alias /vagrant/$1.$2;
}
location ~ ^/(css|js|fonts|favicon.ico) {
root /vagrant;
}
location ~ ^/receipts/js/(.*)$ {
alias /vagrant/receipts/js/$1;
}
location ~ ^/bower_components/(.*)$ {
alias /vagrant/bower_components/$1;
}
location ~ ^/login-promo/ {
access_log off;
proxy_pass https://production;
proxy_set_header X-Real-IP $remote_addr;
proxy_set_header Host $host;
proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;
}
location ~ ^/(admin|login|logout|index|build|testpage|receipts|open|reset|resetpage|privacy|change|activeUser|personPrivacyAcceptances) {
access_log off;
proxy_pass http://appserver;
proxy_set_header X-Real-IP $remote_addr;
proxy_set_header Host $host;
proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;
}
}
I'm not sure where the redirect is actually coming from, it could be coming from the app server backend or from the front end JavaScript. Is there a way that I can make sure that all redirects take the port used by the accessing client?
Update: Simply adding a login link to the root page and trying to navigate with that link redirects me to http://localhost:80/login rather than http://localhost:8080/login.
This is probably an undesired side-effect of fowarding the guest's nginx port to a different one on the host.
See http://nginx.org/en/docs/http/ngx_http_proxy_module.html#proxy_redirect
Desactivating the proxy redirection in the last location block should do the trick:
proxy_redirect off;
It's likely happening due to port_in_redirect being on by default. See: http://wiki.nginx.org/HttpCoreModule#port_in_redirect
Disabling that would likely stop some of the confusion as to why the port is being applied.
From there, it's a simple as setting the appropriate host_port or remote_port in your proxy pass redirects, as necessary. By looking at your config, it seems you are comfortable using the core module variables, it would be quite simple to include those variables.
See:
http://wiki.nginx.org/HttpCoreModule#.24remote_port
http://wiki.nginx.org/HttpCoreModule#.24server_port
This seems to have been caused by doing redirects wrong in application code.
If you have a similar architecture as above and are experiencing the problem, it's likely that the reason you're experiencing the problem is because of a naive attempt at redirecting without accounting for the Host header.
Your application behind nginx sees a request like this:
GET /path/to/resource
Host: virtualinstance:8888
Unfortunately, when it constructs the redirect, it does something dumb and reconstructs the redirect without taking into account the Host header, instead opting for the host and port which it knows it is using. The code that was breaking my redirect looked something like this:
return redirect("http://" + getHostName() + "/" + getPath())
First, it's bad that it hardcodes the protocol, but worse yet that it uses a method which gets the host name without regard for the port. This would return a redirect to http://localhost/path, rather than http://localhost:8888/path.
Developers, this is why you should always use the Host header as a source for your redirect:
return redirect("%s://%s/%s" % (getProtocol(), getHeader("Host"),
getPath())
This makes a sane redirect, using the original protocol, full text from Host, and the path.

Nginx: How to forward requests to a port using proxy_pass

I'm just getting started with Nginx and am trying to set up a server block to forward all requests on the subdomain api.mydomain.com to port 8080.
Here's what I've got:
UPDATED:
server {
server_name api.mydomain.com;
location / {
proxy_pass http://127.0.0.1:8080/;
proxy_set_header Host $host;
proxy_set_header X-Real-IP $remote_addr;
proxy_set_header X-Forwarded-for $remote_addr;
}
}
server {
server_name www.mydomain.com;
return 301 $scheme://mydomain.com$request_uri;
}
server {
server_name mydomain.com;
root /var/www/mydomain.com;
index index.html index.htm;
location / {
try_files $uri $uri/ =404;
}
}
The server block exists in /etc/nginx/sites-available and I have created a symlink in /etc/nginx/sites-enabled.
What I expect:
I'm running deployd on port 8080. When I go to api.mydomain.com/users I expect to get a JSON response from the deployd API, but I get no response instead.
Also, my 301 redirect for www.mydomain.com is not working. That block was code I copied from Nginx Pitfalls.
What I've tried:
Confirmed that mydomain.com:8080/users and $ curl
http://127.0.0.1:8080/users return the expected response.
Restarted the nginx service after making changes to the server block.
Tried removing the proxy_set_header lines.
Any idea what I'm missing here?
You shouldn't need to explicitly capture the URL for your use case. The following should work for your location block:
location / {
proxy_pass http://127.0.0.1:8080;
proxy_set_header Host $host;
}
As it turns out, my problem was not with Nginx configuration but rather with my DNS settings. I had to create an A NAME record for each of my sub-domains (www and api). Rookie mistake.
A colleague of mine actually helped me troubleshoot the issue. We discovered the problem when using telnet from my local machine to connect to the server via IP address and saw that Nginx was, in fact, doing what I intended.

Resources