Skip to content

About

Flask 3 app behind Apache httpd: mod_wsgi vhost for bare metal, httpd + gunicorn via Docker Compose. Python 3.14, uv.

Topics

Resources

Stars

0 stars

Watchers

1 watching

Forks

Repository files navigation

Flask Apache

Flask behind Apache

Apache 2.0 License Python 3.14 Flask CI

The idea: run a Flask app behind Apache httpd, the way many teams still host Python on an existing Apache box. This repo is the small, current version of that setup: a Flask 3 app factory with three JSON endpoints, an Apache 2.4 virtual host for mod_wsgi, and a Docker Compose stack that runs it end to end.

Two ways to put Flask behind Apache

  • mod_wsgi runs the app inside Apache worker processes. One moving part less at runtime, but mod_wsgi must be compiled against the same Python as your venv. With Python 3.14 that usually means building it yourself, so it is the bare-metal path here (flask_apache.conf and flask_apache.wsgi).
  • gunicorn behind mod_proxy keeps Python in its own process and lets Apache forward requests to it. Any stock httpd image works, so this is what Docker Compose uses.

Both serve the same app and the same endpoints.

Endpoints

Path Returns
/ greeting message
/health {"status": "UP"}
/info service name, version, start time, server stack

Every response is JSON and includes a UTC timestamp.

Quickstart

Local

make venv
make dev          # http://localhost:3100/health
make test

Docker (Apache httpd in front of gunicorn)

cp .env.example .env    # set SECRET_KEY
make docker             # http://localhost:3100/health
make docker-down

Bare-metal Apache with mod_wsgi (Debian or Ubuntu)

sudo mkdir -p /var/www/flask_apache && sudo chown $USER /var/www/flask_apache
git clone https://github.com/wallaceespindola/flask-apache /var/www/flask_apache
cd /var/www/flask_apache
# keep the uv-managed Python outside $HOME so www-data can read it
sudo mkdir -p /opt/uv-python && sudo chown $USER /opt/uv-python
export UV_PYTHON_INSTALL_DIR=/opt/uv-python
uv sync --no-dev

sudo apt install apache2 apache2-dev
# mod_wsgi must match the venv Python, so build it from the venv:
uv pip install mod_wsgi
.venv/bin/mod_wsgi-express module-config | sudo tee /etc/apache2/mods-available/wsgi.load
sudo a2enmod wsgi

echo "Listen 3100" | sudo tee -a /etc/apache2/ports.conf
sudo cp flask_apache.conf /etc/apache2/sites-available/
echo 'export SECRET_KEY=change-me' | sudo tee -a /etc/apache2/envvars
sudo chown -R www-data /var/www/flask_apache
sudo a2ensite flask_apache && sudo systemctl restart apache2

Edit ServerName in flask_apache.conf first. SECRET_KEY goes in /etc/apache2/envvars because the daemon process inherits Apache's environment. SetEnv does not work here: it only reaches the per-request WSGI environ, not os.environ at import time. Call .venv/bin/mod_wsgi-express directly, since uv run would reinstall the dev tools. These steps were tested on Ubuntu 24.04 with Python 3.14.

Configuration

Variable Purpose Default
SECRET_KEY Flask session signing key empty
HTTP_PORT Host port Apache publishes in Docker Compose 3100

Development

make format, make lint, make typecheck and make test run black and isort, ruff, mypy in strict mode, and pytest with an 80% coverage floor. CI runs the same checks.

Support

If you find this project helpful, please consider:

Buy Me A Coffee Star on GitHub

GitHub stars GitHub forks GitHub watchers GitHub issues GitHub last commit

Star the repo on GitHub if it helps your Flask and Apache work. It motivates me a lot!

Author

Wallace Espindola, Solution Architect

License

  • This project is released under the Apache 2.0 License.
  • See the LICENSE file for details.
  • Copyright © 2026 Wallace Espindola.

About

Flask 3 app behind Apache httpd: mod_wsgi vhost for bare metal, httpd + gunicorn via Docker Compose. Python 3.14, uv.

Topics

Resources

Stars

0 stars

Watchers

1 watching

Forks

Releases

Packages

Contributors

Languages