0

What I am doing now at the OS level:

Upon initialization, change to the user that needs the variable and export the variables then also specify setting them in the profile-- or in /etc/environment (Debian) in the case of root to account for persistence

I do a lot of this via "echo >>" or "sed" to the config files directly or into a directory the main config looks into for settings.

For me:

export MYVAR=foobar
echo "export MYVAR=foobar" >> /home/bradchesney79/.profile

The top one makes the environment variable available upon execution, but it will be gone when you log out. Putting the command in your .profile will create it for you when you log in.

sed -i s/export MYVAR=.*/export MYVAR=barfoo/g /home/bradchesney79/.profile 

For you:

sudo -u brianchesney80 export HISVAR=something 
sudo -u brianchesney80 echo "HISVAR=something" >> /home/brianchesney80/.profile

For everyone:

((Not fully certain how to export globally just yet))
sudo echo "OURVAR=fffoooooobbbaaarrr" >> /etc/environment

I don't like to reboot. But, I don't see any way around it to enable the environment variables set here for everyone.

So, want to see environment variables for a different user?

sudo -u www-data printenv PATH
sudo -u www-data env

A nice concise list provided by env not enough? Try:

set > /tmp/setOutput.tmp

Environment variables (Ubuntu)

Environment and Shell Variables

Making the environment variables available to PHP:

Worth noting is that the environment variables are not naturally available to services that are daemonized as they are not started traditionally as a child process that would inherit the parent's environment variables. Keep that in mind that this is a security barrier put in place for very good reason (that environment variables would be shared indiscriminately isn't necessarily a good thing.). My goal is to selectively make certain testable environment variable values available so my system behaves differently or with the right credentials set and available for the app in a variable-- all this at instantiation via a provisioning script and some of it persistent between reboots.

Apache

Example:

export PATH="/var/www:/var/www/html"

Neat snippet, you can check the validity of your envvars file with it.

sh -n /etc/apache2/envvars && echo Syntax OK || echo FAIL

There were some settings in /etc/apache2 (Debian) I think I could use in the virtualhost block...

Example:

SetEnv SPECIAL_PATH /foo/bin

The above in the server virtualhost configuration block will make a custom environment variable available via $_SERVER or similar convention somewhere as mentioned by TMR humoring me in the comments.

Apache httpd mod_env

Elsewhere in the httpd.conf file and similar or .htaccess you can set environment variables via rewrite rules.

RewriteRule someurl - [E=dbpass:swordfish]

Apache Rewrite abuse... If you gotta, you gotta I guess. I don't like .htaccess files in general though, not a fan of rewrite either.

NGINX

It appears you may be able to leverage a lua NGINX module to insert environment variables into the server. This other module also needed.

That being said, this being focused on PHP-- if you are using nginx with PHP-- maybe look at the PHP section below which may be a better solution.

env PATH;
http {
    ...
    server {
        location /path {
            set_by_lua $path 'return os.getenv("PATH")';
            ...
        }
    }
}

NGINX mailing list thread sparking the possibility

Blog post about using lua in full

PHP

get-cfg-var() will allow you to retrieve values set by the PHP project developers-- and arbitrary values you set. It is worth bearing caution to be careful naming these variables in the global scope this way and be sure to read the user contributed notes to be aware of some automagical mangling.

Example:

php.ini

environment_type=dev
environment_host=AWS

rando-script-whatever.php

get_cfg_var('environment_type') // returns 'dev'
get_cfg_var('environment_host') // returns 'AWS'

In a php-fpm pool configuration file the below will make a custom environment variable available via $_SERVER or similar convention somewhere as mentioned by TMR humoring me in the comments.

Example:

my-pool.conf

env[FOO] = bar

rando-script-whatever.php

echo $_SERVER['FOO']; // returns 'bar'

Summary

  • What: The end result I am seeking is that I can script standing up a server. Due to weaksauce I have an ansible wrapper and run more bash scripts than I would like to admit. Regardless, I want to set certain variables at the OS User level and have them propagate down to help me more or less 'anonymize' my web application codebase.

  • Why: The benefit is that a lot of particulars like RSA keys for authentication (yes, they fit in an environment variable), passwords, and other "secrets" stay out of the code base-- You've moved all these "secrets" to the provisioning scripts and obviously on to the running server employing low level access controls. nothing needs changed in the code a developer touches for the web application to run. Any configurations or deviations can be checked and handled. Write once, deploy everywhere with confidence everything is very similar if not the same. The provisioning script automagically puts the right DSN user, host, and password for connecting to your database in an environment variable; those PHP variables that refer to the environment variables just pick up the right values from the get go.

  • How: And here is my question. What steps and technology do you employ if you already do this?

