New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Environment variables ignored by php-fpm #74

Closed
mikehaertl opened this Issue Mar 13, 2015 · 30 comments

Comments

Projects
None yet
@mikehaertl

mikehaertl commented Mar 13, 2015

If you use the php-fpm variant, environment variables (e.g. for linked docker hosts) are not available in your $_ENV var in your PHP scripts. This is a problem as usually docker containers are configured via environment variables (following the 12 factor principles). While this is rather a PHP problem, I still think that the official php-fpm image should provide a workaround for this, as otherwhise it's pretty much useless.

For php-fpm all environment variables have to be listed in the php-fpm.conf like:

[www]
env[MY_ENV_VAR_1] = 'value1'
env[MY_ENV_VAR_2] = 'value2'

So I suggest to create a wrapper script to first add all variables from env to the configuration, before actually starting php.

@mikehaertl

This comment has been minimized.

Show comment
Hide comment
@mikehaertl

mikehaertl Mar 13, 2015

For reference, this discussion may also have some useful tips: https://groups.google.com/forum/#!topic/docker-user/FCzUbjTIp_0

mikehaertl commented Mar 13, 2015

For reference, this discussion may also have some useful tips: https://groups.google.com/forum/#!topic/docker-user/FCzUbjTIp_0

@mikehaertl

This comment has been minimized.

Show comment
Hide comment
@mikehaertl

mikehaertl Mar 13, 2015

Here's a workaround that does the job for me. It would be great if we could include that in the php-fpm image:

FROM php:5.6.6-fpm

# Allow to include custom php-fpm config, e.g. to set environment variables
RUN echo 'include=/usr/local/etc/conf.d/*' >> /usr/local/etc/php-fpm.conf \
    && mkdir /usr/local/etc/conf.d/

COPY run-php-fpm /usr/local/bin/

CMD ["run-php-fpm"]

run-php-fpm:

#!/bin/bash

env | sed "s/\(.*\)=\(.*\)/env[\1]='\2'/" > /usr/local/etc/conf.d/env.conf

php-fpm

mikehaertl commented Mar 13, 2015

Here's a workaround that does the job for me. It would be great if we could include that in the php-fpm image:

FROM php:5.6.6-fpm

# Allow to include custom php-fpm config, e.g. to set environment variables
RUN echo 'include=/usr/local/etc/conf.d/*' >> /usr/local/etc/php-fpm.conf \
    && mkdir /usr/local/etc/conf.d/

COPY run-php-fpm /usr/local/bin/

CMD ["run-php-fpm"]

run-php-fpm:

#!/bin/bash

env | sed "s/\(.*\)=\(.*\)/env[\1]='\2'/" > /usr/local/etc/conf.d/env.conf

php-fpm
@md5

This comment has been minimized.

Show comment
Hide comment
@md5

md5 Mar 13, 2015

Contributor

If you're going to re-expose the whole environment, clear_env = no would be simpler.

Contributor

md5 commented Mar 13, 2015

If you're going to re-expose the whole environment, clear_env = no would be simpler.

@mikehaertl

This comment has been minimized.

Show comment
Hide comment
@mikehaertl

mikehaertl Mar 13, 2015

Not sure what you mean. Where would you put that and what does it do?

I've added the whole environment as this is the same what the mod_php module does in Apache. It's what you'd probably expect from inside PHP.

mikehaertl commented Mar 13, 2015

Not sure what you mean. Where would you put that and what does it do?

I've added the whole environment as this is the same what the mod_php module does in Apache. It's what you'd probably expect from inside PHP.

@mikehaertl

This comment has been minimized.

Show comment
Hide comment
@mikehaertl

mikehaertl Mar 13, 2015

Ahhh, now i see: http://php.net/manual/en/install.fpm.configuration.php. Why didn't I find this earlier? Spent quite some time to find a solution (and there are obviously others who also missed this).

So shouldn't this be set by default in this image? I think, env vars is the way to go with docker images.

mikehaertl commented Mar 13, 2015

Ahhh, now i see: http://php.net/manual/en/install.fpm.configuration.php. Why didn't I find this earlier? Spent quite some time to find a solution (and there are obviously others who also missed this).

