Search code examples
nginxflasknginx-reverse-proxyamazon-linux

connect() failed (111: Connection refused) while connecting to upstream) NGINX, Gunicorn when running Flask App


I'm trying to host a flask application on a Public EC2 instance on Amazon-Linux-2 using aws-cdk.

I've configured nginx such for a custom health check endpoint /healthcheck i have created a python env and installed gunicorn there and ran gunicorn --bind 127.0.0.1:5000 wsgi:app in my python env and was able to hit the endpoint ('/' for POST method)using POSTMAN. But the problem arises when i try to create a myproject.service file. the myproject.sock file is created , it has all the necessary permission chmod 755 /home/ec2-user/myproject , the systemctl status myproject also says running but now I can't hit the POST request using POSTMAN.

My reverse.proxy file is as follows-

configuration file /etc/nginx/sites-enabled/reverse-proxy.conf:

server {
        listen 80;
        listen [::]:80;

        access_log /var/log/nginx/reverse-access.log;
        error_log /var/log/nginx/reverse-error.log;

        location /healthcheck {
                limit_except GET {
                        deny all;
                }
                access_log off;
                return 200 "healthy\n";
        }

        location / {
                    error_page 405 =200 $uri;
                    proxy_pass http://127.0.0.1:5000;
  }
}

Where '/' is used to serve post requests from my flaskapp.py file

This is how myproject.service file looks like

[Unit]
Description=Gunicorn instance to serve myproject
After=network.target

[Service]
User=ec2-user
WorkingDirectory=/home/ec2-user/myproject
Environment="PATH=/home/ec2-user/myproject/myprojectenv/bin"
ExecStart=/home/ec2-user/myproject/myprojectenv/bin/gunicorn --workers 3 --bind unix:myproject.sock -m 007 wsgi:app

[Install]
WantedBy=multi-user.target

The sock file is also created and running successfully but unable to hit POST

this is how my flaskapp.py looks

from flask import Flask, request


app = Flask(__name__)

@app.route('/', methods=['POST'])
def handler():
    return f''' Hello {request.get_json()['name']}'''

and this is how my wsgi.py looks

from myproject import app

if __name__ == "__main__":
    app.run(host='127.0.0.1')

Not able to understand what is wrong that when i run gunicorn --bind 127.0.0.1:5000 wsgi:app , i'm able to hit POST requests but when in exit gunicorn and try to create a myproject.service , i can't seem to hit POST requests. The /healthcheck works fine!

Please provide insight


Solution

  • Your NGINX config is pointing to a server listening on localhost port 5000, but your service is listening on the unix socket myproject.sock. As such, NGINX can't find the server when you run the service.

    Try to set your NGINX config to something like:

    server {
       ...
       location / {
          ...
          proxy_pass http://unix:/path/to/myproject.sock;
       }
    }
    

    This should work when gunicorn is listening on a unix socket, such as in your service.

    You need to make sure that NGINX can read and write to the unix socket. Run stat /path/to/myproject.sock and make sure that NGINX's user (most likely, nginx) has enough permissions.

    Consider taking the docker way here: create a group only for the myproject.sock and the clients supposed to connect to it (i.e: nginx user and so on)