Running a proxy_pass on a subpath in NGINX - sockets

I am trying to run a Flask app on Gunicorn through an Nginx server. I would like the app to run on a sub-directory instead of through a different port, if possible, but all I get are 404 errors. Here is my conf file, which is an included file in the conf.d folder:
server {
listen 80;
server_name 127.0.0.1;
location / {
root /var/www/html;
}
location /chess/ {
proxy_pass http://unix:/usr/share/nginx/sockets/chess.sock;
proxy_set_header Host $http_host;
proxy_set_header X-Real-IP $remote_addr;
proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;
proxy_set_header X-Forwarded-Proto $scheme;
}
}
Could someone please tell me how to do this? I have looked all over and tried a lot of different things, to no avail. It runs fine on a different port, but that is not what I want. A subdomain is also a suitable option, but I can only get that to work in production, not development, for some reason. Someone posed the question here but the link they gave to the solution is dead.

when do you get 404's? when you access /chess/?
please attach the flask app's code.
anyway,
the following certainly works, I tested it.
followed this guide
myproject.py:
from flask import Flask
app = Flask(__name__)
#app.route("/chess/",defaults={'name': None})
#app.route("/chess/<name>")
def hello(name):
if name is None:
name="!"
else:
name = ", " + name
# PLEASE don't use the following line of code in a real app, it creates a self-xss vulnerability. ALWAYS sanitize user input.
return f"<h1 style='color:blue'>Hello There{name}</h1>"
if __name__ == "__main__":
app.run(host='0.0.0.0')
nginx - /etc/nginx/sites-enabled/myproject (symlink)
server {
listen 8080;
server_name your_domain www.your_domain;
location / {
root /home/username/myproject/static/;
}
location /chess/ {
include proxy_params;
proxy_pass http://unix:/home/username/myproject/myproject.sock;
}
}
<host>:8080/chess/stackoverflow:
<host>:8080/a.html: (actually served from /home/myproject/static)
generally and for future reference - try looking at nginx logs (/var/log/nginx) or service logs (journalctl -u myproject or systemctl status myproject)

Two methods are available. The first method involves adding the subpath to both the NGINX configuration and the Flask app, as suggested in the answer by Yarin_007. Set up NGINX like so:
server {
listen localhost:80;
location / {
root /var/www/html;
}
location /chess/ {
proxy_pass http://unix:/usr/share/nginx/sockets/chess.sock;
proxy_set_header Host $http_host;
proxy_set_header X-Real-IP $remote_addr;
proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;
proxy_set_header X-Forwarded-Proto $scheme;
}
}
And alter the Flask app to include the subpath:
from flask import Flask, request
...
#app.route("/chess/", methods=["GET", "POST"])
...
The alternative, as suggested in this answer is to run the Gunicorn service on a non-privileged port (or maybe a subdomain) and use two proxy_pass directives to direct from the port 80 subpath like so:
server {
listen localhost:80;
location / {
root /var/www/html;
}
location /chess/ {
proxy_pass http://localhost:8080/;
}
}
server {
listen localhost:8080;
location / {
proxy_pass http://unix:/usr/share/nginx/sockets/chess.sock;
proxy_set_header Host $http_host;
proxy_set_header X-Real-IP $remote_addr;
proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;
proxy_set_header X-Forwarded-Proto $scheme;
}
}
The Flask app can remain as it was originally:
from flask import Flask, request
...
#app.route("/", methods=["GET", "POST"])
...

Related

How can I strip the base url in Nginx for a Mojolicious app?

I am trying to run a Mojolicious up as a reverse proxy. My Nginx configuration looks like this:
upstream printo {
server 127.0.0.1:3000;
}
[..]
location /print {
proxy_pass http://printo;
proxy_http_version 1.1;
proxy_set_header Upgrade $http_upgrade;
proxy_set_header Connection "upgrade";
proxy_set_header Host $host;
proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;
proxy_set_header X-Forwarded-Proto $scheme;
}
I'd like to strip the /printo portion of the URL before the request reaches the Mojolicious app - otherwise, all the requests have a /printo/something URL, which results in a 404.
I've seen this but I'd like to do it in Nginx if possible.
I've tried rewrite like this:
rewrite ^/print/(.+)$ $1;
to no result.
How's that done?
To modify the URI as it passes upstream, you can use a rewrite...break or perform a similar function using the proxy_pass directive itself.
For example:
location /print {
rewrite ^/print(/.*)$ $1 break;
proxy_pass http://printo;
...
}
Remember to keep a leading / in the rewritten URI. See this document for details.
Or:
location /print/ {
proxy_pass http://printo/;
...
}
The location value should have a trailing / to ensure that the text substitution occurs correctly. See this document for details.

