nix-darwin
nix-darwin copied to clipboard
Still cannot set fish as default shell
This is probably a regression of #328, #779, and #811, which were considered fixed:
Updating
/etc/shellsmanually or viaenvironment.shellsshould no longer be necessary since #1118 as long as you set the shell you want to use withusers.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
You'll need to add yourself to users.knownUsers
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.
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 👍
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!
I agree that we should emit a warning, feel free to open a PR
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?
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
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.
any update on this