How to start using Nix(OS)

Imperative-style installation is definitely possible (even if conceptually, adding packages to configuration.nix is not really more complicated, especially if you already have NixOs installed… the imperative style often make you forgot what you installed). nix-env however is maybe not the best tool for that as it as some drawbacks and is starting to look more and more like a legacy tool. A website https://stop-using-nix-env.privatevoid.net/ has even been created explaining why nix-env should be avoided, in favor of nix profile. This way, you can install programs imperatively with:

$ nix profile install nixpkgs#hello

You can search for softwares using:

$ nix search nixpkgs yourpackage

or using search.nixos.org/

This also reminds me another thing that is good to know. The above command will always start by fetching nixpkgs. This is nice to get the very latest version, but it might take more time as it downloads nixpkgs like every day, and it means that your packages might end up using different versions of the libraries, which might consume more disk space space. If you use the flake I provided above, you can add in your configuration.nix:

  ## Enable flakes
  nix = {
    # This will add each flake input as a registry
    # To make nix3 commands consistent with your flake
    # Inspired by https://github.com/Misterio77/nix-starter-configs/blob/972935c1b35d8b92476e26b0e63a044d191d49c3/standard/nixos/configuration.nix
    registry = lib.mapAttrs (_: value: { flake = value; }) inputs;

    # This will additionally add your inputs to the system's legacy channels
    # Making legacy nix commands consistent as well, awesome!
    nixPath = lib.mapAttrsToList (key: value: "${key}=${value.to.path}") config.nix.registry;

    settings = {
      # Enable flakes and new 'nix' command
      experimental-features = "nix-command flakes";
    };
  };

and it will automatically make sure that all your references to nixpkgs are pointing to the same file, so <nixpkgs>'s channel and nixpkgs’s flake will all refer to the flake configured in your /etc/configuration/flake.lock.

2 Likes

One day, when flakes are the default, such config is it too. Hopefully. But again. I like to write my to install package in a file i already have done in my 1st. test vm. Are they or can they places in the configuration.nix or ist there a way to sort them by writing a video.nix, audio.nix to make something like “application areas” to sort …?? :wink:

I’m lost, sometimes you say you want to use flake, sometimes no ^^ Anyway, just pick what you prefer, changing later is anyway not a big deal, just a matter of adding/removing 5 lines in a file.

Any solution (flake or not) can use your configuration.nix. So sure, just don’t use flake if you don’t want to, and configure your channel to follow unstable and/or pin your nix repository if you want to keep it in your repository.

Ohh so this is your real question? Sure, you can always separate your configuration.nix into multiple files (and this has nothing to do with flake), what you want is the import directive to import modules.

configuration.nix:

{ config, pkgs, lib, ... }:
{
  imports = [
    ./my-video-config.nix
    # …
  ];
  # …
}

In my-video-config.nix:

{ config, lib, pkgs, ...}:
{
  environment.systemPackages = with pkgs; [
    your-video-softwares
  ];
}
2 Likes

I think that’s because you often read and hear that flakes are the future, but on the other hand I don’t know what I actually need them for. This also applies to the home manager.
I previously understood that the packages with the activation of flakes were also entered there and no longer in the configuration.nix. That’s why I thought you could split it into different flakes.

I’m sorry, I find this very complex. The Nix package manager solves problems that I don’t actually have. But I’m still interested in the large number of packages, but at the same time I don’t want to get into a technical deadlock by not using flakes.

Long story short:

  • home-manager = declarative configuration/package installation for the user (as opposed to system configuration or imperative installation). If your have NixOs installed + a single user + only want to install basic packages, you don’t need it.
  • flake = thin layer that provides mostly a convention to follow to easily share packages/configurations (but you don’t really care here) + a simple way to pin/upgrade nixpkgs. If you don’t want declarative management or pin nixpkgs, just forget about it. Tools like nix profile use flake under the hood since it provides an elegant way to share packages, but you don’t really need to understand anything about flake to use them.

I think you overthink. If you are happy with a simple configuration.nix that list all your packages, just stay with it. And if you do not want to move to NixOs and if you prefer the imperative style, just use nix-env or, IMHO better, nix profile install yourtool, and forget about flake.

I think there is a confusion between flake and nix. In this context, flake is basically a convention saying:

“Any module/package/configuration can be put in a single flake.nix file where the output nixosModules.default contains the modules to import in other systems, nixosConfigurations.myhostname contains the NixOs configuration of host myhostname…”

but you are free to populate nixosModules.default/nixosConfigurations the way you want, using the nix language. So you can either copy/paste the whole configuration.nix inside flake.nix, or you can import configuration.nix from flake.nix, or you can import in flake.nix multiple files like configurationA.nix and configurationB.nix that import themself other files like myvideo.nix… The beauty on Nix is that a whole system configuration is now a simple variable, so you can generate it the way you like. And if you don’t want to learn the Nix language, just use the default configuration.nix and simply add packages to the list without ever thinking, or use, again, nix profile install (better) or nix-env.

2 Likes

This is great information. It is difficult to remember when you don’t do it everyday though. It would go a long way if they would either change the nix-env tab on the nixos.org packages search or add a new tab for nix profile.

Hmm, seems not to work… The flake.nix is in the same dir as the other configs

