Unable to set or use ZSH shell from standalone Home Manager (using Flakes)

Hi - I am trying to set and use ZSH shell from a standalone Home Manager installation on Arch Linux.

Using the following flake.nix:

{
  description = "Home Manager configuration of tim";

  inputs = {
    # Specify the source of Home Manager and Nixpkgs.
    nixpkgs.url = "github:nixos/nixpkgs/nixos-unstable";
    home-manager = {
      url = "github:nix-community/home-manager";
      inputs.nixpkgs.follows = "nixpkgs";
    };
  };

  outputs = { nixpkgs, home-manager, ... }:
    let
      system = "x86_64-linux";
      pkgs = nixpkgs.legacyPackages.${system};
    in {
      homeConfigurations."tim" = home-manager.lib.homeManagerConfiguration {
        inherit pkgs;

        # Specify your home configuration modules here, for example,
        # the path to your home.nix.
        modules = [ ./home.nix ];

        # Optionally use extraSpecialArgs
        # to pass through arguments to home.nix
      };

    programs.zsh.enable = true;
    targets.genericLinux.enable = true;
    environment.shells = with pkgs; [ zsh ];
    #users.defaultUserShell = pkgs.zsh;

    };
}

home.nix imports the following shell.nix:

{ config, pkgs, lib, users, ... }:

{

programs.zsh.enable = true;

programs.zsh = {
  shellAliases = {
    ll = "ls -l";
    update = "home-manager switch --flake ~/hmconf";
  };
  history = {
    size = 10000;
    path = "${config.xdg.dataHome}/zsh/history";
  };
  zplug = {
    enable = true;
    plugins = [
      { name = "zsh-users/zsh-autosuggestions"; } # Simple plugin installation
    ];
  };
 };

 home.username = "tim";
 home.homeDirectory = "/home/tim";

}

The above two flakes after running do not add ZSH to /etc/shells.

I have tried manually adding the nix ZSH path to /etc/shells and changing the shell with:

chsh tim

Is there a limitation to using standalone home manager in stopping ZSH being activated or being added to /etc/shells for use?

Many thanks in advance for your advice.

1 Like

Yes, unfortunately editing /etc/shells requires root permissions, but standalone home-manager doesn’t have that. You would also need to set the shells for all other users, which isn’t really what you want home-manager to do.

In the past, I did what you are doing, just adding the zsh path to /etc/shells manually. Alternatively you could add exec zsh to your ~/.bash_profile, making sure that runs after the home-manager activation.

1 Like

Thank you TLATER!

I edited /etc/shells with the path to zsh within nix profile. I ran chsh to the zsh path in nix profiles (found with using which zsh) before ahving to reboot for the changed shell to take effect.

Yes, that will be required, though I think relogging may be enough?

Note you will need to repeat this every time the zsh location changes, which will be frequent, since any change in its dependencies will cause NixOS to create a new binary/store path.

your suggestion of exec zsh in .bash_profile works but feels a bit awkward. I’m on macOS and wondering if there’s a “better way”? Perhaps some esoteric setting? Anyway, thanks @TLATER

I encountered a similar issue when attempting to use the standalone Nix Home Manager on Debian.

It turns out that if I use the Zsh shell provided by Debian, the directory path for the Nix package manager (and Home Manager) is not included in the $PATH. As a result, I am unable to use any programs installed via Nix.

However, when I add the Zsh provided by Nix to /etc/shells and set the user’s $SHELL to /home/myusername/.nix-profile/bin/zsh, the Nix package manager’s directory path (and Home Manager’s) gets included in $PATH, allowing me to use Nix Home Manager without any issues.

Why does nix-home-manager only function correctly when the Nix-provided Zsh is set as the default $SHELL but fails with the Debian-provided Zsh?

I’d wager that using the nix-provided one ends up loading the default rcfile from /nix/store, which correctly sets up your env to include your nix profile.

You likely missed a note saying you need to source a specific file as part of your system-wide zsh rcfiles in the home-manager/nix installation instructions.

Hey ! I had the same issue, and wanted it to be automatically done via home-manager (standalone install). Here is what I came up with in my homeManagerConfiguration home:

    # Set zsh as default shell on activation
    activation.make-zsh-default-shell = lib.hm.dag.entryAfter [ "writeBoundary" ] ''
      # if zsh is not the current shell
        PATH="/usr/bin:/bin:$PATH"
        ZSH_PATH="/home/${user}/.nix-profile/bin/zsh"
        if [[ $(getent passwd ${user}) != *"$ZSH_PATH" ]]; then
          echo "setting zsh as default shell (using chsh). password might be necessay."
          if grep -q $ZSH_PATH /etc/shells; then
            echo "adding zsh to /etc/shells"
            run echo "$ZSH_PATH" | sudo tee -a /etc/shells
          fi
          echo "running chsh to make zsh the default shell"
          run chsh -s $ZSH_PATH ${user}
          echo "zsh is now set as default shell !"
        fi
    '';

It first checks if the default shell is already zsh, and if not adds it to /etc/shells (if not already in it) and then makes it default via chsh.

It does require the password, and to be a sudoer tho

Hope it helps some lost souls on the internet :slight_smile: