Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Tracking issue for switching to system-wide activation #96

Open
1 of 4 tasks
LnL7 opened this issue Aug 25, 2018 · 19 comments · May be fixed by #1341
Open
1 of 4 tasks

Tracking issue for switching to system-wide activation #96

LnL7 opened this issue Aug 25, 2018 · 19 comments · May be fixed by #1341

Comments

@LnL7
Copy link
Owner

LnL7 commented Aug 25, 2018

  • use SUDO_USER/SUDO_UID instead of 2 separate scripts
  • move launchd.user.agents to users.users.<user>.launchAgents
  • move ~/Applications, doesn't make much sense to put this in a home directory Disable taking control of ~/Applications folder MkII #470
  • move user-level defaults to users.users.<user>.defaults
@yurrriq
Copy link
Contributor

yurrriq commented Aug 27, 2018

When you get a minute, can you briefly describe the plan for ~/Applications and defaults write? I'm quite curious, especially about the latter.

@LnL7
Copy link
Owner Author

LnL7 commented Aug 27, 2018

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.

@emilazy
Copy link
Collaborator

emilazy commented Jun 2, 2023

It would be convenient for me if this distinction went away, especially if #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 sudoing 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.

@emilazy
Copy link
Collaborator

emilazy commented Jun 20, 2023

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?

@mjm
Copy link

mjm commented Jun 26, 2023

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.

@mjm
Copy link

mjm commented Jun 26, 2023

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.

@emilazy
Copy link
Collaborator

emilazy commented Jun 27, 2023

+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.

@LnL7
Copy link
Owner Author

LnL7 commented Jul 10, 2023

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.

@emilazy
Copy link
Collaborator

emilazy commented Jul 10, 2023

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 :)

@hraban
Copy link
Contributor

hraban commented Aug 16, 2023

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 ("hraban/nix-darwin@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:

globallocal
userbrewdock position
rootnetworkingchsh

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?

@emilazy
Copy link
Collaborator

emilazy commented Aug 16, 2023

For Homebrew I added a homebrew.user option and the system activation script sudos 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.

@emilazy
Copy link
Collaborator

emilazy commented Aug 16, 2023

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 #726.

@hraban
Copy link
Contributor

hraban commented Aug 16, 2023

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.

@hraban
Copy link
Contributor

hraban commented Aug 22, 2023

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?

@emilazy
Copy link
Collaborator

emilazy commented Aug 22, 2023

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 #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.

@hraban
Copy link
Contributor

hraban commented Aug 27, 2023

@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?

This was referenced Jul 25, 2024
@Enzime Enzime changed the title simplify activation and get rid of $systemConfig/activate-user Tracking issue for switching to system-wide activation Dec 2, 2024
@josh1703658784
Copy link

Apologies if this isn't the correct place to post this. My issue is tangentially related but I can remove if it is an issue.

On my personal machine, only used by myself, I keep an admin user with sudo permissions. My normal day-to-day user (I just refer to as user) does not have sudo privileges. As a result I need to use my admin user when running nix-darwin rebuild.

This has been fine, until I started working with system.defaults which results in configuration being applied to admin, not user. My initial thought is for the admin user to authorize temporary (for the life of rebuild) sudo access to user but I couldn't find anything related to this idea.

Is there a known work-around for this use case? Any help is greatly appreciated.

@emilazy
Copy link
Collaborator

emilazy commented Feb 11, 2025

That’s actually a great motivating case for this that I hadn’t considered before! After I send out the PR for the first stage of the plan (should finally be due this week), you’ll be able to set system.primaryUser = "user"; in your configuration, and run sudo darwin-rebuild switch as admin. All the defaults, launchd agents, and so on will apply to user.

In the long run we’d like to be able to manage multiple users at once, but I think this should work for your immediate use case. In the meantime, you could consider using Home Manager, which has per‐user defaults functionality and can integrate with nix-darwin; we may move some functionality out of nix-darwin entirely and into Home Manager over time.

@josh1703658784
Copy link

josh1703658784 commented Feb 11, 2025

@emilazy Absolute legend! Thank you for your hard work. Did not realize how close this was to being resolved. I will keep an eye on this.

Since I cooked up a quick workaround I will document the general idea here. Nobody should copy and paste this blindly. It might very possibly be a Very Bad Idea (tm). I only kept the core idea to keep things terse and to not takeover the thread.

This script should be owned by whichever user has sudo access with 700 set on it. It is very unsafe to let anyone run this.

#!/usr/bin/env bash
readonly TARGET_USER='user'
readonly TARGET_FILEPATH='/private/etc/sudoers.d/temp-grant-nixos-rebuild'
readonly CONTENT="${TARGET_USER} ALL=(root) ALL"

function cleanup {
  sudo rm "${TARGET_FILEPATH}" "/tmp/${TARGET_FILENAME}.${NOW}"
}

trap cleanup EXIT
sudo sh -c "echo '${CONTENT}' > ${TARGET_FILEPATH}"
sudo -iu josh bash -c 'darwin-rebuild switch'

emilazy added a commit to emilazy/nix-darwin that referenced this issue Feb 16, 2025
@emilazy emilazy linked a pull request Feb 16, 2025 that will close this issue
emilazy added a commit to emilazy/nix-darwin that referenced this issue Feb 16, 2025
emilazy added a commit to emilazy/nix-darwin that referenced this issue Feb 19, 2025
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

Successfully merging a pull request may close this issue.

6 participants