Skip to content

Running Behind A Reverse Proxy

Ed Mozley edited this page Sep 26, 2026 · 1 revision

Running behind a reverse proxy

Most production installs don't let people reach FreeITSM directly. Something sits in front and handles HTTPS: nginx, Caddy, Traefik, Cloudflare, an AWS or Azure load balancer. It then passes each request on to FreeITSM over plain HTTP.

That works well, with one catch: FreeITSM only sees plain HTTP. Unless you tell it a proxy is in front, it believes it's running on http:// and builds its addresses that way.


The one setting

Turn on TRUST_PROXY_HTTPS.

Docker - in docker-compose.yml, uncomment:

    environment:
      - TRUST_PROXY_HTTPS=1

then docker compose up -d.

Everything else - in config.php:

define('TRUST_PROXY_HTTPS', true);

What your proxy must send

One header: X-Forwarded-Proto, set to https for visitors who came in over HTTPS. Most proxies send it without being asked. nginx does not, so add it:

location / {
    proxy_pass http://freeitsm:80;
    proxy_set_header Host              $http_host;
    proxy_set_header X-Forwarded-Proto $scheme;
    proxy_set_header X-Forwarded-For   $proxy_add_x_forwarded_for;
}

Pass the Host header through as well ($http_host keeps a port number, if you have one). FreeITSM builds addresses from it.

Chained proxies, such as Cloudflare in front of nginx, are fine. They send https, http, and FreeITSM reads the first value, which comes from the proxy that faced the visitor.


What goes wrong without it

Everything that shows or sends a full address comes out as http://:

  • Single sign-on fails. The redirect address sent to Entra, Google or Okta starts with http://, and they refuse it. Entra's error is AADSTS50011.
  • System β†’ Single Sign-On shows the wrong address to register.
  • Links in password reset, self-service and satisfaction survey emails start with http://.
  • The session cookie is sent without its Secure flag.
  • In Docker, following an old /login.php link, or a folder address without its final /, lands on an error page. Apache sends the browser to http:// on the HTTPS port.

Links in emails sent with nobody at the keyboard (from cron, by workflows, or for SLA warnings) can't take their address from a request at all. Set the public web address for those, whether or not you're behind a proxy.


⚠️ Only turn it on when the proxy is the only way in

Any visitor can send an X-Forwarded-Proto header themselves. That's why FreeITSM ignores it unless you set TRUST_PROXY_HTTPS.

With the setting on, make sure nobody can reach FreeITSM without going through the proxy. In Docker that means not publishing the container's own port to the network, or at least firewalling it. In the Docker image, the setting also makes Apache's own redirects use https, so anyone browsing the container directly on http:// would be bounced to an HTTPS address it doesn't answer.


Apache's own redirects, outside Docker

A few redirects are made by Apache itself, not by FreeITSM: /login.php to /login, and adding the / to a folder address. The Docker image handles these when TRUST_PROXY_HTTPS is set. On your own Apache behind a proxy, do the same by adding a scheme to the ServerName inside the site's <VirtualHost>:

<VirtualHost *:80>
    ServerName https://itsm.example.com
    ...
</VirtualHost>

On a global ServerName, outside the <VirtualHost>, the scheme has no effect. Or have the proxy fix them: in nginx, proxy_redirect http:// https://;.


Checking it

  1. Open System β†’ Single Sign-On. The redirect address shown should start with https://.
  2. Sign in, open your browser's developer tools, and look at the PHPSESSID cookie. It should be marked Secure.

If the address still says http://, the proxy isn't sending X-Forwarded-Proto, or TRUST_PROXY_HTTPS isn't set where FreeITSM reads it. In Docker, check with:

docker compose exec app printenv TRUST_PROXY_HTTPS

See also

FreeITSM

Getting Started

Modules

Multi-tenancy (planned)

Blue sky thinking

Bugs resolved

Links

Clone this wiki locally