Facebook webhook IP address not in the docs

I am creating the webhook to my computer server. According to the official docs. It says the following command will provide me CIDR of them.
Docs
whois -h whois.radb.net -- '-i origin AS32934' | grep ^route
But when I implement. I always got another Facebook IP addresses which are not in the list.
Refer to this I am aware that it frequently changed. But it should not out of the list in 10 seconds.
I got new knowledge today!
Nginx, Docker, Django through the way until reach my code variable
REMOTE_ATTR got mutated by someone in the line. Then I add new reference X-Real-IP with the same variable and then observe my code again.
location / {
proxy_pass_request_headers on;
proxy_set_header Host $host;
proxy_pass http://app;
proxy_set_header X-Real-IP $remote_addr;
proxy_set_header X-Scheme $scheme;
proxy_set_header REMOTE_ADDR $remote_addr;
}
And someone again mutate the variable name from X-Real-IP to HTTP_X_REAL_IP. Finally my WebhookPermission must be this
import logging
from rest_framework import permissions
from poinkbackend.apps.socials.utils import check_whitelist
logger = logging.getLogger('django')
class WebhookPermission(permissions.BasePermission):
def has_permission(self, request, view):
ip_addr = request.META['HTTP_X_REAL_IP']
logger.info(f'{ip_addr} inbound a webhook')
logger.info(f'{request.META}')
return check_whitelist(ip_addr)

prevent redirecting to https and URI hacks nginx reverse proxy