So shouldn't this be set by default in this image? I think, env vars is the way to go with docker images.

@md5

This comment has been minimized.

Show comment
Hide comment
@md5

md5 Mar 13, 2015

Contributor

From http://php.net/manual/en/install.fpm.configuration.php:

clear_env boolean
Clear environment in FPM workers. Prevents arbitrary environment variables from reaching FPM worker processes by clearing the environment in workers before env vars specified in this pool configuration are added. Since PHP 5.4.27. Default value: Yes.

You'd put it in your php-fpm.conf or a file included from it.

FWIW, I don't think the php:fpm image should be changed to act as you've requested, but I do think the environment variable issue should be documented.

Contributor

md5 commented Mar 13, 2015

From http://php.net/manual/en/install.fpm.configuration.php:

clear_env boolean
Clear environment in FPM workers. Prevents arbitrary environment variables from reaching FPM worker processes by clearing the environment in workers before env vars specified in this pool configuration are added. Since PHP 5.4.27. Default value: Yes.

You'd put it in your php-fpm.conf or a file included from it.

FWIW, I don't think the php:fpm image should be changed to act as you've requested, but I do think the environment variable issue should be documented.

@md5

This comment has been minimized.

Show comment
Hide comment
@md5

md5 Mar 13, 2015

Contributor

Or maybe it should be the default... I'm not sure actually.

Contributor

md5 commented Mar 13, 2015

Or maybe it should be the default... I'm not sure actually.

@mikehaertl

This comment has been minimized.

Show comment
Hide comment
@mikehaertl

mikehaertl Mar 13, 2015

FWIW, I don't think the php:fpm image should be changed to act as you've requested, but I do think the environment variable issue should be documented.

Hmm, why not? I don't think it's a security issue as mod_php does the same in Apache. Wouldn't you agree, that PHP apps should follow the 12factor principles and use env vars? If that's the case, we will always need this.

mikehaertl commented Mar 13, 2015

FWIW, I don't think the php:fpm image should be changed to act as you've requested, but I do think the environment variable issue should be documented.

Hmm, why not? I don't think it's a security issue as mod_php does the same in Apache. Wouldn't you agree, that PHP apps should follow the 12factor principles and use env vars? If that's the case, we will always need this.

@md5

This comment has been minimized.

Show comment
Hide comment
@md5

md5 Mar 13, 2015

Contributor

I'd just say that the fact that clear_env = Yes is the default for php-fpm should count for something, but I see your point.

Contributor

md5 commented Mar 13, 2015

I'd just say that the fact that clear_env = Yes is the default for php-fpm should count for something, but I see your point.

@md5

This comment has been minimized.

Show comment
Hide comment
@md5

md5 Mar 13, 2015

Contributor

BTW, if you're going to have a script like run-php-fpm, make sure to do exec php-fpm at the end instead of just php-fpm 👍

Contributor

md5 commented Mar 13, 2015

BTW, if you're going to have a script like run-php-fpm, make sure to do exec php-fpm at the end instead of just php-fpm 👍

@mikehaertl

This comment has been minimized.

Show comment
Hide comment
@mikehaertl

mikehaertl Mar 13, 2015

Ok, thanks. But undoing the above in my project now anyway :)

mikehaertl commented Mar 13, 2015

Ok, thanks. But undoing the above in my project now anyway :)

@mathroc

This comment has been minimized.

Show comment
Hide comment
@mathroc

mathroc Apr 22, 2015

Contributor

👍 for clear_env = Yes by default

Contributor

mathroc commented Apr 22, 2015

👍 for clear_env = Yes by default

@mikehaertl

This comment has been minimized.

Show comment
Hide comment
@mikehaertl

mikehaertl Apr 22, 2015

@mathroc Can you explain why you're against clear_env = no by default?

mikehaertl commented Apr 22, 2015

@mathroc Can you explain why you're against clear_env = no by default?

@mathroc

This comment has been minimized.

Show comment
Hide comment
@mathroc

mathroc Apr 22, 2015

Contributor

oops that was a mistake :/ I meant 👍 for clear_env = no by default… as for the reason, it's because I need to add it manually in each of my php-fpm containers, I guess a lot of people have to do the same or worst are manually adding each need env var in php-fpm conf as you did at first. it's not that easy to find information about clear_env when you search for "php-fpm env var" on google

