nix-darwin
nix-darwin copied to clipboard
simplify activation and get rid of $systemConfig/activate-user
- [ ] use SUDO_USER/SUDO_UID instead of 2 separate scripts
- [ ] deprecate
launchd.user.agents
, system agents run as the current user and actual per-user agents are not supported at the moment anyway - [ ] move ~/Applications, doesn't make much sense to put this in a home directory
- [ ] defaults write?
When you get a minute, can you briefly describe the plan for ~/Applications and defaults write
? I'm quite curious, especially about the latter.
I just listed everything here that runs as the login user. For applications it's easy, that can be moved to /Applications. As for defaults, I'm not sure if that works when running as root.
It would be convenient for me if this distinction went away, especially if https://github.com/LnL7/nix-darwin/pull/664 lands. I assume from the mention of $SUDO_USER
that the idea is to sudo
the whole activation script and then sudo
back to the normal user for anything that needs to be done per-user? That would be better for me than running the script as a user and sudo
ing for root (because I have no sudo
timeout), but I wonder if there are any other pitfalls. For example what about the org.nixos.activate-system
daemon, which presumably runs outside the context of any normal user session and won't have a $SUDO_USER
?
In general it kind of seems like nix-darwin doesn't know whether it wants to be single- or multi-user... If per-user settings were scoped appropriately and could be done for multiple accounts then this wouldn't be a consideration. But I bet macOS might make that complicated in other ways.
I'd be interested in taking a look at this if the question around user stuff was addressed. Should we just have configurations specify what their primary username is so the activation script can sudo
to them?
To me it me, as a user of both nix-darwin and home-manager, it makes sense to let nix-darwin handle system-level things and leave user-specific things to home-manager. I personally find it really confusing, for instance, that nix-darwin supports setting a bunch of defaults under system.defaults
and some of them apply to the whole system and others are only for one user (I guess the one running darwin-rebuild
).
home-manager already supports setting arbitrary user defaults for the user, setting up launch daemons and launch agents, and installing applications under ~/Applications. So nix-darwin can likely get away with dropping those kinds of things.
The big thing left is Homebrew, which can perhaps be solved with a setting for which user it should run as rather than assuming it's the one running darwin-rebuild.
I did forget that there are also several modules in nix-darwin around setting up launch agents, things like yabai or skhd. If nix-darwin removes support for launch agents, these modules would also need to move to home-manager.
+100 to @mjm. When I wrote my previous comments I didn't realize that Home Manager supports setting defaults
; I was torn between not wanting to use useful functionality and my desire for nix-darwin to have a coherent philosophy of managing the system, not the users. Now that it seems clear we can do this without losing significant functionality, it seems much better to me to let the more-active and better-resourced Home Manager handle per-user things and explicitly opt out of doing it ourselves.
As far as agents go, moving those services to HM is one option, but I believe we could also just install system-level agents, which will run as the current user for, I think, all desktop users. This leaves only Homebrew, which can grow a user
option (a valuable addition in its own right for people who want a multi-user or isolated Homebrew setup) and use sudo
to switch to it in a system-level activation script. And yes, putting applications in /Applications/Nix Apps
(or even just /Applications
directly?) makes much more sense.
We could then drop hacks like darwin-rebuild
caring what user it is run as or even supporting being run as non-root (it could sudo
itself to maintain backwards compatibility if desired), bringing us closer to NixOS and giving us a simple story of what nix-darwin is for and what tool should be used for which job. We would not need to use $SUDO_USER
at all.
I would be very happy if we agreed on this approach and am eager to implement it.
I think that's also kind of the summary I described here. This was sort of a brainump asking whether by dropping a few things nix-darwin could just not have any user activation at all. If user activation is needed it's a bit more annoying, I would like to avoid having to specify the admin user in the configuration if possible. Avoids issues or weird behaviour if that's not specified or you want to apply a prebuilt system.
I did forget that there are also several modules in nix-darwin around setting up launch agents, things like yabai or skhd. If nix-darwin removes support for launch agents, these modules would also need to move to home-manager.
There are still launch agents available which run for the currently logged in user, nix-darwin agents would just always be global for all users in that case. Alternatively the current per-user agents could stay but with the actual target user specified (similar to eg. per-user ssh keys). This last one might make .enable
options for services a bit annoying to implement however.
Thanks, it's good to know we're on the same page here; I agree that we shouldn't solve this by essentially staying single-user and just adding an option for that user. I'm not completely opposed to having user-specific options like defaults and agents under users.users.*
, but I think it tends towards reimplementing an inferior version of Home Manager (especially since they already have defaults and launchd agent support that seem equivalent or better to ours), and we'd do better to simply point people there. Our defaults support is a bit wonky too in terms of reverting removed options; obviously that's true of the system defaults we'd keep as well but it's lower-impact, less likely to fight with user-level software, and we could have more freedom to iterate on it.
I have a local implementation of this that rips out user activation entirely and ensures that the activation script doesn't depend on SUDO_USER
or similar in any way. It replaces all launchd.user.agents
with launchd.agents
(though some of those modules are entirely just convenience user agents for non-Darwin-specific programs so in the long run we could probably shift those over to Home Manager as well.). It does keep darwin-rebuild
compatible with older configurations that still have user activation so as to not break rollbacks. It needs a lot of polish and migration instructions as opposed to just throwing evaluation efforts, but it already works with my configuration and I'll continue to iterate on it. I think we should have release branches before pursuing a breaking change like that, though, so I'll open an issue about that soon :)
Thanks @emilazy for pointing me at this issue--I created a POC #763 for this yesterday without knowing about it, + a follow-up patch to use chsh
to set user shells based on users.users.<name>.shell
("https://github.com/hraban/nix-darwin/compare/per-user...hraban:nix-darwin:chsh").
I was also slightly confused by the activation vs user-activation split, although I ended up rationalizing it as "some tools don't like to be run as root, e.g. homebrew":
# /opt/homebrew/bin/brew
Error: Running Homebrew as root is extremely dangerous and no longer supported.
As Homebrew does not drop privileges on installation you would be giving all
build scripts full access to your system.
Where other parts of the activation script should obviously definitely be run as root. Then there are some settings which are "global" or "system-wide" (e.g. networking), and some settings which are "user-local", e.g. the login shell or the dock position. And of those local settings, some must be run as root (chsh
, lest it prompt for a password), and some as the user themselves (dock position).
Non-exhaustive:
global | local | |
---|---|---|
user | brew | dock position |
root | networking | chsh |
You are suggesting, if I read it right, for nix-darwin to entirely stop supporting some of its current duties. I agree that stuff like menu bar and dock position don't feel very nix-darwiny, and could be spun off as home-manager modules. But others do feel to me like they would belong here, in particular anything which has a NixOS parallel, e.g. users.users.<name>.shell
--does NixOS run chsh
on that user for you if you change that? If so, I'd assume nix-darwin to do the same. Homebrew, as well, feels like a nix-darwin responsibility, not home-manager, and since it doesn't like being run as root, there you are already immediately tied in to user-activation vs. activation split.
If I understand it right, this current issue is about a few things simultaneously:
- don't run as admin user but run as root, with carve-out for homebrew
- stop supporting some features (some user-local settings)
- support other, non-home-manager, per-user settings in the first place (chsh?)
These all seem orthogonal, so concretely I propose addressing them separately. I don't think the current activation vs user-activation split is necessarily a huge deal (homebrew does the same and it seems to work for people).
Moving settings to home-manager where they belong is a good idea regardless of what else is decided.
Supporting necessary per-user settings is also orthogonal, and a good feature to have which will end up looking the same no matter how the other two are completed (a script into which the root activation sudos once for every user).
What do you think?
For Homebrew I added a homebrew.user
option and the system activation script sudo
s to it; no separate activate-user
necessary. That's better anyway since people often want to isolate the Homebrew installation with an independent user account. I think that anything that depends on the user running darwin-rebuild
is broken and that anything that needs to run as non-root should have the user explicitly specified in the configuration somehow and should sudo
to that user from root; that's already how the Home Manager module works and of course stuff scoped under users.users
satisfies that property.
Running the two stages as separate scripts also brings its own host of problems: system-wide and per-user stuff cannot be interleaved, user activation runs before system activation(!), running only one of the scripts manually to recover from a broken darwin-rebuild
can break things (so we run etcChecks
twice just in case...), the lack of sudo
makes the execution contexts of the two scripts subtly different, darwin-rebuild
has to manage its own sudo
to root which causes multiple prompts if you have sudo timeout off, ...; it's just the wrong paradigm even when you do want to poke at user-level stuff.
I agree that supporting setting user shells seems like a good idea, if it can be made robust, and wouldn't consider that to be straying too much from "managing the system, not the users"; it's mostly stuff that touches $HOME
that makes me uneasy.
Another consideration here is that anything in activate-user
is something we can't possibly run in the activate-system
daemon; currently it doesn't run much, and there are some things that are probably impractical to run there anyway (e.g. Homebrew cask installation with installers that expect a GUI environment), but it would be nice to minimize the divergence as much as practical; see https://github.com/LnL7/nix-darwin/issues/726.
I'm totally on board with unifying the activation scripts, these are all good points. I think I come at it more from a "there are separate issues at play, so they can be solved separately", but overall: yes, agreed.
What can I do to help make sure some progress is made on this issue? I'm wary that the scope of the original ticket makes this hard to pass, and if that's the case I would advocate for breaking it up into smaller pieces and taking wins where we can get them. If there is a big master PR which fixes everything and is ready to merge, I'm happy with that too, of course.
What's the status, what is left to do, and if the issue has grown too large is Divide and Conquer an option?
So, my branch works and would be easy to update; it's really more removing code than anything else. The tricky part is handling the options that implicitly assume the current user, which are just ripped out wholesale in my branch: for instance, do we want to keep the user defaults code around (duplicating Home Manager functionality) and move them under users.users.*
, or do we want to remove them? In the latter case, I'd like to at least try and print out the corresponding Home Manager options for all the options the user has set. My plan was to start tackling that after I work on https://github.com/LnL7/nix-darwin/issues/727 (which makes all breaking changes harder), leaning towards pointing the user to Home Manager when in doubt. Of course, that part could be handled separately. But it's the bulk of the work, and removing the actual user activation stage after that is pretty trivial.
I'm currently busy in the middle of a move right now, but I'd like to get back to this and other things in a couple weeks time.
@LnL7 what are your thoughts? This currently feels like a textbook "perfect is the enemy of good"--can we merge something small, something that just allows us to e.g. mirror the user options across all users? @emilazy do you maybe have a minimal set of changes that could be forked off of your branch without pulling in the more substantial stuff, just so we can get some small wins while waiting for the bigger works?