Skip to content

Instantly share code, notes, and snippets.

@lheckemann lheckemann/0-readme.md
Last active Apr 10, 2020

Embed
What would you like to do?
Expression for a buildEnv-based declarative user environment.

Expression for a buildEnv-based declarative user environment

This is one way of managing your user profile declaratively.

Alternatives include:

  • an attrset-based nix-env-based environment, installed using nix-env -ir rather than nix-env --set. LnL has an overlay which shows a way of doing this.
  • home-manager, which provides NixOS-like config for your $HOME

Note that this is incompatible with regular imperative use of nix-env, e.g. nix-env -iA nixpkgs.hello. It has the advantage of allowing the installation of multiple outputs of the same package much better than nix-env's builtin profile builder does.

I personally currently use the nix-env -ir approach like LnL, but without an overlay.

Feature comparison:

Prevents imperative use of nix-env (nix-env -iA nixpkgs.hello)

  • buildEnv ✔️
    • buildEnv takes responsibility for the entire user profile, meaning that nix's builtin env builder cannot modify it
  • attrset
    • the attrset approach leaves building the profile up to nix-env, which allows adding packages ad-hoc (though they will be removed on the next profile build) using nix-env -i
  • home-manager
    • home-manager installs a single buildEnv into the user profile, remaining compatible with imperative/impure nix-env

Management of files outside ~/.nix-profile

  • buildEnv
  • attrset
  • home-manager ✔️

Declarative config like NixOS

  • buildEnv
  • attrset
  • home-manager ✔️

Gives good control over outputs installed

  • buildEnv ✔️
  • attrset
  • home-manager
/*
Save this file to ~/default.nix or your preferred path (make sure to
change the location in the update-profile script if you choose a
different place).
Install using `nix-env -f ~ --set`, from then on use `update-profile`.
*/
{ pkgs ? import <nixpkgs> {}
, name ? "user-env"
}: with pkgs;
buildEnv {
inherit name;
extraOutputsToInstall = ["out" "bin" "lib"];
paths = [
nix # If not on NixOS, this is important!
icewm
pavucontrol
redshift
firefox
(writeScriptBin "update-profile" ''
#!${stdenv.shell}
nix-env --set -f ~ --argstr name "$(whoami)-user-env-$(date -I)"
'')
# Manifest to make sure imperative nix-env doesn't work (otherwise it will overwrite the profile, removing all packages other than the newly-installed one).
(writeTextFile {
name = "break-nix-env-manifest";
destination = "/manifest.nix";
text = ''
throw ''\''
Your user environment is a buildEnv which is incompatible with
nix-env's built-in env builder. Edit your home expression and run
update-profile instead!
''\''
'';
})
# To allow easily seeing which nixpkgs version the profile was built from, place the version string in ~/.nix-profile/nixpkgs-version
(writeTextFile {
name = "nixpkgs-version";
destination = "/nixpkgs-version";
text = lib.version;
})
];
}
@ljdwigney

This comment has been minimized.

Copy link

ljdwigney commented Jan 20, 2019

Alternatives include:

  • an attrset-based nix-env-based environment, installed using nix-env -ir rather than nix-env --set. LnL has an overlay which shows a way of doing this.
  • home-manager, which provides NixOS-like config for your $HOME

Sorry if it's a stupid question but what actually are the disadvantages/advantages of these different approaches?

@rendaw

This comment has been minimized.

Copy link

rendaw commented Mar 9, 2020

Thanks, this is nice! It doesn't look like with xfce; is needed - that was confusing me, since I didn't want to install xfce.

So to elaborate, to use this:
0. Put this file in ~/default.nix - the instructions say you can put it where you want with whatever name you want but I'm not sure I trust that. The nix-env docs don't explain how just ~ is sufficient either.

  1. Modify the list of icewm through firefox with the packages you want
  2. Run nix-env -f ~ --set
  3. After that install/remove software by modifying this file and then running update-profile

After running the above script nix-env disappeared from my profile... may want to be careful doing this.

Also https://unix.stackexchange.com/questions/332272/name-collision-in-input-nix-expressions-with-nix-env-f recommends against using nix-env -f ~.

@rendaw

This comment has been minimized.

Copy link

rendaw commented Mar 9, 2020

Okay, this is what I ended up going with:

$ cat ~/.nix-defexpr/default.nix 
{}: with import <nixpkgs> {}; buildEnv {
  name = "user-env";
  extraOutputsToInstall = ["out" "bin" "lib"];
  paths = [
    nix  # important!
    ...my packages...
  ];
}

If you place the file in the location above it will be automatically used if no other expression is listed, so you can just do nix-env --set. IMO this is much simpler. You need to include nix in paths or else you'll destroy your profile... neither this nor the overlay gist mention this which surprises me, maybe I got something wrong.

@lheckemann

This comment has been minimized.

Copy link
Owner Author

lheckemann commented Mar 15, 2020

@ljdwigney Took a while for me to get there, but I've added a feature comparison.

@lheckemann

This comment has been minimized.

Copy link
Owner Author

lheckemann commented Mar 15, 2020

@rendaw thanks for the hint, I left that with xfce; in by accident.

Re. just ~ being enough: as documented for the --file option at https://nixos.org/nix/manual/#common-options, if nix is given a directory it will look for default.nix inside. As the comment saying you can put it anywhere says, you need to adjust the update-profile script to pass the new path if you do put it elsewhere.

Re. ~ making sense at all: if default.nix exists, nix will not touch any subdirectories.

Re. .nix-defexpr: that command is indeed quite pretty! The mechanism is awful though, nix-env is the only nix command that uses it and the search behaviour can be rather unexpected. This is why things like these profile management tools exist in the first place, because nix-env doesn't do a very good job by itself… Anyway, don't let my opinion that nix-defexpr shouldn't exist stop you from using it ;)

@lheckemann

This comment has been minimized.

Copy link
Owner Author

lheckemann commented Mar 15, 2020

Oh, last point I missed: re nix being required: sorry, this is often missed by NixOS users because nix is installed system-wide and shouldn't usually be in user profiles there. I'll add it in here :)

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
You can’t perform that action at this time.