Ajnin123
By:
Ajnin123

I'm having issues using nginx to route my Flask app. What am I doing wrong?

February 5, 2015 3.9k views

Hi All,

Using this guide I created a basic Flask App in Python. This worked well, and connecting my domain successfully showed this page. To make it scalable for multiple apps, I asked how to do it on this thread. Following that, to make my Flask App route via nginx to allow for multiple apps, I did these steps:

  1. I connected my domain via the DNS Settings in Digital Domain, and linked my domain to to route to the IP. I did this by pointing an A record from my domain to my IP, and NS records to the Digital Ocean servers. Since this worked for a single app, I assume there was no error in this stage.

  2. I installed NGINX:
    sudo aptitude install nginx

  3. I added this to the default /etc/nginx/nginx.conf:

    upstream app_server_one { 
        server 127.0.0.1:8000 fail_timeout=0; 
    }
    
    server { 
        listen 80 default_server; 
        server_name: my-domain.com
    
        location / { 
            proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for; 
            proxy_set_header Host $http_host; 
            proxy_redirect off; 
            proxy_pass http://app_server_one; 
        } 
    }
    
  4. I started my nginx server:

    sudo service nginx start

  5. I started my app:

    sudo (nohup) python app.py

For those curious, this is app.py:

from flask import Flask
app = Flask(__name__)

@app.route('/')
def index():
    return 'Hello, World!'

if __name__ == '__main__':
    app.run(host='0.0.0.0', port=8000, debug=True)

Note how I run it on port 8000, replacing the need for Gunicorn.

Doing this, I got the Error 'This webpage is not available' from Chrome. Would anyone be able to identify where I went wrong? According to my ticket, this is a issue in my Apache configuration, but considering I don't have that installed, I'm not sure that's the issue. Pinging my domain does return the ip, so I'm assuming it's server side. If you needed, I would be happy to provide extra details.

Thanks,

Ajnin.

