Install Flask with Gunicorn and Nginx on Oracle Linux 9

Python developers must embark on a Framework. A Framework is a library that makes developers’ work easy by providing them with reusable code or extensions to build reliable, scalable, and maintainable web applications. Frameworks make it easy to reuse code for common HTTP operations and to structure projects so other developers can quickly build and maintain the application. Examples of Web Frameworks include Flask, Tornado, Pyramid, and Django. Like many Python Frameworks, the Flask package is installable via the Python Package Index (PPI). Flask is a micro web framework written in Python. Flask applications are more explicit and easier to get started with compared to Django.

The Flask framework was developed by Armin Ronacher and is based on the Werkzeug WSGI toolkit and Jinja2 template (that builds HTML pages using python concepts such as loops, variables, etc). These are both pocco engines. Flask is flexible and extensible and rich in modules that make website development an easy job. Flask is preferred and has quite a number of uses. Flask can be used for Rest API App, blogging applications, Deploying Machine Learning models, Weather Applications, etc.

Gunicorn (Green Unicorn) is a Python WSGI HTTP Server for UNIX that is compatible with the majority of web frameworks. Gunicorn is simple to implement, it’s very fast while utilizing very minimal server resources. It is also a pre-fork worker model ported from Ruby’s Unicorn project. It is licensed under MIT License and has been in existence since 2010. Just like Flask, it is written in Python programming language. Gunicorn starts and binds all host IP addresses on port number 8081. Gunicorn is very stable and is used to power some of the largest Python-powered web applications e.g Instagram.

NGINX is an open-source web server that is also used as a reverse proxy, mail proxy, HTTP cache, and load balancer. It was released in 2004 and is licensed under the BSD-2-Clause. It is written in C programming language and supports a majority of Operating Systems e.g Windows, macOS, Linux, BSD variants, and UNIX.

With that brief introduction, we will jump right into the day’s business.

Install Flask with Gunicorn and Nginx on Oracle Linux 9

For a successful installation, the following requirements must be fulfilled.

Prerequisites

Ensure you have the following:

  • Sudo account
  • Python
  • Python3 venv
  • Flask
  • Nginx
  • Gunicorn

Begin the installation by updating your system package repository.

sudo dnf update -y

We are now ready to begin.

Step 1: Install EPEL repository on Oracle Linux 9

EPEL repository contains additional packages needed for our installation. These are packages not included in the Oracle Linux 9 official repository. Run the command.

 sudo dnf install epel-release -y

The command above installs the latest oracle-epel-release-el9. Run the update command to refresh the packages.

sudo dnf update -y

Step 2: Install the required dependencies

For a successful installation of Flask and Gunicorn, we must install some dependencies. This is because the dependencies required to run Flask and Gunicorn are not provided by default on the official Oracle Linux 9 repository.

The dependencies can be installed with the command below.

sudo dnf install python3-pip python3-devel gcc -y

The required dependencies are now fully installed.

Install Nginx webserver:

 sudo dnf install nginx -y

Confirm the NGINX version installed:

$ nginx -version
nginx version: nginx/1.20.1

Step 3: Create a Python Virtual Environment

Virtual environments are independent groups of Python libraries. The advantage of working with a Virtual Environment is that individual projects that depend on different libraries can be installed on the same machine with each distinct project having its own dependencies.

In our case, the Virtual Environment will isolate our Flask Application from other python files installed in our system.

Start by installing the virtualenv package using pip:

$ sudo pip3 install virtualenv
Collecting virtualenv
  Downloading virtualenv-20.29.1-py3-none-any.whl (4.3 MB)
     |████████████████████████████████| 4.3 MB 883 kB/s            
Collecting filelock<4,>=3.12.2
  Downloading filelock-3.17.0-py3-none-any.whl (16 kB)
Collecting platformdirs<5,>=3.9.1
  Downloading platformdirs-4.3.6-py3-none-any.whl (18 kB)
Collecting distlib<1,>=0.3.7
  Downloading distlib-0.3.9-py2.py3-none-any.whl (468 kB)
     |████████████████████████████████| 468 kB 31.1 MB/s            
