🟢 Open for freelance projects & consulting —Email me
How to generate URL with HTTPS schema if your Symfony application behind the proxy

How to generate URL with HTTPS schema if your Symfony application behind the proxy

Table of Contents

Introduction

You may find out that your symfony application generates URLS with http schema via

// In a controller:
return $this->generateUrl('admin_panel'); // http://localhost/admin

// Or via service:
return $this->urlGenerator->generate('admin_panel'); // http://localhost/admin

This article explains why it happens and how to fix it.

Prerequisites

Symfony app (any version 4+), proxy server (Cloudflare, Traefik locally with self-signed certificates installed).

Issue cause

In modern applications, it is common to place a reverse proxy (CloudFlare, Traefik, AWS ELB/CloudFront, Kubernetes Ingress) in front of your application. These proxies handle SSL/TLS termination - meaning HTTPS is terminated at the proxy level, and traffic between the proxy and your app is plain HTTP.

That's the reason why your Symfony app is stuck on HTTP scheme internally.

Solution is simple.

Solution

packages/config/packages/framework.yaml
framework:
+    trusted_proxies: 'REMOTE_ADDR' # <--add this

After this change, URL generation will produce https:// URLs correctly.

WARNING

This is safe only if your backend is not publicly accessible. Make sure PHP/Symfony only accepts connections from Nginx (via 127.0.0.1, unix socket, or firewall rules) - otherwise an attacker could send forged X-Forwarded-Proto headers.

Why it works

Symfony determines the scheme via Request::isSecure(). Here is the relevant source code:

// vendor/symfony/http-foundation/Request.php
public function isSecure(): bool
{
    if ($this->isFromTrustedProxy() && $proto = $this->getTrustedValues(self::HEADER_X_FORWARDED_PROTO)) {
        return \in_array(strtolower($proto[0]), ['https', 'on', 'ssl', '1'], true);
    }

    $https = $this->server->get('HTTPS');

    return !empty($https) && 'off' !== strtolower($https);
}

Without trusted_proxies, isFromTrustedProxy() returns false - so Symfony falls back to $_SERVER['HTTPS'], which is empty in a typical proxy setup where SSL is terminated at the proxy level. That's why generateUrl() produces http://.

Adding trusted_proxies: 'REMOTE_ADDR' makes isFromTrustedProxy() return true - Symfony reads X-Forwarded-Proto: https from the proxy and correctly returns https://.

Here is the full picture:

flowchart LR A[Browser HTTPS :443] -->|https| B(Proxy TLS termination) B -->|http| C(Nginx) C -->|http| D(Symfony generateUrl → https)

Possible issues

Issues: URLs are still http:// after the change.

Reason: Your proxy is not sending X-Forwarded-Proto header.

Check your proxy documentation or verify with:

dump($request->headers->get('X-Forwarded-Proto')); // should return 'https'