nix-darwin icon indicating copy to clipboard operation
nix-darwin copied to clipboard

Still cannot set fish as default shell

Open nalzok opened this issue 11 months ago • 9 comments

This is probably a regression of #328, #779, and #811, which were considered fixed:

Updating /etc/shells manually or via environment.shells should no longer be necessary since #1118 as long as you set the shell you want to use with users.users.<user>.shell = pkgs.fish;

However, the following configuration doesn't seem to work on a fresh copy of macOS 15.2 (24C101).

{
  description = "Example nix-darwin system flake";

  inputs = {
    nixpkgs.url = "github:NixOS/nixpkgs/nixpkgs-unstable";
    nix-darwin.url = "github:LnL7/nix-darwin";
    nix-darwin.inputs.nixpkgs.follows = "nixpkgs";
  };

  outputs = inputs@{ self, nix-darwin, nixpkgs }:
  let
    configuration = { pkgs, ... }: {
      # List packages installed in system profile. To search by name, run:
      # $ nix-env -qaP | grep wget
      environment.systemPackages = [
      ];

      # Necessary for using flakes on this system.
      nix.settings.experimental-features = "nix-command flakes";

      # Enable alternative shell support in nix-darwin.
      programs.zsh.enable = true;
      programs.fish.enable = true;

      # Set Git commit hash for darwin-version.
      system.configurationRevision = self.rev or self.dirtyRev or null;

      # Used for backwards compatibility, please read the changelog before changing.
      # $ darwin-rebuild changelog
      system.stateVersion = 5;

      # The platform the configuration will be used on.
      nixpkgs.hostPlatform = "aarch64-darwin";

      # Set fish as the default shell
      users.users.qys.shell = pkgs.fish;
    };
  in
  {
    # Build darwin flake using:
    # $ darwin-rebuild build --flake .#gloaming
    darwinConfigurations."gloaming" = nix-darwin.lib.darwinSystem {
      modules = [
        configuration
      ];
    };
  };
}

After I logout and login again, the default shell is still /bin/zsh. Manually calling chsh fails, and /etc/shells doesn't seem to be updated:

$ dscl . -read ~/ UserShell                                                   
UserShell: /bin/zsh

$ chsh -s /run/current-system/sw/bin/fish
Changing shell for qys.
Password for qys: 
chsh: /run/current-system/sw/bin/fish: non-standard shell

$ cat /etc/shells 
# List of acceptable shells for chpass(1).
# Ftpd will not allow users to connect who are not using
# one of these shells.

/bin/bash
/bin/csh
/bin/dash
/bin/ksh
/bin/sh
/bin/tcsh
/bin/zsh

nalzok avatar Dec 26 '24 07:12 nalzok

You'll need to add yourself to users.knownUsers

Enzime avatar Dec 26 '24 07:12 Enzime

Ah thanks! I added users.knownUsers = [ "qys" ];, but it gave me an error

darwin-rebuild switch --flake ~/.config/nix-darwin
building the system configuration...
error:
       … while calling the 'derivationStrict' builtin
         at <nix/derivation-internal.nix>:34:12:
           33|
           34|   strict = derivationStrict drvAttrs;
             |            ^
           35|

       … while evaluating derivation 'darwin-system-25.05.20241223.de18642+darwin5.a35b08d'
         whose name attribute is located at /nix/store/73cnf2k7mji95fcflvay15pdw4skhhk5-source/pkgs/stdenv/generic/make-derivation.nix:375:7

       … while evaluating attribute 'activationScript' of derivation 'darwin-system-25.05.20241223.de18642+darwin5.a35b08d'
         at /nix/store/9w5mmnkypiqczdlvmc4l2hd4xc3m44bq-source/modules/system/default.nix:97:7:
           96|
           97|       activationScript = cfg.activationScripts.script.text;
             |       ^
           98|       activationUserScript = cfg.activationScripts.userScript.text;

       … while evaluating the option `system.activationScripts.script.text':

       … while evaluating definitions from `/nix/store/9w5mmnkypiqczdlvmc4l2hd4xc3m44bq-source/modules/system/activation-scripts.nix':

       … while evaluating the option `system.activationScripts.users.text':

       … while evaluating definitions from `/nix/store/9w5mmnkypiqczdlvmc4l2hd4xc3m44bq-source/modules/users':

       … while evaluating the option `users.uids':

       … while evaluating definitions from `/nix/store/9w5mmnkypiqczdlvmc4l2hd4xc3m44bq-source/modules/users':

       … while evaluating the option `users.users.qys.uid':

       (stack trace truncated; use '--show-trace' to show the full, detailed trace)

       error: The option `users.users.qys.uid' was accessed but has no value defined. Try setting the option.