Installing collected packages: platformdirs, filelock, distlib, virtualenv
  WARNING: The script virtualenv is installed in '/usr/local/bin' which is not on PATH.
  Consider adding this directory to PATH or, if you prefer to suppress this warning, use --no-warn-script-location.
Successfully installed distlib-0.3.9 filelock-3.17.0 platformdirs-4.3.6 virtualenv-20.29.1
WARNING: Running pip as the 'root' user can result in broken permissions and conflicting behaviour with the system package manager. It is recommended to use a virtual environment instead: https://pip.pypa.io/warnings/venv

If the command above fails, with [SSL: CERTIFICATE_VERIFY_FAILED], work around it by running this command:

sudo update-crypto-policies --set LEGACY
sudo reboot

Next thing is to create the Directory to hold our Flask Project as shown below.

sudo mkdir /sample_project && cd /sample_project
sudo chmod 777 /sample_project

Now Create a virtual environment to store the Flask project’s Python requirements:

[cloudspinx@oracle-linux sample_project]$ virtualenv projectenv
created virtual environment CPython3.9.21.final.0-64 in 920ms
  creator CPython3Posix(dest=/sample_project/projectenv, clear=False, no_vcs_ignore=False, global=False)
  seeder FromAppData(download=False, pip=bundle, setuptools=bundle, wheel=bundle, via=copy, app_data_dir=/home/cloudspinx/.local/share/virtualenv)
    added seed packages: pip==24.3.1, setuptools==75.8.0, wheel==0.45.1
  activators BashActivator,CShellActivator,FishActivator,NushellActivator,PowerShellActivator,PythonActivator

The command above installs Python and pip in the projectenv folder.

Activate your Virtual Environment.

source projectenv/bin/activate

Step 4: Set Up a Flask Application

With an active Virtual Environment, we can now install Flask and Gunicorn. This is where we deploy the pip python package manager. Run the command below within the activated environment.

pip3 install gunicorn flask

The output of the command.

Collecting gunicorn
  Downloading gunicorn-23.0.0-py3-none-any.whl.metadata (4.4 kB)
Collecting flask
  Downloading flask-3.1.0-py3-none-any.whl.metadata (2.7 kB)
Collecting packaging (from gunicorn)
  Downloading packaging-24.2-py3-none-any.whl.metadata (3.2 kB)
Collecting Werkzeug>=3.1 (from flask)
  Downloading werkzeug-3.1.3-py3-none-any.whl.metadata (3.7 kB)
Collecting Jinja2>=3.1.2 (from flask)
  Downloading jinja2-3.1.5-py3-none-any.whl.metadata (2.6 kB)
Collecting itsdangerous>=2.2 (from flask)
  Downloading itsdangerous-2.2.0-py3-none-any.whl.metadata (1.9 kB)
Collecting click>=8.1.3 (from flask)
  Downloading click-8.1.8-py3-none-any.whl.metadata (2.3 kB)
Collecting blinker>=1.9 (from flask)
  Downloading blinker-1.9.0-py3-none-any.whl.metadata (1.6 kB)
Collecting importlib-metadata>=3.6 (from flask)
  Downloading importlib_metadata-8.6.1-py3-none-any.whl.metadata (4.7 kB)
Collecting zipp>=3.20 (from importlib-metadata>=3.6->flask)
  Downloading zipp-3.21.0-py3-none-any.whl.metadata (3.7 kB)
Collecting MarkupSafe>=2.0 (from Jinja2>=3.1.2->flask)
  Downloading MarkupSafe-3.0.2-cp39-cp39-manylinux_2_17_x86_64.manylinux2014_x86_64.whl.metadata (4.0 kB)
Downloading gunicorn-23.0.0-py3-none-any.whl (85 kB)
Downloading flask-3.1.0-py3-none-any.whl (102 kB)
Downloading blinker-1.9.0-py3-none-any.whl (8.5 kB)
Downloading click-8.1.8-py3-none-any.whl (98 kB)
Downloading importlib_metadata-8.6.1-py3-none-any.whl (26 kB)
Downloading itsdangerous-2.2.0-py3-none-any.whl (16 kB)
Downloading jinja2-3.1.5-py3-none-any.whl (134 kB)
Downloading werkzeug-3.1.3-py3-none-any.whl (224 kB)
Downloading packaging-24.2-py3-none-any.whl (65 kB)
Downloading MarkupSafe-3.0.2-cp39-cp39-manylinux_2_17_x86_64.manylinux2014_x86_64.whl (20 kB)
Downloading zipp-3.21.0-py3-none-any.whl (9.6 kB)
Installing collected packages: zipp, packaging, MarkupSafe, itsdangerous, click, blinker, Werkzeug, Jinja2, importlib-metadata, gunicorn, flask
Successfully installed Jinja2-3.1.5 MarkupSafe-3.0.2 Werkzeug-3.1.3 blinker-1.9.0 click-8.1.8 flask-3.1.0 gunicorn-23.0.0 importlib-metadata-8.6.1 itsdangerous-2.2.0 packaging-24.2 zipp-3.21.0

If a new release of pip is available, upgrade it by running the command:

pip install --upgrade pip

With Gunicorn and Flask now installed within your environment, I will now create a simple hello world application using Flask Framework.

vim /sample_project/helloworld.py

Write a simple HelloWorld program as shown below.

from flask import Flask
app = Flask(__name__)

@app.route('/')
def hello_world():
    return "<h1 style='color:red'>Hello, World!</h1>"

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

In the above code, I have called my application app. We are simply importing Flask and instantiating the Flask object. The app can run on any host on the network. Save and exit from the text editor.

The default port for the Flask application is 5000. We need to allow this port through the firewall as shown below.

sudo firewall-cmd --add-port=5000/tcp --permanent
sudo firewall-cmd --reload

Test your application with the code below.

$ python helloworld.py 
 * Serving Flask app 'helloworld'
 * Debug mode: off
WARNING: This is a development server. Do not use it in a production deployment. Use a production WSGI server instead.
 * Running on all addresses (0.0.0.0)
 * Running on http://127.0.0.1:5000
 * Running on http://192.168.201.19:5000
Press CTRL+C to quit

Head to your web browser on your Oracle Linux 9 server and issue the address http://<server_ip_address>:5000 to see if your application is running.

Step 5: Create the WSGI Entry Point

In this step, I will create a file to act as the entry point to my application. This file defines how Gunicorn interacts with your application. Create a WSGI Entry Point as shown below.

vim /sample_project/wsgi.py

Now import the Flask instance from your application and run it. Enter the code below.

from helloworld import app

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

Save your file and exit from the editor.

The default port for the WSGI server is 8000. We need to allow this port through the firewall.

sudo firewall-cmd --add-port=8000/tcp --permanent
sudo firewall-cmd --reload

Let’s now test our Gunicorns ability to serve the project by simply passing it the name of our entry point and specifying the interface and the port number to bind.

$ gunicorn --bind 0.0.0.0:8000 wsgi:app
(projectenv) [cloudspinx@oracle-linux sample_project]$ gunicorn --bind 0.0.0.0:8000 wsgi:app
[2025-01-22 15:30:31 +0300] [73064] [INFO] Starting gunicorn 23.0.0
[2025-01-22 15:30:31 +0300] [73064] [INFO] Listening at: http://0.0.0.0:8000 (73064)
[2025-01-22 15:30:31 +0300] [73064] [INFO] Using worker: sync
[2025-01-22 15:30:31 +0300] [73065] [INFO] Booting worker with pid: 73065

Head to your browser and issue the address http://<server_ip_address>:8000 or http://0.0.0.0:8000 to test if Gunicorn can serve your application.

Our Gunicorn can successfully serve our application. Press CTRL+C to exit from the Gunicron server.

We can now deactivate from our Virtual Environment by the command.

deactivate 

Step 6:Create a Systemd Unit File

We will now create a Systemd Unit File to make Gunicorn and Flask Application start automatically via the init process. Using a text editor do the following.

sudo vim /etc/systemd/system/web-app.service

Paste the following parameters.

[Unit]
Description=The Gunicorn instance to serve Flask Project
After=network.target

[Service]
User=nginx
Group=nginx
WorkingDirectory=/sample_project
Environment="PATH=/sample_project/projectenv/bin"
ExecStart=/sample_project/projectenv/bin/gunicorn --workers 3 --bind unix:myproject.sock -m 007 wsgi:app

[Install]
WantedBy=multi-user.target

Ensure you replace sample_project with the correct Working Directory and set the appropriate PATH to your Working Directory. Then save your file and exit from the editor.

The next thing is to configure SELinux for the path to be accessible.

sudo chcon -R -t bin_t /sample_project/projectenv/bin/

Reload the systemd daemon:

sudo systemctl daemon-reload

Start and enable the Gunicorn service.

sudo systemctl start web-app
sudo systemctl enable web-app

Confirm the status.

Step 7: Configuring the Nginx Web server

The last step is the configuration of the Nginx web server. We need to configure the Nginx web server so that it passes web requests to the Gunicorn server socket.

Edit the Nginx configuration file with the parameters below

sudo vim /etc/nginx/conf.d/sampleapp.conf

Add the following contents.

server {
    listen 80;
    server_name server_domain_or_IP;

    location / {
        proxy_set_header Host $http_host;
        proxy_set_header X-Real-IP $remote_addr;
        proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;
        proxy_set_header X-Forwarded-Proto $scheme;
        proxy_pass http://unix:/sample_project/myproject.sock;
    }
}

Be sure to replace the server_name_domain_or_IP and the Unix socket path /sample_project/myproject.sock.Save your file and exit.

Allow Gunicorn sock to be accessed by Nginx by the command below.

sudo semanage permissive -a httpd_t 

Now allow Nginx to access the project directory. Execute the command below.

sudo chgrp -R nginx /sample_project/

Test the Nginx configuration file for syntax errors:

$ sudo nginx -t
nginx: the configuration file /etc/nginx/nginx.conf syntax is ok
nginx: configuration file /etc/nginx/nginx.conf test is successful

Our Nginx configuration is successful.

Let’s now start and enable the Nginx service.

sudo systemctl start nginx
sudo systemctl enable nginx

Confirm the status.

The Nginx web server is running properly.

Now allow HTTP through the firewall.

sudo firewall-cmd --add-port=80/tcp --permanent
sudo firewall-cmd --reload

We will now test if Nginx can serve my application. On your browser enter the address <http://your_server_hostname_or_IP_Address>. If your configuration is successful, you should see Hello World displayed on your browser.

Final Thoughts

In the guide, we have taken you through a step-by-step approach to installing Flask with Gunicorn and Nginx on Oracle Linux 9. We examined how to install Flask and how to set up a Flask Application. We also covered how to create a Python Virtual Environment using the pip command and then we looked at how to create the WSGI Entry Point for the flask application. Last but not least, we looked at how to install and configure Nginx to serve your application. That is it, we hope the guide will be of great insight to you.

From Techviewleo, we wish you a Merry Christmas. If you love what we do, please buy us a Christmas Coffee. We look forward to more insightful guides in the coming year. Thank you.

Read more guides here:

Your IT Journey Starts Here!

Ready to level up your IT skills? Our new eLearning platform is coming soon to help you master the latest technologies.

Be the first to know when we launch! Join our waitlist now.

Join our Linux and open source community. Subscribe to our newsletter for tips, tricks, and collaboration opportunities!

Recent Post

Leave a Comment

Your email address will not be published. Required fields are marked *

Related Post

Greetings and salutations. In our guide today we will analyze Apache Solr, a standalone, open-source enterprise search and analytics server […]

Apache Spark is an open-source simple, fast, scalable, and integrated multilingual integrated analytics engine. It is used for large-scale data processing, data engineering, data […]

SparkyLinux is an open-source, lightweight, fast, and customizable GNU/Linux distribution based on Debian GNU/Linux operating distribution. It is a desktop-oriented […]

Let's Connect

Unleash the full potential of your business with CloudSpinx. Our expert solutions specialists are standing by to answer your questions and tailor a plan that perfectly aligns with your unique needs.
You will get a response from our solutions specialist within 12 hours
We understand emergencies can be stressful. For immediate assistance, chat with us now

Contact CloudSpinx today!

Download CloudSpinx Profile

Discover the full spectrum of our expertise and services by downloading our detailed Company Profile. Simply enter your first name, last name, and email address.