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: " href="http://127.0.0.1:8006/favicon.ico" rel="nofollow
noreferrer">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 href="http://unix:/tmp/Flask.sock" rel="nofollow
noreferrer">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;
}
}
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.
Comments
Post a Comment