Skip to content
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

Override config.php values through environment variables #3966

Merged
merged 3 commits into from
Apr 13, 2017

Conversation

MorrisJobke
Copy link
Member

@MorrisJobke MorrisJobke commented Mar 21, 2017

@LukasReschke @nickvergessen @rullzer @karlitschek Should we rename the env variables to NC_ or should leave them?

@mention-bot
Copy link

@MorrisJobke, thanks for your PR! By analyzing the history of the files in this pull request, we identified @nickvergessen, @LukasReschke and @bartv2 to be potential reviewers.

@MorrisJobke MorrisJobke changed the title Override config.php values through ENV variables (#26570) Override config.php values through environment variables Mar 21, 2017
@karlitschek
Copy link
Member

i think it should be nc_

@MorrisJobke
Copy link
Member Author

i think it should be nc_

Your wish shall be granted 🎆

*
* @param string $key key
* @param mixed $default = null default value
* @return mixed the value or $default
*/
public function getValue($key, $default = null) {
$envValue = getenv(self::ENV_PREFIX . $key);
if ($envValue) {
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

from http://php.net/manual/en/function.getenv.php

Returns the value of the environment variable varname, or FALSE if the environment variable varname does not exist.

hence I would suggest to explicitly check for that with if ($envValue !== false). Not sure which string values PHP considers truthy, but to me this looks error-prone otherwise.

Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Yes, also all int values we have with 0 (log level and rotation, ... ) can not be set otherwise

Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Good point. Do we need casting here? E.g. if you set NC_LOGLEVEL=0, it will return the string "0".

Copy link
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

What about values that should actually be set to false 🙈

Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

getenv will always return a string, according to the documentation, so in case of NC_xxx=false it returns "false" (string), not false (bool) 😉

Copy link
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

But for those options we also rely on the fact that there is actual boolean returned if there is a boolean in the config.php 🙈

Copy link
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Fixed and added unit tests.

Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Yup, that's the same problem as in #3966 (comment). Can we handle this somehow? We don't know what the consuming code expects 🤔

Copy link
Member

@nickvergessen nickvergessen left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

As per above

*
* If it does not exist, $default will be returned.
* gets its value from an `OC_` prefixed environment variable
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

OC -> NC

tests/lib/ConfigTest.php Show resolved Hide resolved
@MorrisJobke MorrisJobke force-pushed the downstream-26570 branch 2 times, most recently from 1ced627 to 6198b22 Compare March 21, 2017 20:53
@MorrisJobke MorrisJobke dismissed stale reviews from nickvergessen and icewind1991 March 21, 2017 20:54

Fixed

@MorrisJobke
Copy link
Member Author

@rullzer @icewind1991 @nickvergessen All issues addressed - ready for review

@MorrisJobke
Copy link
Member Author

👍 from me on this

@icewind1991
Copy link
Member

I feel that it would be better to try and case non-string values to their proper types.

maybe try a json_decode and return original string if that fails.

That would also allow settings things like arrays trough ENV

*
* @param string $key key
* @param mixed $default = null default value
* @return mixed the value or $default
*/
public function getValue($key, $default = null) {
$envValue = getenv(self::ENV_PREFIX . $key);
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Should we cache this as well? I think it makes sense. otherwise we might call this hunderd times

Copy link
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

The only problem is: How do we know that we need to cache a ENV variable? I can move it below the cache statement, but then the ENV variable would not overwrite config.php values. I guess this is fine. Don't set the config option in config.php, but only in the ENV and it will be used from there.

Copy link
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Implemented like this.

Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Could also just add $this->envCache

Copy link
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

But this would not solve anything for empty env variables, because they are not cached then and the getenv would happen all the time for them.

if (isset($this->cache[$key])) {
return $this->cache[$key];
}

$envValue = getenv(self::ENV_PREFIX . $key);
if ($envValue !== false) {
$this->cache[$key] = $envValue;
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

The problem is, that now since the value is in cache, it will be written to the disk when any other config is changed/saved and therefor future changes on the env will not be reflected.
I'd just add it to a second cacheEnv array instead.

Copy link
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Anyway - this second cache array doesn't solve the actual problem: For all entries, that don't have a env variable set the getenv is still called. And I would say, that most env variables are not used at all -> still the overhead and we don't need to investigate into the cache way of doing it.

Copy link
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I removed this again. I would say that we just check the env variable without any caching.

phisch and others added 3 commits April 4, 2017 15:56
* added functionality to override config.php values with 'OC_' prefixed environment variables

* use getenv to read environment variables since apache does not set $_ENV variables, fixed test

Signed-off-by: Morris Jobke <hey@morrisjobke.de>
Signed-off-by: Morris Jobke <hey@morrisjobke.de>
Signed-off-by: Morris Jobke <hey@morrisjobke.de>
@MorrisJobke
Copy link
Member Author

@ChristophWurst @rullzer @nickvergessen @LukasReschke Ready for review

@nickvergessen
Copy link
Member

Should add to the docs that this is possible, but not recommended

Copy link
Member

@LukasReschke LukasReschke left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Not a big fan but well…

@TechupBusiness
Copy link

Great change thanks! Do you guys have a suggestion how we could resolve arrays? I'm struggling with setting trusted_domains... this happens when using docker and automatic installation feature. I can do a pull request but I would like to hear how you guys would solve it. Checking for a prefix like "array:" in the ENV and then separating the values by an unusual delimiter like {;} ?
@LukasReschke @MorrisJobke

@kesselb
Copy link
Contributor

kesselb commented Apr 24, 2019

Keep in mind that config options with "." does not work. You might use another approach for them. I'm not a fan of this at all (and neither the official vm image or docker image use it). It's at least one additonal function call for every system variable.

@TechupBusiness
Copy link

Unfortunately it's common nowadays to use container and set the variables (db credentials, etc.) via enviornment variables. Therefore I would really like to see a better support here in nextcloud.

@kesselb
Copy link
Contributor

kesselb commented Apr 25, 2019

I think its a better approach to enable getenv only for certain configuration variables like the docker image does: https://github.com/nextcloud/docker/tree/master/.config

@TechupBusiness
Copy link

TechupBusiness commented Oct 10, 2019

Keep in mind that config options with "." does not work. You might use another approach for them. I'm not a fan of this at all (and neither the official vm image or docker image use it). It's at least one additonal function call for every system variable.

Well you could simply read $_ENV ($_SERVER should usually also contain it) if you want avoid another function call. Even though I don't think that a function call to ENV variables would have a measurable performance impact.

I think its a better approach to enable getenv only for certain configuration variables like the docker image does: https://github.com/nextcloud/docker/tree/master/.config

I can't agree on that. Isn't a configuration of an application there to configure it for the environment? So probably most configurations (that are not accessible) are relevant.

@ChristophWurst
Copy link
Member

Please use https://help.nextcloud.com/ for discussion or open a new ticket for bug reports. Thanks.

@nextcloud nextcloud locked as resolved and limited conversation to collaborators Oct 10, 2019
Sign up for free to subscribe to this conversation on GitHub. Already have an account? Sign in.
Labels
3. to review Waiting for reviews enhancement
Projects
None yet
Development

Successfully merging this pull request may close these issues.

Read Env variables to configure Nextcloud
10 participants