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

nixos/direnv: init #192667

Closed
wants to merge 2 commits into from
Closed

nixos/direnv: init #192667

wants to merge 2 commits into from

Conversation

infinisil
Copy link
Member

Description of changes

nix-direnv is surprisingly annoying to configure correctly, due to it needing both system-wide adjustments (nix.conf changes), but also user-wide adjustments (telling direnv to load nix-direnv using ~/.config/direnv/direnvrc).

This module puts an end to that, allowing a direnv + nix-direnv installation with just

{
  programs.direnv.enable = true;
}

Currently this module comes with nix-direnv enabled by default and there's no way to turn it off. If there ever is a need to only enable direnv without nix-direnv we can do that in another PR. I don't need that myself.

Ping @zimbatm @Mic92 @bbenne10

Things done
  • Tested the module

This allows setting DIRENV_CONFIG to (nix-profile)/share/direnv and have
it find the nix-direnv script, while also allowing other direnv
integrations to coexist.

Old path kept for backwards compat.
nix-direnv is surprisingly annoying to configure correctly, due to it
needing both system-wide adjustments (`nix.conf` changes), but also
user-wide adjustments (telling direnv to load nix-direnv using
~/.config/direnv/direnvrc).

This module puts an end to that, allowing a direnv + nix-direnv
installation with just

  programs.direnv.enable = true;
