12 ms·
Programs should not only report where the configuration files are located, but also report how configuration options contained therein are read in: Some progra
by Eduard 3y ago
Programs should not only report where the configuration files are located, but also report how configuration options contained therein are read in:
Some programs use a "last occurrence wins" approach, while other programs (e.g. sshd) use a "first occurrence wins" approach.
Buried in https://man.freebsd.org/cgi/man.cgi?sshd_config(5) https://man.freebsd.org/cgi/man.cgi?sshd_config(5) and awkwardly expressed:
"Unless noted otherwise, for each keyword, the first obtained value will be used."
That's why e.g. Debian's /etc/ssh/sshd_config ( https://salsa.debian.org/ssh-team/openssh/-/blob/debian/1%259.3p1-1/sshd_config?ref_type=tags#L13 https://salsa.debian.org/ssh-team/openssh/-/blob/debian/1%25... ) starts with
Include /etc/ssh/sshd_config.d/*.conf
, so that custom configurations in that directory win over the distribution-provided defaults set up after this Include directive inside /etc/ssh/sshd_config.
- Eduard 3y agoAlso: processes / running programs should provide a straightforward way to show their configuration. While "sshd -T" shows the effective configuration from all configuration file parsing, there is no straightforward way to see the configuration of the/a currently running sshd process. This has footgun potential, as someone could think their sshd is secured and hardened by checking with "sshd -T", while the actually running sshd process still uses old configurations. Apache also makes it needlessly hard to find out its effective (and active / currently running) configuration. I don't know of any better way then awkwardly using mod_info ( https://httpd.apache.org/docs/2.4/mod/mod_info.html https://httpd.apache.org/docs/2.4/mod/mod_info.html ) to get such insights.
- mike_hock 3y agoNot sure I get the reasoning here. That requires you to actually go and proofread the configuration of each and every running process, at which point it's easier to just verify the effective configuration on disk and restart the service. SSH is a special case because it leaves active sessions alive when it restarts, but that doesn't generalize to other daemons. Just restart if in doubt.
- Shrezzing 3y agoIt's a little bit away from the domain of config files, but I think CSS is the most graceful example of handling this as a generalised problem. Style configurations cascade, and the last one read is the one that gets applied. There are overrides to that flow, but you have to very overtly add a piece of syntax to the overriding line like `!important`. Two overlapping overrides revert back to the "last read" approach. The approach is so fundamental to CSS that the entire language is named after it, so there's no ambiguity or forwards compatibility concerns in this regard whatsoever.
- masklinn 3y agoYou might want to read on specificity because it’s a huge spanner in your assumptions.
- lioeters 3y ago> Specificity is the algorithm used by browsers to determine the CSS declaration that is the most relevant to an element, which in turn, determines the property value to apply to the element. The specificity algorithm calculates the weight of a CSS selector to determine which rule from competing CSS declarations gets applied to an element. https://developer.mozilla.org/en-US/docs/Web/CSS/Specificity#how_is_specificity_calculated https://developer.mozilla.org/en-US/docs/Web/CSS/Specificity...
- lavela 3y agoThe rules of CSS specificity are a bit more involved than '!important' or not, and I frequently see beginners trip there, but apart from that I agree that the CSS rule set might be worth incorporating.
- yard2010 3y agoFun trick to use if you use a css post processing (less, sass, etc.) is "&&&", it will resolve to a very specific rule which overwrites the other rules
- blowski 3y agoI’m sure you know this, but for readers who don’t, it’s much more complex than “last defined wins with a few override options”. Based on “specificity”, rules based on the selector used. Some examples: 1. #mydiv overrides .mydiv - IDs are more specific than classes 2. .outerdiv .innerdiv overrides .innerdiv - nested selectors are more specific 3. .mydiv overrides div - classes are more specific than elements And a lot of other rules. I can’t imagine I’d want this level of complexity in config files.
- Eduard 3y agoAnd yet another gotcha with configuration file loading: Over-elaborated hierarchies where configuration files may reside, and their precedence schemes. E.g. from systemd.unit manpage ( https://www.freedesktop.org/software/systemd/man/systemd.unit.html https://www.freedesktop.org/software/systemd/man/systemd.uni... ): >... > In addition to /etc/systemd/system, the drop-in ".d/" directories for system services can be placed in /usr/lib/systemd/system or /run/systemd/system directories. Drop-in files in /etc/ take precedence over those in /run/ which in turn take precedence over those in /usr/lib/. Drop-in files under any of these directories take precedence over unit files wherever located. Multiple drop-in files with different names are applied in lexicographic order, regardless of which of the directories they reside in. > ... And this is just an excerpt which doesn't cover the details. Read the manpage for all the hilarity.
- nick__m 3y agosystemd configuration lookups are lightweights and straightforward compared to ansible variables lookups rules : -- Understanding variable precedence Ansible does apply variable precedence, and you might have a use for it. Here is the order of precedence from least to greatest (the last listed variables override all other variables): 1 command line values (for example, -u my_user, these are not variables) 2 role defaults (defined in role/defaults/main.yml) 1 3 inventory file or script group vars 2 4 inventory group_vars/all 3 5 playbook group_vars/all 3 6 inventory group_vars/* 3 7 playbook group_vars/* 3 8 inventory file or script host vars 2 9 inventory host_vars/* 3 10 playbook host_vars/* 3 11 host facts / cached set_facts 4 12 play vars 13 play vars_prompt 14 play vars_files 15 role vars (defined in role/vars/main.yml) 16 block vars (only for tasks in block) 17 task vars (only for the task) 18 include_vars 19 set_facts / registered vars 20 role (and include_role) params 21 include params 22 extra vars (for example, -e "user=my_user")(always win precedence) ‐‐ that is a RedHat-isim
- oblio 3y agoMeh, it's not Red Hat. Configuration management tools do this. Chef is similar.
- micheles 3y agoThis is good advice and my own software is following it: $ oq info cfg Looking at the following paths (the last wins) /opt/openquake/oq-engine/openquake/engine/openquake.cfg /opt/openquake/venv/openquake.cfg However, I do not think there is any standard API to follow, I used "info cfg" but many alternatives were possible. So sysadmins have to explore to find out which is the introspection command to give. Not ideal, but I don't think there is a solution.
- kataklasm 3y agoI would look for something like this in the help output, i.e. --help or -h. And of course the manpage if you do supply one.
- cesarb 3y agoAnother good place for that is the --version output, if your --version is one of those verbose multi-line ones (instead of a basic single-line output).
- vishnugupta 3y agoWhile at it I’ve made it a practice to expose an internal endpoint for every service to output its config. It has saved me on numerous occasions to catch config related bugs.
- simply_seal 3y agoCould you explain a little more? I am not sure what exactly you mean by "exposing an internal endpoint" - do you mean that as a secured API endpoint which you can call? Isn't that hard to secure?
- delecti 3y agoDepending on your environment, endpoints might not default to exposed. As an example where I work, we have to explicitly enumerate endpoints to expose (potentially including wildcards, like admin/*), and anything else is only accessible with direct access to the pod.
- shrimpx 3y agoPresumably you can access it while on a secure VPN but not publicly. You can do this by serving the config route on an internal port.
- vishnugupta 3y agoIndeed, that’s exactly how my team did it.
- twic 3y agoThis is not an endorsement, but Spring Boot has this built in (but not enabled by default): https://docs.spring.io/spring-boot/docs/current/reference/html/actuator.html#actuator.endpoints https://docs.spring.io/spring-boot/docs/current/reference/ht... I have been leaning towards a different approach. Rather than reading multiple config sources at runtime, read them at build time, and emit a single config file with everything fully resolved. Put that on the filesystem, and have the app read it. You have an easy canonical reference for the configuration, with no need to expose anything. The lifecycle of the config doesn't have to match that off the app binary, so it could (and probably should) have a separate build and release process.
- cesaref 3y agoAgreed, logging in config retrieval code should log all this stuff, requests, where they are filled from, that sort of thing. The problems with this approach when it's enabled is that log aggregators (e.g splunk) can end up including stuff like passwords which shouldn't be visible to the group able to view those logs, so some care is needed.
- TeMPOraL 3y agoLogging keys only should be sufficient for this.
- usrusr 3y agoI'd rather have some config reserialization capability with provenance (perhaps as an opt-in). A good config reserialization can make itself useful in so many situations, if it has the right features. Like pointing out key-value pairs that don't have any effect, or simply writing out some documentation. Logging has its merits, like discoverability when you stare at it without suspecting configuration to be the culprit, but I believe that there can and should be more.
- amelius 3y agoAlso, they should report where logs are written.
- preseinger 3y agologs always go to stdout/stderr hopefully!
- rapind 3y agoI would prefer a convention… but first wins is backwards IMO. It really sucks when a bad convention gets adopted, like this first wins, or spaces instead of tabs. ;)
- AlecSchueler 3y agoFirst/last is ambiguous anyway and implementation dependant.
- nebulous1 3y agoHow so?
- jonhohle 3y agoIf there are multiple files in a wildcard pattern, what order are they resolved? I know for classpath loading, for example, it’s in directory order, which is file system dependent, and often based on the order the files were written to the directory and/or the size of the directory inode. Lots of fun figuring out why the wrong version of a class is consistently loaded on one or two servers out of twenty. (Always check your classpaths for duplicates kids.)
- cesarb 3y ago> Always check your classpaths for duplicates kids. I recently discovered extra-enforcer-rules which can help with that, as long as your classpath comes from Maven dependencies.
- ycombobreaker 3y agoI've always seen this solved by sorting (lexicographical order of bytes, originally). First two characters were digits, for all files within a wildcard directory.
- justsomehnguy 3y ago> If there are multiple files in a wildcard pattern, what order are they resolved If you don't care (eg [0]) then do nothing and let the user bang it's head and reinvent the wheel. If you care - just sort it and mark it as 'platform dependent' or somehow. Nobody really cares for the exact rules and a simple \d\d\-\w+\.conf pattern for the filenames is more than enough in 99% of cases. [0] https://www.zabbix.com/documentation/6.0/en/manual/appendix/config/special_notes_include https://www.zabbix.com/documentation/6.0/en/manual/appendix/...
- jonhohle 3y agoAmazon had a hierarchical configuration system for loading config that could override other config (or add to it, depending on the implementation). The Java framework would provide an endpoint to show you the final resolved config along with which file and line that value came from. Very helpful when trying to figure out why config was different than expected. At least the inspector in Safari (and maybe other WebKit browsers) does something similar for CSS. I’m all for it. It’s a pain when writing config systems (no longer just key/value, but key+value+meta), but very helpful. It can be a pain for things like JSON where libraries don’t give you that type of diagnostic information easily, however.
- offbyone 3y agoI had the distinct pleasure (?) of owning the C++, Python, and Java implementations of that config for a while and ... yeah, it had some positives, but the fact that it had two orthogonal hierarchies of configuration in addition to implementation-specific feature gaps and nuances made it something of a nightmare in practice.
- bayindirh 3y agoIf you pass -verbose switch to any of my programs you'll definitely see a line similar to this: verbose: Configuration file found at $PATH. There are a couple of places I look for my config files: /etc, ~/.config and "./conf", at that order. The last one accelerates testing a great deal. And every configuration that overrides the built-in defaults are reported one by one. Also, I started to detail how configuration file works in README.md file, under its section now. Lastly, I decided to fix all of my tools to work on same specs from now on, regardless of the programming language they're written in: 1. Use TOML, and TOML only. 2. Config file overrides the defaults, Command line flags overrides the configuration file.
- cperciva 3y agoConfig file overrides the defaults, Command line flags overrides the configuration file. Don't forget "user configuration file overrides system configuration file (but is overridden by command line)". In tarsnap the priority (lowest wins) is: 0: Command line 1: ~/.tarsnaprc 2: /etc/tarsnap.conf (may be in a different system etc depending on platform standards) 3: tarsnap defaults.
- spc476 3y agoWhere would configuration options via environment variables fit in? I can see between 0 and 1, or 1 and 2, but can't quite decide which is better.
- cperciva 3y agoNot relevant to tarsnap (and in general something I would be very careful about adding since people often don't realize what's in their environment) but I would say that command line options take priority over the environment and the environment takes priority over all configuration files.
- CoolCold 3y ago+1 on both points - support for env and handling env priority
- __MatrixMan__ 3y agoI prefer the "setting it twice to different values is an error" mode, which isn't especially common.
- m4lvin 3y agoNice example, which opened a small rabbit hole for me: what does "first occurrence wins" mean for options that are meant to be used multiple times, such as "Port" in sshd_config. The man page only says "Multiple options of this type are permitted.", but now I wonder what happens when I put my own Port into /etc/ssh/sshd_config.d/whatever.conf but leave "Port 22" in sshd_config? Or is the (new since bookworm) default sshd_config commenting it out for this reason? More generally, for multi-options do we maybe want "first file wins"?
- florbo 3y agoReading in general to more specific configuration directories in order and using the last value read makes the most sense to me. This is usually how I write my own applications. Anyway, I thoroughly document the order and precedence, but the suggestion from Chris' blog to report more detail about the process is a good one.
- hinkley 3y agoAnt also had first writer wins. I tried to explain this so, so many times to so many people, and only rarely did it stick. On that project I spent way too much time fixing build errors, and ended up rearranging things to make the behavior more obvious rather than less, because without it people would fool themselves into thinking they had it right, because sometimes it would appear to work. And the thing with developers is that they make lousy scientists. If they want something to work, they’ll take any information that supports that theory and run straight to the repository with it. The trick is not to fool yourself, and you’re the easiest person to fool.
- doctorpangloss 3y agoIt's crazy that a year from now, no one is ever going to be thinking about this garbage ever again. By then, enough programmers will have discovered how insanely good GPT4 is at doing software configuration, and in the absence of the right answer, reading these verbose docs to finally just tell you what to do.
- preseinger 3y agolol
- bredren 3y agoIt would also help if an active process said if it was running using the current config. For example, if a change has been introduced to a config file, but the process has not been restarted to incorporate those changes, this should be conveniently mentioned.
- AtlasBarfed 3y agoWhen discussing, let's keep in mind what really mature configuration can look like: https://docs.spring.io/spring-boot/docs/2.1.13.RELEASE/reference/html/boot-features-external-config.html https://docs.spring.io/spring-boot/docs/2.1.13.RELEASE/refer... This is a big ridiculous, but the fact is that the entire order of processing there is a result of practical need evolved over likely thousands of organizations. There are unit testing concerns, dev/test/stage/prod concerns, CLI args, OS vars, config files, IDE vs non-ide concerns, and more. And even some references to databases (if you squint and see JNDI as a database). So yeah, finding out where property value X was set can be a bit maddening oftentimes. "Configuration" is an afterthought in most languages and frameworks in initial iterations. So bespoke / one-off solutions will explode early on. As the original complaint details, "configuration" isn't just a simple property file. It gets complex pretty quickly, and a good configuration subsystem would be nice: - supports most of the concerns above - provides a means for logging the final config value set and WHERE IT SOURCED FROM But... oh wait, config values aren't just key-value. Wait until you get to trees of values or other more complicated config. Then value overlaying gets pretty hard, and resolution code gets complicated too. Think of infrastructure as code frameworks. The configuration is insanely deep and complicated. Many complicated systems have "configuration languages", and they are probably Turing Complete. And once your configuration system is complicated enough ... your configuration system kind of implicitly needs ITS OWN configuration system. So maybe the first config layer is actually a bootstrap for loading all the configuration info. And.... then you have config values you need to secure. Hooo boy, now you have all the complexity of high security systems interfaces: authentication and authorization, decryption and hashing. And invariably there are binary blobs encoded in text friendliness. It gets crazy. Fast. BUT THE AMOUNT OF SIMILARITY IS NUTS. NUTS. This is begging for a common approach or standard or library.
- patmcc 3y ago>>>Some programs use a "last occurrence wins" approach, while other programs (e.g. sshd) use a "first occurrence wins" approach. A bunch of applications at my job use a config-loading library that will fail on startup if the same option is set to two different value (on different lines). It's certainly frustrating at times...but it's also prevented a huge amount of ambiguity.
- fbdab103 3y agoI am incredibly torn on if this is brilliant or would have me cursing the developer's name.
- wizofaus 3y agoThat would actually be my preference TBH. Failing quickly at startup is usually far better than unpredictable behaviour later on, particularly if it's a long-running service. Though I've always thought that the behaviour of tools when launched interactively by the user, vs launched via an automated background process should probably be different - it may well be that if a user/administrator isn't aware it failed on machine startup the consequences of it not being running at all are worse than an ambiguous configuration setting.
- jrochkind1 3y agoThere should be an option to report where any currently active non-default configuration settings actually came from, individually. (including if that's shell environment vars, etc). I forget what tool I use regularly that actually does this. Is it git?