7 comments
  • What's in /etc/nginx/sites-enabled/default ? A good best practice is to put your site specific Nginx configurations there and leave /etc/nginx/nginx.conf for global changes. Either way, make sure there isn't a conflicting Nginx server block there.

    On a fresh Ubuntu server, with the Nginx configuration you have above in /etc/nginx/sites-enabled/default, I am able to successfully run that Flask app and access it from the IP address directly (no port appended).

  • @asb Note how I said that a single app worked on the default configuration. The challenge is to make it suited towards multiple apps.

  • @Ajnin123 It's hard to tell what your issue is without more information. Let's try to rule a few things out? Are both Flask apps actually running and accessible? Can you connect to both of them via the IP address with their ports? Check the output of netstat -plunt It should show both apps listening:

    # netstat -plunt
    Active Internet connections (only servers)
    Proto Recv-Q Send-Q Local Address           Foreign Address         State       PID/Program name
    tcp        0      0 0.0.0.0:80              0.0.0.0:*               LISTEN      1614/nginx      
    tcp        0      0 0.0.0.0:22              0.0.0.0:*               LISTEN      893/sshd        
    tcp        0      0 0.0.0.0:8000            0.0.0.0:*               LISTEN      3223/python     
    tcp        0      0 0.0.0.0:7000            0.0.0.0:*               LISTEN      3224/python      
    tcp6       0      0 :::22                   :::*                    LISTEN      893/sshd 
    

    As the error you're seeing is 'This webpage is not available' as opposed to an HTTP error code, it doesn't seem like you are not even reaching the server. Could you describe your DNS setup? You should have two A records pointing to this IP address and they should match the FQDNs that you are using in the server directives of your two Nginx server blocks.locks.

    This guide focuses on identifying and troubleshooting the most commonly encountered HTTP error codes, i.e. 4xx and 5xx status codes, from a system administrator's perspective. There are many situations that could cause a web server to respond to a request with a particular error code--we will cover common potential causes and solutions.
  • @asb To allow me to test 2 apps, I am now running 2 apps (which individually run without nginx running). These are run from nohup (which I can't seem to stop now).

    I am currently running two files (app.py and app2.py)

    app.py:

    from flask import Flask
        app = Flask(__name__)
    
    @app.route('/')
    def index():
        return 'Cloud'
    
    if __name__ == '__main__':
        app.run(host='0.0.0.0', port=7000, debug=True)
    

    app2.py

    from flask import Flask
    app = Flask(__name__)
    
    @app.route('/')
    def index():
        return 'Cloud'
    
    if __name__ == '__main__':
        app.run(host='0.0.0.0', port=7000, debug=True)
    

    I have now removed everything previously added from /etc/nginx/nginx.conf and made /etc/nginx/sites-enabled/default this:

    upstream app_server_one {
        server 127.0.0.1:7000 fail_timeout=0;
    }
    
    upstream app_server_two {
        server 127.0.0.1:8000 fail_timeout=0;
    }
    
    server {
        listen 80 default_server;
        server_name: cloud.ajnin.me
    
       # [snip...]
    
        location / {
            proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;
            proxy_set_header Host $http_host;
            proxy_redirect off;
            proxy_pass http://app_server_one;
        }
    }
    
    server {
        listen 80 default_server;
        server_name: cloud2.ajnin.me
    
       # [snip...]
    
        location / {
            proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;
            proxy_set_header Host $http_host;
            proxy_redirect off;
            proxy_pass http://app_server_two;
        }
    }```
    

    This is my Domain setup (for ajnin.me subdomains):

    From my Domain Host
    From the DigitalHosting side

    I got a little confused when you asked me to do this: "You should have two A records pointing to this IP address and they should match the FQDNs that you are using in the server directives of your two Nginx server blocks.locks." - I'm not sure how to do this, would it be ok if you could explain?

    For some reason it doesn't seem to be showing the apps running on plunt. I'm not sure why this is. Here's the logs. This is probably part of the issue, as connecting to the ip and port doesn't seem to work (http://178.62.69.188:8000).

    I'm guessing this isn't an issue with the app code, but diagnosing why nginx is not allowing the app to connect to the client is proving fairly difficult (and then getting the domain to link to the nginx as well).

    Ajnin.

  • @asb as an update, I found that the ip works when running either apps, the domain doesn't however.

  • @asb as a side note, if I run a Python script, how do I make it run in the background and restart on a server restart, and close it at a later time? I know I can use nohup, but when I close the terminal it seems to stop the program. Using python app.py & seems to work, but I'm not sure how to stop it.

  • @asb Alternatively, using this tutorial, would it be possible (and if so how) could I do this using a Apache Virtualhost?

    <VirtualHost *:80>
            ServerName cloud.ajnin.me
            WSGIScriptAlias the/location/flaskapp.wsgi
            <Directory the/location/FlaskApp/>
                Order allow,deny
                Allow from all
            </Directory>
            Alias /static the/location/FlaskApp/FlaskApp/static
            <Directory the/location/FlaskApp/FlaskApp/static/>
                Order allow,deny
                Allow from all
            </Directory>
            ErrorLog ${APACHE_LOG_DIR}/error.log
            LogLevel warn
            CustomLog ${APACHE_LOG_DIR}/access.log combined
    </VirtualHost>
    
    <VirtualHost *:80>
            ServerName cloud2.ajnin.me
            WSGIScriptAlias the/location/flaskapp.wsgi
            <Directory the/location/FlaskApp2/>
                Order allow,deny
                Allow from all
            </Directory>
            Alias /static the/location/FlaskApp2/FlaskApp/static
            <Directory the/location/FlaskApp2/FlaskApp/static/>
                Order allow,deny
                Allow from all
            </Directory>
            ErrorLog ${APACHE_LOG_DIR}/error.log
            LogLevel warn
            CustomLog ${APACHE_LOG_DIR}/access.log combined
    </VirtualHost>
    
    by Kundan Singh
    Here's our guide on deploying a flask app on an Ubuntu VPS.
1 Answer

According to some searching, I've found that I need to use Supervisord to run apps in the background. I'll do some more research to see if I can make this work.

Have another answer? Share your knowledge.