@@ -26,6 +26,9 @@ stdenv.mkDerivation rec {
installPhase = ''
runHook preInstall
install -m500 -D direnvrc $out/share/nix-direnv/direnvrc

# Allows NixOS to set DIRENV_CONFIG to /run/current-system/sw/share/direnv and have direnv load this
Copy link
Member

Choose a reason for hiding this comment

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

In that case, the module will also have to handle user settings since DIRENV_CONFIG is also used to locate the direnv.toml.

Alternatively, it could make sense to change direnv so it also loads all the libraries in
share/direnv/lib/*.sh, following the XDG spec?

Copy link
Contributor

Choose a reason for hiding this comment

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

I think that, given that direnv already reads ${XDG_CONFIG_HOME:-$HOME/.config}/direnv/lib/*.sh it makes perfect sense for it to read the equivalent system directory, does it not?

Copy link
Member Author

Choose a reason for hiding this comment

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

Yeah I think so too, I quote the XDG Base Directory Specification:

$XDG_CONFIG_DIRS defines the preference-ordered set of base directories to search for configuration files in addition to the $XDG_CONFIG_HOME base directory. The directories in $XDG_CONFIG_DIRS should be seperated with a colon ':'.

If $XDG_CONFIG_DIRS is either not set or empty, a value equal to /etc/xdg should be used.

Copy link
Member Author

Choose a reason for hiding this comment

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

I created a direnv PR for this: direnv/direnv#990

@bbenne10
Copy link
Contributor

This generally looks okay.
I would like to see the addition of something like programs.direnv.initExtra that allows the user to specify the additional direnv snippets they're using. The way we're overriding DIRENV_CONFIG now makes that impossible (and so the additional snippet that I use that changes where caches are stored is not available at all with this configuration method).

I will say though that I'm not completely sure I see the need to introduce this.
Direnv is somewhat explicitly a user-level tool.
nix-direnv changes this user-level tool a bit to enable caching.
That caching is still useful even if they're occasionally garbage collected without the user knowing.

All of this to say that the system changes are good but not wholly necessary to eek out use from nix-direnv.
That being said: I support this change, but I don't think such a simple approach as we see here is as useful in the general sense as @infinisil maybe hopes it'll be?

"/share/direnv"
];

environment.sessionVariables.DIRENV_CONFIG = "/run/current-system/sw/share/direnv";
Copy link
Contributor

Choose a reason for hiding this comment

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

As mentioned: This disallows user customization entirely, I think.
Either we need a change to direnv to address this or we need a change here to give us the ability for the user to specify additional contents.

@@ -26,6 +26,9 @@ stdenv.mkDerivation rec {
installPhase = ''
runHook preInstall
install -m500 -D direnvrc $out/share/nix-direnv/direnvrc

# Allows NixOS to set DIRENV_CONFIG to /run/current-system/sw/share/direnv and have direnv load this
install -m500 -D direnvrc $out/share/direnv/lib/nix-direnv.sh
Copy link
Member

Choose a reason for hiding this comment

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

Could this not be a symlink?

@infinisil
Copy link
Member Author

This generally looks okay. I would like to see the addition of something like programs.direnv.initExtra that allows the user to specify the additional direnv snippets they're using. The way we're overriding DIRENV_CONFIG now makes that impossible (and so the additional snippet that I use that changes where caches are stored is not available at all with this configuration method).

Sounds like this will be addressed by #192667 (comment)

I will say though that I'm not completely sure I see the need to introduce this. Direnv is somewhat explicitly a user-level tool. nix-direnv changes this user-level tool a bit to enable caching. That caching is still useful even if they're occasionally garbage collected without the user knowing.

All of this to say that the system changes are good but not wholly necessary to eek out use from nix-direnv. That being said: I support this change, but I don't think such a simple approach as we see here is as useful in the general sense as @infinisil maybe hopes it'll be?

I had a bit of trouble understanding your concern, but I believe you're trying to say that the nix.settings are somewhat optional in this module, since they only affect GC relating to nix-direnv. And if we don't need to set nix.settings, the module can be entirely user-level, like a home-manager module (of which there already is one here).

Here's some arguments for why I think such a module is useful:

  • It is a main feature for nix-direnv to prevent shells from being garbage-collected, see the first couple sentences of its readme. Users of nix-direnv expect that feature to work
  • Currently if one wants to use direnv + nix-direnv and prevent GC, there is no easy way to do this in a single step. The NixOS installation instructions for nix-direnv require a manual step of editing ~/.direnvrc, while the home-manager install instructions require a separate step for adding the correct nix.conf settings.
  • Personal anecdote: When I installed my NixOS configuration onto a new machine, I was confused to find that my direnv shells were not cached with nix-direnv anymore. Turns out I manually added ~/.direnvrc (as described in the NixOS installation guide for nix-direnv), which I of course forgot to copy to my new machine (and also every separate user). Preventing such situations is a core selling-point of NixOS.
  • If a program can be configured both on a system-level (meaning for all users) and on a user-level (overriding the system-level config), then it makes sense for there to be a NixOS module, because one might want to provide a default for all users. This is also often seen with user-level systemd services provided by the system.

@bbenne10
Copy link
Contributor

I had a bit of trouble understanding your concern, but I believe you're trying to say that the nix.settings are somewhat optional in this module, since they only affect GC relating to nix-direnv. And if we don't need to set nix.settings, the module can be entirely user-level, like a home-manager module (of which there already is one here).

This is exactly it.

There are already about 5 ways to install nix-direnv.
This adds a 6th that must additionally be supported.
We already spend quite a bit of debugging time figuring out what version of nix-direnv someone has and how it was installed (as each installation procedure has different pitfalls), and this will (maybe) make this just a bit harder.

@infinisil
Copy link
Member Author

There are already about 5 ways to install nix-direnv. This adds a 6th that must additionally be supported. We already spend quite a bit of debugging time figuring out what version of nix-direnv someone has and how it was installed (as each installation procedure has different pitfalls), and this will (maybe) make this just a bit harder.

No this PR doesn't add another, it will allow you to replace the existing instructions for NixOS with much simpler ones, namely

{
  programs.direnv.enable = true;
}

@nixos-discourse
Copy link

This pull request has been mentioned on NixOS Discourse. There might be relevant details there:

https://discourse.nixos.org/t/tweag-nix-dev-update-37/22409/1

@mweinelt
Copy link
Member

Can we get a release notes entry please, so we nudge people to use this instead of the clumsy things they configured before.

@bbenne10
Copy link
Contributor

No this PR doesn't add another, it will allow you to replace the existing instructions for NixOS with much simpler ones, namely

{
  programs.direnv.enable = true;
}

I will have to describe the old behavior and the new behavior until acceptance of the new version is high enough. Likely well beyond the 22.11 release, as old installs may not be updated immediately.

Do know that I have said I support this change once appropriate changes are made to direnv as to allow the user to provide augmentations to the direnv stdlib. I am holding off approval until direnv/direnv#990 is approved, merged, released and updated in nixpkgs.

@infinisil
Copy link
Member Author

@bbenne10 Awesome that sounds great. You can also just keep everything as-is for now, the old way of installing it continues working the same way.

Comment on lines +8 to +10
Whether to enable direnv integration. Takes care of both installation and
setting up the sourcing of the shell. Additionally enables nix-direnv
integration. Note that you need to logout and login for this change to apply.
Copy link
Member

Choose a reason for hiding this comment

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

This should mention the nix setting changes.

@drupol
Copy link
Contributor

drupol commented Jun 2, 2023

What's the status of this useful PR ?

@bbenne10
Copy link
Contributor

bbenne10 commented Jun 3, 2023

direnv/direnv#990 is still open. I still haven't signed off on it. This PR would still artificially limit the ability of users to override direnv stdenv functions when using this installation mechanism.

that is to say: no - there's no change, as the referenced PR is stagnate right now too. If we can get that merged, I'm happy to assign here once the appropriate changes are made to allow extraConfig or such to propagate into the nix installed direnv / nix-direnv environments.

@Gerg-L Gerg-L mentioned this pull request Jul 4, 2023
1 task
@jian-lin
Copy link
Contributor

jian-lin commented Jul 5, 2023

FYI, #241528

@Artturin Artturin deleted the direnv-module branch August 28, 2023 00:13
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Projects
None yet
Development

Successfully merging this pull request may close these issues.

None yet

10 participants