Yeah, I would really like to see `nix-env -i` recommended far less often, or at least with the caveat that this should only be for testing packages at the most. I still haven't found a good use case for it personally.
One of the big wins for Nix is its declarative nature (especially for reproducibility) and installing packages in an imperative manner like this just seems to put folks back in the same position as using pacman or apt-get. Please correct me if I'm wrong Nix-ers.
Having used NixOS as the main OS on my personal laptop for the past year or two (and loving it), I've only used `nix-env -i` to install a package once, and immediately regretted it after trying to add a different version of the same package to my main configuration files. This resulted in a conflict, which from memory required me to force reinstall the package again via `nix-env` but specify a lower priority so that it could be replaced automatically when enabling the package via my configuration files... A really strange experience that re-affirmed that nix-env is at least not for me.
For testing packages, I would always recommend `nix-shell -p <package>` as a preferred option. Just type `exit` and then you've left the shell, it's no longer in your PATH and there's no risk of conflicts.
It sucks that you ran into this, but also totally understandable. I think generally the community would consider the nix-env approach of installing and updating packakges an anti-pattern these days, but this certainly isn't obvious when reading through the docs.
nix-env is a little worse than your examples suggest. It's really:
nix-env -iA nixpkgs.package_name
Can't forget the leading `nixpkgs.`. And searching is:
nix-env -qaP '.*keyword.*'
Because `--query` takes a regex -- unlike all of the other nix-env subcommands, which take globs.
But `nix search` has been available for years, and works great.
There's still no nice interface for installing packages, but that's not actually an operation you do very often with Nix, since you're mostly specifying environments in files, rather than mutating your own user environment. Of course, newcomers don't know that, and they want to manipulate things in their PATH like every other package manager, so that's not an excuse for the bad ergonomics. The upcoming version of Nix adds `nix profile install` which is a bit more intuitive.
I think Nix's current CLI makes git look positively humane, but I'm encouraged that it's been steadily improving.
for those one-off times I want to just jump into a shell with, say, ranger available, it's as simple as
$ nix shell nixpkgs#ranger
if I am starting up a project that needs a tool, I just throw together a simple shell.nix in a folder for the project and run
$ nix shell
from that folder. there's ways to set it up so you automatically switch to a shell with the specified packages (iirc with direnv just like you'd do it for python venvs) but I haven't felt the need yet.
> This is a game-changer, you don’t have to pollute your system to run a one-off command, or you can try a package out before committing to installing it.
Is there a way to run the command isolated from the rest of the system? Because while this is nice it will still leave behind whatever configuration files / caches the program created on start up.
Can I just do “nix install foo”? I looked into nix ages ago but opening a text file any time I wanted to install some random package just felt too weird.
I have had a great experience using the Nix package manager on other Linux distros. It's super easy to try out software with `nix-shell -p somepackage`. (It's a little rockier on macOS.)
Another neat trick is reproducible shell scripts that use Nix to declare their dependencies in a sort of extended shebang line.
I highly recommend using the Nix package manager alongside whatever you're comfortable with. That way you can `nix shell -p foobar` when you need a package quickly or fallback to brew/apt/etc if you're not yet comfortable addressing the situation in Nix.
Yes. (Docs at https://nixos.org/manual/nix/stable/command-ref/new-cli/nix3....) Although it won't "throw it away" in the sense of uninstalling it; it's just that when you exit the shell, you'll be back in an environment which doesn't have the symlink to `ranger` on the PATH.
One idea, if the customers tend to be NixOS enjoyers, would be to put the tool in Nix Packages and then use nix-shell for them to access it.
Perhaps the nix packages configuration could reference a script with everything properly debugged and then the snake can eat its own tail.
It seems like a provisioner to install and configure stuff, in which case one obvious method to install is copy pasting bash code. Have we really reached an era where folks expect to use CLI tools without using a CLI?
Can nixpkgs install from brew? Maybe that’s the answer, use the annoying stuff and wrap it with something to make it less annoying. Or, you could wrap your CLI with Tauri and install with Cargo. Might be more robust but not in the comfort zone of a nix shop.
Yeah, you can just have a couple of config files and spin up a shell that auto-installs everything. The packages are all on your system, so the next time you start the shell, nothing has to be downloaded, but they're not installed globally, and a you can do a garbage collection command at any time to clean up everything.
When I first started using NixOS I had a huge list of globally installed packages, but that has become smaller and smaller over time. For instance, my main browser is Firefox, which is installed globally, but if I need to use Chrome, then it gets fired up in a temporary shell.
- nix-shell-env init # creates an "empty-ish" shell.nix
- nix-shell-env install nixpkgs.whatever # adds dep. to shell.nix
- nix-shell # activate it
So you don't have to learn any Nix-language / nixpkgs ropes, but can still have a viable shell.nix built for your project. I could see that being a nice stepping stone between "nix-shell -p" and "learning the language."
I remember reading that nix unlike all other distros can install multiple version of the same package and I want this feature, but I guess programming a package config might be too much for me. Maybe I'll try nix package manager then.
Even with old `nix-shell`, you could always use `nix-shell ... --command fish` or whatever it is to launch a different shell. Historically other `nix-shell` wrappers, like `direnv`' Nix integration, have also supported non-bash shells well.
> [I] read somewhere that [nix-shell]'s not really made for this purpose originally, rather for just building packages, bash being only one of the limitations.
Yeah, nix-shell was originally made for debugging Nix builds. The first capability it gained was setting up the build environment of a given package, which equips you with the same compiler, linker configuration, etc., as the package would get if you ran nix-build, or when the package is built on CI/CD or whatever. It even loads the bash functions that the build system invokes so that you can experiment with manually adding steps before and after them and things like that.
But it's gained other capabilities since then, like `nix-shell -p`, whose purpose is a more general try-before-you-buy CLI and magic shebangs. It also has two descendants, `nix shell` which is just about letting you set up software, and `nix develop` which is more oriented toward setting up whole development environments and all the env vars associated with it. Anyway I think that's mostly trivia; it doesn't pose any problems for devbox afaict.
> I tried to experiment myself with nix-shell, but I think it doesn't provide separation on the machine on which you run, it's not a chroot nor a docker container
That's true, and that's really the beauty of it: you can set up complex toolchains and use them as if they were simply part of your normal system, but without worrying that they unwittingly depend on parts of your base system that may be unique to you. Likewise, they don't require any permanent changes to your normal, global environment at all. If you've used Python before, you can think of nix-shell like a generalized venv.
> If you are interested in some level of separation to make sure that a dev environment is "safe" to run on your machine without making side effects to things external to the project
Nix can provide sandboxing for builds, for proper packages. So if you want to make sure your environment is complete, adding to your Nix shell development environment to make a complete package may help you.
But the purpose of shells like this isn't to protect you from running `rm -rf /`, if that's what you're after. It doesn't protect you from dogecoin miners in your `npm install` hooks, if you're just using Nix to provide `nodejs` and then running `npm install` as usual.
What something like this does do is allow you to use all that software without installing it. So if you open up a new session, none of that stuff will be loaded.
Nix can generate container images and VMs for you, though, and that is also one of the things `devbox` can do, if your isolation concerns have more to do with security (disallowing access to your system) than 'purity' (disallowing dependency on your system, not installing things to your system).
Sure - you're Nixing wrong. Not to worry, it actually takes ages to figure out how to Nix right - there's not enough documentation on the matter.
The correct way to get almost anything installed is to write a Nix package, and install that. This is actually remarkably easy in comparison to other package managers - you write the package definition in a single file, normally just having to set the source code location and list its dependencies, and you can make it available to install with nix-env by adding it to a packageOverrides declaration in ~/.config/nixpkgs/config.nix.
The "stdenv" build system that nixpkgs uses will automatically install anything that can be configured via "./configure && make && make install" - cmake is supported just by listing that as a build dependency. Stuff written in scripting languages is more fiddly, but the nixpkgs documentation usually has examples. The downside is that a significant amount of the time, libraries written in scripting languages aren't packaged either, and you wind up packaging half a dozen libraries just to get some tool working. The <X>2nix tools can be useful in these cases to generate a package definition.
I agree, but I think nix-env is only the tip of the iceberg with respect to bad upfront experiences. If you try to make a Go package, for example, you end up having to provide a hash. To generate the hash `vendorSha256`, you have to run `nix-prefetch`, but that program is broken on MacOS. I mentioned elsewhere that I spent a weekend working with the Nix discord to try to install VS Code with some extensions for Rust development, and we collectively couldn't figure it out (I'm not using NixOS, but just Nix the package manager). In the past I've tried to package a simple Python app thinking it would be a simple reference to a pypi package, and I ended up having to package a never-ending matrix of the most obscure C dependencies and ultimately gave up. Maybe if I were doing Haskell development I might find the Nix happy path, but for now I just have a nix shell that installs a few basic CLI utilities and that's the only way I've managed to use Nix successfully. Further, any time I have to do anything in nixpkgs, I find that everything is a slog--since there are so few imports (and because the Nix people don't believe in documentation or types or even sane file/directory organization), in order to find the "shape" of argument `foo` to the Nix package function `Bar`, I need to grep the whole nixpkgs repo for something that uses `Bar` and then figure out what it's passing in for the `foo` parameter. Often `Bar` is passed to several other functions (defined in several other files) before it's called and the thing that gets passed in for the `foo` parameter might be the return value of a function which itself is returning the result of some other function (each of which is defined in other files), etc. This results in a combinatorial explosion of inefficiently grepping around the codebase just to get the type of a symbol (something that would come for free in a statically typed language).
I'm a big believer in the Nix approach to builds, and that this approach holds a lot of potential for DevOps (especially CI/CD); however, there are so many practical problems with Nix and the community doesn't seem especially interested in fixing them. Of course, what volunteers spend their time on is there prerogative, I could volunteer my time rather than criticize, shame on me, etc but it's a loss for the broader world. Personally I would really like to see a community with the ethos of the Rust community pick up the torch and try to build something inspired by Nix, but perhaps with more pragmatic choices (e.g., instead of inventing an obscure scripting language, they might use something more familiar and thus easier on new users; rather than the chaos of nixpkgs, they might give users a type system and/or good editor tooling; rather than the difficult-to-Google "Nix" label, they might pick something a bit less overloaded; etc).
Not automatic, but as a replacement for nix-env and nix-shell, it's great. When I need an x86_64 package, I find `nix shell nixpkgs#legacyPackages.x86_64-darwin.neovim` easier to recall and reason about.
(Or `nix profile install nixpkgs#...` for a persistent version of the same)
My tip: don't use nix-env to install packages like it's Aptitude or Pacman, use `nix run` if you need a package temporarily, home-manager if you need a user-level package permanently, or just straight up change the configuration.nix to include the package as a system-wide one.
If you use nix-env you're just polluting your environment in an imperative way and that is pretty much going against Nix' declarative nature.
Or frequently just `nix shell nixpkgs#foo` or even `nix run nixpkgs#bar -- --baz` (as opposed to `brew install foo; foo; brew uninstall (or it is it remove?) foo`
I still have both installed as the union of their packages is better than either in isolation, but I really like having a good idea of what I have permanently installed (and why) in my nix config files, as opposed to re-spending 5 minutes in the brew docs to remember the brew incantation that will give me a reverse dependency tree and try to sort out whether I can uninstall something without breaking something else.
You can also test-drive a package without committing to it, e.g. you want to try the program `cowsay` but only want to use it once:
This spawns a new shell with `cowsay` available, and after you exit it won't be cluttering your system packages. The CLI UX can get better, and I'm fairly sure folks are working on it.reply