Hide port with gunicorn and nginx - nginx

The Flask server starts at port 5000. With gunicorn and nginx, when I typed http://localhost:80 (or http://localhost) in browser, the browser redirects to http://localhost:5000.
I added a few lines in the nginx config file
location / {
# First attempt to serve request as file, then
# as directory, then fall back to displaying a 404.
try_files $uri $uri/ =404;
proxy_pass http://127.0.0.1:5000;
proxy_set_header Host $host;
proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;
}
How can I hide port(5000 in this case) after redirection? Thanks a lot.

This is how you should structure your configuration file:
server {
# listen on port 80
listen 80;
server_name _;
location / {
# First attempt to serve request as file, then
# as directory, then fall back to displaying a 404.
try_files $uri $uri/ =404;
proxy_pass http://127.0.0.1:5000;
proxy_set_header Host $host;
proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;
}
}
A server block is a subset of Nginx’s configuration that defines a virtual server used to handle requests of a defined type.
A location block lives within a server block and is used to define how Nginx should handle requests for different resources and URIs (the part of the request that comes after the domain name or IP address/port) for the parent server
How nginx processes a request

Related

NGINX Forward HTTPS request to HTTP Backend Server and Back

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.

Configure Nginx to serve a node js app from a location within root directory

I am trying to serve a Node JS app alongside some static sites that are already functioning and only serving static content (/insta-app is one of the apps, there is another nginx file with another server block for the other ones which sit on different subdomains). I am successfuly getting the server.js app when I navigate to the URL /nodejsapp. The problem is that all the static content the app requires does not get served and comes up as a 404 (images, js files and css). I wrote a location block for nodejsapp/dist where the static content exists but this did not fix the problem. The content is being requested by a handlebars template that gets successfully called and is sitting in a views folder in the root. I am running the whole thing on an ubuntu server, and the node app is running through pm2 which is working fine when I request curl localhost:3000. How can I get the static content into the server?
Nginx server block:
server {
listen 443 ssl default_server;
root /var/www;
index index.html index.htm server.js;
server_name uat.com www.uat.com;
ssl on;
ssl_certificate /etc/letsencrypt/live/uat.com/fullchain.pem;
ssl_certificate_key /etc/letsencrypt/live/uat.com/privkey.pem;
location / {
try_files $uri $uri/ =404;
}
location ~ /.well-known{
allow all;
}
location /insta-app{
alias /var/www/insta-app/html;
allow all;
}
location /nodeJsApp{
proxy_set_header X-Real-IP $remote_addr;
proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;
proxy_set_header X-NginX-Proxy true;
proxy_pass http://127.0.0.1:3000;
proxy_http_version 1.1;
proxy_set_header Upgrade $http_upgrade;
proxy_set_header Connection 'upgrade';
proxy_set_header Host $proxy_host;
proxy_cache_bypass $http_upgrade;
proxy_redirect off;
}
# attempt to serve the static content of the app
location /nodeJsApp/dist{
root /var/www/sydney-sevens/dist;
try_files $uri $uri/ =404;
}
}

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.

Trying to activate an nginx website on Raspbian on port 8000

