TRENDING
A mountain gorilla looks at the camera from green forest undergrowth
October 28, 2026
How to Compress Time-Series Metrics in Python With Gorilla Delta-of-Delta and XOR Encoding
A bronze-framed hourglass with white sand beside a small Ferris wheel ornament on a wooden table against a teal wall
October 28, 2026
NIST’s Final Post-Quantum Transition Report Puts Every Quantum-Vulnerable Public-Key Scheme on One 2030 and 2035 Clock, and Three Federal Documents Word the Deadline Three Ways
Six weathered stone columns of the Temple of Apollo at Delphi, Greece, standing on a stone platform above a valley of olive groves
October 28, 2026
Honeypots Recorded Probes Against Oracle E-Business Suite CVE-2026-101767 Seven Days After Its Patch, and the Finder’s Write-Up Is Dated Patch Day
Vintage silver stopwatch with a chain on a black background, its dial showing seconds from 5 to 60
October 28, 2026
How to Find a Slow Query in PostgreSQL 18 With pg_stat_statements, Read Its EXPLAIN ANALYZE Plan, and Fix It With the Right Index
A wooden Tower of Hanoi puzzle on a market table, with three pegs and stacked discs of different sizes
October 28, 2026
Two Labs’ Claimed Refutations of the Exponential Time Hypothesis Turn Verification Into a Statement-Reading Problem, and Their Lean Theorems Promise Only That a Constant Exists
28 Oct 2026
SXZ.io SXZ.io
  • Home
Search the Site
Popular Searches:
Technology Amazon AI
Recent Posts
A flock of snow geese in flight, seen as dark silhouettes against an orange and red sunset sky with layered clouds
How to Run Zero-Downtime Schema Migrations on PostgreSQL 18 and Block Unsafe ALTER TABLE Statements With a Python Lint Gate
October 28, 2026
An old green steel truss bridge resting on temporary supports beside a new arch bridge under completion on a river in Portland, Oregon
The Angular 2 Rewrite Turns a Migration Lesson Into a Security Bill: AngularJS Still Draws 533,480 Downloads a Week, and 10 Advisories Have No Open-Source Fix
October 28, 2026
Hundreds of yellow rubber ducks floating in a river enclosure during a duck race
WordPress 7.1.4 Closes an Unauthenticated Race in Its Own Update Routine, but 19 Older Branches Had No Backport Hours After Release
October 28, 2026
SXZ.io SXZ.io
  • Home

Categories

Articles 270 Posts
News 273 Posts
Learning Hub 243 Posts
Home/Learning Hub/Apache Reverse Proxy Basics for Hosting Admins
Learning Hub

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.

June 9, 2026 7 Min Read
65

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/*.conf enabled 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 configtest or httpd -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/, and systemctl reload apache2.
  • If the server is RHEL, AlmaLinux, Rocky Linux, or non-cPanel CloudLinux, use httpd, /etc/httpd/conf.d/, apachectl configtest, and systemctl 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 On in the public vhost and proxy to http://127.0.0.1:PORT/.
  • If the backend is HTTPS, add SSLProxyEngine On and 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.

Tags:

ApacheLinux Hostingmod_proxyReverse ProxyWeb Hosting

Share

Rows of illuminated server racks in a computer room
Previous Post

CentOS’s Rise Still Explains the Enterprise Linux Split

A laptop secured with a chain and padlock, symbolizing account security around encrypted messaging.
Next Post

Tchap Breach Shows Account Hijacking Still Beats Encrypted Messaging

No Comment! Be the first one.

Leave a Reply Cancel reply

Your email address will not be published. Required fields are marked *

Latest
28 Oct
How to Run Zero-Downtime Schema Migrations on PostgreSQL 18 and Block Unsafe ALTER TABLE Statements With a Python Lint Gate
28 Oct
The Angular 2 Rewrite Turns a Migration Lesson Into a Security Bill: AngularJS Still Draws 533,480 Downloads a Week, and 10 Advisories Have No Open-Source Fix
Trending
October 28, 2026
How to Run Zero-Downtime Schema Migrations on PostgreSQL 18 and Block Unsafe ALTER TABLE Statements With a Python Lint Gate
October 28, 2026
The Angular 2 Rewrite Turns a Migration Lesson Into a Security Bill: AngularJS Still Draws 533,480 Downloads a Week, and 10 Advisories Have No Open-Source Fix
October 28, 2026
WordPress 7.1.4 Closes an Unauthenticated Race in Its Own Update Routine, but 19 Older Branches Had No Backport Hours After Release
October 28, 2026
How to Compress Time-Series Metrics in Python With Gorilla Delta-of-Delta and XOR Encoding
October 28, 2026
NIST’s Final Post-Quantum Transition Report Puts Every Quantum-Vulnerable Public-Key Scheme on One 2030 and 2035 Clock, and Three Federal Documents Word the Deadline Three Ways
October 28, 2026
Honeypots Recorded Probes Against Oracle E-Business Suite CVE-2026-101767 Seven Days After Its Patch, and the Finder’s Write-Up Is Dated Patch Day

Related Posts

A laptop wrapped in a chain and padlock, illustrating least-privilege controls for AI agents.
Learning Hub

How to Secure Tool-Using AI Agents Before They Touch Production

June 8, 2026
Colorful sticky notes arranged on an office wall, symbolizing governance checklists and planning.
Learning Hub

AI Governance for Agentic Apps: A Practical Checklist for Builders

June 8, 2026
A technician connects green fiber optic cables at a data center, representing a private production inference endpoint.
Learning Hub

How to Deploy a Fine-Tuned LLM Behind a Private Production Inference Endpoint

June 8, 2026
Narrow aisle behind black supercomputer racks in a data center
Learning Hub

Kubernetes SELinux Volume Labeling: What Cluster Operators Should Audit Before v1.37

June 8, 2026
SXZ.io SXZ.io
  • [email protected]

Categories

Articles
Learning Hub
News

All Rights Reserved by SXZ.io ©2026