How to Run Flask Applications with Nginx Using Gunicorn


We have recently bought a VPS for İTÜ24, the online newsletter of Istanbul Technical University. The server is running on Ubuntu Server 12.04 operating system. Due to limited memory resources and performance concerns, we preferred to setup nginx as web server.

Our server will serve several web pages and applications developed in various programming languages, such as PHP, Python, Ruby (on Rails). Currently, we have one Python application, which is using Flask framework.

How we run Flask application with nginx, step by step…

Step 0: Requirements

We work on a virtual Python environment, using virtualenv, and install Python packages with pip. Install these by typing:

sudo apt-get install python-virtualenv python-pip

Create a virtual environment and activate it.

virtualenv hello
source hello/bin/activate

Notice, your prompt is now prefixed with the name of the virtual environment.

Step 1: The Application

After installing Flask with pip, you can save the following code as “hello.py” and run it.

pip install Flask
from flask import Flask
app = Flask(__name__)

@app.route('/')
def hello():
    return "Hello world!"

if __name__ == '__main__':
    app.run()

Flask has a built-in web server that allows you to run your application. However, it is not scalable and production ready. On the other hand, there is gunicorn which is a production ready Python WSGI server that also provides scalability.

Step 2: Gunicorn

pip install gunicorn

In order to make our application to work with gunicorn, we have to add two lines to it:

from flask import Flask
from werkzeug.contrib.fixers import ProxyFix
app = Flask(__name__)

@app.route('/')
def hello():
    return "Hello world!"

app.wsgi_app = ProxyFix(app.wsgi_app)

if __name__ == '__main__':
    app.run()

Notice the 2nd and 9th lines. Now we can serve our application with Gunicorn.

gunicorn hello:app

“hello” is the name of the file (without extension). And “app” is the name of the Flask object. You can find more info about configuration of gunicorn on their web pages.

Step 3: Nginx

Create new server configuration and save the file in /etc/nginx/sites-available/hello.conf.

server {
    listen 80;
    server_name hello.itu24.com;

    root /path/to/hello;

    access_log /path/to/hello/logs/access.log;
    error_log /path/to/hello/logs/error.log;

    location / {
        proxy_set_header X-Forward-For $proxy_add_x_forwarded_for;
        proxy_set_header Host $http_host;
        proxy_redirect off;
        if (!-f $request_filename) {
            proxy_pass http://127.0.0.1:8000;
            break;
        }
    }
}

Enable new configuration by creating a symbolic link in sites-enabled directory.

sudo ln -s /etc/nginx/sites-available/hello.conf /etc/nginx/sites-enabled/

Check configuration for errors:

nginx -t

If your configuration is ok, you can reload nginx and access your application now.

sudo service nginx reload

Update 2012/09/07: In order to start gunicorn automatically when the system reboots, check my new blog post!

Update 2012/10/05: You had better not use if statements in Nginx configurations, because if is evil! See this comment