mod_wsgi: hosting WSGI applications inside Apache httpd
Source code for Apache/mod_wsgi.
At a glance
- What is it?
- mod_wsgi is the C module for Apache HTTP Server that hosts Python applications implementing WSGI, and it now ships as three separate PyPI packages covering a system Apache build, a standalone private Apache build and an out-of-process telemetry pipeline. The code is old, the release line is 6.x, and the maintainer asks contributors to open an issue before large changes.
- Who is it for?
- Adopt mod_wsgi if you run Apache and want Python applications served by the same process model, and if the deployment hardening guidance and the WSGI error code reference are worth having in one place. Do not adopt it for a greenfield deployment if your platform ships a modern application server, since a fifteen year old C module is a different kind of dependency.
- Can I use it commercially?
- Yes. Apache-2.0 is a permissive licence: you can use, modify and sell software built on it, as long as you keep its copyright and licence notices.
- Is it still maintained?
- Yes. The repository last received commits 4 days ago.
- What is it written in?
- Mainly C, according to GitHub's language statistics.
Answers come from the project's GitHub data, last synced on October 23, 2026, and from our analysis. They are not legal advice.
Editorial analysis
A C module that is older than most of its users
mod_wsgi is an Apache HTTP Server module for hosting Python web applications that implement the WSGI specification, PEP 3333. The primary language in the repository is C, and the licence is the Apache License, Version 2.0.
The project states that it has been used in production deployments for over 15 years and continues to be actively maintained. That combination is unusual and worth taking at face value rather than as marketing, because a project that has been in production for that long has a large installed base and the maintenance burden that comes with it.
The platform requirements are explicit: Python 3.10 or later and Apache 2.4. The 6.x release line is the current focus of development, and the documentation covers the full version support policy, which is the kind of thing you want to read before pinning a version in a distribution's package repository.
The default branch is develop, not master or main, which is the usual signal that the trunk carries work in progress and that releases are cut from it.
The reason a project like this still exists is worth stating, because the alternative answers have all been offered. Putting Python behind a web server in the same process model means one thing to deploy, one thing to authenticate against, one thing to configure TLS for and one set of logs, and for organisations that have standardised on Apache, replacing that with a separate application server is a larger change than it looks on paper.
Three packages, three deployment shapes
This source repository publishes three distinct packages to the Python Package Index, and the split is the most useful thing in the README for anyone deciding how to install it.
The first is mod_wsgi, which builds the mod_wsgi Apache module against an existing Apache and Python installation on your host. It also installs the mod_wsgi-express command-line wrapper, which runs Apache with a generated configuration tuned for hosting a single WSGI application. That wrapper is the pragmatic path for people who want one application served and do not want to hand-write a virtual host.
The second is mod_wsgi-standalone, which additionally installs a private build of Apache into your Python environment, for use on UNIX-like systems where no system Apache is available. It is the same source code and version as mod_wsgi, with an added dependency on the separate mod_wsgi-httpd package, which supplies that Apache.
The third is mod_wsgi-telemetry, which is a different thing entirely and is worth reading about if you run a fleet of these instances. It is the out-of-process telemetry ingester and live UI that consume datagrams emitted when the WSGITelemetryService directive is enabled. The telemetry package provides the out-of-process ingester, a browser-based live UI and a top-style curses monitor.
Why telemetry is distributed separately is the interesting design point. It is separated so that installations using the operating-system mod_wsgi package, or any other manually-configured Apache, can adopt the telemetry pipeline without switching to the PyPI mod_wsgi or mod_wsgi-express packages. A monitoring tool that forces you to change how you install the thing it monitors is a monitoring tool nobody installs.
The build finds apxs, or works around not having it
Building from source requires a complete Apache installation including its development headers, apache2-dev or httpd-devel depending on the distribution, and the Python development headers. The installation page in the documentation has the full prerequisites.
The setup.py is where the interesting engineering sits, because the Apache module compilation normally goes through the apxs command, and apxs is a script that has to match the Apache you are building against. The code works out the Apache specific compilation flags using the standard apxs command, and the comment explains the exception: when the project is installing its own build of Apache, Python code does the equivalent of apxs, because apxs will not work due to paths not matching where it was installed.
The discovery logic is a chain. The APXS environment variable is checked first. If it is unset, the build looks for mod_wsgi-apxs next to the running interpreter, which is how the standalone package finds its own bundled Apache. Only if that fails does it fall back to the usual apxs2 or apxs names, searching /usr/sbin and the current directory. There are separate flags for the Windows and macOS cases, and a WITHOUT_APXS path for when no usable apxs exists at all.
The two development commands are short:
uv pip install -e . --no-cachefor an editable development build into a virtual environment, and:
./scripts/run-tests.shto run the test suite. The repository layout backs this up, with src/server holding the Apache module sources in C, src/express and the rest of src holding the Python side package with mod_wsgi-express and the diagnostics WSGI applications, telemetry/ for the separate package, tests/ for the test suite and sample WSGI applications, scripts/ for the helper scripts including the test runner, and docs/ for the Sphinx sources published to modwsgi.org.
Where bugs go, and what the maintainer expects first
Bug reports and feature requests go on the GitHub issue tracker, but the README asks you to do something before that. Work through the troubleshooting guide in the documentation first, because a substantial share of reports against mod_wsgi turn out to be configuration, application or third-party package issues rather than mod_wsgi bugs.
That is a maintainer writing down the triage reality of a fifteen year old project. A module that sits between Apache and Python sees symptoms that originate in either layer, and the first question is always which one. The troubleshooting guide, the WSGI#### error code reference and the deployment and hardening guides are all on the documentation site, and the WSGI error code reference in particular is the thing to have open when you are reading a log line.
Security issues have a separate path. For suspected security issues, do not open a public issue, and instead submit a private security advisory via GitHub. The security issues page in the documentation holds the full disclosure process and the list of past CVEs.
The private advisory route is not a formality. A WSGI module runs as the Apache user and processes request bodies, so a parsing or input-handling bug in it is a server-side issue, and a public issue with a proof of concept is exactly the wrong place to put one.
The documentation sources live under docs in the repository and are built with Sphinx, and the site covers installation on the various supported platforms, the complete reference for WSGI configuration directives, the error code reference, deployment and hardening guides and troubleshooting. That is a real reference manual, and its existence is part of the reason to pick this module over assembling the same pieces yourself.
Contributing to code that sits on two C APIs
The contribution guidance is short and has one important instruction in it.
Pull requests are welcome, and small fixes and self-contained features can be sent straight through. For larger changes it is worth opening an issue first to discuss the approach, since mod_wsgi sits across both the Apache and CPython C APIs and the relevant context is not always obvious from the code alone.
That is the honest description of the problem. The module holds references into Apache's request and configuration structures and calls into CPython's C API, and the ownership rules between the two are not something a newcomer can infer from the source. A change that looks local in the Python-facing code can break an assumption about the Apache side, and a change to the Apache side can break a CPython reference count that nobody can see. An issue first costs a day and saves a rejected pull request.
The second half of the guidance is unusual and worth repeating, because it is not how most maintainers write. If you have hit a problem or have an idea but writing the code yourself would be more friction than help, describing it in an issue is just as useful. The maintainer is usually quicker at producing a fix or a small feature in this code base than a first-time contributor would be.
The project is also set up for tooling. There is an AGENTS.md and a CLAUDE.md at the root, a Justfile alongside the older Makefile.in, configure.ac and configure, tox.ini for the test environments, a TESTING.md, a CREDITS.rst, and a .readthedocs.yaml. The presence of both a Justfile and the autotools files suggests a transition in progress in the build tooling, and a contributor would do well to check which one the current documentation expects.
Release cadence and the current line
The release history is short and tells you where the project is.
mod_wsgi 6.1.0 was published on 2026-09-26, mod_wsgi-telemetry 1.1.0 on the same day, and mod_wsgi 6.1.1 on 2026-10-13. The last push to the repository was on 2026-10-13, the same day as the newest tag. The repository is not archived.
The pairing of the telemetry release with the 6.1.0 release is informative. The telemetry package has its own version line, 1.1.0, independent of the 6.x module line, which tells you the two are decoupled in the packaging even though they share a repository. The README says as much when it explains that telemetry is distributed separately so that existing installations can adopt the pipeline without changing how they install mod_wsgi.
The 6.1.x patches come with the kind of release notes you would expect from a mature project: the module version and the telemetry version move independently, and the telemetry feature itself is a directive-gated subsystem, WSGITelemetryService, rather than something always on. That matters for deployments, because the default configuration of a long-established module should not change behaviour for existing users, and this one does not.
Sponsorship is set up through GitHub Sponsors, and the maintainer is Graham Dumpleton, whose name is on the repository. For a project that has been maintained by one person for a long time, that fact is worth weighing: it is also a reason the contribution guidance asks for an issue before a large change, since there is a single person with the context to evaluate it.
Editorial conclusion
Adopt mod_wsgi if you run Apache and want Python applications served by the same process model, and if the deployment hardening guidance and the WSGI error code reference are worth having in one place. Do not adopt it for a greenfield deployment if your platform ships a modern application server, since a fifteen year old C module is a different kind of dependency. Before you start, read the troubleshooting guide, because the project states that a substantial share of reported bugs are configuration or application issues, choose the PyPI package that matches your setup rather than mixing the standalone build with a system Apache, and report security issues through the private advisory route rather than a public issue.
Frequently asked questions
What are the three PyPI packages published by mod_wsgi?
mod_wsgi builds the Apache module against an existing Apache and Python on your host and installs the mod_wsgi-express wrapper, mod_wsgi-standalone additionally installs a private Apache build through the mod_wsgi-httpd dependency, and mod_wsgi-telemetry provides the out-of-process telemetry ingester, live UI and curses monitor.
What does mod_wsgi require to build from source?
A complete Apache installation including its development headers, apache2-dev or httpd-devel depending on the distribution, and the Python development headers. The build finds the Apache compiler flags through apxs, or through equivalent Python code when the project is installing its own Apache build, and the editable build command is uv pip install -e . --no-cache.
How do I report a security issue in mod_wsgi?
Do not open a public issue. Submit a private security advisory through GitHub's security advisory form for the repository, and see the security issues page in the documentation for the full disclosure process and the list of past CVEs.
Why do so many mod_wsgi bug reports turn out not to be bugs?
The project states that a substantial share of reports turn out to be configuration, application or third-party package issues rather than mod_wsgi bugs, which is why the README asks reporters to work through the troubleshooting guide first, with the WSGI error code reference for reading the log messages.
What is the current mod_wsgi release line and its requirements?
The 6.x line is the current focus of development, with 6.1.0 published on 2026-09-26 and 6.1.1 on 2026-10-13, and the telemetry package on its own 1.1.0 line. mod_wsgi requires Python 3.10 or later and Apache 2.4, and the licence is the Apache License, Version 2.0.
Official sources
Add this badge to your README
If you maintain this project, the badge below links readers to this analysis and shows its maintenance status from the daily GitHub snapshot. Paste the markdown into your README; add ?metric=license or ?metric=stars to the image URL for a different field.
[](https://hysenlabs.com/projects/grahamdumpleton-mod-wsgi)Was this useful?