Tuesday, May 12, 2015

Localhost reverse proxy fails nginx AWS Ubuntu



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;
}
}

Answer



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.


No comments:

Post a Comment

linux - How to SSH to ec2 instance in VPC private subnet via NAT server

I have created a VPC in aws with a public subnet and a private subnet. The private subnet does not have direct access to external network. S...