How to setup Flask with gunicorn and nginx with example



This guide will help you to setup a Flask app using gunicorn and nginx. It will cover also how to do a load balance with many instances. You need to be familiar with virtualenv and some minimal python.

Step 1: Install requirements

Install nginx and python dependencies

sudo apt update
sudo apt install python-pip python-dev nginx

Step 2: Install python dependencies

Prepare the virtualenv. In this guide we will use virtualenv wrapper. If you want to know more about virtualenv wrapper installation check here.

sudo pip install pip -U  # update pip
sudo pip install virtualenvwrapper
# next command are for using virtualenvwrapper with bash
export WORKON_HOME=$HOME/.virtualenvs
source /usr/local/bin/virtualenvwrapper.sh
mkvirtualenv flask_app

All your virtualenv will be saved at your home directory under the name .virtualenv. Now it's time to isntall your flask app deps:

workon flask_app
pip install -r requirements.txt #  or python setup.py install

You are done with dep installation, continue to step 3.

Step 3: Congirue gunicorn to work with flask

Install gunicorn with:

pip install gunicorn

Create a wsgi module like this one:

from myproject import application

if __name__ == "__main__":

Start gunicorn with:

gunicorn --bind wsgi

Test with your browser at your ip address and port 8000 or localhost If everything if working, you can configure gunicorn to start at boot with step 4.

Step 4: Configure gunicorn at boot

We are going to use systemd to start the app at boot. Add a new file at /etc/systemd/system/ with .serice extension and with this content: If you every need to debug systemd, remeber to use journalctl command (example sudo journalctl -u flask_app.service)

Description=gunicorn daemon

ExecStart=/home/application_user/.virtualenvs/flask_app/bin/gunicorn --pid /home/application_user/app.pid --workers=8  \
          --bind unix:/home/application_user/app.socket applicationname.wsgi
ExecReload=/bin/kill -s HUP $MAINPID
ExecStop=/bin/kill -s TERM $MAINPID


Remeber to modify the settings according to your setup. We used 8 workers since we had a 8 core cpu.

Add the .socket file at /etc/systemd/system/gunicorn.socket with:

Description=gunicorn socket



And finnaly add the file /etc/tmpfiles.d/gunicorn.conf with:

d /run/gunicorn 0755 someuser somegroup -

Enable the service with:

systemctl enable gunicorn.socket

Finnaly start the service with:

systemctl start gunicorn.socket

Step 5: Configure nginx with gunicorn

Add a new file to /etc/nginx/sites-available with this content:

server {
    listen 80;
    server_name server_domain_or_IP;

    location / {
        include proxy_params;
        proxy_pass unix:/home/application_user/app.socket;

Enable the site with:

sudo ln -s /etc/nginx/sites-available/flask_app /etc/nginx/sites-enables/flask_app
sudo service nginx restart

Step 6: Load balance with multiple hosts usign nginx

We will use 3 computers with the backend running using gunicorn. Each will use 8 workers. This time it will bind to port 8000.

The ExecStart we used was the following:

ExecStart=/home/application_user/.virtualenvs/flask_app/bin/gunicorn --pid /home/application_user/app.pid --workers=8\
          --bind applicationname.wsgi

Then we created an upstream on nginx using this settings:

http {
    upstream app_cluster {

    server {
        listen 80;

        location / {
            proxy_pass http://app_cluster;