Direnv basic setup kubernetes

I have various kubernetes clusters of different versions, some old enough that the current kubernetes kubectl will not work with them.

I’ve been looking at Nix · direnv/direnv Wiki · GitHub and also working through the NixOS - Nix Pills so I’m slowly getting a foothold.

Specifically, it seems I need to create a default.nix file and setup direnv in that directory. If I have something like the following, how would I specify a specific version of the kubernetes package?

stdenv.mkDerivation {
  name = "env";
  buildInputs = [
    kubernetes
  ];
}

Then after that there are some packages not in nix, such as the lastpass command line tool. I need to learn how to download and install that binary from their site. Is there some tutorial or guide I’ve missed in the documentation that covers basics such as these?

Thanks!

Monty

What works well for me is to add an overlay with new or modified packages. On mobile now so I can point you to NixOS - Nixpkgs 21.05 manual (I like to either include the overlay in the repo or fetch a likewise pinned version).

Hi @montyz!

The version of kubernetes depends on which current version is declared in nixpkgs. I assume that the default.nix also contains a first line that would look like this:

with import <nixpkgs> {};
stdenv.mkDerivation {
...

When using <nixpkgs>, it resolves by looking at the NIX_PATH environment variables, which then points to the channel by default.

Because each machine can have a different NIX_PATH or channel checked out a lot of project resolve to pinning the version of nixpkgs. Search “nixpkgs pinning” as there are various variations to it. Just to give an example the new version could look like:

with import ./nixpkgs.nix
stdenv.mkDerivation {
...

Regarding lastpass, lastpass-cli already seem to be packaged, at least in unstable.

If you need to package binaries we have this tutorial Packaging/Binaries - NixOS Wiki
In general I would recommend autoPatchelfHook for new stuff: an example cups-kyodialog3: use autoPatchelfHook, add missing qt4 · NixOS/nixpkgs@ea5787a · GitHub

If this does not work for you can also look at fhsUserEnv as a last resort.

Note that you can also add new packages just within the default.nix that you are using for direnv if dependencies are only needed within the context of the project.

Oh, so what’s the easy way to find packages? My first try was:

$ nix-env -qa lastpass
error: selector 'lastpass' matches no derivations

but now that I know the full name is lastpass-cli, this works:

$ nix-env -qa lastpass-cli
lastpass-cli-1.3.1

This is the best approach:

$ nix search lastpass
* nixpkgs.lastpass-cli (lastpass-cli)
  Stores, retrieves, generates, and synchronizes passwords securely

By my approach is not that sophisticated. I tend to just grep the nixpkgs repo :smiley:

I was hoping specifying a version would be as simple as:

with import <nixpkgs> {};
stdenv.mkDerivation {
  name = "env";
  buildInputs = [
    bashInteractive
    kubernetes
    "lastpass-cli-1.3.1"
  ];
}

However, that doesn’t work. So apparently I have to somehow search the git repo for the version I want, determine the commit where that was introduced, then overlay nixpkgs to point to that version, for that specific package I want to install? Seems like there should be an easier way?

Nix doesn’t have a dependency-resolution mechanism built-in. An overlay would work nicely, or it’s also possible to override some of the package attributes inline:

with import <nixpkgs> {};
stdenv.mkDerivation {
  name = "env";
  buildInputs = [
    bashInteractive
    kubernetes
    (lastpass-cli.overrideAttrs {
       name = "lastpass-cli-1.3.1";
       src = fetchFromGitHub {
         owner = "lastpass";
         repo = "lastpass-cli";
         rev = "v1.3.1";
         sha256 = "11drzmfdvb8ydw1dxaz9zz8rk0jjqmfv076vydz05qqvgx59s38h";
      };
    })
  ];
}

Unless the build instructions have changed that should be enough.

That is very close to what I want, however there is an error I don’t quite understand:

direnv: loading .envrc
direnv: using nix
error: while evaluating the attribute 'buildInputs' of the derivation 'env' at /nix/store/6kk8n31wh67f26d551vxksmvxp4vqpw6-nixpkgs-19.03pre154774.cefd0f7e86b/nixpkgs/pkgs/stdenv/generic/make-derivation.nix:177:11:
while evaluating 'getOutput' at /nix/store/6kk8n31wh67f26d551vxksmvxp4vqpw6-nixpkgs-19.03pre154774.cefd0f7e86b/nixpkgs/lib/attrsets.nix:455:23, called from undefined position:
while evaluating anonymous function at /nix/store/6kk8n31wh67f26d551vxksmvxp4vqpw6-nixpkgs-19.03pre154774.cefd0f7e86b/nixpkgs/pkgs/stdenv/generic/make-derivation.nix:125:17, called from undefined position:
while evaluating 'overrideAttrs' at /nix/store/6kk8n31wh67f26d551vxksmvxp4vqpw6-nixpkgs-19.03pre154774.cefd0f7e86b/nixpkgs/lib/customisation.nix:76:67, called from /Users/montgomeryzukowski/lark/k8s-dev/tools/default.nix:7:6:
while evaluating 'makeOverridable' at /nix/store/6kk8n31wh67f26d551vxksmvxp4vqpw6-nixpkgs-19.03pre154774.cefd0f7e86b/nixpkgs/lib/customisation.nix:67:24, called from /nix/store/6kk8n31wh67f26d551vxksmvxp4vqpw6-nixpkgs-19.03pre154774.cefd0f7e86b/nixpkgs/lib/customisation.nix:77:11:
while evaluating anonymous function at /nix/store/6kk8n31wh67f26d551vxksmvxp4vqpw6-nixpkgs-19.03pre154774.cefd0f7e86b/nixpkgs/lib/customisation.nix:77:28, called from /nix/store/6kk8n31wh67f26d551vxksmvxp4vqpw6-nixpkgs-19.03pre154774.cefd0f7e86b/nixpkgs/lib/customisation.nix:69:12:
while evaluating 'overrideAttrs' at /nix/store/6kk8n31wh67f26d551vxksmvxp4vqpw6-nixpkgs-19.03pre154774.cefd0f7e86b/nixpkgs/pkgs/stdenv/generic/make-derivation.nix:292:28, called from /nix/store/6kk8n31wh67f26d551vxksmvxp4vqpw6-nixpkgs-19.03pre154774.cefd0f7e86b/nixpkgs/lib/customisation.nix:77:34:
attempt to call something which is not a function but a set, at /nix/store/6kk8n31wh67f26d551vxksmvxp4vqpw6-nixpkgs-19.03pre154774.cefd0f7e86b/nixpkgs/pkgs/stdenv/generic/make-derivation.nix:292:55
direnv: error unmarshal() zlib opening: unexpected EOF
direnv: error exit status 1

The issue was that the overrideAttrs function is taking a function instead of a attrset as an argument. Here is a working and a bit re-factored version:

with import <nixpkgs> {};
let
  my-lastpass-cli = lastpass-cli.overrideAttrs (super: {
    name = "lastpass-cli-1.3.1";
    src = fetchFromGitHub {
      owner = "lastpass";
      repo = "lastpass-cli";
      rev = "v1.3.1";
      sha256 = "11drzmfdvb8ydw1dxaz9zz8rk0jjqmfv076vydz05qqvgx59s38h";
    };
  });
in
stdenv.mkDerivation {
  name = "env";
  buildInputs = [
    bashInteractive
    kubernetes
    my-lastpass-cli
  ];
}
1 Like

Oh, good. Now the question is how to find the available versions. For instance I see in the git repo that kubernetes has a 1.9.7 version that I would need to use instead of the current 1.12.1. How would I go about finding that sha256 value that I need?

According to kubernetes package versions - Repology nixpkgs-unstable has the 1.12.1. It also looks like there is a kubectl package that is a lighter version with just the CLI bits, this would allow to download less things from the binary cache.

nixpkgs-unstable also has lastpass-cli 1.3.1 available.

Since it looks like you want bleeding-edge version, it’s possible to start the project on a different channel from the system one.

Try:

$ nix-shell -I nixpkgs=channel:nixpkgs-unstable

Then if you’re happy with this, look for “nixpkgs pinning” for solutions that don’t involve changing the command-line options.

1 Like

Actually the problem is that I need an older version of kubectl, from the 1.9 series. 1.10 and above are incompatible with one of my existing clusters. That said, now that I know how to install a github binary it looks like that is an easier solution for me. My understanding is that I would need to figure out and then pin to an older version of nixpkgs in order to get a 1.9.x version of kubectl and hence get the sha256 for it.

Okay good. If needed it’s also possible to import two or more different versions of nixpkgs and mix them together.