mod_proxy
mod_proxy lets Apache forward requests on to another server -- typically an application server like Gunicorn, Node.js, or a backend on a different machine -- and hand the response back as if Apache had generated it itself.In this page:
Forward vs. Reverse Proxy
A forward proxy sits in front of clients, fetching the internet on their behalf (like a corporate proxy). A reverse proxy sits in front of servers, receiving requests from the public internet and forwarding them to a backend the public never talks to directly. mod_proxy is almost always used the second way with Apache, covered in full in the dedicated Reverse Proxy lesson later in this course.
Enabling the Right Sub-Modules
mod_proxy itself is the base module, but you also need a protocol-specific one: mod_proxy_http for HTTP/HTTPS backends, or mod_proxy_wstunnel for WebSocket connections. On Ubuntu: sudo a2enmod proxy proxy_http (add proxy_wstunnel too if needed).
ProxyPass and ProxyPassReverse
ProxyPass "/api/" "http://127.0.0.1:8000/" forwards any request under /api/ to that backend address. ProxyPassReverse does the matching job in the other direction: it rewrites Location/Set-Cookie headers coming back from the backend so they reference the public-facing URL instead of the internal one, which matters for redirects and cookies to work correctly.
A Typical Use Case
A very common pattern: run a Python (Gunicorn/uWSGI) or Node.js app listening only on 127.0.0.1:8000, not exposed to the internet at all, and let Apache on port 80/443 be the only thing the public actually reaches -- handling TLS, static files, and logging, then proxying dynamic requests through to the app.
Example: Proxying /api/ to a local backend
ProxyPreserveHost On
ProxyPass "/api/" "http://127.0.0.1:8000/"
ProxyPassReverse "/api/" "http://127.0.0.1:8000/"
{# Flagged by hand after confirming a runner can't handle this example
(a shell command / go.mod file stored as a TopicExample, a language
feature the configured runner version doesn't support, or output
that blows a runner's sandbox limit) -- see TopicExample.norun.
Never render the run button for these, regardless of language,
since it would just fail at execute_code (or worse, hang the
Judge0 queue on a submission that can never finish cleanly). #}
- Enabling
mod_proxybut forgettingmod_proxy_http, so plain HTTP/HTTPS proxying doesn't actually work. - Using ProxyPass without a matching ProxyPassReverse, breaking redirects or cookies coming back from the backend.
- Exposing the backend app server's port directly to the internet in addition to proxying it through Apache, defeating the point of putting Apache in front of it.
Chapter Quiz — Complete all 5 topics to unlock
0/5 topics done
Complete these topics first: