How to add a new package to the Virtualbox demo appliance? (and other beginner questions)

I’ve downloaded and got running the NixOS demo appliance for VirtualBox from here

I have also modified it to install guest extensions, which is working fine.

My current configuration.nix looks like this:

{ config, pkgs, ... }:
  imports = 
  virtualisation.virtualbox.guest.enable = true;

So what I do understand is (I think):

  1. Each nix file is an expression.
  2. This is a function of two arguments, which returns a name/value pair set.
  3. The statement is replaced by the value of the expression in the file specified, by grabbing it from the Nix github site.

And what I’m guessing is:

  1. Nix actually passes some values of “config” and “pkgs” to this function.
  2. The return value of this function is essentially the state of my system

What I don’t understand is:

  1. What is the return value? A list of packages? A list of “actions”? Something else? I know it’s a key/value map in this form, but that doesn’t give me much of a hint about how that translates into what’s installed on my system.
  2. What exactly is passed in to “pkgs” and “config”? Surely I don’t know these things until I have the result of the configuration.nix function. Or is there something loopy going on here with laziness where I pass the result of the function in as an argument?
  3. How can I just add an additional package to my system? Say VSCode for example. I’d like to just add to the demo system, eventually I’ll probably customise my own, but for the moment just adding some packages to the demo system will work fine. I’d like to do this declaratively though not just use command line tools.

I have done a bit of work with Haskell so the functional programming aspect of Nix I should be comfortable with, I’m just having trouble contextualising it all, and I feel the answers to these questions may sort this out.

a function that needs at least two arguments, but that allows the passed in mapping to have more (due to the ...)

mmm, you need to clarify

of course, where config contains the the global configuration and pkgs is the a mapping (or attrs) containing all the packages defined by the nixpkgs distribution, tailored to your system architecture.

The result of the evaluation of all the configuration modules, is indeed what your system is or will be. It’s in part state and in part code that will realize the final configuration.

The configuration expressed as a tree of mappings is used to produce a tree of derivations, a core concept of Nix, you will find it explained many times in the documentation. Each derivation produces a package under /nix/store.
For example, you can see the list of the actual packages installed (i.e. the realization of all the derivations created by your configuration) by executing:

$ nix-store -q -R /nix/var/nix/profiles/system

Yes, something like that, reading the NixOS documentation on writing configuration modules can help you understand the strengths and caveats of such an approach, I’m sure you can immagine at least one of the latter category, infinite recursion.

Add it to the environment.systemPackages list and make the configuration active with nixos-rebuild switch.

You can see all the configuration entries by running man configuration.nix.

Thanks for all the answers @azazel75. Just one follow-up (at least initially):

How do I “Add it to the environment.systemPackages list”? Isn’t this immutable? Can you show what will need to be done to my current configuration.nix to add a package (any package, assuming the concept is the same for all of them)?

Immutable? Is your configuration.nix read only? :smiley: Just add the following before the closing bracket:

environment.systemPackages = [ pkgs.vscode ];

@azazel75 but how does my system currently have any packages if environment.systemPackages is not yet defined? Wouldn’t it already be defined somewhere in <nixpkgs/nixos/modules/installer/virtualbox-demo.nix>?

It would be very difficult to extend and customize a system configuration if a single value could be defined only in one place. That’s one of the strengths of the NixOS module system, each key defined in a module gets merged with all the other keys defined in the other configuration modules. How that merging happens is defined by the type of the option that the programmer has decided that option to be. In the case of lists, they get concatenated.

Another reason why your definition wouldn’t wipe out all the other packages from your system is because Nix has a way of implicitly install required packages: for example if your dear vscode package needs the bash shell package at runtime, that will be automatically installed on your system. It will be much more clear once you experiment a bit with Nix, if you want to.

1 Like