Contributor

mathroc commented Apr 22, 2015

oops that was a mistake :/ I meant 👍 for clear_env = no by default… as for the reason, it's because I need to add it manually in each of my php-fpm containers, I guess a lot of people have to do the same or worst are manually adding each need env var in php-fpm conf as you did at first. it's not that easy to find information about clear_env when you search for "php-fpm env var" on google

@sherter

This comment has been minimized.

Show comment
Hide comment
@sherter

sherter Apr 23, 2015

Contributor

I think in general it's a good idea to have clear_env = yes for php, since env variables may contain sensible data which php should not be able to access.
You normally have a modified php-fpm.conf anyway, so adding this one line is not to much of a hassle.

Contributor

sherter commented Apr 23, 2015

I think in general it's a good idea to have clear_env = yes for php, since env variables may contain sensible data which php should not be able to access.
You normally have a modified php-fpm.conf anyway, so adding this one line is not to much of a hassle.

@mikehaertl

This comment has been minimized.

Show comment
Hide comment
@mikehaertl

mikehaertl Apr 23, 2015

@sherter Then why is this different to the default configuration PHP apache module? The same would apply there. I can't see why it would make more sense in php-fpm. And as said before: Environment variables are a very common way to configure your docker container at runtime. So they should work by default, for both, Apache module and php-fpm.

mikehaertl commented Apr 23, 2015

@sherter Then why is this different to the default configuration PHP apache module? The same would apply there. I can't see why it would make more sense in php-fpm. And as said before: Environment variables are a very common way to configure your docker container at runtime. So they should work by default, for both, Apache module and php-fpm.

@yosifkit

This comment has been minimized.

Show comment
Hide comment
@yosifkit

yosifkit Apr 27, 2015

Member

This is the same default that is in debian when installing the php5-fpm package, as well as the default in php (php.net). There is no corresponding setting for non-fpm php.

$ cat /etc/php5/fpm/pool.d/www.conf
...
; Clear environment in FPM workers
; Prevents arbitrary environment variables from reaching FPM worker processes
; by clearing the environment in workers before env vars specified in this
; pool configuration are added.
; Setting to "no" will make all environment variables available to PHP code
; via getenv(), $_ENV and $_SERVER.
; Default Value: yes
;clear_env = no

That said, since php is the only process in the container, I think it would be sane to change from upstream's default and add clear_env = no, since then php will have access to things like linked sql address and port variables.

Member

yosifkit commented Apr 27, 2015

This is the same default that is in debian when installing the php5-fpm package, as well as the default in php (php.net). There is no corresponding setting for non-fpm php.

$ cat /etc/php5/fpm/pool.d/www.conf
...
; Clear environment in FPM workers
; Prevents arbitrary environment variables from reaching FPM worker processes
; by clearing the environment in workers before env vars specified in this
; pool configuration are added.
; Setting to "no" will make all environment variables available to PHP code
; via getenv(), $_ENV and $_SERVER.
; Default Value: yes
;clear_env = no

That said, since php is the only process in the container, I think it would be sane to change from upstream's default and add clear_env = no, since then php will have access to things like linked sql address and port variables.

mathroc added a commit to mathroc/php that referenced this issue Apr 27, 2015

Tells FPM not to clear the environment in workers
Allows php scripts executed with FPM to access env vars such as env vars
from linked containers

see #74
@mikehaertl

This comment has been minimized.

Show comment
Hide comment
@mikehaertl

mikehaertl Apr 28, 2015

Cool, thanks!

mikehaertl commented Apr 28, 2015

Cool, thanks!

@yosifkit yosifkit closed this Jun 3, 2015

@yosifkit

This comment has been minimized.

Show comment
Hide comment
@yosifkit

yosifkit Jun 3, 2015

Member

Fixed in #93

Member

yosifkit commented Jun 3, 2015

Fixed in #93

@szepeviktor

This comment has been minimized.

Show comment
Hide comment
@szepeviktor

szepeviktor Jun 12, 2015

ENV[*] from fpm config can be reached as $_SERVER[*] in PHP.

szepeviktor commented Jun 12, 2015

