Configure Apache HTTP Server as a Reverse Proxy
Learn how to configure Apache on Debian or Ubuntu as a reverse proxy for a local hostname, including modules, VirtualHost settings, access control, testing, and troubleshooting.
A reverse proxy lets Apache accept requests from clients and retrieve content from another web server, called the backend or origin server. Clients connect to Apache by using the proxy hostname; they do not need direct knowledge of the backend address.
This guide configures Apache on Debian or Ubuntu to receive requests for msn.local and forward them to an HTTP backend. Use an upstream service that you own or are explicitly authorized to proxy in a real deployment.
How a Reverse Proxy Works
The client sends an HTTP request to Apache. Apache selects a matching VirtualHost, contacts the backend, receives its response, and returns that response to the client under the proxy hostname.
A VirtualHost is an Apache configuration container for a particular address, port, or hostname. ServerName identifies the hostname associated with that virtual host.
- Client requests
http://msn.local/. - DNS or a local hosts-file entry resolves
msn.localto the Apache server. - Apache matches the request to the virtual host with
ServerName msn.local. - Apache requests the corresponding resource from the backend.
- Apache returns the backend response to the client as if it came from
msn.local.
The client must be able to resolve and reach the Apache hostname. For a lab, add a suitable entry to the client's hosts file, or create an internal DNS record. The Apache host must separately be able to resolve and reach the backend.
Reverse Proxy Compared with Forward Proxy
| Characteristic | Reverse Proxy | Forward Proxy |
|---|---|---|
| Who configures the proxy | The service owner or administrator | Clients or their network administrator |
| Who uses the proxy | Clients accessing a published service | Clients reaching remote destinations |
| Arbitrary destinations | Normally no; routes are explicitly configured | Often yes, if permitted |
| Typical use case | Network boundaries, hostname routing, access consolidation, and traffic distribution | Centralized client internet access, filtering, or privacy controls |
ProxyRequests | Off | On, only when deliberately configured and secured |
A reverse proxy hides backend addresses, can publish several services behind one entry point, route hostnames or paths, and distribute traffic across multiple backends. A forward proxy acts on behalf of clients that choose where to connect.
Required Apache Modules
mod_proxy is Apache's core proxy framework. Because this example uses an HTTP backend, it also requires mod_proxy_http. mod_proxy_connect is used for CONNECT tunneling and is not normally needed for a basic HTTP reverse proxy.
| Item | Purpose | Required for Basic HTTP Reverse Proxy | Notes |
|---|---|---|---|
mod_proxy | Provides Apache's proxy framework | Yes | Required by proxy directives |
mod_proxy_http | Proxies HTTP requests to HTTP backends | Yes | Enable for an http:// upstream |
mod_proxy_connect | Provides CONNECT tunneling | No | Enable only for a specific tunneling requirement |
ProxyPass | Maps an incoming path to an upstream URL | Yes | Defines the reverse-proxy route |
ProxyPassReverse | Rewrites suitable backend redirect headers | Strongly recommended | Helps clients remain on the proxy hostname |
ProxyRequests | Controls forward-proxy request handling | Must be Off | Never enable it just to configure reverse proxying |
ProxyVia | Controls Via headers | Optional | On can make proxy hops visible in headers |
sudo a2enmod proxy
sudo a2enmod proxy_http
sudo systemctl reload apache2
Apache modules are commonly represented by links in /etc/apache2/mods-enabled/, managed from the available module definitions. Module availability and service names can vary on distributions other than Debian and Ubuntu. Reload or restart Apache after changing enabled modules.
Forward-Proxy Settings That Must Stay Disabled
Set ProxyRequests Off for an ordinary reverse proxy. If it is set to On and access is broadly allowed, Apache may become an open forward proxy. That can let unrelated users use the server to reach arbitrary destinations and can cause abuse or data exposure.
<Proxy> authorization blocks control access to proxy functionality, especially forward-proxy requests. They are not a replacement for access rules on a reverse-proxy route. Use a <Location> block or virtual-host authorization rule to restrict clients accessing the published reverse-proxy URL.
ProxyVia On adds or manages a Via header that identifies proxy participation. This can be useful for transparent proxy-chain information, but it is optional for this setup.
ProxyRequests Off
ProxyVia On
Create the Reverse-Proxy Virtual Host
Create a dedicated site file at /etc/apache2/sites-available/reverse_proxy.conf:
<VirtualHost *:80>
ServerName msn.local
ProxyRequests Off
ProxyPass / http://www.msn.com/
ProxyPassReverse / http://www.msn.com/
<Location />
Require ip 192.168.0.0/16
</Location>
</VirtualHost>
The example uses the private network 192.168.0.0/16. The access rule is optional; change or remove it to match the intended client network. Restricting an internal service is preferable to exposing it publicly by accident.
Understanding the Directives
VirtualHost *:80makes the site listen for HTTP requests on port 80.ServerName msn.localtells Apache which hostname selects this virtual host.ProxyPass / http://www.msn.com/maps every request under the incoming root path to the backend root path.ProxyPassReverse / http://www.msn.com/adjusts supported redirect response headers so redirects can point back through the proxy hostname.Require ip 192.168.0.0/16permits only clients from the specified private network.
Keep source and target slash usage consistent. With ProxyPass /app/ http://backend.example/app/, a request such as /app/file maps predictably to /app/file on the backend. Inconsistent trailing slashes can produce unexpected path joining or redirects.
Root-Path Application Example
For an application listening on an internal host and port, a root-path mapping can look like this:
<VirtualHost *:80>
ServerName app.internal.example
ProxyRequests Off
ProxyPass / http://10.0.0.20:8080/
ProxyPassReverse / http://10.0.0.20:8080/
</VirtualHost>
The backend application should know its public URL when it generates absolute links, cookies, redirects, or security headers. Apache cannot automatically correct every application-generated reference.
Enable and Apply the Site
On Debian-family systems, enable the site, validate the complete Apache configuration, and then reload the service:
sudo a2ensite reverse_proxy.conf
sudo apache2ctl configtest
sudo systemctl reload apache2
Proceed only when the syntax check reports Syntax OK. A restart can be used when a full process restart is required:
sudo systemctl restart apache2
Confirm that the site is loaded and that Apache selected the expected virtual host:
sudo apachectl -S
The enabled site normally appears through the Debian-family site-management layout under /etc/apache2/sites-enabled/. The available configuration remains under /etc/apache2/sites-available/.
Verify the Configuration
Check Name Resolution and Connectivity
From an internal client, verify that the proxy hostname resolves to the Apache server, not directly to the backend. Then check that port 80 is reachable:
getent hosts msn.local
curl -I http://msn.local/
If the name is for a test environment, the client hosts file must contain an entry equivalent to APACHE_IP msn.local. Replace APACHE_IP with the Apache server's address.
Request the Proxy
Use verbose output to inspect the request, response status, redirects, and connection behavior:
curl -v http://msn.local/
A successful test shows that the client reached Apache, Apache connected to the backend, and the expected backend content or response was returned. A response status alone is not always sufficient: inspect redirects and application content as well.
Use Logs to Locate Failures
Apache's access log records requests received from clients. The error log records configuration problems, connection failures, timeouts, and other proxy errors. On many Debian and Ubuntu installations, these logs are under /var/log/apache2/.
sudo tail -f /var/log/apache2/access.log
sudo tail -f /var/log/apache2/error.log
- No access-log entry usually points to client DNS, client routing, a firewall, or a request reaching a different server.
- An access entry with proxy errors in the error log usually points to Apache-to-backend connectivity, an incorrect upstream URL, or backend behavior.
- A successful Apache request with unexpected application content may indicate backend hostname, redirect, cookie, or application configuration problems.
Troubleshooting
Unknown ProxyPass Directive or Apache Will Not Start
Usually mod_proxy is not enabled, or HTTP proxy support is missing. Enable both required modules and validate before reloading:
sudo a2enmod proxy
sudo a2enmod proxy_http
sudo apache2ctl configtest
502 Bad Gateway or 503 Service Unavailable
Apache may not be able to connect to the backend. Test the backend URL directly from the Apache server:
curl -v http://BACKEND_HOST:BACKEND_PORT/
Check the upstream hostname, port, scheme, routing, firewall policy, DNS, backend service status, and Apache error log. A backend that listens only on a different interface can also be unreachable from Apache.
The Proxy Hostname Does Not Open
- Check DNS or the client hosts-file mapping.
- Confirm that the site is enabled and Apache was reloaded.
- Confirm that
ServerNameexactly matches the requested hostname. - Use
sudo apachectl -Sto inspect loaded virtual hosts. - Verify that client traffic to port 80 is allowed by host and network firewalls.
Redirects Expose the Backend Hostname
Ensure that ProxyPassReverse matches the ProxyPass mapping. Inspect redirect headers with:
curl -I http://msn.local/
ProxyPassReverse handles supported backend redirect headers, but an application may also generate absolute URLs in HTML, JavaScript, or API responses. Configure the application's external base URL or trusted-proxy settings when available.
Apache Acts as an Open Proxy
Set ProxyRequests Off, remove unnecessary forward-proxy configuration, and restrict the reverse-proxy virtual host or route with appropriate Require rules. Do not use ProxyRequests On for reverse proxying.
Broken Links, Scripts, Cookies, or Security Headers
A third-party site or backend that assumes its original hostname may not work reliably behind a reverse proxy. Absolute URLs, cookies, redirects, content security policies, origin checks, and application routing can all depend on the backend hostname. Prefer an application designed to operate behind a proxy and configure its public URL and trusted proxy behavior.
Operational and Security Considerations
- Limit access with
Require ipor other appropriate authorization when the service is intended only for an internal network. - Keep
ProxyRequests Offand review forward-proxy authorization so Apache cannot be used as an unintended open proxy. - Permit the Apache host to reach the backend through DNS, routing, firewall policy, and network security controls.
- Production deployments commonly use HTTPS between clients and Apache. Some environments also use HTTPS between Apache and the backend.
- When proxying to an HTTPS backend, additional TLS configuration such as
SSLProxyEnginemay be required. - Remote third-party websites are often poor proxy backends because of redirects, required host headers, content security policies, cookies, or application-specific behavior.
- For multiple backends, investigate load-balancing features such as
mod_proxy_balancerrather than duplicating ad hoc routes.
Configuration Reference
| Path or Command | Role | When Used |
|---|---|---|
/etc/apache2/mods-enabled/ | Contains enabled module configuration links | Check whether proxy modules are enabled |
/etc/apache2/sites-available/reverse_proxy.conf | Stores the dedicated virtual-host configuration | Create and edit the reverse-proxy site |
a2enmod | Enables an Apache module | Enable proxy and proxy_http |
a2ensite | Enables an Apache site | Activate the virtual-host file |
apache2ctl configtest | Checks Apache syntax | Run before reload or restart |
systemctl reload apache2 | Applies configuration without a full stop | Use after a successful syntax check |