I do not like declarative config management, declarative packaging, etc
configuration and software installation are transitive. you're doing something to something. the allure of declarative approaches is strong but at some point someone has to write the code that takes the declarations and applies them.
if the declarations provided are outside of the expectations of the person who wrote that code, there's a good chance that shit just blows up. this one problem creates more problems:
1. expecting all syntactically valid declarations to result in the expected configuration requires a shitload of validation code, none of which benefits the user directly
2. avoiding conflicting declarations by e.g. having dedicated per-task trees explodes the amount of space and processing power required to maintain a coherent (or at least consistent) system
3. the 'users' (whether that's the end user or the user consuming the declarative abstraction on behalf of the end user) need to know how the sausage is made in order to have any hope of fixing whatever goes wrong, obviating the point of the declarative layer
It reminds me of Java programming, where 'design patterns' became the abstraction layer, and the resulting class-inheritance nightmare means debugging hello world is a full-time job.
Stuff like Nix and Guix and Ansible work because an absolute shitload of people spend a horrific amount of time greasing the declarative wheels, and the end result is a massive complex tool whose inputs you have to learn just as much as you'd have had to learn whatever imperative tools you had before. The sheer amount of work involved creates a whole new set of problems that almost all declarative tools share:
1. the people who do the wheel-greasing need to eat, so money is sought; the people with all the money are horrible fucks and associating with them reduces the total population of people willing to put in that work. the result in a popular tool is strife and drama; the result in a nascent tool is extinction
2. people burn out, retire, buy goats, and otherwise lose interest in the wheelgreasing roles, which means new people have to step in, and given the massive workload they want to do things the most efficient way they know how. this leads to situations like popular tools being abandoned, replaced by some other subtly incompatible successor, or just straight up being rewritten so the ground shifts under the user. the result is more strife, more drama, more burnout
3. nobody gets something like this right on the first try, because it's a fantastic effort, and so as the Main Thing ages, it develops backwards-incompatible changes or else explodes in complexity to preserve backwards-compatibility. One road leads to strife and drama, the other leads to burnout. Both speed up the downstream treadmill and put more load on the wheelgreasers.
Obviously none of this stuff is unique to declarative syntax. So why am I harping about it? Because in the end, you're still left with a bunch of imperative code, but now the declarative frosting is a tremendous additional cognitive load and second source of problems everything already had, just to avoid having designed the imperative version correctly in the first place.
I guess it's like Bill Griffith wrote: "Going too far is half the pleasure of not getting anywhere."