Hi,
I’m asking for opinions and preferences.
There is no right or wrong.
Scenario:
I have a tool (server component, api only, no gui) that has a config file and no per-user adjustable things. The admin can change things, of course.
Now the tool gets plugins, where to configure them?
- All in one config file with plugins having a section for their things,
- plugins get their own config file.
- the main config points to a storage (database) with config options for everything, a kind of variant of 1.
- something else/better
Hoping for a civil discussion ;)
Cheers
Grumpy
Imo, plugins should have separate config files, with uniform, consistent formatting. Separating them ensures that plugins never modify primary configuration details, they can be updated independently, or deprecated without affecting future functionality. It also means you can take regular and reliable backups of each config.
I like how Symfony does it in PHP:
Config files have well known locations (e.g.,
<project root>/config
for main project, and<plugin root>/Resources/config
for plugins) for config files. The main config is loaded into memory, and then each plugin config is loaded and merged into the main config.This has several advantages:
- Each path allows for auto-discovery of new config files
- The config files can be in any file format that the app supports read (e.g.,
.ini
,.yaml
,. php
, etc) - The plugin config can overwrite anything in the main config
- Environment-specific configs can be loaded based on a
$ENV
variable (e.g.,dev
ortest
), or by ignoring files in your VCS
For Symfony, it is more complicated than that in that they also have mechanisms to define valid configuration values and their expected types, but that’s beyond the scope of your question.
Database configuration is an interesting choice. It certainly would help with scaling across multiple servers. Of course there is still a need for local configuration to access the database, but how often does that really change? But if you don’t need to scale more than two or three servers, it might be a bit of overkill IMO.
Depends on how “separate” the plugins are.
Single config file eases configuration of a service you consider one, and extend with plugins.
If the plugins reach a certain size, or are so distinct or separate, it may be preferable have separate configs.
A complicated plugin ecosystem (e.g. Jenkins) makes for a terrible use experience. It’s annoying to configure a bunch of config files. Managing dependencies can be a complete nightmare. these problems also complicate your ci/cd.
So I’ll offer a slightly different answer. I prefer a single file instead of splitting up the config. And I’ll use OpenTelemetry as an excellent example of why. the plugins are compiled right into the app binary. This offers a ton of advantages, including a great reason to merge all of your app configs in a single file.
This really only works well if you have a good app though.
Heh. Those of us with experience with these approaches know that there are plenty of wrong answers here, at least. The vote counts seem to be doing a pretty good job for anyone who wants a hint…
Annecdotaly, I just pushed a costly release to correct problems caused by my naive past use of approach 1.
Edit: a good rule of thumb for civil discussion is to use “I / me” statements, so:.
- I just had the all one file approach cause me a bunch of pain.
- I appreciate this approach where I find it. One config file per separately maintained code base is great.
- I actually do use a database to configure most of my network. I push my configuration decisions from my own database, into flat config files, with Ansible. Having the end product require another database complicates my efforts significantly. It’s not too bad if the product provides a command line option for each config change.
- I appreciate products that configure everything in one flat file per develeoper/maintainer, which is essentially option 2. This allows me to solve advanced use cases with my own configuration database, Ansible orchestration, and Jinja config file templates.