Skip to content

feat(apply): Don't re-exec as root by default and add a flag for escalating to root locally#155

Merged
water-sucks merged 1 commit intonix-community:mainfrom
Sporif:apply-feat-no-re-exec-by-default
Jan 31, 2026
Merged

feat(apply): Don't re-exec as root by default and add a flag for escalating to root locally#155
water-sucks merged 1 commit intonix-community:mainfrom
Sporif:apply-feat-no-re-exec-by-default

Conversation

@Sporif
Copy link
Copy Markdown
Collaborator

@Sporif Sporif commented Jan 24, 2026

The new option --local-root provides behaviour equal to that of nixos-rebuild --sudo
by escalating certain operations as necessary:

  • Channel upgrades
  • Local Nix profile modifications
  • Local switch-to-configuration runs

By not re-executing by default we avoid bypassing a non-root user's eval cache
when running nixos apply after having already built the configuration.

The previous behaviour can be enabled with the new setting apply.reexec_as_root.

Additionally, channel upgrades now always run as root (see NixOS/nixpkgs@028893d7)

@coderabbitai
Copy link
Copy Markdown

coderabbitai bot commented Jan 24, 2026

Important

Review skipped

Auto reviews are disabled on this repository.

Please check the settings in the CodeRabbit UI or the .coderabbit.yaml file in this repository. To trigger a single review, invoke the @coderabbitai review command.

You can disable this status message by setting the reviews.review_status to false in the CodeRabbit configuration file.


Thanks for using CodeRabbit! It's free for OSS, and your support helps us grow. If you like it, consider giving us a shout-out.

❤️ Share

Comment @coderabbitai help to get the list of available commands and usage tips.

@Sporif Sporif force-pushed the apply-feat-no-re-exec-by-default branch 3 times, most recently from cb01dec to 240b929 Compare January 25, 2026 23:04
@water-sucks
Copy link
Copy Markdown
Collaborator

While I am on board with not re-executing as root, it does raise the question of whether or not we want re-execution at all by default. It has been a feature since the early days of nixos-cli, so it would be a breaking change, which I am not opposed to, but we should take the time to think this through a bit before merging a new flag for re-execution, since I would rather not make a flag for something that a user can do on their own very trivially with an external command.

Either the user would like for the non-root eval cache to be used at all times, and we should only elevate the functionality that requires it (i.e. a la the nixos-rebuild-ng --sudo flag, which would require some refactoring), or the user needs to run certain things as root directly (i.e. when using -p and the system profile directory needs to be created, which I do with os.MkdirAll and this is not really feasible to elevate in-process).

I personally think that we should go the nixos-rebuild-ng route and add an --as-root flag, which elevates necessary operations as needed, which would be:

  • Channel upgrades
  • Nix profile modifications
  • Local switch-to-configuration runs

And to simply fail with "permission denied" errors in the cases where these are not able to be ran, describing the error as such and the fact that adding --as-root or running as root directly can be specified to solve it. This would match nixos-rebuild-ng's UX and be more familiar for users that are switching away.

There is a slight problem with elevating as necessary, though. From what I understand, a user may have to type in their password at least two times: one for Nix profile modifications, and another for local switch-to-configuration. This seems unwieldy to me, but as far as I know there is no way around it.

In the case that a user does want the previous re-execution as root behavior, this can be controlled through a setting (i.e. apply.reexec_as_root), since I believe that some users may want to avoid all this in the first place.

@Sporif
Copy link
Copy Markdown
Collaborator Author

Sporif commented Jan 29, 2026

Though I'd prefer it was automatic, I'm fine with a flag for elevating to root, as I can just add it to the relevant aliases. I'm not sure about calling it --as-root, perhaps --local-root would be better as that sounds more consistent with --remote-root.

For the re-exec setting, I think it should also apply to nix channel upgrades (on top of local activations).

And as for the "permission denied" errors, should we handle that by failing if the uid is not root and --as-root has not been passed? nixos-rebuild-ng seems to do it that way, at least for channel upgrades.