It turns out that I also need to specify my uid. I believe uid should default to 501, so the fact that I have to manually specify uid is probably a (minor) bug?

# Set fish as the default shell
users.knownUsers = [ "qys" ];
users.users.qys.uid = 501;
users.users.qys.shell = pkgs.fish;

In addition, the document for users.knownUsers looks pretty scary. Is this fine?

List of users owned and managed by nix-darwin. Used to indicate what users are safe to create/delete based on the configuration. Don’t add the admin user or other system users to this.

nalzok avatar Dec 26 '24 07:12 nalzok

Yeah it's fine, there are safeguards in place, I don't have the time at the moment to update the docs, but if you could open a PR to update it I would review it 👍

Enzime avatar Dec 26 '24 07:12 Enzime

Today is literally the first time I tried Nix, so I don't feel confident enough to update the docs right now (e.g., I'm not sure if the default user id is indeed 501, and if so, why I needed to specify it explicitly; I also think it's better to emit a warning instead of silently ignoring the configuration when we cannot "find" the user). Will try to help in the future though!

nalzok avatar Dec 26 '24 07:12 nalzok

I agree that we should emit a warning, feel free to open a PR

Enzime avatar Dec 26 '24 07:12 Enzime

As a follow up question: how does this work with home-manager? I am confused because there are two programs.fish modules: one by nix-darwin and another by home-manager. It's probably a bad idea to enable both because that would be redundant and may cause inconsistency. Since I want to set fish as the default shell, I have to use the module from nix-darwin. Now, the document of home-manager specifies that

If you do not plan on having Home Manager manage your shell configuration then you must add either

. "$HOME/.nix-profile/etc/profile.d/hm-session-vars.sh"

or

. "/etc/profiles/per-user/$USER/etc/profile.d/hm-session-vars.sh"

to your shell configuration, depending on whether home-manager.useUserPackages is enabled. This file can be sourced directly by POSIX.2-like shells such as Bash or Z shell. Fish users can use utilities such as foreign-env or babelfish.

Since programs.fish.enable = false; in home-manager, now I need to manually put . "/etc/profiles/per-user/$USER/etc/profile.d/hm-session-vars.sh" in ~/.config/fish/config.fish and configure foreign-env or babelfish to do the translation, which seems non-trivial.

In some sense, home-manager works by setting environment variables in these scripts, so it's very important to source them properly. For example, I have programs.neovim = {enable = true; defaultEditor = true; }; in the home-manager configuration. This translates to the following initialization script

$ cat "/etc/profiles/per-user/$USER/etc/profile.d/hm-session-vars.sh"
# Only source this once.
if [ -n "$__HM_SESS_VARS_SOURCED" ]; then return; fi
export __HM_SESS_VARS_SOURCED=1

export EDITOR="nvim"

Without . "/etc/profiles/per-user/$USER/etc/profile.d/hm-session-vars.sh", the default editor would still be nano instead of nvim.

What's the proper way to source the initialization script created by home-manager in the programs.fish module managed by nix-darwin?

nalzok avatar Dec 27 '24 05:12 nalzok

I remember for ZSH you need programs.zsh.enable = true; in both nix-darwin and home-manager, so i suspect the same is true for fish

Samasaur1 avatar Dec 27 '24 08:12 Samasaur1

What's the proper way to source the initialization script created by home-manager in the programs.fish module managed by nix-darwin?

In my case, I specify a posix shell like bash, zsh, and dash as the login shell (or system layer shell). I also enable the option 'programs.fish.enable' in my nix-darwin config file, By doing so, nix-darwin will generate the enviroment setup scripts in /etc/fish for fish but don't set fish as default shell. Then I enable the 'programs.fish.enable' option in my home-manager, At last, I specific fish as the terminal shell (shell options in kitty.conf).

So I can use fish like a default shell that all nix env sourced when I open a kitty terminal.

shusoyo avatar Dec 30 '24 06:12 shusoyo

any update on this

phucisstupid avatar Aug 18 '25 03:08 phucisstupid