3
\$\begingroup\$

I've started looking at Heroku for application hosting and deployment and it appears that my configuration constants need to be stored in environment variables. I can do this in Heroku, but my application might also be deployed to shared servers and it may not be secure according to this question.

Basically I want the information to be read from a configuration file if it is present, otherwise try to read from the environment variables (in the case of Heroku).

  1. Is this the best way of doing it?
  2. Are there security implications?

settings.php

<?php

define('DB_URL', 'mysql://root:password@localhost:3306/database');
define('APP_URL', '[::1]');
define('APP_URL_PATH', '/path/to/application');
define('FOO', 'more things');

config.php

<?php

if (!is_file('settings.php')) {
    require 'settings.php';
    return;
}

define('DB_URL', getenv('DB_URL'));
define('APP_URL', getenv('APP_URL'));
define('APP_URL_PATH', getenv('APP_URL_PATH'));
define('FOO', getenv('FOO'));

index.php (and other application files)

<?php

require 'config.php';

$app = new \Slim\Slim\App();

// code

$app->run();
\$\endgroup\$
1
\$\begingroup\$

I'm wondering if settings.php is in the same directory tree where you have other scripts like index.php served by the web server. I don't know if this is possible on Heroku, but I recommend to move files that should never be served by the web server outside of the document root.

One time, I had a web server malfunction: the well-tuned configuration file got replaced with something primitive, and php disabled, where visiting settings.php in a browser would simply display the contents of the file without running through the PHP interpreter. Sure, this seems unlikely to happen, but by moving sensitive files outside the document root, you can effectively safeguard against such or similar misconfiguration issues. I also find it good organization to separate public files from internal details. So my PHP projects all have a public/ directory inside, containing practically views only, the model is elsewhere, cleanly separated.

About this:

define('DB_URL', 'mysql://root:password@localhost:3306/database');

Even if it's a dedicated and isolated database for your project only, I don't see why would you ever use the root account. Create a dedicated user with carefully selected grants instead.

Needless to say, settings.php should have restrictive permissions in the filesystem.

\$\endgroup\$
  • \$\begingroup\$ The root user is only used in the local development environment. There is a proper user configured with the appropriate permissions on the actual deployment environments. And I believe settings.php has permissions of 744. \$\endgroup\$ – rink.attendant.6 Nov 23 '14 at 19:25
  • 1
    \$\begingroup\$ settings.php doesn't need to be executable. And it may depend on your webserver setup, but most probably it shouldn't need to be readable by group and other. So 600 permission should be enough. It's a security sensitive file, so it's good to tune the permissions to the minimum necessary. \$\endgroup\$ – janos Nov 23 '14 at 22:17
  • \$\begingroup\$ 9 months later and my proposal to move to envvars finally got accepted… this library really helps for dev. \$\endgroup\$ – rink.attendant.6 Aug 16 '15 at 3:37
0
\$\begingroup\$

I would perhaps use a JSON string for configuration purposes.

The JSON might look like this:

{
    "DB_URL":"mysql://root:password@localhost:3306/database",
    "APP_URL", "[::1]",
    ...
}

And reading it into constants might look like this:

$config_file = '/path/to/config.json';
if(is_file($config_file) && is_readable($config_file) {
    // get file system config   
    $configs = json_decode(file_get_contents($config_file), true);
} else if(!empty(getenv('heroku_config')) {
    // use Heroku config value
    $configs = json_decode(getenv('heroku_config'), true);
} else {
    throw new Exception('No config found!');
}

// load configs into constants
foreach($configs as $key => $value) {
    define($key, $value);
} 

This leave a very flexible configuration model where you can easily change configs, without needing to change your code at all.

\$\endgroup\$
  • \$\begingroup\$ Welcome to Code Review! .json files are often directly readable on webservers, so that you would get the actual content of it. The positive thing about a .php config file is that there's no way for a visitor to see the actual content of that php file. I would personally not recommend a JSON configuration for PHP. \$\endgroup\$ – Simon Forsberg Jan 19 '15 at 21:16
  • \$\begingroup\$ @SimonAndréForsberg You obviously would not put it in a web directory, nor would you want to even for a PHP file. \$\endgroup\$ – Mike Brant Jan 19 '15 at 22:56
  • 1
    \$\begingroup\$ Sure, that would help. But what is really the advantage of modifying a JSON file instead of a PHP file? \$\endgroup\$ – Simon Forsberg Jan 19 '15 at 22:59
  • 1
    \$\begingroup\$ What is easier about changing a JSON file compared to a settings.php file with define statements as in the question? \$\endgroup\$ – janos Jan 19 '15 at 23:19
  • \$\begingroup\$ @SimonAndréForsberg This would allow you to change your configuration, without having to change your code. \$\endgroup\$ – Mike Brant Jan 20 '15 at 14:43

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service, privacy policy and cookie policy

Not the answer you're looking for? Browse other questions tagged or ask your own question.