ENV[*] from fpm config can be reached as $_SERVER[*] in PHP.

@olegstepura

This comment has been minimized.

Show comment
Hide comment
@olegstepura

olegstepura Feb 16, 2016

Hi!

just googled this issue and it looks like a good place for my 5 cents.it's not according this concrete docker image, but a caution to a docker image writers:

many docker images are built so that all passwords are configured during the first run. This means you specify passwords that are available as environment variables in a running container during all docker container life cycle. For containers like the ones with PHP or any other server-side scripting language inside which have access to environment variables this looks like a security issue: anyone who can eval some code on the server may read environment variables (if allowed, actually. But tuning this off may be forgotten, or be changed in a running container without recalling the side effects or by another person who tries to solve some other issue).

So personally I decided that it should be always separated. I build my own containers with all sensitive data being provided during the build step. Then I run it without providing any passwords. Yes, not very share-friendly and not that much convenient, but it works.

Please let me know if I'm missing something, or if you feel like I'm doing this completely wrong. Thanks!

olegstepura commented Feb 16, 2016

Hi!

just googled this issue and it looks like a good place for my 5 cents.it's not according this concrete docker image, but a caution to a docker image writers:

many docker images are built so that all passwords are configured during the first run. This means you specify passwords that are available as environment variables in a running container during all docker container life cycle. For containers like the ones with PHP or any other server-side scripting language inside which have access to environment variables this looks like a security issue: anyone who can eval some code on the server may read environment variables (if allowed, actually. But tuning this off may be forgotten, or be changed in a running container without recalling the side effects or by another person who tries to solve some other issue).

So personally I decided that it should be always separated. I build my own containers with all sensitive data being provided during the build step. Then I run it without providing any passwords. Yes, not very share-friendly and not that much convenient, but it works.

Please let me know if I'm missing something, or if you feel like I'm doing this completely wrong. Thanks!

@mathroc

This comment has been minimized.

Show comment
Hide comment
@mathroc

mathroc Feb 16, 2016

Contributor

Hi @olegstepura