I've managed to install nginx and bring up a website on port 81 (port 80 is blocked by my isp). I am trying to enable a second website on port 8000 with someone elses code. My test website was much simpler as I only had to put:
server {
listen 81;
root /var/www;
index index.html;
}
If I go to [http://127.0.0.1:81] in a browser, I will get the above website.
The second website is a bit more complicated and I'm not getting nginx to forward requests on port 8000. I have the second website in /var/www/website2. If I type [http://127.0.0.1:8000], I get "page not found. However, if I type [http://127.0.0.1:81/website2], then I get the website.
I have both sites available and enabled and I have a website2.cfg file located in /etc/nginx/.
Here is the content of the website2 file located in sites-available:
server {
server_name localhost;
auth_basic "Private Site";
auth_basic_user_file .htpasswd;
location / {
root /var/www;
index index.html ;
}
location /captures/ {
root /var/www;
}
location /api/ {
proxy_pass http://localhost:8000;
proxy_redirect off;
proxy_set_header Host $host;
proxy_set_header X-Real-IP $remote_addr;
proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;
}
location /video {
proxy_pass http://localhost:8002;
proxy_redirect off;
proxy_buffering off;
proxy_set_header Host $host;
proxy_set_header X-Real-IP $remote_addr;
proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;
}
}
Here is the content of the website2.cfg file located in /etc/nginx/:
[DEFAULT]
# Root directory of the service
root=/var/www/website2
[main]
logFile = /var/log/website2/website2.log
[web]
# Relative URL path to the captured images. Must match what is configurd in nginx, which much
match the directory specified in the [camera] section
capturePath=/captures
# Port on which the web server will listen
port=8000
[camera]
# The number of captured images to retain before pruning old ones
capturesToRetain=100
# The directory to store captured images. Please make sure this matches what was specified in the
[web] section
captureDir=%(root)s/captures
# The port on which the motion program listens for HTTP commands
motionControlPort = 8001
# The port on which the motion program streams video
motionStreamPort = 8002
If I can get this website serving on port 8000, I should be able to get the rest of the site working. Any help would be appreciated.

Using nginx as reverse proxy for apache and want more htaccess control

I'm using nginx in a reverse proxy configuration with apache2. I have used other, preconfigured web servers in this way and enjoyed complete control over redirects from an .htaccess file.
My current configuration does not allow for this. First, I'll explain what happens.
Let's say I want to redirect /google to http://google.com. I add the following line to my .htaccess file.
redirect 307 /google http://google.com
I know it's working because I can test with curl from my server. This is hitting apache directly, behind the proxy.
curl -I localhost:8080/google
and I get a 307 as I would expect.
But if this request hits nginx from the outside, nginx knows there is no such file in the web root and responds 404.
Is there a configuration change I can make to remedy this?
Here's my nginx configuration file for this vhost.
server {
listen 80;
root /var/www/mywebsite.com/html;
index index.php index.html index.htm;
server_name mywebsite.com;
access_log /var/log/nginx/mywebsite.com.access.log;
error_log /var/log/nginx/mywebsite.com.error.log;
location / {
try_files $uri $uri/ /index.php;
}
location ~ \.php$ {
proxy_set_header X-Real-IP $remote_addr;
proxy_set_header X-Forwarded-For $remote_addr;
proxy_set_header Host $host;
proxy_pass http://127.0.0.1:8080;
}
location ~ /\. {
deny all;
}
}
It seems that I might need to take the reverse approach and proxy everything but exclude certain file types from the proxy.
Thanks for advice folks!
If you want to forward that request to /google to apache, then just change the location ~ \.php$ pattern to include the request you desire:
location ~ (/google/?)|(\.php)$ {
On the other hand if you want nginx to handle the redirect you can add new rule:
location ~ /google {
return 307 http://google.com;
}
Just make sure to put it before the location block which contains try_files.
EDIT:
To forward all requests that don't hit a file use this:
location /
{
if (!-f $request_filename) #test if a static file does not exists
{
# forward the request if there is no file to serve:
proxy_set_header X-Real-IP $remote_addr;
proxy_set_header X-Forwarded-For $remote_addr;
proxy_set_header Host $host;
proxy_pass http://127.0.0.1:8080;
}
}
Additionally if you want for nginx to also serve entire directories then add another condition:
!-d $request_filename
Also note that if you want only specific files to be served then instead location / use the pattern to match those files. For example if you want to serve only jpg's and css's use
location ~ \.(jpg|css)$
EDIT2: Here you have a simplified version of your script, which is also more robust - lets you serve only the types of files you want:
server {
listen 80;
server_name test.lcl;
root /home/www/test;
location / {
try_files $uri $uri/ #apache;
}
location #apache
{
proxy_set_header X-Real-IP $remote_addr;
proxy_set_header X-Forwarded-For $remote_addr;
proxy_set_header Host $host;
proxy_pass http://127.0.0.1:8080;
}
}

Resources