I have setted up a reverse proxy on my server with nginx inside docker, and since then all request are redirecting to https although i didn't set all locations to https redirection.
Basically what i want is to be able to serve both https and http with the reverse proxy.
In addition i want to be able to redirect to different URI dynamically, for example i want to set all routes of /bla2/foo/bar to be redirected to only what comes after /bla2
what i tried to get here is that whenever accessing to example.com/bla2/foo/bar it should redirect it to example.com/foo/bar without the bla2 section...
Is it possible on the same configuration file?
what can cause my server to redirect all request to https
This is my server nginx.conf
server {
listen 443;
ssl on;
ssl_certificate /etc/ssl/example.com.crt;
ssl_certificate_key /etc/ssl/example.com.key;
listen 80;
server_name example.com;
location /bla/bla {
proxy_pass http://example.com:3980/foo/bar1;
}
**location /bla2/**{
# proxy_pass http://example.com:3004;
return 301 http://example.com:3004$request_uri;
proxy_set_header X-Real-IP $remote_addr;
proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;
proxy_set_header Host $http_host;
proxy_set_header X-NginX-Proxy true;
proxy_redirect off;
proxy_http_version 1.1;
proxy_set_header Upgrade $http_upgrade;
proxy_set_header Connection "upgrade";
proxy_set_header X-Forwarded-Proto $scheme;
}
location /app3 {
rewrite ^/app3(.*) /$1 break;
proxy_pass http://example.com:1236/app3;
}
}
I want to be able to get directly content of http://example.com:3004 if i put it in the browser without any redirection to https.
Only if i try access example.com/bla2 i want it to be required https instead of http, and to be redirected to different path.
You need to use regular expression and capture groups for this
location ~* /bla2/(.*) {
return 301 http://example.com:3004$1$is_args$args;
}
Another way of doing it would be just use rewrite
rewrite ^/bla2/(.*)$ http://example.com:3004/$1 redirect;
If you want to transparently proxy it to the example.com:3004 removing /bla2 then you should use
location /bla2/ {
proxy_pass http://example.com:3004/;
}
The trailing slash / in /bla2/ and http://example.com:3004/ is very important here

Virtual host with sails.js

I want to have subdomains for my app.
For example:
myapp.com
admin.myapp.com
static.myapp.com
And directory structure like this:
myapp
frontend [sails app] -> myapp.com
backend [sails app] -> admin.myapp.com
static [express app] -> static.myapp.com
app.js
In express I could use vhost.
How can I achieve this in sails.js?
I have not tried it, but I think it can be done using Nginx's reverse proxy.
Let's say you have 2 SailsJS projects (Sails1 and Sails2) configured to run on two different ports (port 1337 and port 1338) respectively. You can configure the SailsJS app to run on any port by making changes in /config/locals.js
Now follow below steps:
Run both applications using "sails lift" or "forever" commands
Install Nginx
Config Nginx
$ cd /etc/nginx/sites-available/
$ sudo touch sails1.conf
$ sudo touch sails2.conf
$sudo ln -s /etc/nginx/sites-available/sails1.conf
/etc/nginx/sites-enabled/sails1.com.conf
$ sudo ln -s /etc/nginx/sites-available/sails2.conf
/etc/nginx/sites-enabled/sails2.conf
Put below content in /etc/nginx/sites-available/sails1.conf
server {
listen 80;
server_name sails1.com;
location / {
proxy_pass http://localhost:1337;
proxy_http_version 1.1;
proxy_set_header Upgrade $http_upgrade;
proxy_set_header Connection 'upgrade';
proxy_set_header Host $host;
proxy_cache_bypass $http_upgrade;
}
}
Put below content in /etc/nginx/sites-available/sails2.conf
server {
listen 80;
server_name sails2.com;
location / {
proxy_pass http://localhost:1338;
proxy_http_version 1.1;
proxy_set_header Upgrade $http_upgrade;
proxy_set_header Connection 'upgrade';
proxy_set_header Host $host;
proxy_cache_bypass $http_upgrade;
}
}
Restart Nginx and try accessing sails.com and sails2.com hopefully you should be able to see both your website.
I haven't used vhosts directly with sails, but you can access the underlying express engine pretty easily..
//./config/express.js
module.exports.express = {
customMiddleware: function (app) {
app.use(vhost('*.example.com', require('app1'));
app.use(vhost('example.com', function(..){...}));
app.use('/queue', require('kue').app);
}
}

Socket.io/WebSockets continuously reconnecting — issue with Nginx proxy configuration?

I am using Socket.IO in my Node.js application. Today I deployed it for the first time, and I noticed that my sockets keep reconnecting. I have "connect" and "disconnect" logging to the console in the respective socket events, and this is the result:
What's more, it seems that the polling technique is being used, when my browser is surely modern enough to use WebSockets — so I believe this is a configuration issue. WebSockets work fine when I am running the Node.js in development with no proxy in the middle.
This is my Nginx configuration, which serves as a proxy to my Node.js server:
upstream reader.oliverjash.me {
server 127.0.0.1:3000;
}
server {
listen 80;
server_name reader.oliverjash.me;
access_log /var/log/nginx/reader.oliverjash.me.access.log;
error_log /var/log/nginx/reader.oliverjash.me.error.log;
location / {
proxy_set_header X-Real-IP $remote_addr;
proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;
proxy_set_header Host $http_host;
proxy_set_header X-NginX-Proxy true;
proxy_http_version 1.1;
proxy_set_header Upgrade $http_upgrade;
proxy_set_header Connection "upgrade";
proxy_pass http://reader.oliverjash.me;
proxy_redirect off;
}
}
I believe that the lines:
proxy_http_version 1.1;
proxy_set_header Upgrade $http_upgrade;
proxy_set_header Connection "upgrade";
are significant in enabling WebSockets (as per this reference/tutorial). Before I added these, WebSockets did not work at all with the proxy. Now I seem to get polling, which is better than nothing.
My Nginx version is 1.4.0 stable.
Turns out the problem was because I had clustered my Node apps. Added Redis as a memory store for Socket.IO and that solved all of my problems! http://adamnengland.wordpress.com/2013/01/30/node-js-cluster-with-socket-io-and-express-3/