skip to Main Content

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.

2

Answers


  1. Chosen as BEST ANSWER

    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"])
    ...
    

  2. 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

    project directory

    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:

    flask-app

    <host>:8080/a.html: (actually served from /home/myproject/static)

    static-file

    generally and for future reference – try looking at nginx logs (/var/log/nginx) or service logs (journalctl -u myproject or systemctl status myproject)

    Login or Signup to reply.
Please signup or login to give your own answer.
Back To Top
Search