Flask Set up Flask Application, uWGSI, Nginx - Server Configurations boiler template (default, proxy and cache)


Example

This is a porting of set up sourced from DigitalOcean's tutorial of How To Serve Flask Applications with uWSGI and Nginx on Ubuntu 14.04

and some useful git resources for nginx servers.

Flask Application

This tutorial assume you use Ubuntu.

  1. locate var/www/ folder.
  2. Create your web app folder mkdir myexample
  3. cd myexample

optional You may want to set up virtual environment for deploying web applications on production server.

sudo pip install virtualenv

to install virtual environment.

virtualenv myexample

to set up virtual environment for your app.

source myprojectenv/bin/activate 

to activate your environment. Here you will install all python packages.

end optional but recommended

Set up flask and gateway uWSGI

Install flask and uSWGI gateway:

pip install uwsgi flask

Example of flask app in myexample.py:

from flask import Flask
application = Flask(__name__)

@application.route("/")
def hello():
    return "<h1>Hello World</h1>"

if __name__ == "__main__":
    application.run(host='0.0.0.0')

Create file to communicate between your web app and the web server: gateway interface [https://en.wikipedia.org/wiki/Web_Server_Gateway_Interface]

nano wsgi.py

then import your webapp module and make it run from the gateway entry point.

from myexample import application

if __name__ == "__main__":
    application.run()

To test uWSGI:

uwsgi --socket 0.0.0.0:8000 --protocol=http -w wsgi

To configure uWSGI:

  1. Create a configuration file .ini

    nano myexample.ini

  2. Basic configuration for gateway uWSGI

# include header for using uwsgi
[uwsgi]
# point it to your python module wsgi.py
module = wsgi
# tell uWSGI to start a master node to serve requests
master = true
# spawn number of processes handling requests
processes = 5
# use a Unix socket to communicate with Nginx. Nginx will pass connections to uWSGI through a socket, instead of using ports. This is preferable because Nginx and uWSGI stays on the same machine.
socket = myexample.sock
# ensure file permission on socket to be readable and writable
chmod-socket = 660
# clean the socket when processes stop
vacuum = true
# use die-on-term to communicate with Ubuntu versions using Upstart initialisations: see:
# http://uwsgi-docs.readthedocs.io/en/latest/Upstart.html?highlight=die%20on%20term
die-on-term = true

optional if you are using virtual env You can deactivate your virtual environment.

Nginx configuration We are gonna use nginx as:

  1. default server to pass request to the socket, using uwsgi protocol
  2. proxy-server in front of default server
  3. cache server to cache successful requests (as example, you may want to cache GET requests if your web application)

Locate your sites-available directory and create a configuration file for your application:

sudo nano /etc/nginx/sites-available/myexample

Add following block, in comments what it does:

server {
   

    # setting up default server listening to port 80
    listen 8000 default_server;
    server_name myexample.com; #you can also use your IP 
    
    # specify charset encoding, optional
    charset utf-8;

    # specify root of your folder directory
    root /var/www/myexample;

    # specify locations for your web apps.
    # here using /api endpoint as example
    location /api {
        # include parameters of wsgi.py and pass them to socket
        include uwsgi_params;
        uwsgi_pass unix:/var/www/myexample/myexample.sock;
    }

}

# Here you will specify caching zones that will be used by your virtual server
# Cache will be stored in /tmp/nginx folder
# ensure nginx have permissions to write and read there!
# See also:
# http://nginx.org/en/docs/http/ngx_http_proxy_module.html

proxy_cache_path /tmp/nginx levels=1:2 keys_zone=my_zone:10m inactive=60m;
proxy_cache_key "$scheme$request_method$host$request_uri";

# set up the virtual host!
server {
    listen   80  default_server;
    
    # Now www.example.com will listen to port 80 and pass request to http://example.com
    server_name www.example.com;

    # Why not caching responses

    location /api {
        # set up headers for caching
        add_header X-Proxy-Cache $upstream_cache_status;

        # use zone specified above
        proxy_cache my_zone;
        proxy_cache_use_stale updating;
        proxy_cache_lock on;
        
        # cache all responses ?
        # proxy_cache_valid 30d;

        # better cache only 200 responses :)
        proxy_cache_valid 200 30d;

        # ignore headers to make cache expire
        proxy_ignore_headers X-Accel-Expires Expires Cache-Control;

        # pass requests to default server on port 8000
        proxy_pass http://example.com:8000/api;
    }
}

Finally, link the file to sites-enabled directory. For an explanation of available and enabled sites, see answer: [http://serverfault.com/a/527644]

sudo ln -s /etc/nginx/sites-available/myproject /etc/nginx/sites-enabled

You are done now with nginx. However, you may want to check out this very precious boiler template: [https://github.com/h5bp/server-configs-nginx]

Very useful for fine tuning.

Now test Nginx:

sudo nginx -t

Launch Nginx:

sudo service nginx restart

Automate Ubuntu to start uWSGI The last thing is to make Ubuntu start the wsgi gateway communicating with your application, otherwise you should do it manually.

  1. Locate directory for initialisation scripts in Ubuntu, and create a new script:

sudo nano /etc/init/myexample.conf

  1. Add following block, comments in line to explain what it does

    # description for the purpose of this script
    description "uWSGI server instance configured to serve myproject"
    
    # Tell to start on system runtime 2, 3, 4, 5. Stop at any other level (0,1,6). 
    # Linux run levels: [http://www.debianadmin.com/debian-and-ubuntu-linux-run-levels.html]
    start on runlevel [2345]
    stop on runlevel [!2345]
    
    # Set up permissions! "User" will be the username of your user account on ubuntu.
    setuid user
    # Allow www-data group to read and write from the socket file. 
    # www-data is normally the group Nginx and your web applications belong to.
    # you may have all web application projects under /var/www/ that belongs to www-data group
    setgid www-data
    
    # tell Ubunutu which environment to use.
    # This is the path of your virtual environment: python will be in this path if you installed virtualenv. Otherwise, use path of your python installation
    env PATH=/var/www/myexample/myexample/bin
    # then tell to Ubuntu to change and locate your web application directory
    chdir /var/www/myexample
    # finally execute initialisation script, that load your web app myexample.py
    exec uwsgi --ini myexample.ini
    
    

Now you can activate your script: sudo start myexample