phpsymfonydocker-compose

Symfony in Docker: %env(csv:...)% makes framework.trusted_headers crash with “got array” error


When using Symfony inside a container, %env(csv:...)% seems to break when populating a config option that expects an array. For example, in config/packages/framework.yaml:

# see https://symfony.com/doc/current/reference/configuration/framework.html
framework:
    trusted_proxies: '%env(string:APP_TRUSTED_PROXIES)%'
    trusted_headers: '%env(csv:APP_TRUSTED_HEADERS)%'

Because .env files are not read in my containerized setup, I set APP_TRUSTED_HEADERS via Docker Compose as a comma-separated string.

Running:

docker compose exec php php bin/console debug:container --env-vars | grep APP_

I get:

In BaseNode.php line 496:
                                                                               
  Invalid type for path "framework.trusted_headers.0". Expected one of "bool"  
  , "int", "float", "string", but got "array".                                 

trusted_headers expects an array<int, int|bool|string>, but Symfony complains it receives an array<int, array>.

How to reproduce? Start a new Symfony app in Docker (I used the FrankenPHP image from symfony-docker):

git clone https://github.com/dunglas/symfony-docker
cd symfony-docker
docker compose build --pull --no-cache
docker compose up --wait

Then edit the config/packages/framework.yaml and add:

framework:
    trusted_headers: '%env(csv:APP_TRUSTED_HEADERS)%'

In compose.yaml, define the env var. I tried the following (each variant tested separately):

service:
  php:
    environment:
      APP_TRUSTED_HEADERS: forwarded,x-forward-port # does NOT WORK
      APP_TRUSTED_HEADERS: forwarded # does NOT WORK
      APP_TRUSTED_HEADERS: "forwarded" # does NOT WORK
      APP_TRUSTED_HEADERS: "'forwarded'" # does NOT WORK
      APP_TRUSTED_HEADERS: "${APP_TRUSTED_HEADERS}" # with the host env set

All variants result in the same error. I read "Environment variable processors", this post about "Environment variables in a dockerized Symfony" and How to Configure Symfony to Work behind a Load Balancer or a Reverse Proxy

What am I doing wrong, and how should APP_TRUSTED_HEADERS be passed so that %env(csv:...)% resolves to a flat array of strings?

Note on possible duplicates

I’ve read “docker-compose variable substitution/interpolation with list/map or array values?” and I believe this is not a duplicate: I’m not trying to pass an array via Compose.

I’m intentionally passing a single comma-separated string (e.g., forwarded,x-forwarded-for,…) and relying on Symfony’s %env(csv:VAR)% processor to parse it at runtime. The problem is that, even with a plain string in the container env, Symfony ends up treating framework.trusted_headers.0 as an array (i.e., array). So this question is about Symfony/Dotenv CSV processing in a containerized setup, not Compose array interpolation.


Solution

  • I found a solution with the new simpler trusted proxies configuration .

    In Symfony 7.2 we're simplifying this thanks to new environment variables. Instead of configuring the previous file, you can now set the trusted proxies configuration in these env vars:

    • SYMFONY_TRUST_X_SENDFILE_TYPE_HEADER

    • SYMFONY_TRUSTED_HEADERS

    • SYMFONY_TRUSTED_HOSTS

    • SYMFONY_TRUSTED_PROXIES

    So I removed the two configuration lines in my framework.yaml file.

    framework.yaml is empty, so the default configuration is applied:

    framework:
        trusted_proxies: '%env(default:SYMFONY_TRUSTED_PROXIES)%'
        trusted_headers: '%env(default:SYMFONY_TRUSTED_HEADERS)%'
    

    And I updated my compose.<environment>.yaml files

    # compose.test.yaml
    services:
      php:
        environment:
          # All private subnets are trusted in test environment
          SYMFONY_TRUSTED_PROXIES: PRIVATE_SUBNETS
          SYMFONY_TRUSTED_HEADERS: x-forwarded-host,x-forwarded-proto,x-forwarded-port
    
    # compose.dev.yaml
    services:
      php:
        environment:
          SYMFONY_TRUSTED_PROXIES: 
          SYMFONY_TRUSTED_HEADERS: 
    
    
    # compose.prod.yaml
    services:
      php:
        environment:
          SYMFONY_TRUSTED_PROXIES: 172.16.0.xxx # The IP of your reverse-proxy 
          SYMFONY_TRUSTED_HEADERS: x-forwarded-host,x-forwarded-proto,x-forwarded-port