Please upgrade here. These earlier versions are no longer being updated and have security issues.
HackerOne users: Testing against this community violates our program's Terms of Service and will result in your bounty being denied.

config.php file overwritten

tsabattsabat New
edited November 2010 in Vanilla 2.0 - 2.8
Hi guys, I've posted about this problem before with no response. Hopefully somebody will have some advice for me today.

Ok, my config.php file is overwritten if I make manual changes to it. I'd like to learn the correct procedure to

1) make changes to config.php
2) see them reflected in my admin console.

also, could someone answer this question:

Is there a command somewhere to force a configuration reading from disk?

As it stands now, I can make a change to this file, but 90% of the time the new values are overwritten by older ones. Does this have something to do with caching?

EDIT: This seems to happen when I go to the Plugins folder. Maybe this helps?
Tagged:
«1

Comments

  • LincLinc Detroit Admin
    Manual editing should be possible as long as you're formatting your additions/changes correctly. What you're describing would be a bug. What changes are you trying to make that aren't sticking?
  • tsabattsabat New
    edited April 2011
    Here's the route I take do, say, install a plugin:

    1) start with my config file all nice-like.
    2) decide to install, for example, the sitemap plugin as described here http://vanillaforums.org/discussion/13331/sitemaps-0.9-released/#Item_3, so I copy the plugin files to the appropriate location
    3) open the forums to /path/to/vanilla
    4) switch to the dashboard
    5) make the change
    6) look at the result

    and that's where the funny-stuff happens. I'll see the change to the plugin worked as expected:

    $Configuration['EnabledPlugins']['Sitemaps'] = 'Sitemaps';

    But, the configuration I've customized

    $Configuration['Cache']['Filecache']['Store'] = '/wufoo_fs/forums/cachevanilla';
    $Configuration['HtmlPurifier']['Cache']['SerializerPath'] = '/wufoo_fs/forums/cachevanilla/HtmlPurifier';

    // Conversations
    $Configuration['Conversations']['Version'] = '2.0';

    // Database
    $Configuration['Database']['Name'] = 'forums_new';
    $Configuration['Database']['Host'] = Config::getDbHost();
    $Configuration['Database']['User'] = Config::getDbUser();
    $Configuration['Database']['Password'] = Config::getDbPassword();
    has been written back to the default state:

    // Cache
    $Configuration['Cache']['Filecache']['Store'] = '/wufoo_fs/forums/cachevanilla';

    // Conversations
    $Configuration['Conversations']['Version'] = '2.0';

    // Database
    $Configuration['Database']['Name'] = 'forums_new';
    $Configuration['Database']['Host'] = 'localhost:3306';
    $Configuration['Database']['User'] = 'root';
    $Configuration['Database']['Password'] = 'root';
    My current route is to just keep clicking around and restoring the file when it is overwritten. Eventually the settings stick, but there's no standard for when this happens. I try logging back out, back in, and sometimes the settings stay, sometimes they revert. I've never determined a pattern.

    Short of this bug being fixed, what I'd really like to find is a way to call a function which forces a read from disk. This way I could make the changes I want, then force the read.
  • LincLinc Detroit Admin
    edited November 2010
    As far as I know, you can't include functions in the config file. It must be static values (strings).

    I would bet the HtmlPurifier value is just being moved elsewhere to reorganize.
  • If you can't include functions in config, then nobody told Vanilla Forums :) Our configuration depends on these functions and they work. Without them there'd be no way to switch between dev, stage, and production. Is it possible that the values written back to the config.php are somehow read from the DB, since the code does not expect functions? If I know what to expect, I know how to plan.

    Let's forget about HTMLPurifier for now. I've moved back to htmlawd.
  • LincLinc Detroit Admin
    Vanilla will evaluate the the function when opening/reading the config file, but it will not preserve them when writing back to it. I haven't opened up the code to look, but I conjecture the config.php file is completely re-written upon save.
  • TimTim Operations Vanilla Staff
    @tsabat

    Lincoln is correct. The config file is valid PHP for a reason: we directly include() it when loading it. It causes the creation / modification of the $Configuration array. By nature of PHP, this resolves those function calls and their values are saved back to the file if changes are detected. The only time these settings will 'stick' is if you make them and then don't do anything that causes the config file to be written.

    Sitemaps DOES cause the config file to be updated each time a discussion is created. That's probably why you're seeing 'random' overwrites.

    I'm guessing that:
    $Configuration['Database']['Host'] = Config::getDbHost();
    $Configuration['Database']['User'] = Config::getDbUser();
    $Configuration['Database']['Password'] = Config::getDbPassword();

    is some kind of DB load balancing thing?

    Vanilla Forums COO [GitHub, Twitter, About.me]

  • TimTim Operations Vanilla Staff
    edited November 2010
    The one way you could get around this (but with other headaches) is to make your changes to config-defaults.php. Delete any references to those three settings from your actual config file.

    I haven't tested this, but I suspect that this might solve your problem.

    The downsides I alluded to earlier are the fact that we'll likely be pretty cavalier about overwriting the config-defaults.php file when updating, so your changes might be trashed.

    I've just talked to @Todd about this and we came up with another, albeit more complex option.

    The config options are loaded in the bootstrap.php file, quite near the top. What you can do is override those options later on in the bootstrap by creating an application for Garden. This application would be a shell, only there to provide a hook... a point where you can execute some code after the framework is mostly loaded, and write your own values (temporarily, in-memory only) to the config object. These changes could be added in the application's own bootstrap.php file (applications/loadbalancer/settings/bootstrap.php).

    I've written such an application for you. Download it and unzip it and put it in your applications/ folder, and then enable it in the dashboard under "Addons > Applications".

    Good luck

    Vanilla Forums COO [GitHub, Twitter, About.me]

  • LincLinc Detroit Admin
    @Tim You gonna upload that to addons? I think I've seen similar concerns from a number of people and that might be really useful for deployment processes as well.
  • tsabattsabat New
    edited April 2011
    Hi guys, sorry for the slow response. The dinner bell rang! :)

    Ok, what you've given me to work with is as close to perfect as I'm going to get. I never considered uploading it to addons, but I will do so after adding some documentation and an explanation for why this may be needed. I feel a bit guilty, since I wrote very little code to make it work, but if it will help someone else out, why not...

    For posterity, here's the reason why I'm going through so much trouble:

    In our environment, we lock the permission of all php files down to minimize the potential damage posed by rouge plugins, libraires, etc. This means no writing back to any directory for any reason by the PHP process. This also means that we can't edit config.php anywhere but on localhost. So, when we add new functionality (a plugin, application, theme, etc.) to VanillaForums we test it on localhost, then commit the config.php file to Dev, Stage, and Production.

    Along with the in-memory changes to the config using the application you got me started on, I also modified class.configuration.php to prevent errors when it tries to write to a the readonly config.php on the deployment servers like this:
    if (!is_writable($File)) {
    if (Config::jobServerName() == 'name=dev' || Config::jobServerName() == 'name=prod') {
    return TRUE;
    } else {
    throw new Exception(sprintf(T("Unable to write to config file '%s' when saving."),$File));
    }
    }
    If you have a better 'vanilla' way of doing this through the framework rather than hacking the class itself, I'd be happy to hear about it.

    I'm really thankful for all your help and I'll commit my 'config file' application later this week.
  • tsabattsabat New
    edited November 2010
    Hey guys, I posted the application to the addons. You can read about it here: http://vanillaforums.org/addon/readonlyconfig-application/. If you see something wrong feel free to fork/edit from https://github.com/wufoo/VanillaForums-Readonly-Config

    I can't thank you enough for all your advice. If you have a stronger way to override the save functionality in class.configuration.php, let me know.

    Edited cause the period broke the url
  • LincLinc Detroit Admin
    @tsabat Cool, "watching" the repo on GitHub now. Thanks.
  • TimTim Operations Vanilla Staff
    Everyone whose name is Timothy writes badass code.

    This is a Science Fact (tm).

    Vanilla Forums COO [GitHub, Twitter, About.me]

  • That's not just science, that nature.
  • JeffDunneJeffDunne New
    edited November 2010
    I took a different approach as I was having similar issues due to multiple domains pointing to the same Vanilla installation. The domain used to enter the site determines which theme, plugins and even applications are available (we have some custom applications)

    Initially to prevent the config.php being overwritten we simply made the file read-only on our production server. Unless something has changed in recent updates then Vanilla doesn't seem to have a problem with the file being read only.

    As our config.php became more complex, we chose to use a bootstrap.before.php to switch the PATH_CONF to point to a different sub-directory for each domain. It's working well and allows the sort of switching discussed here for our test server and our production sever without changing any code.

  • @JeffDunne, the code here (https://github.com/wufoo/VanillaForums-Readonly-Config) has a snippet I had to use because of the check

    !is_writable($File)

    around line 375 in class.configuration.php throws an error.
  • JeffDunneJeffDunne New
    edited November 2010
    Ah I see, that's been added from older releases.

    Is it really needed? Maybe that test should be a config-defaults.php setting?

    Glad I switched to the method I did or I'd have run into the same problem. For me, having a different config.php for each domain works fine but ultimately I'd like to make them read-only too. I'll have to have a look at your application.

  • Have at it. I think you'll be underwhelmed. There's not much to it. If you know of a way to override the Save() call in class.configuration without hacking the actual code, I'd love to see it.
  • Sorry, I meant if the check for writable in the core is really needed.

    Your application looks fine for the purpose and could probably include it's own config.php type file rather than the settings being coded in the application. This config file obviously would never be over-written and could include any setting you like.

    Unless there's a good reason for config.php to be writable, a config-defaults setting and test for it in class.configuration.php would be useful without the need for the application. Having said that, if the application read it's own config settings then it would achieve the same flexibility without the need for that sort of change.
  • Here's how I solved this problem:
    I created a file called dyn_config.php in the conf folder. The code in this script calculates the appropriate$Configuration values based on the server's name. For me this means selecting a different Database.Host and Garden.Cookie.Domain depending on the deployment stage, but the same logic can be extended to any$Configuration variable.

    Then, I created a bootstrap.early.php file (also in the conf folder) that loads dyn_config.php into the configuration in exactly the same manner as bootstrap.php loads config.php into the configuration. The end result is that the configuration is dynamically overwritten without changing config-default.php or any of the Vanilla core source code.

    dyn_config.php

    <?php
    // Custom develop/deploy logic
    $database_host = 'localhost';
    if (strpos($_SERVER['SERVER_NAME'],'localhost') !== -1){
        $database_host = '<MY DEV DATABASE HOST>.com';
    }
    
    $cookie_domain = substr($_SERVER['SERVER_NAME'], strpos($_SERVER['SERVER_NAME'], '.'));
    if (substr_count($cookie_domain, '.') === 1) {
        $cookie_domain = '.' . $_SERVER['SERVER_NAME'];
    }
    $Configuration['Database']['Host'] = $database_host;
    $Configuration['Garden']['Cookie']['Domain'] = $cookie_domain;
    

    bootstrap.early.php

    <?php
    Gdn::Config()->Load(PATH_CONF.'/dyn_config.php', 'Configuration', TRUE);
    
  • lvl99lvl99 New
    edited April 2017

    Thanks to @furlender's suggestion, I've implemented a slightly edited method here to support multiple different environments from the same codebase: https://gist.github.com/lvl99/ed62e91b550b33e1a62b4dbe2a6708f1

    // bootstrap.early.php
    <?php
    // Detect any specific server environment config setup to apply
    // I use a custom variable where you can set like so in Apache VirtualHost or in .htaccess:
    //   `SetEnv HTTP_SERVER_ENVIRONMENT "staging"
    // Default: development
    $server_environment = 'development';
    if ( ! empty( $_SERVER['HTTP_SERVER_ENVIRONMENT'] ) ) {
      $server_environment = $_SERVER['HTTP_SERVER_ENVIRONMENT'];
    }
    // Load the server environment config, only if a corresponding file exists
    $env_config_path = PATH_CONF . '/config-' . $server_environment . '.php';
    if ( ! empty( $_SERVER['HTTP_SERVER_ENVIRONMENT'] ) && file_exists( $env_config_path ) ) {
      Gdn::Config()->Load( $env_config_path, 'Configuration', TRUE );
    }
    
    // config-development.php
    <?php if (!defined('APPLICATION')) exit();
    // Database
    $Configuration['Database']['Name'] = 'example_forums_development';
    $Configuration['Database']['Host'] = 'localhost';
    $Configuration['Database']['User'] = 'root';
    $Configuration['Database']['Password'] = 'root';
    
Sign In or Register to comment.