Edits:

tl;dr - removed a controversial provisioning idea distilling to one succinct question topic

I have removed mention of detecting things about the host and provisioning the server based upon the findings. It has been strongly suggested that this way of provisioning a server may be a poor strategy and that provisioning tools are designed to declare the settings instead of the target host discovering things about itself upon instantiation and reacting appropriately. --And, most importantly, it is secondary to the task at hand. I want to know more about storing particulars that might change in environment variables which is awesome.

-Specifially mentioned by AnrDaemon was breaking the principle of least surprise.

BradChesney79
  • 67
  • 5
  • 12
  • 1
    There are a lot of different options, depending on the SAPI, orchestration tools, and other deeply-local decisions. I can give a few examples, but recommend you clarify the question a bit: if using the "Apache 2.0 Handler" SAPI, you can use Apache's SetEnv and SetEnvIf directives; if using the FPM SAPI, you can do `env[FOO] = bar` right in the pool config (see [Example #1](http://php.net/manual/en/install.fpm.configuration.php) in the FPM configuration docs.) – TML Nov 30 '16 at 15:48

3 Answers3

1

From the way the question asked, the only possible answer is "don't do that".

Website should not "try to figure out" anything, it should work.

It is a job of deployment script to setup environment and configure website according to it.

As @TML pointed out, there's lots of orchestration tools exist to do that. Saltstack, puppet, … name your choice.

AnrDaemon
  • 261
  • 2
  • 6
  • One thing mentioned outside of here specifically by AnrDaemon was that it breaks the principle of least surprise. [wikipedia - principle of least astonishment](https://en.wikipedia.org/wiki/Principle_of_least_astonishment) -- not word for word exact, but good enough for government work – BradChesney79 Nov 30 '16 at 16:11
  • If you don't know what he is talking about-- that is because of extreme editing of the above on my part. I removed the things being referenced to put the focus on the core topic. I did explain that I did this above as well. – BradChesney79 Dec 08 '16 at 18:01
1

For providing environment information to your application, what about something like dotenv?

phpdotenv reads from a configuration file to populate PHP's $_ENV and $_SERVER variables so you can get separate API keys or other configuration information per-server, outside of version control, without dealing with configuring the web server itself.

tbradbury
  • 11
  • 1
  • Yes. Very much so. Unfortunately, "phpdotenv is made for development environments, and generally should not be used in production. In production, the actual environment variables should be set so that there is no overhead of loading the .env file on each request. This can be achieved via an automated deployment process with tools like Vagrant, chef, or Puppet, or can be set manually". Which puts us at square one for production hosts... but, it looks like a nice and easy way to bootstrap a project and get something started faster. – BradChesney79 Nov 30 '16 at 20:16
0

For me, at the end of the day, I am hosting one site on a host using the AWS platform.

Most likely when I deploy new code or host configurations I am going to create a new server image, take my site off line for a minute or two, specify for my autoscaling group to use the new image, kill all of the old instances, and bring my site back on line as the first new instance fires back up. Granted, I'll have tested everything beforehand and have high confidence everything is going to work as planned. If not I'll kill the new instances and replace them with instances from the old image...

So, my plan for having my code use the correct configuration values (for db access credentials and IP addresses of supporting services as examples) via environment variables will be not as I had envisioned.

My provisioning script will set the environment variables for the other things that can use them. For PHP on this single site server I will be appending my own arbitrary key=value variable pairs as below.

get-cfg-var() will allow you to retrieve values set by the PHP project developers-- and arbitrary values you set. It is worth bearing caution to be careful naming these variables in the global scope this way and be sure to read the user contributed notes to be aware of some automagical mangling.

Example:

php.ini

environment_type=dev
environment_host=AWS

rando-script-whatever.php

get_cfg_var('environment_type') // returns 'dev'
get_cfg_var('environment_host') // returns 'AWS'

Thank you to everyone that took time to make me smarter and I've cut/pasted what I learned here to save the next schmuck some grief and time.

BradChesney79
  • 67
  • 5
  • 12