giving your credentials to external services is a recommended practice (eg: http://12factor.net/config). I'm wondering, how are your storing your passwords in the container in a way that someone "who can eval some code on the server" cannot access your passwords ?
I mean, if your code is able to access the passwords, any code running on the same server should also be able to access thoses passwords

Contributor

mathroc commented Feb 16, 2016

Hi @olegstepura

giving your credentials to external services is a recommended practice (eg: http://12factor.net/config). I'm wondering, how are your storing your passwords in the container in a way that someone "who can eval some code on the server" cannot access your passwords ?
I mean, if your code is able to access the passwords, any code running on the same server should also be able to access thoses passwords

@mikehaertl

This comment has been minimized.

Show comment
Hide comment
@mikehaertl

mikehaertl Feb 16, 2016

many docker images are built so that all passwords are configured during the first run

@olegstepura That's not what this issue is about. Environment variables are usually passed at runtime to a container, not when you build them.

mikehaertl commented Feb 16, 2016

many docker images are built so that all passwords are configured during the first run

@olegstepura That's not what this issue is about. Environment variables are usually passed at runtime to a container, not when you build them.

@olegstepura

This comment has been minimized.

Show comment
Hide comment
@olegstepura

olegstepura Feb 16, 2016

@mathroc Well, if it's a password for connecting to this container - it won't be saved in plaintext (password for connecting to Mysql - may be). For example I setup a hybrid container (I know it's not the Docker way, I would never do this, but let's assume) with PHP and openssh server. For SFTP access I need to setup a unix user. I need to provide this password either during build or during run. But SFTP user password should not be an ENV variable accessible by PHP. So we cannot pass it to run.

  • If provided during build phase (docker build --build-arg SFTP_PASS=123), it's stored on the server encrypted or I believe one-way hashed. So even if you would get read access to /etc/passwd and read that hash - you still got no password (and thus cannot use it). Password will not be an environment variable in a running container.
  • If passed during run (docker run -e SFTP_PASS=123) - it's an ENV variable accessible by PHP in some cases. May end up being a security issue.

@mikehaertl Sorry, if this was completely wrong place to write this. Didn't find better one to connect to experts. This issue seem very close to the issue I try to discuss. And yes, concrete issue has nothing to do with my discussion.

olegstepura commented Feb 16, 2016

@mathroc Well, if it's a password for connecting to this container - it won't be saved in plaintext (password for connecting to Mysql - may be). For example I setup a hybrid container (I know it's not the Docker way, I would never do this, but let's assume) with PHP and openssh server. For SFTP access I need to setup a unix user. I need to provide this password either during build or during run. But SFTP user password should not be an ENV variable accessible by PHP. So we cannot pass it to run.

  • If provided during build phase (docker build --build-arg SFTP_PASS=123), it's stored on the server encrypted or I believe one-way hashed. So even if you would get read access to /etc/passwd and read that hash - you still got no password (and thus cannot use it). Password will not be an environment variable in a running container.
  • If passed during run (docker run -e SFTP_PASS=123) - it's an ENV variable accessible by PHP in some cases. May end up being a security issue.

@mikehaertl Sorry, if this was completely wrong place to write this. Didn't find better one to connect to experts. This issue seem very close to the issue I try to discuss. And yes, concrete issue has nothing to do with my discussion.

@liaol

This comment has been minimized.

Show comment
Hide comment
@liaol

liaol May 2, 2016

clear_env = no works

liaol commented May 2, 2016

clear_env = no works

@samirfor

This comment has been minimized.

Show comment
Hide comment
@samirfor

samirfor Aug 3, 2016

sed -i "s|;*clear_env\s*=\s*yes|clear_env = no|g" /etc/php5/php-fpm.conf

samirfor commented Aug 3, 2016

sed -i "s|;*clear_env\s*=\s*yes|clear_env = no|g" /etc/php5/php-fpm.conf
@huangyanxiong01

This comment has been minimized.

Show comment
Hide comment
@huangyanxiong01

huangyanxiong01 Dec 22, 2016

Thank you very mach

huangyanxiong01 commented Dec 22, 2016

Thank you very mach

@deiucanta

This comment has been minimized.

Show comment
Hide comment
@deiucanta

deiucanta Mar 9, 2017

This is strange - I've uncommented clear_env = no but I can't access ENV vars inside PHP.

deiucanta commented Mar 9, 2017

This is strange - I've uncommented clear_env = no but I can't access ENV vars inside PHP.

@coredumperror

This comment has been minimized.

Show comment
Hide comment
@coredumperror

coredumperror Mar 10, 2017

For those of us on CentOS 7 who can't use clear_env = no (php-fpm is just a tiny bit too old), mikehaertl's comment regarding the workaround with sed is a lifesaver.

coredumperror commented Mar 10, 2017

For those of us on CentOS 7 who can't use clear_env = no (php-fpm is just a tiny bit too old), mikehaertl's comment regarding the workaround with sed is a lifesaver.

select added a commit to select/documentation that referenced this issue Jan 29, 2018

Added a simpler way to get env vars in php-fpm
Answer was discussed here docker-library/php#74 not and expert though

wmilewski pushed a commit to wmilewski/docker-php that referenced this issue Mar 2, 2018

wojtek Wojciech Milewski
Add xdebug
As a necessary step, enable all environment variables
to be seen in PHP.

See docker-library/php#74

MorrisJobke added a commit to nextcloud/documentation that referenced this issue Apr 4, 2018

Added a simpler way to get env vars in php-fpm
Answer was discussed here docker-library/php#74 not and expert though
@origaminal

This comment has been minimized.

Show comment
Hide comment
@origaminal

origaminal Jun 9, 2018

@deiucanta

This is strange - I've uncommented clear_env = no but I can't access ENV vars inside PHP.

In the case you were starting php-fpm not in a container but with systemd you need to said it where to get environment variables. For example set in /lib/systemd/system/php7.2-fpm.service:

EnvironmentFile=/etc/environment

origaminal commented Jun 9, 2018

@deiucanta

This is strange - I've uncommented clear_env = no but I can't access ENV vars inside PHP.

In the case you were starting php-fpm not in a container but with systemd you need to said it where to get environment variables. For example set in /lib/systemd/system/php7.2-fpm.service:

EnvironmentFile=/etc/environment
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment