Installing Flask on RHEL Linux

Charles Roth, 23 August 2023       (Techblog top)

I. Introduction

Flask is a powerful web framework for Python. 

And Python in turn is a wonderful language, written by an equally wonderful (and dry-witted) man, Guido van Rossum.  (I had dinner with him several times on-board Linux Lunacy III.  Yes, I'm a name-dropper; I also taught Linus Torvalds' kids how to play rock-paper-scissors.  But I digress...)

But... Flask, IMHO like many Python tools, suffers from oft-times vague and inconsistent documentation. 

In my case, I wanted to install Flask on a RHEL-style (e.g. CentOS, AlmaLinux, etc.) production Linux server, using Apache.  It took several hours of googling and experimentation and assembling different (and sometimes contradictory) clues from different pages, in order to create a coherent set of installation instructions.

Which, gentle reader, I offer to you, below.

II. Assumptions and Terminology

  1. These instructions were developed and tested on AlmaLinux 8.5.  They should apply to CentOS or any RHEL-based Linux distribution.  Other distributions have other tools or locations (e.g. get-apt instead of yum, different installation locations for Apache httpd, etc.), but the overall pattern will be the same.
  2. Requires 'root' access.
  3. Python 3.8 was used throughout.
  4. Apache 2.4.37 with wsgi.
  5. The test Flask app lives in a newly-created Linux user, in this case 'flask', in /home/flask.
  6. Similarly, the test Flask app has its own virtual host, with the domain name
  7. The WSGI 'daemon' group(s) are flask1 (for http) and flask1s (for https).  Each distinct Flask app must have unique daemon group name(s).
  8. The WSGI interface script is called flaskapp.wsgi.
The names of the app, WSGI interface, and daemon groups can vary, they just need to be consistent across the scripts and virtual host definitions.

III. Supporting Software Installation

  1. Python 3.8.  Flask needs Python 3.8 or higher.  As root:
       yum install python38.x86_64
    This installs the python command at /usr/bin/python3.8.
  2. mod wsgi 3.8.  While Linux can handle multiple versions of Python, Apache/WSGI can only support one version of WSGI at a time.  In order to support Flask, I needed the python 3.8 version, so I removed the default WSGI module, and added the Flask-compatible version:
       yum remove  python3-mod_wsgi.x86_64
       yum install python38-mod_wsgi.x86_64

III. Set up test Flask app

  1. App dir.  Logged in as user 'flask', create test app directory:
       mkdir Test
  2. venv.  Install the virtual environment:
       cd Test
       python3.8 -m venv .venv
  3. Install Flask
       . .venv/bin/activate
       pip install Flask
  4. App.  Create the test app (in Test/
       from flask import Flask
       app = Flask(__name__)
       def hello():
           return "Hello, Flask!"
    Note the "shebang" in the first line, that specifies python 3.8.
  5. WSGI.  Create the WSGI interface, in Test/flaskapp.wsgi:
       import sys
       import logging
       sys.path.insert(0, "/home/flask/Test/")
       sys.path.insert(0, "/home/flask/Test/.venv/lib/python3.8/site-packages")
       from index import app as application
  6. Permissions.  The Flask and python scripts must be accessible by the Apache httpd user.
       chmod 711 . Test
       chmod 755 Test/*

IV. Connect to Apache

This assumes that you are already familiar with setting up virtual hosts.

  1. Virtual Host.  Create the virtual host file, in (e.g.) /etc/httpd/conf/vhosts/
    <VirtualHost *:80>
        WSGIDaemonProcess flask1
        WSGIScriptAlias   /  /home/flask/Test/flaskapp.wsgi/
        DocumentRoot         /home/flask/Test
        <Directory /home/flask/Test>
            Order allow,deny
            Allow from all
            AllowOverride All
            Require all granted
        ErrorLog  /var/log/httpd/flask-error.log
        CustomLog /var/log/httpd/flask-access.log combined
        RewriteEngine on
        RewriteCond %{SERVER_NAME}
        RewriteRule ^ https://%{SERVER_NAME}%{REQUEST_URI} [END,NE,R=permanent]
  2. https.  Configuring https can be tricky.  I find it easiest to use the Apache Certbot to both create the https virtualhost file, and automatically create the SSL certificate.

    Warning:  Apache httpd may complain about the (seemingly) duplicate WSGIDaemonProcess name.  I found it easiest to:

    1. Delete the WSGIDaemonProcess line.
    2. Run certbot to create & install the https virtualhost for
    3. Add the line back in to both virtualhost files.
    4. In the https virtualhost file, change the group name, e.g. WSGIDaemonProcess flask1s (note the 1s).
  3. Restart.  And, of course, restart http:
       service httpd restart

V. Testing

You should now be able to point a browser at, and see "Hello, Flask!".

If you run into problems, see /var/log/httpd/flask-error.log (and flask-access.log).

When it comes time to optimize for production usage, see the documentation for WSGIDaemonProcess.  It provides many options for controlling the number of available threads, and other features.


VI. Relevant links

These are links that I found in my searching; most of them have some useful clues, but as noted in the introduction, they vary wildly.

  1. Flask Quickstart
  2. RedHat: doc on Python & WSGI 3
  3. Stackoverflow: get WSGI to pick up virtual env
  4. General/vague article about virtualhosts
  5. Google: More WSGI configuration
  6. Windows Apache/Flask
  7. Plain English: Apache/Flask
  8. Hello World with Flask/Apache