Introduction
As modern web applications continue to evolve, it has become increasingly common to run application services on non-standard ports such as 3000, 5000, 8000, or 8080. Frameworks like Node.js, Django, Flask, Spring Boot, and various API services often listen on these ports instead of directly serving traffic through ports 80 (HTTP) or 443 (HTTPS).
While exposing these application ports directly to the internet may work, it is generally not considered a best practice. Doing so can create management challenges, complicate SSL/TLS implementation, and expose internal application infrastructure unnecessarily.
A better approach is to place Apache HTTP Server in front of the application and configure it as a reverse proxy. Apache receives incoming requests on standard web ports and transparently forwards them to the backend application. Users continue to access the website using the main domain name, while the backend application remains hidden behind Apache.
This setup offers several advantages:
- Keeps backend application ports hidden from public access
- Provides a consistent URL structure for users
- Simplifies SSL/TLS certificate management
- Allows multiple applications to run behind a single web server
- Improves security by isolating backend services
- Makes application migrations and upgrades easier
- Enables future load balancing and high-availability configurations
In this tutorial, we will configure Apache’s ProxyPass and ProxyPassReverse directives to forward requests from a domain to a backend application running on port 8000, while ensuring that the browser URL remains unchanged.
Understanding Reverse Proxying
Before diving into the configuration, it is important to understand how reverse proxying works.
Without Reverse Proxy
Users must connect directly to the application port:
User → http://example.com:8000
In this scenario:
- The application port is exposed publicly.
- Users must know the port number.
- SSL configuration becomes more complex.
- Backend services are directly accessible.
With Apache Reverse Proxy
Apache sits between users and the application:
User → http://example.com
|
↓
Apache
|
↓
http://localhost:8000
The user only sees:
http://example.com
while Apache forwards the request internally to:
http://localhost:8000
This process is completely transparent to the end user.
Assumptions
For this guide, we will assume:
- Apache is already installed and running.
- The backend application is listening on port 8000.
- The application can be accessed locally using:
http://localhost:8000
If your application runs on a different port or on a different server, simply replace the values used in the examples below.
Prerequisites
Before proceeding, ensure the following requirements are met:
Server Requirements
- Ubuntu, Debian, CentOS, Rocky Linux, AlmaLinux, or RHEL
- Apache HTTP Server 2.2 or Apache HTTP Server 2.4
- Root or sudo privileges
- Running backend application
Apache Proxy Modules
Apache’s reverse proxy functionality requires the following modules:
- mod_proxy
- mod_proxy_http
These modules handle the communication between Apache and the backend application.
Verify Proxy Modules
Check whether the required proxy modules are loaded:
apachectl -M | grep proxy
Example output:
proxy_module
proxy_http_module
Ubuntu / Debian
If the modules are not enabled:
a2enmod proxy
a2enmod proxy_http
systemctl restart apache2
CentOS / RHEL / Rocky Linux
Verify loaded modules:
httpd -M | grep proxy
If necessary, ensure the modules are included in your Apache installation.
Verify Backend Application
Before configuring Apache, confirm that the backend application is responding correctly.
Run:
curl http://localhost:8000
If the application is running, you should receive a valid response.
You can also verify that the application is listening on the expected port:
ss -tulpn | grep 8000
or
netstat -nltp | grep 8000
Example:
tcp LISTEN 0 128 127.0.0.1:8000
Locate the Virtual Host Configuration
Apache virtual host files are typically located in the following directories.
Ubuntu / Debian
Default virtual host:
/etc/apache2/sites-enabled/000-default.conf
Custom site configuration:
/etc/apache2/sites-available/example.com.conf
CentOS / RHEL
/etc/httpd/conf.d/example.com.conf
Open the configuration file:
vi /etc/apache2/sites-enabled/000-default.conf
Configure Apache Reverse Proxy
Inside the appropriate <VirtualHost> block, add the following directives:
<VirtualHost *:80>
ServerName example.com
ProxyPass / http://localhost:8000/
ProxyPassReverse / http://localhost:8000/
</VirtualHost>
Save the file after making the changes.
Understanding the Configuration
ProxyPass
ProxyPass / http://localhost:8000/
This directive tells Apache:
Forward every request received on the root URL (
/) to the backend application running on port 8000.
For example:
http://example.com/login
is forwarded internally to:
http://localhost:8000/login
The browser remains unaware of this forwarding process.
ProxyPassReverse
ProxyPassReverse / http://localhost:8000/
This directive handles redirects generated by the backend application.
Suppose the application sends:
Location: http://localhost:8000/login
Without ProxyPassReverse, users may be redirected to the internal application URL.
With ProxyPassReverse, Apache automatically rewrites the redirect:
Location: http://example.com/login
This ensures users always remain on the public-facing domain.
Proxying to a Remote Backend Server
The backend application does not have to run on the same server.
For example:
<VirtualHost *:80>
ServerName example.com
ProxyPass / http://10.0.0.50:8000/
ProxyPassReverse / http://10.0.0.50:8000/
</VirtualHost>
In this case:
- Apache receives requests.
- Apache forwards traffic to another server.
- Users continue accessing the application through the main domain.
This is commonly used in multi-server environments.
Proxying a Specific Application Path
Instead of forwarding the entire website, you can proxy only a specific path.
Example:
ProxyPass /app http://localhost:8000/
ProxyPassReverse /app http://localhost:8000/
Result:
http://example.com/app
forwards traffic to:
http://localhost:8000
while the rest of the website continues to be served normally.
Validate the Configuration
Before restarting Apache, always verify the configuration syntax.
Run:
apachectl -t
Expected output:
Syntax OK
Fix any reported errors before continuing.
Restart Apache
Ubuntu / Debian
systemctl restart apache2
CentOS / RHEL
systemctl restart httpd
Verify the service status:
systemctl status apache2
or
systemctl status httpd
Testing the Reverse Proxy
Open a browser and navigate to:
http://example.com
The application running on:
http://localhost:8000
should now load successfully.
The browser address bar should continue displaying:
http://example.com
without exposing the backend port.
You can also test using curl:
curl -I http://example.com
HTTPS Reverse Proxy Configuration
For production deployments, HTTPS should always be used.
Example SSL-enabled virtual host:
<VirtualHost *:443>
ServerName example.com
SSLEngine on
SSLCertificateFile /path/to/certificate.crt
SSLCertificateKeyFile /path/to/private.key
ProxyPass / http://localhost:8000/
ProxyPassReverse / http://localhost:8000/
</VirtualHost>
Benefits include:
- Encrypted communication
- Centralized certificate management
- Backend application can continue running over HTTP
Common Troubleshooting
1. 503 Service Unavailable
Check whether the backend service is running:
ss -tulpn | grep 8000
If nothing is listening on port 8000, start the application.
2. Proxy Modules Missing
Verify loaded modules:
apachectl -M | grep proxy
Enable missing modules and restart Apache.
3. Firewall Issues
Ensure firewall rules permit Apache traffic:
firewall-cmd --add-service=http --permanent
firewall-cmd --add-service=https --permanent
firewall-cmd --reload
For Ubuntu:
ufw allow 80/tcp
ufw allow 443/tcp
4. Redirect Loops
Check:
- Application base URL settings
- ProxyPassReverse configuration
- SSL redirect rules
Misconfigured redirects are a common cause of proxy loops.
5. Backend Returns Incorrect URLs
Some applications require awareness that they are behind a reverse proxy.
You may need to forward additional headers:
ProxyPreserveHost On
RequestHeader set X-Forwarded-Proto "https"
RequestHeader set X-Forwarded-Port "443"
Security Best Practices
For production environments:
- Enable HTTPS using SSL/TLS certificates.
- Keep backend services bound to localhost whenever possible.
- Restrict direct access to backend ports.
- Regularly update Apache and application dependencies.
- Enable security headers.
- Monitor Apache access and error logs.
- Use Web Application Firewalls (WAF) where required.
Real-World Use Cases
Apache reverse proxying is commonly used for:
- Node.js applications running on port 3000 or 8000
- Django and Flask applications
- Java Spring Boot services
- Internal APIs
- Kubernetes ingress alternatives
- Dockerized applications
- Load balancers and application gateways
- SSL offloading architectures
Conclusion
Apache’s ProxyPass and ProxyPassReverse directives provide a simple and powerful way to publish backend applications without exposing internal ports to the internet. By configuring Apache as a reverse proxy, organizations can maintain clean URLs, improve security, centralize SSL management, and create a more scalable application architecture.
Whether your application is running locally on the same server or on a dedicated backend host, Apache reverse proxying offers a reliable and production-ready solution for routing traffic while keeping the user experience seamless. For most modern deployments, implementing a reverse proxy should be considered a foundational best practice rather than an optional enhancement.
Frequently Asked Questions (FAQ)
1. What is the difference between ProxyPass and ProxyPassReverse?
ProxyPass forwards incoming requests from Apache to the backend application.
Example:
ProxyPass / http://localhost:8000/
ProxyPassReverse rewrites redirect responses generated by the backend application so users continue to see the public URL instead of the internal backend URL.
Example:
ProxyPassReverse / http://localhost:8000/
In most reverse proxy setups, both directives should be used together.
2. Can I proxy traffic to another server instead of localhost?
Yes.
You can forward requests to a remote server by specifying its IP address or hostname.
ProxyPass / http://10.0.0.50:8000/
ProxyPassReverse / http://10.0.0.50:8000/
This is commonly used when Apache acts as a frontend server while applications run on separate backend servers.
3. Can I proxy only a specific URL path?
Yes.
For example, to proxy only requests under /app:
ProxyPass /app http://localhost:8000/
ProxyPassReverse /app http://localhost:8000/
Requests to:
http://example.com/app
will be forwarded to the backend application, while the rest of the website continues to be served normally.
Related Articles
- Apache Bandwidth Limiting Per User: Limit Apache Bandwidth Per User
- Protect Apache from DDoS Attacks with Security Modules: Modules to Install with Apache to Avoid DDoS Attacks
- Install and Compile Apache with PHP from Source: How to Install/Compile Apache with PHP via Source Installation