How to run HestiaCP with Global SSL Offloading (pfSense + HAProxy)

Happy new year :partying_face:

I am looking for a way to configure my HestiaCP server to work behind a remote pfSense + HAProxy firewall that handles all SSL termination (SSL Offloading).

My Infrastructure:

  • Server: Ubuntu 22.04.5 LTS

  • HestiaCP: 1.9.4

  • DNS: Cloudflare (Proxied) pointing to pfSense WAN.

  • Traffic Router: pfSense with HAProxy listening on Port 443.

  • SSL Handling: HAProxy handles the Let’s Encrypt certificates (SSL Offloading).

  • Backend: HestiaCP (internal IP) receiving traffic from HAProxy on Port 443.

  • SSL Handling: HestiaCP handles the Let’s Encrypt certificates too

  • Volume: I have over 100 sites on this HestiaCP instance.

The Current Problem:
When I route traffic through HAProxy to HestiaCP on port 80, I get the “Too Many Redirects” error on sites.

For WordPress sites i have tried to edit wp-config.php

by adding this to it

// Fix for "Too Many Redirects" when using HAProxy SSL Offloading if (isset($_SERVER['HTTP_X_FORWARDED_PROTO']) && $_SERVER['HTTP_X_FORWARDED_PROTO'] === 'https') { $_SERVER['HTTPS'] = 'on'; }

sometimes it works sometimes doesn’t work.

I am looking for a Global Server-Side Fix so that HestiaCP/Nginx/Apache recognizes the X-Forwarded-Proto https header sent by my HAProxy and tells PHP/Sites that the connection is secure.

My Questions:

  1. Template Modification: Which Nginx/Apache templates should I modify in /usr/local/hestia/data/templates/web/ to ensure the X-Forwarded-Proto header is respected globally across all domains?

  2. Redirect Prevention: How can I globally disable Hestia’s internal HTTP->HTTPS redirects (for all existing and future sites) since the redirect should only be handled by the firewall/Cloudflare?

  3. PHP-FPM: Is it better to use a global auto_prepend_file in PHP-FPM to set $_SERVER['HTTPS'] = 'on' when the proxy header is present, or is there a native HestiaCP way to achieve this?

I want to avoid manual edits per domain. Any advice for a way to “Sync” Hestia with an external SSL proxy would be greatly appreciated!

HAProxy Configuration:

To ensure the backend (HestiaCP) receives the correct metadata, I have configured my HAProxy Frontend and Backend as follows:

  • Mode: http (Layer 7) to allow header manipulation.

  • SSL Offloading: HAProxy terminates the SSL and communicates with HestiaCP via its internal IP on Port 80.

  • Forced Headers (Backend Pass-thru): I have added the following directives to the backend configuration to signal the secure nature of the original request:

    Codefragment

    http-request set-header X-Forwarded-Proto https
    http-request set-header X-Forwarded-Port 443
    http-request set-header X-Real-IP %[src]
    
    
  • ACL Priority: I am using a Shared Frontend where specific Host-based ACLs (e.g., api.test.nl) are prioritized over broader web rules to ensure correct routing to different containers and the HestiaCP VM.

The Goal for the Hestia Side:

I need the HestiaCP Nginx/Apache stack to “trust” these headers globally. Specifically, when Hestia receives X-Forwarded-Proto: https on port 80, it should:

  1. Not trigger a 301 redirect to HTTPS.

  2. Pass the “HTTPS” status to PHP so that $_SERVER['HTTPS'] is evaluated as 'on', preventing WordPress from creating its own redirect loops.

1 Like