Python/Flask: Difference between revisions

From Omnia
Jump to navigation Jump to search
 
Line 114: Line 114:


Another WSGI option using mod_wsgi and WSGIScriptAlias
Another WSGI option using mod_wsgi and WSGIScriptAlias
Install:
sudo apt install apache2 libapache2-mod-wsgi-py3


TIP: You can also use the touch command on your .wsgi file to gracefully restart the application processes without restarting the entire Apache server when you make code changes.  
TIP: You can also use the touch command on your .wsgi file to gracefully restart the application processes without restarting the entire Apache server when you make code changes.  

Latest revision as of 22:42, 13 December 2025

Flask

Installation

## Linux / macOS
mkdir myproject
cd myproject
# python3 -m venv .flask
python3 -m venv .venv
. .venv/bin/activate
## Windows
mkdir myproject
cd myproject
py -3 -m venv .venv
.venv\Scripts\activate
## Next Common Step
# pip install Flask
pip3 install Flask
# End
deactivate

References:

Quick Start

Flask Hello World

helloworld.py

from flask import Flask

app = Flask(__name__)

@app.route("/")
def hello_world():
    return "<p>Hello, World!</p>\n"


Run the server:

flask --app helloworld run

NOTE: As a shortcut, if the file is named app.py or wsgi.py, you don’t have to use --app. See Command Line Interface for more details.

  • Meaning, just simply rename helloworld.py to app.py (or wsgi.py) and you can simply run run:
flask run

WARNING: This is a development server. Do not use it in a production deployment. Use a production WSGI server instead.

Note:

* Running on http://127.0.0.1:5000

Test the server:

curl http://127.0.0.1:5000
   <p>Hello, World!</p>

References:

Hello World Headers

$ curl -i http://127.0.0.1:5000
HTTP/1.1 200 OK
Server: Werkzeug/3.1.4 Python/3.12.3
Date: Sat, 13 Dec 2025 22:05:42 GMT
Content-Type: text/html; charset=utf-8
Content-Length: 20
Connection: close

<p>Hello, World!</p>

WSGI

Apache mod_wsgi-express

$ cd hello-app
$ python -m venv .venv
$ . .venv/bin/activate
$ pip install .  # install your application
$ pip install mod_wsgi

wsgi.py : (or yourapp.wsgi)

## IIMPORT PATTERN
from hello import app
application = app

## OR

## FACTORY PATTERN
from hello import create_app
application = create_app()

Configure mod_wsgi-express and specify the number of worker processes:

mod_wsgi-express start-server wsgi.py --processes 4

Example running mod_wsgi-express as root, to bind to port 80/443, but then drop permissions and binding app as different user:

sudo /home/hello/.venv/bin/mod_wsgi-express start-server /home/hello/wsgi.py \
   --user hello --group hello --port 80 --processes 4

Reference: https://flask.palletsprojects.com/en/stable/deploying/mod_wsgi/

Apache mod_wsgi and WSGIScriptAlias

Another WSGI option using mod_wsgi and WSGIScriptAlias

Install:

sudo apt install apache2 libapache2-mod-wsgi-py3

TIP: You can also use the touch command on your .wsgi file to gracefully restart the application processes without restarting the entire Apache server when you make code changes.


/path/to/your/yourapp.wsgi : ( the "bridge" between apache and Flask )

import sys
import os

# Add your project directory to Python's path
project_home = os.path.dirname(os.path.abspath(__file__))
if project_home not in sys.path:
    sys.path.insert(0, project_home)

# Import the 'app' object from your Flask application file (e.g., app.py)
from app import app as application


Virtual Host :

<VirtualHost *:80>
    ServerName yourdomain.com

    # Points to your WSGI script
    WSGIScriptAlias / /path/to/your/yourapp.wsgi

    # Configure daemon processes
    WSGIDaemonProcess yourapp_daemon user=www-data group=www-data threads=5
    WSGIProcessGroup yourapp_daemon

    # Grant access to the application directory
    <Directory /path/to/your/project/folder>
        WSGIProcessGroup yourapp_daemon
        WSGIApplicationGroup %{GLOBAL}
        Order deny,allow
        Allow from all
        Require all granted
    </Directory>

    ErrorLog /var/log/apache2/yourdomain.com_error.log
    CustomLog /var/log/apache2/yourdomain.com_access.log combined
</VirtualHost>


Enable the virtual host:

# On Ubuntu/Debian
sudo a2ensite yourdomain.com.conf
sudo systemctl restart apache2

# On Fedora/RHEL
sudo systemctl restart httpd


Prerequisites

  • Python Virtual Environment: Your Flask application should be installed in a dedicated Python virtual environment for dependency isolation.
  • Apache Web Server: Apache must be installed and running.
  • mod_wsgi: The mod_wsgi package must be installed and enabled for the correct Python version (e.g., libapache2-mod-wsgi-py3 on Ubuntu systems).
  • No app.run(): Ensure that any app.run() calls are removed or placed inside an if __name__ == '__main__': block in your Flask app's main file, as Apache will manage the server lifecycle.

Reverse Proxy

Tell Flask it is being reverse Proxied:

from werkzeug.middleware.proxy_fix import ProxyFix

app.wsgi_app = ProxyFix(
    app.wsgi_app, x_for=1, x_proto=1, x_host=1, x_prefix=1
)

reference: https://flask.palletsprojects.com/en/stable/deploying/proxy_fix/

Apapache Configuration:

LoadModule proxy_module modules/mod_proxy.so
LoadModule proxy_http_module modules/mod_proxy_http.so
ProxyPass / http://127.0.0.1:8000/
RequestHeader set X-Forwarded-Proto http
RequestHeader set X-Forwarded-Prefix /

reference: https://flask.palletsprojects.com/en/stable/deploying/apache-httpd/

Systemd Flask Service

/etc/systemd/system/myproject.service

[Unit]
Description=Gunicorn instance to serve myproject
After=network.target

[Service]
User=youruser
WorkingDirectory=/path/to/your/project
Environment="FLASK_ENV=production"
ExecStart=/path/to/your/project/venv/bin/gunicorn -w 4 'app:app' -b 0.0.0.0:8000
Restart=always

[Install]
WantedBy=multi-user.target
sudo systemctl daemon-reload
sudo systemctl start myproject
sudo systemctl enable myproject

Check logs with:

sudo systemctl status myproject
journalctl -u myproject

keywords