Put My full configuration in git

Hi,
I’m new to nix but kinda like the idea.
I want to have all my config declaratively stateted in config file. To do that I need to use home manager I believe because home manager have the ability to control so called dotfiles.
But ti enable homemanager channel declaratively I need flakes, also flakes help with version switching and … my head is complete mess I and I don’t understand how to accomplish the task.

Can you share your config and probably explain how to have I all my setup declaratively stated in few files

There’s a collection of people’s personal configs here, however if you’re just starting out, they’ll probably mostly be too complex to help you.

There are 6 ways to install home-manager:

  • nonflake + standalone
  • nonflake + nixos module (nixos specific)
  • nonflake + nix-darwin module (macos specific)
  • flake + standalone
  • flake + nixos module (nixos specific)
  • flake + nix-darwin module (macos specific)

The home-manager manual has a section on setting up home-manager standalone with a flake, along with other sections for the other 5 modes.

You can try the (arguably) simplest mode first (nonflake + standalone), then convert your config later, if you’re feeling overwhelmed.

4 Likes

Thanks
I looked at few sources to help me with my own setup with flakes and home manager but I have some troubles. Here is my flake so far

{
  description = "System config";

  inputs = {
    # nixpkgs.url  = "nixpkgs/nixos-22.11";
    nixpkgs.url  = "github:nixos/nixpkgs/nixos-22.11";
    #home-manager.url = "github:nix-community/home-manager/release-22.11";
    #home-manager.inputs.nixpkgs.follow = "nixpkgs";
    home-manager = {
      url = "github:nix-community/home-manager/release-22.11";
      inputs.nixpkgs.follows = "nixpkgs";
    };
  };

  outputs = { nixpkgs, home-manager, ... }:
    let 
      system = "x86-64-linux";
      pkgs = import nixpkgs {
        inherit system;
        config = {allowUnfree = true;};
      };

      lib = nixpkgs.lib;

    in {
      nixosConfiguration = {
        # hostname
        myhostname = lib.nixosSystem {
          inherit system;

          modules = [
            ./system/configuration.nix
          ];
        };
      };
    };
}

and here is the error that I get

nixos-rebuild build --flake .# --show-trace
building the system configuration...
error: flake 'path:/home/kalin/Projects/nixosconfig' does not provide attribute 'packages.x86_64-linux.nixosConfigurations."myhostname".config.system.build.toplevel', 'legacyPackages.x86_64-linux.nixosConfigurations."myhostname".config.system.build.toplevel' or 'nixosConfigurations."myhostname".config.system.build.toplevel'
       Did you mean nixosConfiguration?

I probably can set config.system.build.toplevel to point to my store path but the sources that I look at didn’t have that issue

should be nixosConfigurations = {.

2 Likes

Thanks, I missed that “s” somehow.
I will continue with my experiments and will ask more questions later.
In some of the examples I can see that some people remove home-manager at some point
Do I need it ? is there a better option ?

For managing homedir configuration with nix, there isn’t really much of an alternative to home-manager. Some people just decide they don’t want to do that, or they keep the home-manager config in a separate repo entirely.

You certainly don’t “need” it. You can always just leave your dotfiles non-declarative, but home-manager is the best, and basically only, way to make them declarative in a manner similar to nixos.

1 Like

I struggle to understand the following

lib = import ./lib {lib = digga.lib // nixos.lib;};

what this double back slash mean as nix construction and why alfter import ./lib we have attribute set

      sharedOverlays = [
        (final: prev: {
          __dontExport = true;
          lib = prev.lib.extend (lfinal: lprev: {
            our = self.lib;
          });
        })

        nur.overlay
        agenix.overlay
        nvfetcher.overlay

        (import ./pkgs)
      ];

almost everything from here

all = base ++ tools ++ development ++ writing;

What those double pluses mean

A list of builtin operators: Operators

Spaces (outside of lists) mean function application, and are left associative. import ./lib evaluates to a function, so you then apply that function to another argument, which happens to be an attrset. This is fairly standard fare for a purely functional language. Look up “currying” if you’re interested the concept in general.

1 Like

That whole section is defining a list of overlays to pass on to something. Without context I don’t know what.

The first is inline, and seems to be intended to fit some extra stuff under nixpkgs lib by shoving in a lib.our.

The next 3 are overlays defined elsewhere, presumably in input flakes given the names.

The final one is importing ./pkgs/default.nix, which presumably also defines an overlay of packages coming from this flake itself.

1 Like

lib = import ./lib {lib = digga.lib // nixos.lib;};

if I get it right “import” work like include in c/c++ and directly bring the content of the imported file (like text) at the place of the import
In my case it should be that

{lib}:
lib.makeExtensible (self: {})

I believe that this is function return the result of call to its argument function (lib.makeExtensibe) with argument another function that take self as argument and return empty set
Here I struggle to understand what is the meaning of self and what () do
Can I put them everywhere ?

Close. There is one important difference. Variables do not propagate into the imported file.

Correct.

It’s just a variable, but people tend to use this variable name specifically in cases where an expression is being fed its own final value lazily through some path. nixpkgs’ lib.makeExtensible is designed to do this kind of “fixed-point” operation, so naming the argument to the function you pass to it self does make sense. Fixed-points tend to confuse even fairly experienced nix programmers, though, so don’t feel bad if you don’t fully understand this.

Just grouping to override or clarify precedence of operations, like in algebra.

Just like with algebra expressions, you can put parens in a lot of places that you don’t actually need to, but you generally shouldn’t if you want your code to be readable.

1 Like
      sharedOverlays = [
        (final: prev: {
          __dontExport = true;
          lib = prev.lib.extend (lfinal: lprev: {
            our = self.lib;
          });
        })

        nur.overlay
        agenix.overlay
        nvfetcher.overlay

        (import ./pkgs)
      ];

It seems that I put too much effort to understand that. This should be some kind of convention that something expect list with name sharedOverlays that contain function with “two” arguments and return set that contain certain attributes, right ?
Is that sharedOverlays comes from flakes itself or come from digga lib that I look right now

Well, the concept of an “overlay” being a function of two arguments, and how it applies to an extensible package set like nixpkgs is a well established convention, yes. See Overlays - NixOS Wiki.

Given that, the attribute name sharedOverlays is mostly self-explanatory.

1 Like

It’s seems that the task is harder then I expected
I decide to try with template

I also don’t understand how to use the template for now. Hopefully I will find some tutorial for morons like me

Digga is pretty over-engineered for a typical starting nixos user, and it adds significant complexity to learning, by introducing additional layers between you and what’s going on. It also greatly reduces the amount of the available documentation that applies to your situation, which already wasn’t too big because you’re on NixOS. Add Digga and there’s close to nothing. If you want to do something, there’s a decent chance you’ll find directions for flakes and for non-flakes, but nobody gives directions for how to use their thing with Digga. I honestly can’t recommend going that way for a new user.

Such structured systems can add valuable organization to an experienced user’s complex config, but only because he understands how they work and how to translate directions for normal flakes into the additional organizational structure.

2 Likes

Could you suggest me example or template that I can easily read and understand.
I have the following needs
I need to be able to put my config in git
I need to be able to manage dotfiles
I need to be able to have latest version of various programming languages (rust, c++, python etc)
I need to easily transfer my config to another machine with potentially different hardware (not sure if I need hardware-configuration.nix)

Honestly, you don’t need much of a template at all for this.

flake.nix: (Lifted largely from the Home Manager Manual)

{
  inputs = {
    nixpkgs.url = "github:nixos/nixpkgs/nixos-22.11";
    home-manager.url = "github:nix-community/home-manager/release-22.11";
    home-manager.inputs.nixpkgs.follows = "nixpkgs";
  };

  outputs = inputs@{ nixpkgs, home-manager, ... }: {
    nixosConfigurations = {
      hostname = nixpkgs.lib.nixosSystem {
        system = "x86_64-linux";
        specialArgs = { inherit inputs; };
        modules = [
          ./configuration.nix
          home-manager.nixosModules.home-manager
          {
            home-manager.useGlobalPkgs = true;
            home-manager.useUserPackages = true;
            home-manager.extraSpecialArgs = { inherit inputs; };
            home-manager.users.jdoe = import ./home.nix;
          }
        ];
      };
    };
  };
}

Replace hostname and jdoe here with appropriate values, and add a bog-standard configuration.nix, hardware-configuration.nix and home.nix placed in the same directory, and of course checked into git, and you have a pretty good template to get started with, which will cover everything you’re asking for except the programming languages. That should be done using per-project development shells, not as part of your global config.

Remember, the best way to learn nix, like most things, isn’t read everything under the sun, it’s to get your hands on it and try things.

3 Likes

Ok thanks but can you give me one more answer. How I can mix packages from different channels in home manager. For example I want to use vscode and discord from unstable.
I found this solution with overlays but I didn’t manage to implement it

If you followed my template:

  • Add a unstable.url = "github:nixos/nixpkgs/nixos-unstable"; line in your flake.nix’s inputs section.
  • Add inputs to the top line of your home.nix. For example, if it currently says { config, pkgs, lib, ... }: then you change it to { config, pkgs, lib, inputs, ... }:
  • After that line, but before the main opening {, add:
let
  unstable = import inputs.unstable {
    system = pkgs.system;
    # Uncomment this if you need an unfree package from unstable.
    #config.allowUnfree = true;
  };
in
  • Put unstable.foo (where foo is the package you want from unstable) in your home.packages list.
2 Likes

Thanks, it’s works but I cant figure out how to enable unfree for this unstable packages