Help needed, overlays for unstable neovim

Hey guys, I’m pretty new to NixOS. This is the first time I try to configure something.

So I needed neovim 0.6.1. because some features I want to use only exist there. The most recent version on the stable channel is 0.5.1. This is why I tried to use the unstable channel, and use it only for this one package.

In my configuration.nix I used:

environment.systemPackages = with pkgs;
let
  unstable = import <nixos-unstable> { config = { allowUnfree = true; }; };
in [
unstable.neovim
...
];

which installs the neovim version I want. However after that, my configuration doesn’t work anymore and isn’t applied. ( I suppose due to a naming thing?!) Here is my original neovim config in a separate file in a shortened form:

{ pkgs, ... }:
{
  nixpkgs.overlays = [
    (self: super: {
      neovim = super.neovim.override {
        vimAlias = true;
      }
    }
  ]
}

Typing vim after nixos-rebuild doesn’t work anymore. Can I make this work without resorting to HomeManager?

I think the problem mainly has to do with the configuration being in an external file. When I move the contents of my configuration into the systemPackages then everything works fine. But of course I don’t want that kind of bloat in my configuration.nix file.

I use flakes with home-manager for neovim and this overlay: https://github.com/nix-community/neovim-nightly-overlay

I think you can do it without flakes, that repo haves an example. That will build NVIM v0.7.0-dev.

Then I just use this config:

  programs.neovim = {
    enable = true;
    package = pkgs.neovim-nightly;
    viAlias = true;
    withPython3 = true;
    extraConfig = ''luafile /home/${username}/.config/nvim/nix.init.lua'';

    extraPackages = with pkgs; [
      tree-sitter
      pkgs.rnix-lsp
      nodePackages.typescript
      nodePackages.typescript-language-server
      nodePackages.bash-language-server
      nodePackages.vscode-langservers-extracted
      nodePackages.vim-language-server
      nodePackages.typescript
      nodePackages.typescript-language-server
      nodePackages.intelephense
      nodePackages.dockerfile-language-server-nodejs
      sumneko-lua-language-server
      texlab
      rust-analyzer
      deno
      stylua
      nodePackages.prettier
      perl534Packages.PerlTidy
      perl534Packages.PerlCritic
      sqlite
    ];
  };

This is my config:

The two interesting files are:

https://github.com/marcelarie/nix/blob/663e3e2f46b5de8b5fbbbab0636be20d339e2ed3/flake.nix
https://github.com/marcelarie/nix/blob/663e3e2f46b5de8b5fbbbab0636be20d339e2ed3/home-manager/home.nix

I am pretty new to NixOs too but If you have any questions tell me and I try to help :slight_smile:

This is because your overlay isn’t applied to the unstable.neovim package that you pull into your system environment. Edit: or more accurately, the overlay isn’t applied to the unstable import of nixpkgs.

Two possible ways to go about fixing this would be to either:

  1. Do the unstable import in your overlay, and override that, or
  2. Simply do (unstable.neovim.override { vimAlias = true; }) in your systemPackages, dropping the overlay entirely.

To reiterate, you could use:

environment.systemPackages = with pkgs;
let
  unstable = import <nixos-unstable> { config = { allowUnfree = true; }; };
in [
  (unstable.neovim.override { vimAlias = true; })
...
];

And not use an overlay at all.

The problem with that approach is that this doesn’t change the version of neovim your config uses elsewhere. If you do make an overlay, you literally change what neovim means in your system to refer to the unstable version. I’d recommend sticking to that, but you need to refer to the overridden package if you want to use the modified version, not to the one in your unstable import. I.e. you should use:

{ pkgs, ... }:

let
  unstable = import <nixos-unstable> { }; # Not using anything unfree at the moment
in {
  nixpkgs.overlays = [
    (self: super: {
      neovim = unstable.neovim.override { # We're overriding with the unstable package
        vimAlias = true;
      };
    })
  ];
}
environment.systemPackages = with pkgs; [
  neovim # This is overridden using `nixpkgs.overlays`, so will be 0.6.1
...
];

Personally I would also treat configuration.nix as a sort of entrypoint, and put all my unstable overrides there. Then other files can just use the overridden packages from pkgs and don’t need to import unstable all over the place, which will be expensive if there are a lot of unstable packages. But that’s not strictly necessary :slight_smile:

If you really want to separate concerns, you can also do this with two overlays:

{ pkgs, ... }:

let
  unstable = import <nixos-unstable> { }; # Not using anything unfree at the moment
in {
  nixpkgs.overlays = [
    (self: super: {
      neovim = unstable.neovim;
    })
    (self: super: {
      neovim = super.neovim.override { vimAlias = true; };
    })
  ];
}

And then put the two overlays in separate files somehow (ordering might be tricky). That will first override with the unstable version, and then override that by taking the previously overridden neovim and setting its option.

2 Likes

Hey guys,

thanks for the quick responses.

marcelarie (Sorry, I only can mention 2 users per post as I’m new) I didn’t want to use home manager. However I looked into your approach and it seems pretty solid and it almost got me into switching to home manager.

@gravndal I kind of got it to work with your solution. Thank you.

@TLATER After reading your reply, I refactored to use overlays again. Thanks for the explanation! I didn’t understand overlays before that properly.

Thank all of you. For anyone looking for help reading this in the future: I wrote a little step by step guide of my setup. Might not be optimal, but it’s at least some boilerplate to start somewhere.
Critique is also wellcome :slight_smile:

My NixOS installation guide

Once again thanks everyone!!

@marcelarie (Sorry couldn’t mention you in the last answer, but I also didn’t want to leave you out since you took your time to write me an answer. Thank you!)

1 Like

Out of interest, where does the reluctance of using home manager come from? It really is just nix modules designed for day-to-day desktop users, rather than servers (although NixOS does have pretty good user stories for both these days).

For context, if you use the nixos module, it more or less just allows you to configure your applications without forcing all other users on the same machine to have the same configuration. It still uses nix packages behind the scenes, and everything goes through configuration.nix as it should, just the configuration modules are different (i.e., write to /home/user instead of /etc).

1 Like

This is the first real program I am configuring with nix. I just didn’t want to resort to some other method as I figured that there can be something I could learn here. I will for sure look into home manager in the future, but for now I want to stick to the “basics”. Idk if that makes sense. Hope that answers your question at least a little bit.

It does, you’re not the only one with this mindset. I’m curious because I’m wondering what we can do to change the perceived difficulty here, because I imagine it could help a lot of newbies get started if home-manager felt more like it was part of the minimal solution.

I don’t really know. The wiki site seemed a bit convoluted. I didn’t get how to install Home Manager when I first visited it. But I think that comes mainly down to not being used to the way how programs in nix get configured. Not using home manager feels a lot more familiar.