Use bash 5 by default

Hi, relatively new nixos user here:
I’m trying to change the default shell for my user, from bash 4 to bash 5,
so I’ve put

users.users.greg.shell = pkgs.bashInteractive_5;

into my configuration.nix.
But even after # nixos-rebuild switch and reboot my default shell version is still 4.4.23.

$ bash --version
GNU bash, version 4.4.23(1)-release (x86_64-unknown-linux-gnu)
Copyright (C) 2016 Free Software Foundation, Inc.
License GPLv3+: GNU GPL version 3 or later <http://gnu.org/licenses/gpl.html>

This is free software; you are free to change and redistribute it.
There is NO WARRANTY, to the extent permitted by law.

$ ls -l $(which bash)
lrwxrwxrwx 1 root root 77  1. Jan 1970  /run/current-system/sw/bin/bash -> /nix/store/s9l4454hlkrbj5fd5yv1dr9xz1daqswj-bash-interactive-4.4-p23/bin/bash

What am I doing wrong here?

System information:

$ nix run nixpkgs.nix-info -c nix-info -m
  - system: `"x86_64-linux"`
  - host os: `Linux 5.3.1-hardened, NixOS, 20.03pre194293.2436c27541b (Markhor)`
  - multi-user?: `yes`
  - sandbox: `yes`
  - version: `nix-env (Nix) 2.3`
  - channels(root): `"nixos-20.03pre194293.2436c27541b"`
  - nixpkgs: `/nix/var/nix/profiles/per-user/root/channels/nixos`

Update as of 2019-09-30 19:53 CEST:
I’ve tried to run bashInteractive_5 via nix, this seems to be working OK. But default bash is still symlinked to bash 4.

$ nix run nixpkgs.bashInteractive_5 -c bash --version
GNU bash, version 5.0.9(1)-release (x86_64-pc-linux-gnu)
Copyright (C) 2019 Free Software Foundation, Inc.
License GPLv3+: GNU GPL version 3 or later <http://gnu.org/licenses/gpl.html>

This is free software; you are free to change and redistribute it.
There is NO WARRANTY, to the extent permitted by law.

Are Greg? I mean login as Greg. What’s in your /etc/passwd ?

Yep, everything seems to be right there

$ whoami
greg

$ grep $(whoami) /etc/passwd 
greg:x:1000:100::/home/greg:/run/current-system/sw/bin/bash

Could you try something different, like zsh, and see if it makes difference?

It looks like the way user configuration works is it takes the package’s shellPath attribute and tacks it on to /run/current-system/sw. In bash's case the shellPath is /bin/bash, so this ends up as /run/current-system/sw/bin/bash.

Which is to say, this appears to only work if you actually install the same shell as a system package.

It’s not clear to me why it’s done this way instead of making it relative to the package’s out path. On my NixOS system /etc/shells includes both the system package versions of the shells as well as the full store path to them.

In any case, the alternative is to specify the path to the shell instead, so you could try something like

users.users.greg.shell = "${pkgs.bashInteractive_5}${pkgs.bashInteractive_5.shellPath}";

If this needs to be a literal path instead of a string you could do /. + "…" instead, though I expect the string to be fine.

You may also need to add this to your environment.shells. I think the shell modules do this normally, but if you’re not enabling the shell’s module then it won’t work.

It is done like that so that updates get a chance to work, you are not stuck with the old shell until next reboot.

It also avoids issues where the shell path gets garbage collected, as /etc/passwd it not tracked in the derivation. In this case the proper workaround is to either define a bash5 alias to bash 5, and use that, or install bash 5 as the system bash.

Not too sure about using a path in the nix store directly. I need to think more about it. But you may experience various login refusals, from ssh to the whole system. The shell won’t be in /etc/shells for a start.

TL;DR please test and ensure you have a backup access in case of issues.

If you add it to environment.shells then it should end up in etc.shells. That uses the same utils.toShellPath helper that /etc/passwd does.

I’ve been running nix-installed bash5 on macOS (with nix-darwin) for the past few months. I’m not sure this is helpful since:

  • Obviously not nixos
  • I haven’t tried to port this change from my macbook back to my nixos system yet
  • I wasn’t trying to set it for a specific user as you are

Still, on the off chance it does help, I accomplished it with something like this:

# .config/nixpkgs/overlays/overrides.nix
self: super: {
	bashInteractive = super.bashInteractive_5;
}

# .nixpkgs/darwin-configuration.nix
...
environment.shells = with pkgs; [ bashInteractive ];
...

FWIW, my macos bootstrap script also has to:

  • replace the system /etc/shells with the one nix-darwin generates, and
  • sudo chsh -s $(which bash) username