Apache Reverse Proxy Basics for Hosting Admins
A detailed, system-specific Apache reverse proxy guide for Ubuntu/Debian, RHEL-family Linux, CloudLinux, and cPanel/WHM hosting admins, with safe vhost patterns and verification steps.
An Apache reverse proxy is useful only when the reader knows which machine they are configuring. On Ubuntu, the commands use apache2, a2enmod, and a2ensite. On RHEL-family systems such as RHEL, AlmaLinux, Rocky Linux, and many CloudLinux servers, the service is usually httpd and the configuration layout is different. On cPanel/WHM servers, you normally should not hand-edit the generated httpd.conf at all.
Table Of Content
- What a reverse proxy is doing
- Before you touch Apache, identify the system
- Ubuntu and Debian servers
- RHEL, AlmaLinux, Rocky Linux, and non-cPanel CloudLinux servers
- cPanel/WHM and CloudLinux hosting servers
- Step 1: make the backend private first
- Step 2: enable the right Apache modules
- Ubuntu/Debian
- RHEL/AlmaLinux/Rocky/CloudLinux without cPanel
- cPanel/WHM
- Step 3: choose the right virtual-host file
- Ubuntu/Debian file path
- RHEL/AlmaLinux/Rocky/CloudLinux file path
- cPanel/WHM userdata include path
- Step 4: use a minimal HTTPS reverse-proxy vhost
- Step 5: if the backend is HTTPS, add SSL proxy settings
- Step 6: test before reload
- Ubuntu/Debian test and reload
- RHEL/AlmaLinux/Rocky/CloudLinux test and reload
- cPanel/WHM rebuild and restart
- Step 7: verify from both sides
- Useful log commands by system
- Common mistakes that cause outages
- Using Ubuntu commands on RHEL-family systems
- Editing generated cPanel Apache files
- Leaving the backend public
- Forgetting WebSockets
- Skipping the syntax test
- A practical decision checklist
This guide uses one simple target: a public hostname, app.example.com, served by Apache and forwarded to an application listening on 127.0.0.1:3000. The examples are intentionally split by platform so a hosting admin can copy the right pattern instead of guessing which Linux family the command belongs to.
What a reverse proxy is doing
Apache’s reverse-proxy features live in the mod_proxy family. The core mod_proxy module provides proxy infrastructure, while protocol modules such as mod_proxy_http handle HTTP and HTTPS proxying. Apache’s reverse-proxy guide describes ProxyPass as the mapping from a public URL path to a backend server, and ProxyPassReverse as the response-header rewriting that keeps redirects pointing at the public proxy instead of the private backend. Apache reverse proxy guide
The direction matters. A reverse proxy accepts outside requests for your site and forwards them to a known backend. A forward proxy accepts arbitrary client proxy requests. Apache explicitly warns not to enable forward proxying with ProxyRequests until the server is secured because open proxies are dangerous to your network and to the internet. Apache mod_proxy
Before you touch Apache, identify the system
The same Apache directives work across distributions, but the package names, service names, file paths, and helper commands do not. Use this quick map before applying a snippet.
Ubuntu and Debian servers
- Service name:
apache2 - Main configuration root:
/etc/apache2/ - Per-site files:
/etc/apache2/sites-available/*.confenabled into/etc/apache2/sites-enabled/ - Module helper:
a2enmod - Site helper:
a2ensite
The a2enmod manual describes it as the Debian/Ubuntu helper for enabling Apache modules by creating links from mods-available into mods-enabled. Ubuntu a2enmod man page That is why a2enmod appears in Ubuntu examples and should not be assumed to exist on RHEL-family systems.
RHEL, AlmaLinux, Rocky Linux, and non-cPanel CloudLinux servers
- Service name:
httpd - Main configuration root:
/etc/httpd/ - Common per-site directory:
/etc/httpd/conf.d/*.conf - Module loading files: commonly under
/etc/httpd/conf.modules.d/ - Syntax check:
apachectl configtestorhttpd -t
Rocky Linux’s Apache guide shows the RHEL-family pattern of installing httpd with dnf and working under /etc/httpd/. Rocky Linux Apache guide On these systems, do not paste Ubuntu-only a2enmod or a2ensite commands.
cPanel/WHM and CloudLinux hosting servers
cPanel/WHM generates Apache configuration through EasyApache and cPanel userdata. cPanel documents per-virtual-host include files under paths such as /etc/apache2/conf.d/userdata/ssl/2_4/user/domain/includename.conf, followed by /usr/local/cpanel/scripts/rebuildhttpdconf and /usr/local/cpanel/scripts/restartsrv_httpd. cPanel include-file documentation
That means the cPanel rule is different: if the server is managed by WHM, do not edit the generated Apache httpd.conf directly. Use WHM’s Include Editor for global includes or cPanel’s userdata include paths for a specific virtual host, then rebuild and restart Apache through the cPanel scripts. cPanel’s Include Editor documentation describes it as a way to add configuration through Apache’s Include directive. cPanel Include Editor
Step 1: make the backend private first
The safest reverse proxy starts with a backend that is not directly exposed to the internet. If your Node, Python, Go, Rails, or internal dashboard service listens on every interface, Apache is no longer the only public entry point. Bind the app to loopback, a private interface, a private container network, or a Unix socket if your stack supports it.
For this guide, the backend is:
http://127.0.0.1:3000/
Before changing Apache, test the backend locally from the web server:
curl -I http://127.0.0.1:3000/
If that fails, fix the application service first. Apache cannot proxy a backend that is stopped, bound to a different interface, blocked by local firewall policy, or speaking HTTPS when the proxy URL says HTTP.
Step 2: enable the right Apache modules
Ubuntu/Debian
Use this only on Debian-family systems:
sudo apt update
sudo apt install apache2
sudo a2enmod proxy proxy_http headers ssl
sudo systemctl reload apache2
proxy provides the core proxy infrastructure, proxy_http handles HTTP backend proxying, headers lets the vhost set forwarded headers, and ssl enables Apache TLS termination. If the application needs WebSocket proxying, enable proxy_wstunnel as well; Apache documents that module separately for WebSocket tunneling. Apache mod_proxy_wstunnel
RHEL/AlmaLinux/Rocky/CloudLinux without cPanel
Use this pattern on RHEL-family systems where you administer Apache directly:
sudo dnf install httpd mod_ssl
sudo systemctl enable --now httpd
sudo apachectl configtest
The proxy modules are normally provided by the Apache/httpd package family and loaded through module configuration files. If a directive is reported as unknown during configtest, check the module-loading files under /etc/httpd/conf.modules.d/ and install the distribution package that provides the missing module.
cPanel/WHM
On cPanel/WHM, module availability is controlled through EasyApache 4. Use WHM/EasyApache to confirm that the needed Apache modules are present, then put vhost-specific proxy configuration in the appropriate userdata include rather than editing generated configuration files. cPanel’s advanced Apache configuration documentation says EasyApache builds Apache configuration from templates and userdata content under /etc/apache2/conf.d/userdata/. cPanel Advanced Apache Configuration
Step 3: choose the right virtual-host file
Ubuntu/Debian file path
/etc/apache2/sites-available/app.example.com.conf
After creating the file, enable it with a2ensite.
RHEL/AlmaLinux/Rocky/CloudLinux file path
/etc/httpd/conf.d/app.example.com.conf
Files ending in .conf under conf.d are included by the standard httpd configuration on typical RHEL-family installations. If your host has a custom layout, confirm with apachectl -V and the server’s main configuration file before assuming the include path.
cPanel/WHM userdata include path
For one SSL virtual host on cPanel/WHM, cPanel documents this pattern:
/etc/apache2/conf.d/userdata/ssl/2_4/USER/DOMAIN/includename.conf
Replace USER with the cPanel account username and DOMAIN with the domain. After writing the include, rebuild and restart through cPanel:
sudo /usr/local/cpanel/scripts/rebuildhttpdconf
sudo /usr/local/cpanel/scripts/restartsrv_httpd
If you only have a regular cPanel account and no root/WHM access, you probably cannot safely add this Apache reverse-proxy configuration yourself. Use your host’s application manager, Passenger/Node.js feature, or ask the host to add the vhost include.
Step 4: use a minimal HTTPS reverse-proxy vhost
This example assumes Apache terminates public HTTPS and forwards to a local plain-HTTP backend. It is appropriate for Ubuntu/Debian or direct RHEL-family Apache administration after adjusting the file path and service commands.
<VirtualHost *:443>
ServerName app.example.com
SSLEngine On
SSLCertificateFile /path/to/fullchain.pem
SSLCertificateKeyFile /path/to/privkey.pem
ProxyRequests Off
ProxyPreserveHost On
RequestHeader set X-Forwarded-Proto "https"
ProxyPass "/" "http://127.0.0.1:3000/"
ProxyPassReverse "/" "http://127.0.0.1:3000/"
ErrorLog ${APACHE_LOG_DIR}/app.example.com-error.log
CustomLog ${APACHE_LOG_DIR}/app.example.com-access.log combined
</VirtualHost>
On RHEL-family systems, ${APACHE_LOG_DIR} is not normally defined the same way it is on Debian-family systems. Use explicit paths instead:
ErrorLog /var/log/httpd/app.example.com-error.log
CustomLog /var/log/httpd/app.example.com-access.log combined
The important directives are not decorative. ProxyRequests Off keeps the server out of forward-proxy mode. ProxyPreserveHost On preserves the original host header for applications that route by hostname. RequestHeader comes from Apache’s headers module and lets the proxy tell the backend that the public scheme was HTTPS. Apache mod_headers
Step 5: if the backend is HTTPS, add SSL proxy settings
If the backend URL is https://127.0.0.1:3000/ or another HTTPS upstream, the vhost needs SSL proxy support. Apache’s mod_ssl documentation describes SSLProxyEngine as the directive that enables SSL/TLS proxy support for a virtual host. Apache mod_ssl SSLProxyEngine
SSLProxyEngine On
SSLProxyVerify require
SSLProxyCheckPeerName On
SSLProxyCACertificateFile /path/to/upstream-ca.pem
Do not turn off backend certificate verification just to make a warning disappear. If the backend uses a private CA, install that CA and point Apache at it. If the backend is only local and you do not need encrypted loopback traffic, proxying to http://127.0.0.1:3000/ is often simpler.
Step 6: test before reload
Apache documents apachectl as a control interface that can pass arguments to the server binary, and configtest is the common syntax-check path before restarting or reloading. Apache apachectl
Ubuntu/Debian test and reload
sudo apache2ctl configtest
sudo systemctl reload apache2
RHEL/AlmaLinux/Rocky/CloudLinux test and reload
sudo apachectl configtest
sudo systemctl reload httpd
cPanel/WHM rebuild and restart
sudo /usr/local/cpanel/scripts/rebuildhttpdconf
sudo /usr/local/cpanel/scripts/restartsrv_httpd
Use reload when possible so existing connections are handled gracefully. Use restart when the platform’s management tool requires it or when module changes need a full restart.
Step 7: verify from both sides
Check the backend locally:
curl -I http://127.0.0.1:3000/
Then check the public site:
curl -I https://app.example.com/
If the public check returns a redirect to 127.0.0.1, the backend is probably generating redirects with its private hostname and ProxyPassReverse is missing or not matching the backend URL. If the public check returns 502 or 503, start with the Apache error log and then verify that the backend is actually listening.
Useful log commands by system
Ubuntu/Debian:
sudo journalctl -u apache2 -n 100 --no-pager
sudo tail -n 100 /var/log/apache2/error.log
RHEL/AlmaLinux/Rocky/CloudLinux:
sudo journalctl -u httpd -n 100 --no-pager
sudo tail -n 100 /var/log/httpd/error_log
cPanel/WHM paths vary by server and EasyApache configuration, but Apache errors are commonly visible through WHM and under the server’s Apache log directory. On cPanel, prefer WHM’s service/log interfaces unless you are the root administrator.
Common mistakes that cause outages
Using Ubuntu commands on RHEL-family systems
a2enmod and a2ensite are Debian-family helpers. If an article tells a CloudLinux/RHEL admin to run them without saying “Ubuntu/Debian,” it is incomplete.
Editing generated cPanel Apache files
On cPanel/WHM, EasyApache can overwrite generated configuration. Use userdata include files or WHM’s Include Editor, then rebuild Apache configuration with cPanel’s scripts. cPanel include-file documentation
Leaving the backend public
If the backend also listens on a public IP and port, attackers can bypass Apache, TLS, authentication, rate limits, ModSecurity rules, and logging assumptions. Bind the application to loopback or a private network unless there is a specific reason to expose it.
Forgetting WebSockets
Applications that use WebSockets may need mod_proxy_wstunnel and explicit WebSocket proxy rules. Apache’s WebSocket module documentation covers this separate module. Apache mod_proxy_wstunnel
Skipping the syntax test
A typo in a public Apache vhost can break more than the app you are trying to proxy. Always run the system-specific syntax test before reload: apache2ctl configtest on Ubuntu/Debian or apachectl configtest on RHEL-family systems.
A practical decision checklist
- If the server is Ubuntu/Debian, use
apache2,a2enmod,a2ensite,/etc/apache2/sites-available/, andsystemctl reload apache2. - If the server is RHEL, AlmaLinux, Rocky Linux, or non-cPanel CloudLinux, use
httpd,/etc/httpd/conf.d/,apachectl configtest, andsystemctl reload httpd. - If the server is cPanel/WHM, use EasyApache and cPanel include mechanisms; do not hand-edit generated
httpd.conf. - If Apache terminates public HTTPS and the backend is local HTTP, use
SSLEngine Onin the public vhost and proxy tohttp://127.0.0.1:PORT/. - If the backend is HTTPS, add
SSLProxyEngine Onand verify the upstream certificate instead of disabling checks blindly. - Always test the backend locally, run Apache’s config test, reload the correct service, and verify the public hostname from outside the server.
The principle is simple: Apache should be the public contract, the backend should be private, and every command should match the operating system actually running the web server. Once those three things are clear, ProxyPass stops being a magic incantation and becomes a predictable routing rule.








No Comment! Be the first one.