3 ms·
> This is a fundamental problem that you cannot escape. You can escape it if you design for it. You can't escape it for exim.conf, but you can escape it for sy
by dale_glass 5y ago
> This is a fundamental problem that you cannot escape.
You can escape it if you design for it. You can't escape it for exim.conf, but you can escape it for systemd's own files, because it designed for that particular case, as explained below.
> No, it doesn't. You're describing doing the exact same thing as if you just ignore the config file diffs - keeping your own version and ignoring upstream. If the upstream changed something relevant, your forked config breaks.
No. The way it works is that stuff in /etc overrides stuff in /lib, line by line. Eg, in /etc you place something like this:
[Service]
Environment=FOO=bar
And that's all the file contains. This file adds an extra environment variable to the unit it overrides, and nothing more. If upstream has two variables now and adds a third in the next release, then it all still adds up correctly and without any interaction. There's also a special syntax for saying "Ignore whatever this says in the packaged original, I only want my version".
> I'm talking about the design of systemd, not the complexity of services.
One and the same. Systemd exists to run existing services. If an existing program is composed of 3 cooperating binaries and needed hacks where signals must be sent to the other processes, there's nothing for systemd to do but to implement the required functionality to support that.
> Your packages would drop a unit in say /etc/sysd/units/, and augment the toplevel config by dropping something in say /etc/sysd/graph.d
I'm not seeing the benefit then. What's the difference, keeping the config in two files vs one?
- mindslight 5y ago> The way it works is that stuff in /etc overrides stuff in /lib, line by line Oof, I did not know that. Likely because the last thing I'd want to do is split a simple service config between an even larger number of files. Also IME automerging just ends up creating a different type of upgrade error - it's more straightforward to just fork the whole config and take over responsibility. Software packages generally don't remove functionality, but default config files often change as maintainers get better ideas. > there's nothing for systemd to do but to implement the required functionality to support that Eleven types of dependencies. I know many of those could be implemented more generally. Perhaps not straightforwardly in an ini file, but that's what I mean about overall design. > What's the difference, keeping the config in two files vs one? A single service config is currently kept in at least 4 config files - the lib unit, the etc unit, the wants symlink, the wantedby symlink. Never mind all the extra .target files and their own duplications, plus the reverse injections. And this is for every single service. In my example, the distribution services would each only have one file, as their dependencies would be in an easily readable graph file. The answer to the expression problem is to add the appropriate hooks, not to just give up on factoring. The standard response from systemd advocates about all this complexity is to use bespoke tools to analyze its computed internal model. This would be reasonable if it didn't purport to be working with the configuration file model. Instead it's like a bait and switch of complexity. It would have been more honest to store the config in sqlite.
- dale_glass 5y ago> Oof, I did not know that. Likely because the last thing I'd want to do is split a simple service config between an even larger number of files. Also IME automerging just ends up creating a different type of upgrade error - it's more straightforward to just fork the whole config and take over responsibility. That's one reason why the systemd unit files are declarative -- things are unlikely to go wrong, because declarations are easy to override or add to without things going horribly wrong as a result. And 99% of the time, you're not doing this at all and just using the defaults. > Eleven types of dependencies. I know many of those could be implemented more generally. Most of those are kind of special cases you don't normally use, but that are needed for some obscure application or two. > A single service config is currently kept in at least 4 config files - the lib unit, the etc unit, the wants symlink, the wantedby symlink. Never mind all the extra .target files and their own duplications, plus the reverse injections. And this is for every single service No, not really. The lib unit exists always. That's what defines what the unit is, what it wants, etc. That's the only thing you ship for most things. The etc unit exists only if the administrator didn't like something about the system one and decided to modify something. It's not part of a package, the admin creates it. The symlinks are system configuration state -- that's what "systemctl enable" does. They're not part of the unit, they tell the system what to start on boot. The admin creates them when enabling a service. .target units are the equivalent of runlevels. They're a way to bring the whole system into a desired state easily. They're mostly a distro-level thing and are shipped with it. > The standard response from systemd advocates about all this complexity is to use bespoke tools to analyze its computed internal model. This would be reasonable if it didn't purport to be working with the configuration file model. Instead it's like a bait and switch of complexity. It would have been more honest to store the config in sqlite. I don't quite understand. You seem to be confusing the difference between what the service itself declares ("I need a network connection") and the system's configuration state ("Apache should be started on boot").
- mindslight 5y ago> That's one reason why the systemd unit files are declarative ... 99% of the time, you're not doing this at all You're pulling out the three dog defense here. Yes, unnecessary config complexity will make it so you have more conflicts. But simplification cannot eliminate the problem of merging. And we're explicitly talking about the times you need to interact with the system on this level. > No, not really. [explanation of 4 different files] Yes, really. You need to look at all of those to know a unit definition. And then you need to look at those for all the other units to see the dependency graph. Except nobody is capable of holding all that in their head. The closest programming analogy is Java, which effectively requires using an IDE to manage the complexity of splaying out structure in lots of tiny files. > You seem to be confusing the difference between what the service itself declares and the system's configuration state When you're the sysadmin writing/modifying a service, which is the only time you're touching unit files, the abstract distinction becomes moot - there is little point to installing a new unit without also enabling it. Meanwhile WantedBy etc can very much exist in unit files and not just the symlinks, and therefore to grok the complexity you need to take it into account. As I referenced, take a look at how NixOS uses systemd while encapsulating its filesystem mess. There's no concept of a disabled unit - you take it out of the config and the unit file disappears. There's no concept of overriding a config, since that's done at the level of system config. There's no concept of making mutable changes to the system state, since you just rebuild a whole new config. If you do fark up, make a loop, and your system doesn't boot, you don't diagnose where that happened but just boot the independent old configuration without the loop. Whereas on Debian you're suffering the mental overhead from these needless reinventions.