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 = 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 <>

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 <>

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

$ grep $(whoami) /etc/passwd 

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 = "${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.

1 Like

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

Any help with how to do that? Can’t seem to find it. :laughing:

Well here is a way to get bash5 in /run/current-system/sw/bin/bash.
:warning: Not tested on my live system;
:warning: May break some stuff;
:warning: Try in vm before;
:warning: Etc, etc, etc.
:white_check_mark: Could also work just like that :slight_smile:
:white_check_mark: You can go ahead an just trust nixos rollback in case of emergency :smiley:

environment.systemPackages = [
    (lib.hiPrio pkgs.bashInteractive_5)

Thanks for the help! I tried your suggestion and it gives “undefined variable ‘lib’”.

he probably has lib exposed at a global level, you could also change lib -> pkgs.lib and that should work

1 Like

Thank you @jonringer and @layus ! Worked like a charm! (Rebuilt almost everything, but that’s okay.) Here’s what I ended up using (after testing, and not including all my other packages):

  environment = {
    systemPackages = with pkgs; [
      (lib.hiPrio bashInteractive_5)

Edit: It does throw some errors upon the first upgrade after doing this. It has to relocate some symlinks to the original BASH version. I’ve tested everything that I use, though, and everything seems to be working normally. Don’t know. Maybe it causes issues down the road, maybe it doesn’t. Good thing about NixOS, doing a completely fresh install is painless!

Nice to hear that it worked :-). If you still have a copy of the warnings emitted and the weird stuff that happened, it may be wise to collect them in a gist, or in an issue / PR on the github. So others can find it, and it could help if we ever decide to switch to bash5 by default. You could even devise a nixos option for that :-).