0

I am attempting to to host a Flask app with Gunicoron on a server that hosts multiple web services on Nginx. I am using AWS ubuntu as a test bed for evetually hosting it on said Nginx mutilple web service (that's not AWS). I've been trying to make it production status by changing the IP from external AWS to localhost 127.0.0.1 with socket 8006 as well as others. I tried to do the reverse proxying with no luck. I get a 502 Bad Gateway error with the following error:

Site Error Log

2019/06/11 05:08:58 [error] 9310#9310: *9 connect() failed (111: Connection refused) while connecting to upstream, client: 162.155.112.131, server: 127.0.0.1, request: "GET /favicon.ico HTTP/1.1", upstream: "http://127.0.0.1:8006/favicon.ico", host: AWS

Error Log:

2019/06/11 05:08:08 [emerg] 9311#9311: open() "/run/nginx.pid" failed (13: Permission denied) 2019/06/11 05:08:25 [warn] 9313#9313: could not build optimal proxy_headers_hash, you should increase either proxy_headers_hash_max_size: 512 or proxy_headers_hash_bucket_size: 64; ignoring proxy_headers_hash_bucket_size

Here's the code reproduced. I tried showing what I did while making it reproducible

/etc/nginx/sites-available/Flask

upstream tester {
    server 127.0.0.1:3306;
}
server {
    listen 80;
    server_name 127.0.0.1;
    listen [::]:80;
    listen 443 ssl;
    location / {
        include proxy_params;
#       proxy_pass 34.215.33.211;
#       proxy_pass http://unix:/tmp/Flask.sock;
        proxy_pass http://127.0.0.1:8006;
        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 ^~ /static/  {
        rewrite ^/static$ / break;
        rewrite ^/static/(.*) /$1 break;
        include  /etc/nginx/mime.types;
        proxy_pass http://127.0.0.1:8009;
        }

}

/etc/nginx/nginx.conf (Only the Virtual Host)

  ##
    # Virtual Host Configs
    ##

    include /etc/nginx/conf.d/*.conf;
    include /etc/nginx/sites-enabled/*;

Please and thank you for helping me out on this issue.

Edit: The http://unix:/tmp/Flask.sock works for proxy pass on my AWS but not on the production server

Edit 2: Now I'm also triggering 500 errors with the following:

768 worker_connections are not enough while connecting to upstream, client: 127.0.0.1, server: [AWS] request: "GET /favicon.ico HTTP/1.0"

The code for /etc/nginx/sites-available/Flask is now the following:

upstream gnx{
        server  127.0.0.1:8006;
}
server {
    listen 80;
    server_name [AWS URL];
    listen [::]:80;
    listen 8006;
    listen [::]:8006;
    listen [::1];
    access_log /var/log/nginx/site_access.log;
    error_log /var/log/nginx/site_error.log;

    location / {
        include proxy_params;
#        proxy_pass http://unix:/tmp/Flask.sock;
        proxy_pass http://gnx;
        proxy_redirect off;
    }
    location ^~ /static/  {
        #root  /home/ubuntu/Flask/static/;
        #proxy_pass http://gnx;

        proxy_redirect http://127.0.0.1:8006/static/ http://$host/static/;
        proxy_set_header SCRIPT_NAME /static;
        }

    location /docs  {
        alias /home/ubuntu/Flask/docs;
 }
}
0

Okay, I found the issue so first let's address the /sites-available/Flask (or /default) file

upstream gnx{
        server  127.0.0.1:8006;
}
server {
    listen 80;
    server_name [AWS URL];
    listen [::]:80;
    listen [::1];
    access_log /var/log/nginx/site_access.log;
    error_log /var/log/nginx/site_error.log;

    location / {
        include proxy_params;
#        proxy_pass http://unix:/tmp/Flask.sock;
        proxy_pass http://gnx;
       proxy_set_header X-SCRIPT-NAME "/";
    }
    location ^~ /static/  {
        #root  /home/ubuntu/Flask/static/;
        #proxy_pass http://gnx;

        proxy_redirect http://127.0.0.1:8006/static/ http://$host/static/;
        proxy_set_header SCRIPT_NAME /static;
        }

    location /docs  {
        alias /home/ubuntu/Flask/docs;
 }
}

So we do not need to listen to the ports 8006 as we will be using them. The next part we added was the following:

proxy_set_header X-SCRIPT-NAME "/";

X-SCRIPT-NAME allows redirection of the Flask Reverse proxying to the Flask script. You can also put it in the proxy_params file (/etc/nginx/proxy_params), which I did, but I wanted to put it in the script so it was visible.

So now, the trick is to implement the reverse proxying. This is the Python code and function you would want to put in:

from werkzeug.serving import WSGIRequestHandler
class ScriptNameHandler(WSGIRequestHandler):
    def make_environ(self):
        environ = super().make_environ()
        script_name = environ.get('HTTP_X_SCRIPT_NAME', '')
        if script_name:
            environ['SCRIPT_NAME'] = script_name
            path_info = environ['PATH_INFO']
        if path_info.startswith(script_name):
            environ['PATH_INFO'] = path_info[len(script_name):]
        scheme = environ.get('HTTP_X_SCHEME', '')
        if scheme:
            environ['wsgi.url_scheme'] = scheme
        return environ

Then finally for your app.run file, you want to switch it to the following:

app.run(request_handler=ScriptNameHandler)

Which now runs the reverse proxy for you and have the setup. This method was 99.9% derived from David which also has the Apache version. I hope it helps anyone in this issue.

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service, privacy policy and cookie policy

Not the answer you're looking for? Browse other questions tagged or ask your own question.