[wolf@daw:/etc/nixos]$ sudo nixos-rebuild switch --flake “/etc/nixos/#daw
[sudo] Passwort für wolf:
warning: creating lock file ‘/etc/nixos/flake.lock’
error:
… while calling the ‘seq’ builtin

     at /nix/store/vqljs1ixabpdbfmq3llnlkj5dac1hq4c-source/lib/modules.nix:322:18:

      321|         options = checked options;
      322|         config = checked (removeAttrs config [ "_module" ]);
         |                  ^
      323|         _module = checked (config._module);

   … while evaluating a branch condition

     at /nix/store/vqljs1ixabpdbfmq3llnlkj5dac1hq4c-source/lib/modules.nix:261:9:

      260|       checkUnmatched =
      261|         if config._module.check && config._module.freeformType == null && merged.unmatchedDefns != [] then
         |         ^
      262|           let

   (stack trace truncated; use '--show-trace' to show the full trace)

   error: undefined variable 'lib'

   at /nix/store/h1d9xnhsa1wbsm0f0kgqnqp0jyz9jvyh-source/configuration.nix:150:15:

      149|     # Making legacy nix commands consistent as well, awesome!
      150|     nixPath = lib.mapAttrsToList (key: value: "${key}=${value.to.path}") config.nix.registry;
         |               ^
      151|

Oh you directly added the code to have a unified pkgs, you are adventurous, nice :wink:

The error error: undefined variable 'lib' suggests that you forgot to add lib in your first line. This line should look like { pkgs, config, lib, inputs, ... }:. I created here a minimalist flake + nixos configuration. You can try to build it and run it in a VM with:

$ nixos-rebuild build-vm --flake git+https://gist.github.com/1f19628dc6b12bcd4438164b24226c6c.git#daw --refresh
$ ./result/bin/run-nixos-vm

(the user is daw and the password is foo, you may want to remove the nixos.qcow2 file when restarting the VM)

Proof:

Peek 09-01-2024 19-39

This is an example of what I meant when I say that flakes allows to easily share configurations :wink:

More precisely, I used this flake.nix:

{
  description = "The configuration of my system";

  inputs = {
    nixpkgs.url = "nixpkgs/nixos-unstable";
  };
  
  outputs = { self, nixpkgs }@inputs: {
    nixosConfigurations.daw = nixpkgs.lib.nixosSystem {
      system = "x86_64-linux";
      specialArgs = { inherit inputs; };
      modules = [
        ./configuration.nix
      ];
    };
  };
}

and this configuration.nix

# inputs is made possible thanks to the specialArgs line in flake.nix forwarding inputs:
{ pkgs, config, lib, inputs, ... }:
{
  imports = [
    ./hardware-configuration.nix
  ];
  
  ## Enable flakes
  nix = {
    # This will add each flake input as a registry
    # To make nix3 commands consistent with your flake
    # Inspired by https://github.com/Misterio77/nix-starter-configs/blob/972935c1b35d8b92476e26b0e63a044d191d49c3/standard/nixos/configuration.nix
    registry = lib.mapAttrs (_: value: { flake = value; }) inputs;

    # This will additionally add your inputs to the system's legacy channels
    # Making legacy nix commands consistent as well, awesome!
    nixPath = lib.mapAttrsToList (key: value: "${key}=${value.to.path}") config.nix.registry;

    settings = {
      # Enable flakes and new 'nix' command
      experimental-features = "nix-command flakes";
    };
  };


  ################################### Add here your configuration like:
  system.stateVersion = "24.04";
  boot.loader.systemd-boot.enable = true;
  boot.loader.efi.canTouchEfiVariables = true;

  users.users.daw = {
    isNormalUser = true;
    initialPassword = "foo";
  };
  
  # Not really needed, but recommended if you want to run non-nixos binaries.
  # You can customize programs.nix-ld.libraries = []; to add more libraries not present in systemPackages.
  programs.nix-ld.enable = true;

  # List of packages:
  environment.systemPackages = with pkgs; [
    hello
  ];

}

Means i have to add lib and inputs in the 1st line of the config…nix?

and to create a vm is interesting. Thats the first time i see that. Normaly i use KVM virt. machine with proxmox gui…

Yes, first line of configuration.nix.

Yeah, that’s a very cool feature of nix: since the whole system is in a single file, we can spawn VM easily. I use it for instance to locally work on a configuration for a raspberry pi on my laptop (much easier since I don’t always have access to the raspberry), and then I can just git pull and nixos-rebuild switch on the raspberry pi and it just works!

Nice. It works with ur VM…

Now i try to run the rebuild again…

Seems to run. And it looks like it is unstable…

Great! Running unstable is expected due to the line:

nixpkgs.url = "nixpkgs/nixos-unstable";

Yes, and this seems to overwrite the setting in config…nix, if there is one.

Btw. it has finished. And that the application mc does not start, is bec. i have to reboot??

If you got a newer kernel, a reboot might be necessary, but I’m not sure it is needed for basic stuff. Do you have the error?

[wolf@daw:~]$ mc
The program ‘mc’ is not in your PATH. It is provided by several packages.
You can make it available in an ephemeral shell by typing one of the following:
nix-shell -p mc
nix-shell -p minio-client

I have a videoconference running atm. Takes 20min to be ready to reboot

OK, after reboot mc is running. The other application i will test tomorrow… Good night

Ok cool. I guess if it was your first install the PATH was maybe not correctly configured. Later, you usually don’t need to reboot unless you have a kernel update or alike.

After reboot the mc was gone. On Grub i have seen that the config is from yesterday. No other programs are installed. After running again
sudo nixos-rebuild switch --flake “/etc/nixos/#daw
i can start the nextcloud client.

Could it be that after enabling flakes, i 'm not allowed to run
sudo nixos-rebuild switch…?