1

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 Docker Compose array interpolation.

7
  • 1
    You can run docker compose exec php env | grep APP_TRUSTED_HEADERS to check the value of APP_TRUSTED_HEADERS, to ensure that it is passed properly to the container. Commented Sep 1 at 19:54
  • 2
    Are you sure this is related to Docker at all? Does it work when using a "plain" PHP setup with the given configuration? Checking this helps to rule out whether this is a problem with PHP, Symfony, or Docker Commented Sep 3 at 11:24
  • @NicoHaase, an array perfectly works when I use a plain PHP setup. A coma separated string works too when I use a yaml file. It only crashed when I replace the coma separated string by %env(string:...)% Commented Sep 25 at 12:55
  • 2
    @AlexandreTranchant I'm not one of the close voters but yes that is probably why--there is a lot of debate about docker-related issues as docker itself is not really a programming tool but rather a virtualization software tool (e.g. server management; sysadmin stuff). Given this question/issue appears to be about network configuration (e.g. proxies, network addresses, subnets), it is likely off-topic here and more appropriate for our Server Fault or maybe DevOps sister sites. Commented Oct 6 at 18:03
  • 1
    I think some Docker questions are off-topic, but this one seems to have an impact on code, so it is not exclusively an operational-side question. I will give it the benefit of the doubt. Commented Oct 6 at 18:31

2 Answers 2

3

The /framework/trusted_headers is always treated as a plain scalar, even if properly¹ tagged as sequence.

What happens is, that Symfony renders it as the first member of the sequence then, e.g.:

framework:
    trusted_headers: XXX

effectively becomes:

framework:
    trusted_headers:
        - XXX

This is also the reason why the schema validation reports an array on the first member of the sequence with the built-in environment variable processor that decoded the environment parameter value into an array:

Invalid type for path "framework.trusted_headers.0". Expected one of "bool"
, "int", "float", "string", but got "array".

This is now an array inside an array. From the Symfony configuration guidelines you have to put the array into the YAML file.

The single test on the trusted_headers configuration setting is limited to a single only for SYMFONY_TRUSTED_HEADERS (#58161), the underlying parameter and the latest step towards featuring the environment.


¹ The Symfony YAML parser is limited in terms of standard YAML tags, for example tagged as a sequence.

Sign up to request clarification or add additional context in comments.

1 Comment

Thank you for your help and your explanations. Your answer focus on symfony and is exact, but your answer doesn't solve my configuration problem. It's why I upvote, but I didn't accept it as a solution.
1

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

Comments

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.