As a Nginx newbie i am trying to get a reverse proxy working to an external domain. Later on I will need to port to an internal domain. When trying to reverse proxy to an external domain i seem to hit a wall and the response is a 404 cannot be found.
The goal is when i try to access http://localhost/example the reverse proxy serves www.example.com.
This is my config:
server {
listen 80;
server_name localhost;
location / {
root /usr/share/nginx/html;
index index.html index.htm;
}
location /example/ {
proxy_set_header Host $host;
proxy_set_header X-Real-IP $remote_addr;
proxy_pass http://www.example.com/;
}
#error_page 404 /404.html;
# redirect server error pages to the static page /50x.html
#
error_page 500 502 503 504 /50x.html;
location = /50x.html {
root /usr/share/nginx/html;
}
}
Any hint what i am doing wrong?
When speaking about http, webserver detects which of configured servers was requested by checking Host header. In you case, you tell nginx to proxy requests to another server, but instruct it to pass original Host header to that server. Obviously, there is no configuration on remote server, which could accept request with that domain. So it responds you with 404.
To make it work, just change header to proxy_set_header Host www.example.com; where instead of www.example.com you should use same host as in proxy_pass directive. (or same variable)
Related
On a single server instance, I have an NGINX web server that operates without any problems with the HTTPS and I have a backend server in Spring Boot running on port 8080. I do not want to open this port to the internet, therefore I would like to setup a reverse proxy with NGINX to forward the request that start with /api to my backend and return the response.
When I send request to the domain in the browser, my frontend application which runs in browser, sends some requests to my backend (starting with /api), my frontend uses the following base url:
http://my-ip:8080/api
And the nginx configuration is as follows:
server {
listen 80;
ssl_certificate /cert/cert.pem;
ssl_certificate_key /cert/privkey.pem;
server_name www.mydomain.com;
rewrite ^(.*) https://$server_name$1 permanent;
}
server {
listen 443 ssl;
server_name www.mydomain.com mydomain.com;
ssl_certificate /cert/cert.pem;
ssl_certificate_key /cert/privkey.pem;
location / {
root /usr/share/nginx/html;
index index.html index.htm;
try_files $uri $uri/ /index.html;
}
error_page 404 /index.html;
location = / {
root /usr/share/nginx/html;
internal;
}
error_page 500 502 503 504 /50x.html;
location = /50x.html {
root /usr/share/nginx/html;
}
location /api {
proxy_set_header X-Forwarded-Host $host:$server_port;
proxy_set_header X-Forwarded-Server $host;
proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;
proxy_set_header X-Forwarded-Proto $scheme;
proxy_pass http://127.0.0.1:8080;
}
}
I keep getting Mixed Content Error and my backend requests are being blocked by the browser since my Frontend uses http for the request.
If I try to use https in the Frontend URL, such as:
https://my-ip:8080/api
Then I get a different error:
GET https://my-ip/api/... net::ERR_CERT_COMMON_NAME_INVALID
This is probably because my certificate is generated for my domain name and not for the IP.
Solution: In the frontend, we should send the request to https version and use the actual domain instead of the ip address because the domain name should match the domain of the certification.
The request: https://my-domain:8080/api
Then the nginx forwards this request properly.
I'm trying to display a custom 404 error page on my site, but it seems that Nginx does not catch the 404. Instead, it shows a 404 page from Gunicorn(flask app)
nginx.conf:
server {
listen 80 default_server;
server_name example.com www.example.com;
location / {
proxy_pass http://flask:8080/;
proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;
proxy_set_header Host $host;
proxy_redirect off;
}
error_page 404 /notfound.html;
location /notfound.html {
root /var/www/html;
}
error_page 500 502 503 504 /maintenance.html;
location /maintenance.html {
root /var/www/html;
}
}
Both flask app and Nginx are running on separate docker containers.
I purposefully brought the flask app down to see what happens, after a
while It redirects to 504(Timeout) and the maintenance.html appeared. - works fine.
But on a 404 error instead of displaying this custom notfound.html, it displays a 404 Not Found from Flask App (The 404 page did not had any nginx version on it).
proxy_intercept_errors on; should solve this problem.
I am attempting to develop a web app with nginx and fastapi and react. These are all new to me.
Regarding the fastapi, I have a main FastAPI that has a login route. I have added additional routes with APIRouter class and FastAPI.include_router method. I refered to this documentation
Development setup
fastapi runs on port 8000 with uvicorn
react frontend runs on port 5000 with npm start
axios base url is localhost:8000
Everything works as expected and the axios calls return correct response.
Production setup
fastapi runs on port 80 with gunicorn
frontend built with npm build
axios base url is localhost
all request handled with nginx in frontend
I based the following nginx conf file on this documentation
# conf file for server
# proxy pass for api requests
upstream api {
server backend;
}
# main server for app
server {
listen 80;
server_name localhost;
access_log /var/log/nginx/frontend;
error_log /var/log/nginx/frontend;
location / {
root /usr/share/nginx/html;
index index.html index.htm;
try_files $uri $uri/ /index.html;
}
location /api {
proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;
proxy_set_header X-Forwarded-Proto $scheme;
proxy_set_header X-Forwarded-Host $server_name;
proxy_redirect off;
proxy_pass http://api;
}
#error_page 404 /404.html;
# redirect server error pages to the static page /50x.html
#
error_page 500 502 503 504 /50x.html;
location = /50x.html {
root /usr/share/nginx/html;
}
}
Note that I am using docker compose and have a backend service and a frontend service.
With this configuration the login route works correctly, but the routes added via FastAPI.include_router return HTTP 307 redirect and the response header shows requested url as http://api/api/path/to/route instead of http://localhost/api/path/to/route. So it appears that nginx successfully proxy passes requests for a route directly in the main fastapi app module but redirects to the wrong url for requests to routes added with app.include_router. According to this reference, I should have proxy_redirect off; in the /api location block, but if I remove this line, then nginx redirects the request and returns the correct response.
question
why is nginx redirecting the request even when I include proxy_redirect off; in the conf file.
why does the redirect not return the correct response unless I remove proxy_redirect off;
I have an EC2 Instance with Nginx as the web server. I have an Angular 7 SPA sitting in an S3 bucket, that has been properly set up to serve web content. I have Nginx reverse proxy set up so that request to '/' will be served up by the staic SPA in the S3 bucket. After a bit of configuring the Nginx reverse proxy I was able to get the SPA served up and appears to be working properly.
The Problem
In Chrome when watching the network tab in DevTools the network request is showing as "404 Not Found" same in Firefox.
So the app appears to be loading and working but I think that I need to do something to address the fact the request comes back as 404 Not Found.
Eventually this will be a Angular SPA served up from the S3 bucket with an /api that Nginx will also reverse proxy to a Node Express app running on the EC2 instance.
The file that I can think that would be relevant to this discussion would be my Nginx default.conf, which is shown here.
server {
server_name idlewildeave.com;
location / {
# root /usr/share/nginx/html;
# index index.html index.htm;
proxy_http_version 1.1;
proxy_set_header Connection '';
proxy_set_header Host ng4app.s3-website-us-west-2.amazonaws.com;
proxy_set_header Authorization '';
proxy_hide_header x-amz-id-2;
proxy_hide_header x-amz-request-id;
proxy_hide_header Set-Cookie;
proxy_ignore_headers 'Set-Cookie';
proxy_buffering off;
proxy_intercept_errors on;
proxy_redirect off;
proxy_pass http://ng4app.s3-website-us-west-2.amazonaws.com;
}
#error_page 404 /404.html;
# redirect server error pages to the static page /50x.html
#
error_page 500 502 503 504 /50x.html;
location = /50x.html {
root /usr/share/nginx/html;
}
listen 443 ssl; # managed by Certbot
ssl_certificate /etc/letsencrypt/xxxx/xxxx.com/xxxx; # managed by Certbot
ssl_certificate_key /etc/letsencrypt/xxxx/xxxx.com/xxxxx; # managed by Certbot
include /etc/letsencrypt/xxxx.conf; # managed by Certbot
ssl_dhparam /etc/letsencrypt/xxxx.pem; # managed by Certbot
}
server {
if ($host = idlewildeave.com) {
return 301 https://$host$request_uri;
} # managed by Certbot
listen 80;
server_name idlewildeave.com;
# return 404; # managed by Certbot
}
So I have an app that spins up a web service at http://localhost:4206.
I have copied the app to an EC2 instance, and now want to start the service, but allow everyone (external consumers) to hit the service. I know that I can configure nginx to add a forward proxy from port 8080 (external) to my server's port (4206).
I've found the following guide: https://ef.gy/using-nginx-as-a-proxy-server
However, I'm unsure of what exactly on this guide I should be doing...
What should this snippet look like for me?
server {
listen 8080;
location / {
resolver 8.8.8.8;
proxy_pass http://$http_host$uri$is_args$args;
}
error_page 500 502 503 504 /50x.html;
location = /50x.html {
root html;
}
}
Some direction would be appreciated. Thanks!
server {
# Port
listen 8080;
# Set the name of the virtual server
server_name _;
# Proxy pass everything to http://localhost:4206/
location / {
proxy_pass http://localhost:4206;
# Set the proxied host
proxy_set_header Host localhost;
}
}
Read more on proxy_pass and other directives here: http://nginx.org/en/docs/http/ngx_http_proxy_module.html