Making PHP Think It’s on HTTPS (Even When It Isn’t)

When you move PHP sites behind a load balancer, reverse proxy, or CDN, the browser may connect over HTTPS while PHP only ever sees plain HTTP. That’s when URLs, cookies, and “force HTTPS” logic start misbehaving. In this article we explain how PHP actually detects HTTPS, why simply setting $_SERVER['HTTPS'] = 'on' is risky, and how to correctly configure Apache, nginx, and Plesk so your apps generate secure URLs and behave as if they’re truly running over HTTPS.

Table of Contents

When you move sites behind a load balancer, reverse proxy, or CDN, you’ll often terminate SSL before the request reaches PHP. The browser connects over HTTPS, but by the time the request hits Apache/PHP-FPM, it might look like plain HTTP.

That’s when things get weird:

  • Apps think they’re on http:// and generate insecure URLs
  • “Force HTTPS” logic stops working
  • Secure cookies don’t get set correctly
  • Frameworks start complaining about “Insecure request” or “unexpected scheme”

Under the hood, most PHP applications decide “am I on HTTPS?” by inspecting a couple of $_SERVER variables. If we understand those, we can safely “fool” PHP into behaving as if the request is HTTPS—as long as the original client really did connect over HTTPS.

Let’s walk through how this works and the right way to configure it.


How PHP Detects HTTPS

This is the key: PHP itself doesn’t run TLS. The web server or proxy does that. PHP just looks at environment variables the web server passes in.

Typical detection logic in PHP looks like this:

So the main signals are:

  • $_SERVER['HTTPS'] – usually on for HTTPS, empty or off for HTTP
  • $_SERVER['SERVER_PORT'] – often 443 for HTTPS, 80 for HTTP

Frameworks and CMSs also sometimes check:

  • $_SERVER['HTTP_X_FORWARDED_PROTO'] (when behind a proxy)
  • $_SERVER['REQUEST_SCHEME'] (set by some servers)

If you can control these values, you can control what PHP thinks is going on.


The Wrong Approach: Faking It in PHP

You can directly override the variables at the top of your script:

This will usually convince any “am I HTTPS?” checks that they are secure.

The problem: PHP has no idea whether the original client came in over HTTPS or not. If you turn this on unconditionally, your app will assume every request is encrypted. That can:

  • Mark cookies as Secure when they’re actually being sent over HTTP
  • Skip redirects intended to force HTTPS
  • Confuse logging / debugging tools

This might be acceptable on a dev box or in a very controlled environment, but it’s not what you want as a general solution.


The Right Approach: Let the Web Server Tell the Truth

The correct pattern is:

Only tell PHP “this is HTTPS” if the front-end connection is HTTPS.

When you’re behind a proxy or load balancer, that front-end usually passes its own signal (like X-Forwarded-Proto) to the backend. We then translate that into HTTPS=on before PHP runs.

Apache / .htaccess Example

If Apache is sitting behind a load balancer that sets X-Forwarded-Proto: https, you can do this in your vhost or .htaccess:

What this does:

  • Looks at the incoming X-Forwarded-Proto header
  • If it’s “https”, it sets the environment variable HTTPS=on
  • PHP then sees $_SERVER['HTTPS'] = 'on'

Many apps will immediately start generating correct https:// URLs after this change.

You may also want to ensure that $SERVER_PORT looks right (some apps check it):

Usually SERVER_PORT is set by Apache to whatever port it’s listening on, so you don’t always need to fake it. For most apps, HTTPS=on is enough.


nginx + PHP-FPM Example

In nginx, you control what goes into $_SERVER using fastcgi_param. Here’s a typical snippet in the PHP location block:

If nginx is directly terminating TLS, you can often just do:

Where $https will be on for HTTPS requests and an empty string otherwise.


Special Case: Plesk, Proxies, and Panels

On panels like Plesk/Obsidian and similar hosting environments, you might have multiple layers:

Browser → CDN → Load Balancer → Apache/nginx (Plesk) → PHP-FPM

Common gotchas in this setup:

  • CDN terminates HTTPS and forwards as HTTP
  • Plesk’s Apache/nginx doesn’t see the real scheme
  • PHP thinks everything is plain HTTP

The fix is conceptually the same:

  1. Confirm what header your front-end is sending (X-Forwarded-Proto, X-Forwarded-Scheme, etc.).
  2. Configure Apache/nginx at the panel level to set HTTPS=on when that header is https.
  3. Test from a real HTTPS request, not just curl to the backend.

Once that’s done correctly, apps like WordPress, Laravel, Symfony, etc. usually “just work” without hacks.


Detecting HTTPS Robustly in Your Own PHP Code

If you’re writing your own app or library, use a slightly more complete detection function that understands proxies:

This won’t fix a broken server config by itself, but it will respect correctly-passed headers when your infrastructure is set up to send them.


When Is It Safe to “Fool” PHP?

It’s reasonable to spoof HTTPS only when you’re absolutely certain of one of these:

  • You’re in a local/dev environment and don’t care about real TLS
  • You’ve already validated (in the web server) that the original connection was HTTPS, and you’re just translating that fact to PHP

If you blindly set $_SERVER['HTTPS'] = 'on' in production, you’re asking for security and debugging headaches.


Summary

  • PHP doesn’t do TLS; it trusts $_SERVER to know if a request is HTTPS.
  • Most code checks $_SERVER['HTTPS'] and sometimes $_SERVER['SERVER_PORT'].
  • You can “fool” PHP by setting those values manually, but that’s usually the wrong tool.
  • The right way is to configure your web server (Apache/nginx/Plesk/etc.) to set HTTPS=on only when the client actually connected over HTTPS (often using X-Forwarded-Proto).
  • For your own code, prefer a helper that understands both HTTPS and proxy headers.

Have a project or a problem?

Talk with a senior engineer for practical recommendations—no obligation.

Leave a comment

Leave a Reply

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

Related Posts

Categories

Get a free consultation from Reliable Penguin

Submit the form—or for immediate service call 866-649-7984.