
How to Use Apache as a Reverse Proxy with mod_proxy on Ubuntu 24
Setting up Apache as a reverse proxy using mod_proxy on Ubuntu 24 is one of those essential server admin skills that seems complicated until you actually do it. Whether you’re load balancing across multiple application servers, adding SSL termination to legacy apps, or just need to route different paths to different services, Apache’s reverse proxy functionality has you covered. This guide will walk you through the complete setup process, common configurations, troubleshooting tips, and real-world scenarios where this setup shines.
How Apache Reverse Proxy Works
A reverse proxy sits between clients and your backend servers, forwarding client requests to the appropriate upstream service and then returning the response back to the client. Unlike a forward proxy that hides client identities from servers, a reverse proxy hides server details from clients.
Apache’s mod_proxy module handles this by intercepting requests matching specific criteria and forwarding them to configured backend servers. The module supports various protocols including HTTP, HTTPS, FTP, and even WebSocket connections. It can perform load balancing, failover, and even modify requests/responses on the fly.
Here’s how the request flow works:
- Client sends request to Apache server
- Apache matches request against ProxyPass directives
- Request gets forwarded to designated backend server
- Backend processes request and returns response
- Apache forwards response back to client
Step-by-Step Setup Guide
First, make sure Apache is installed and update your system:
sudo apt update && sudo apt upgrade -y
sudo apt install apache2 -y
sudo systemctl start apache2
sudo systemctl enable apache2
Enable the necessary modules for reverse proxy functionality:
sudo a2enmod proxy
sudo a2enmod proxy_http
sudo a2enmod proxy_balancer
sudo a2enmod lbmethod_byrequests
sudo a2enmod headers
Restart Apache to load the modules:
sudo systemctl restart apache2
Now create a basic reverse proxy configuration. Create a new virtual host file:
sudo nano /etc/apache2/sites-available/reverse-proxy.conf
Add this basic configuration:
<VirtualHost *:80>
ServerName example.com
# Enable reverse proxy
ProxyPreserveHost On
ProxyRequests Off
# Forward all requests to backend server
ProxyPass / http://localhost:3000/
ProxyPassReverse / http://localhost:3000/
# Optional: Add headers for backend awareness
ProxyPassReverse / http://localhost:3000/
ProxyPassReverseHeader Location http://localhost:3000/ http://example.com/
# Logging
ErrorLog ${APACHE_LOG_DIR}/proxy_error.log
CustomLog ${APACHE_LOG_DIR}/proxy_access.log combined
</VirtualHost>
Enable the site and restart Apache:
sudo a2ensite reverse-proxy.conf
sudo systemctl restart apache2
Advanced Configuration Examples
Here’s a more sophisticated setup that demonstrates path-based routing and load balancing:
<VirtualHost *:80>
ServerName api.example.com
ProxyPreserveHost On
ProxyRequests Off
# Load balancer for API servers
ProxyPass /api/ balancer://api-cluster/
ProxyPassReverse /api/ balancer://api-cluster/
# Static content server
ProxyPass /static/ http://cdn.example.com/static/
ProxyPassReverse /static/ http://cdn.example.com/static/
# WebSocket support
ProxyPass /ws/ ws://localhost:8080/ws/
ProxyPassReverse /ws/ ws://localhost:8080/ws/
# Define the cluster
<Proxy balancer://api-cluster>
BalancerMember http://10.0.1.10:3000
BalancerMember http://10.0.1.11:3000
BalancerMember http://10.0.1.12:3000 status=+H
ProxySet lbmethod=byrequests
</Proxy>
# Balancer manager (remove in production)
<Location "/balancer-manager">
SetHandler balancer-manager
Require local
</Location>
ProxyPass /balancer-manager !
</VirtualHost>
For SSL termination, create an HTTPS virtual host:
<VirtualHost *:443>
ServerName secure.example.com
SSLEngine on
SSLCertificateFile /etc/ssl/certs/example.com.crt
SSLCertificateKeyFile /etc/ssl/private/example.com.key
ProxyPreserveHost On
ProxyRequests Off
# Forward to HTTP backend
ProxyPass / http://localhost:8000/
ProxyPassReverse / http://localhost:8000/
# Set headers for SSL awareness
RequestHeader set X-Forwarded-Proto "https"
RequestHeader set X-Forwarded-Port "443"
</VirtualHost>
Real-World Use Cases and Examples
Here are some practical scenarios where Apache reverse proxy excels:
Microservices Architecture: Route different API endpoints to separate services:
# Route user service
ProxyPass /api/users/ http://user-service:3001/
ProxyPassReverse /api/users/ http://user-service:3001/
# Route order service
ProxyPass /api/orders/ http://order-service:3002/
ProxyPassReverse /api/orders/ http://order-service:3002/
# Route payment service
ProxyPass /api/payments/ http://payment-service:3003/
ProxyPassReverse /api/payments/ http://payment-service:3003/
Legacy Application Integration: Gradually migrate from old to new systems:
# New features go to new app
ProxyPass /v2/ http://new-app:4000/
ProxyPassReverse /v2/ http://new-app:4000/
# Everything else goes to legacy system
ProxyPass / http://legacy-app:8080/
ProxyPassReverse / http://legacy-app:8080/
Development Environment: Route to different versions based on headers:
# Route beta traffic
RewriteEngine On
RewriteCond %{HTTP:X-Beta-User} ^true$
RewriteRule ^/(.*)$ http://beta-server:3000/$1 [P,L]
# Normal traffic
ProxyPass / http://production-server:3000/
ProxyPassReverse / http://production-server:3000/
Performance Comparison and Optimization
Here’s how Apache mod_proxy compares to other reverse proxy solutions:
Feature | Apache mod_proxy | Nginx | HAProxy |
---|---|---|---|
Memory Usage | Higher (50-100MB base) | Lower (10-20MB base) | Lowest (5-10MB base) |
Concurrent Connections | Good (1000+) | Excellent (10000+) | Excellent (10000+) |
Configuration Complexity | Moderate | Simple | Complex |
SSL Termination | Good | Excellent | Good |
Load Balancing Methods | Basic | Advanced | Very Advanced |
To optimize Apache’s reverse proxy performance, tune these settings in your configuration:
# Increase worker limits
ServerLimit 16
MaxRequestWorkers 400
ThreadsPerChild 25
# Optimize proxy settings
ProxyTimeout 300
ProxyReceiveBufferSize 8192
# Enable compression
LoadModule deflate_module modules/mod_deflate.so
<Location "/">
SetOutputFilter DEFLATE
SetEnvIfNoCase Request_URI \
\.(?:gif|jpe?g|png)$ no-gzip dont-vary
</Location>
Common Issues and Troubleshooting
The most frequent problems you’ll encounter and their solutions:
502 Bad Gateway Errors:
- Check if backend service is running:
curl http://localhost:3000/
- Verify firewall rules aren’t blocking connections
- Check Apache error logs:
sudo tail -f /var/log/apache2/error.log
- Ensure ProxyPassReverse matches ProxyPass directive
SSL Certificate Issues:
# Test SSL configuration
sudo apache2ctl -S
sudo ssl-cert-check -c /etc/ssl/certs/example.com.crt
Headers Not Being Forwarded:
# Debug headers being passed
RequestHeader set X-Debug-Original %{Host}i
RequestHeader set X-Debug-Forward %{X-Forwarded-For}i
Performance Issues:
- Enable KeepAlive connections:
KeepAlive On
- Increase KeepAliveTimeout if needed:
KeepAliveTimeout 15
- Monitor with:
sudo apache2ctl status
- Use ab for load testing:
ab -n 1000 -c 10 http://your-site.com/
Security Best Practices
Lock down your reverse proxy configuration with these security measures:
# Disable server signature
ServerTokens Prod
ServerSignature Off
# Prevent proxy abuse
ProxyRequests Off
<Proxy *>
Require all denied
</Proxy>
# Only allow specific backend
<Proxy http://localhost:3000/*>
Require all granted
</Proxy>
# Security headers
Header always set X-Frame-Options "SAMEORIGIN"
Header always set X-Content-Type-Options "nosniff"
Header always set Strict-Transport-Security "max-age=63072000; includeSubDomains"
# Hide sensitive headers from backend
ProxyPassReverse / http://localhost:3000/
RequestHeader unset X-Forwarded-Server
RequestHeader unset X-Forwarded-Host
Monitor your setup with these commands:
# Check active connections
ss -tulpn | grep :80
# Monitor Apache processes
ps aux | grep apache2
# Watch logs in real-time
sudo tail -f /var/log/apache2/access.log /var/log/apache2/error.log
For production environments, consider implementing rate limiting with mod_evasive and monitoring with tools like Nagios or Zabbix. The official Apache mod_proxy documentation provides comprehensive reference material for advanced configurations.
This setup gives you a solid foundation for running Apache as a reverse proxy. Start with basic configurations and gradually add complexity as your needs grow. The modular nature of Apache makes it easy to extend functionality without starting from scratch.

This article incorporates information and material from various online sources. We acknowledge and appreciate the work of all original authors, publishers, and websites. While every effort has been made to appropriately credit the source material, any unintentional oversight or omission does not constitute a copyright infringement. All trademarks, logos, and images mentioned are the property of their respective owners. If you believe that any content used in this article infringes upon your copyright, please contact us immediately for review and prompt action.
This article is intended for informational and educational purposes only and does not infringe on the rights of the copyright owners. If any copyrighted material has been used without proper credit or in violation of copyright laws, it is unintentional and we will rectify it promptly upon notification. Please note that the republishing, redistribution, or reproduction of part or all of the contents in any form is prohibited without express written permission from the author and website owner. For permissions or further inquiries, please contact us.