"programs.foo.enable = true" vs "systemPackages=[foo]" is confusing

I find the configuration.nix system to be a bit confusing.

For example, how do I install zsh?

Is it

environment.systemPackages = with pkgs; [ zsh ];


programs.zsh.enable = true


As a new user I searched for “zsh” to see if that was available, then thought “great, I’ll just stick that in systemPackages and I’ll have zsh”, only to find out weeks later that I should actually write programs.zsh.enable = true if I want to have nix-zsh-completions and other system-wide zsh features.

This experience is not well-documented.


The former installs the zsh package.

The latter leverages the zsh module to install/configure the software. I am fairly new here but from my limited experience the modules usually provide configuration of system wide features when applicable. They also operate at a higher level of abstraction since they handle both configuration and package installation.

I am sure someone with more experience will be able to explain it in more detail/more accurately.


Thanks, this is definitely good information to know, and it should be included in the nixos docs up front.

Do you mind adding this recommendation over at Does my first-ever configuration.nix look alright? in case I’ve installed anything there that can be installed a better way (f.e. with programs.*.enable instead of systemPackages)?

Also, how do we search for what’s available in programs? Using nix search is the first thing that I learned from the docs, but this doesn’t tell me what’s available in programs.


If you run nixos-option programs you will get a complete listing of all of the programs configurable in this fashion. There’s also nixos-option services, which has a lot more stuff in it.


In addition to what @lilyball pointed out, I use this site quite a lot: NixOS Search - Loading...

It allows you search easily and has links back to the nix files in github so you can see how something works directly. It is basically the same info found in nixos-option but in an easily consumable format.

Ah, great to know! This was not mentioned in the nixos manual section 6.1. Declarative Package Management.

Nice! This would be great to add to the manual up front too. I think it can be mentioned in Chapter 6 as a way to discover what available in programs, etc.

TODO, github issue to add it: https://github.com/NixOS/nixpkgs/issues/77959

Opened https://github.com/NixOS/nixpkgs/pull/77960


If you’re on nix, don’t forget about man configuration.nix

It will be a good local reflection of whats on nixos-option / NixOS Search - Loading... . If you prefer man format.

To answer your original question, generally the ‘.enable = true’ options are preferred as they will be smart about a system effects which are needed to the application/service to run correctly. For example, ‘virtualization.docker.enable = true’ will create the necessary groups, install the docker-daemon, install the docker cli, and a few other things to enable normal docker usage.