Deploying Python Flask with Gunicorn, nginx, and systemd

The following tutorial is an example of deploying a simple Python Flask web application. The steps should be adaptable to other Python web frameworks which implement WSGI. See this list for more Python web frameworks.

In order to run a WSGI Python application, a WSGI-compliant server must be installed. In this instance, I have chosen Gunicorn for its simplicity. There are many ways in installing Gunicorn but I recommend installing it using pip. This way you will be able to install it easily in the context of Python virtual environments.  


In your project directory, assuming your virtual environment directory is venv, install Gunicorn.

# Activate the virtual environment.
source venv/bin/activate

# In the context of the virtual environment, install Gunicorn.
pip install gunicorn

Now check to see that all the project dependencies are recognised by running your Flask application.

venv/bin/gunicorn app:app

The first app in the above command is the Python .py file which contains the line

app = Flask(__name__)

and the second app corresponds to the Flask app object. If everything went well, you should be able to see your Flask application at http://localhost:8000.

If everything worked, it is now time to create a systemd service for the Python application. This service will be managed by systemd to ensure that when the server restarts, the Python application will automatically start running again.


Create a new unit file at /etc/systemd/system/flask-app.service. I've named the file flask-app.service, you can name it whatever you want. The name of the unit file without the .service extension is now the name of your new service. In the unit file, enter something like this:

Description=Flask App Demo

ExecStart=/home/edmond/PycharmProjects/cms/venv/bin/gunicorn --chdir /home/edmond/PycharmProjects/cms/ app:app


Change the absolute directory paths in the ExecStart to suit your needs.

Save the file and start the new service.

sudo systemctl start flask-app

Check if there were any errors.

sudo systemctl status flask-app

If there were no errors and it is active and running, then you have successfully created your web application as a service with systemd. Don't forget to activate it so that it automatically starts flask-app when the system starts.

sudo systemctl enable flask-app


Now we need to use nginx as a gateway to our application. We will be using proxy_pass to proxy incoming requests on port 80 to port 8000, which is the port where our Gunicorn Python application is running at.

Create a new nginx configuration file.

sudo nano /etc/nginx/sites-available/flask-app.conf

Now populate it with the following:

server {
    listen 80;

    location / {

We are telling nginx to listen on port 80 and on /, proxy the requests to the localhost on port 8000.

To enable this configuration, we need to create a symbolic link.

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

Likely by default, the nginx default configuration is running on port 80. Disable it by removing the symbolic link.

sudo rm /etc/nginx/sites-enabled/default

Now give nginx a restart.

sudo systemctl restart flask-app

Go to http://localhost and you should see your Flask application's / page.