How to start using Nix(OS)

Okay, then I’ll have to work through it. Maybe I’ll use a virtual machine again first. A daily driver as a learning platform is probably not a really good idea.

Thank you

The template above is not bad, but maybe a bit overly complicated since it also configures home-manager etc.

Once you have a valid configuration.nix and hardware-configuration.nix, using flake is fairly easy: just create a file flake.nix containing:

{
  description = "The configuration of my system";

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

Just make sure to change yourhostname to match the name you want to give to your machine, and to use a coherent value in your configuration.nix, and to change your architecture if you are not running on x86_64. The first time you run it, you might need to run:

$ sudo nixos-rebuild switch --flake "/etc/nixos/#yourhostname"

Then, you should just be good running:

$ nixos-rebuild switch

and it should automatically use the flake version (if not, make sure to add flake.nix to your git repository if you have one), using yourhostname based on the current hostname.

If you already have NixOs installed, I don’t see the point of using a virtual machine for testing flake: that’s a whole point of NixOs; if you do something bad and your system becomes somehow unusable, you can always reboot an older generation. And Nix will only install the current derivation if there is no build error, so there is very little risk to play with your nix configuration.

And i don’t think that i need home-manager. The question ist, all packages as shown in mein pastbin url have to be in the configuration.nix?

Yeah, you don’t need to change your configuration.nix, it seems good to me (putting aside indentation, you might want to install a nix mode in your editor to automatically fix indentation for you :wink: ).

I am certainly newer to NixOS than many of the people here, but as a new user I am going to offer an opposing opinion to that given above.

You don’t need to install all of your packages through configuration.nix or through home-manager. You can just nix-env.
This works well when you first start with NixOS, because it is like every other package manager you have ever user.

nix-env -iA nixos. - installs the package for your user
nix-env -q - queries the current list of packages you have installed with nix-env
The rest of the nix-env commands are easy enough to figure out with nix-env --help.

This should keep you able to use things while you learn more about Nix. Just be aware that like a normal package manager, nix-env will not give you a config file where you can rebuild easily on another computer.

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?