There is a slight problem with elevating as necessary, though. From what I understand, a user may have to type in their password at least two times: one for Nix profile modifications, and another for local switch-to-configuration. This seems unwieldy to me, but as far as I know there is no way around it.

Unless I'm misunderstanding you, elevating as necessary is what this patch does, just without having to specify a flag. I'm using it now with sudo-rs and it doesn't ask for a password twice. It shouldn't happen with the default configuration of sudo and sudo-rs. As for run0 and pkexec, they should work with polkit 127 (which includes this fix) but they still ask for a password twice in my testing.

@water-sucks
Copy link
Copy Markdown
Collaborator

perhaps --local-root would be better as that sounds more consistent with --remote-root.

Agreed, let's call it that instead.

Unless I'm misunderstanding you, elevating as necessary is what this patch does, just without having to specify a flag.

Yes, which is the previous functionality as well. To clarify, I am talking about re-execution of the process in-place using root_command. This is what causes the bypass of the user-level Nix eval cache, and instead uses the root's Nix cache.

What I am trying to propose we do instead, is that we do not re-execute the whole process in place and instead pass sudo to relevant invocations based on if --local-root is passed, which you are already pretty much doing with the effective root stuff. Since re-execution happens so early on in the nixos apply sequence, the user-level cache would be bypassed anyway after an in-place re-execution and no benefit is realized other than having to not type in sudo or run0 or whatever.

I'm using it now with sudo-rs and it doesn't ask for a password twice.

Yes, due to the in-place re-execution this does not happen at the moment. I'm saying if we do remove that like I said, a user that passes --local-root would have to type in their password multiple times for each elevation.

Sorry if this has been confusing, I am talking about multiple things at once that you haven't necessarily touched in the PR. I just don't think a flag for in-place re-execution is the right thing to do, but I am willing to be convinced otherwise.

@Sporif Sporif force-pushed the apply-feat-no-re-exec-by-default branch from 240b929 to eca3eea Compare January 30, 2026 18:19
@Sporif
Copy link
Copy Markdown
Collaborator Author

Sporif commented Jan 30, 2026

What I am trying to propose we do instead, is that we do not re-execute the whole process in place and instead pass sudo to relevant invocations based on if --local-root is passed

Yes, I agree completely here.

Yes, due to the in-place re-execution this does not happen at the moment. I'm saying if we do remove that like I said, a user that passes --local-root would have to type in their password multiple times for each elevation.

See, this is the misunderstanding. Even without re-execution, passing --local-root does not cause this issue, at least with root_command set to sudo, since by default it caches the credentials using a time stamp on a per terminal session basis. Only if the commands take longer than the time stamp timeout will the user be required to re-enter their password. And that should never happen with nix profile modifications (it might happen with nix channel upgrades, I've never tried that).

Anyways, I've the added --local-root flag and apply.reexec_as_root setting, so you can test if it works the same for you.

@Sporif Sporif changed the title feat(apply): Don't re-exec as root by default and add a flag for the previous behaviour feat(apply): Don't re-exec as root by default and add a flag for escalating to root locally Jan 30, 2026
Copy link
Copy Markdown
Collaborator

@water-sucks water-sucks left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Looks great! Just one suggestion beforehand; when you mark as resolved, I'll merge.

…lating to root locally

The new option `--local-root` provides behaviour equal to that of `nixos-rebuild --sudo`
by escalating certain operations as necessary:
 - Channel upgrades
 - Local Nix profile modifications
 - Local switch-to-configuration runs

By not re-executing by default we avoid bypassing a non-root user's eval cache
when running `nixos apply` after having already built the configuration.

The previous behaviour can be enabled with the new setting `apply.reexec_as_root`.
@Sporif Sporif force-pushed the apply-feat-no-re-exec-by-default branch from eca3eea to 9be2dd9 Compare January 31, 2026 08:33
@water-sucks water-sucks merged commit a0a9f47 into nix-community:main Jan 31, 2026
2 checks passed
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 this pull request may close these issues.

2 participants