NixOS / nix

Nix, the purely functional package manager
https://nixos.org/
GNU Lesser General Public License v2.1
11.48k stars 1.44k forks source link

Nix remote store commands (ping, copy etc..) don't work with Fish shell #11010

Open fzakaria opened 3 days ago

fzakaria commented 3 days ago

Describe the bug

I cannot seem to use any Nix commands that work with a remote store over SSH or SSH-NG using the Fish shell.

Steps To Reproduce

❯ SHELL=$(which fish) nix store ping --store ssh://nixie
Store URL: ssh://nixie
error: failed to start SSH connection to 'nixie'

❯ SHELL=$(which bash) nix store ping --store ssh://nixie
Store URL: ssh://nixie

It matters what is $SHELL in the environment and not actually the current active shell. This took me a long time to figure out the culprit but I'm not sure the cause.

Expected behavior

Should work regardless of shell.

nix-env --version output

nix-env (Nix) 2.18.2

Additional context

Running NixOS 24.05

Priorities

Add :+1: to issues you find important.

cole-h commented 2 days ago

I can't reproduce this on Nix 2.18.2 or Nix 2.24.0pre20240617_daf1b6b:

$ nix store ping --store ssh://root@192.168.1.55
warning: 'nix store ping' is a deprecated alias for 'nix store info'
Store URL: ssh://root@192.168.1.55
$ echo $status
0
$ echo $SHELL
/run/current-system/sw/bin/fish
$ nix --version
nix (Nix) 2.24.0pre20240617_daf1b6b

$ nix shell nixpkgs#nixVersions.nix_2_18
$ nix store ping --store ssh://root@192.168.1.55
Store URL: ssh://root@192.168.1.55
$ echo $status
0
$ echo $SHELL
/run/current-system/sw/bin/fish
$ nix -- version
nix (Nix) 2.18.2

Could it possibly be a configuration issue in your SSH / fish configs?

fzakaria commented 2 days ago

Yea -- my friend (@markrwilliams) who helped me debug this couldn't reproduce it with basic Fish so something from my config.

Here is my full fish config:

{
  config,
  pkgs,
  lib,
  ...
}: {
  programs.fish = {
    enable = true;

    shellAliases = {
    };

    functions = {
      # TODO(fzakaria): This can be removed when https://github.com/zimbatm/h/pull/12 is landed
      h = {
        body = ''
          set _h_dir $(${pkgs.h}/bin/h --resolve $(path resolve ${config.programs.h.codeRoot}) $argv)
          set _h_ret $status
          if test "$_h_dir" != "$PWD"
            cd "$_h_dir"
          end
          return $_h_ret
        '';
        wraps = "h";
      };
      # disable welcome message
      fish_greeting = "fish_prompt";
      nix-closure-size = {
        body = ''
          nix path-info --recursive --size --closure-size \
                        --human-readable $(readlink -f $(which $program))
        '';
        argumentNames = ["program"];
      };
      # Got this sweet function from HackerNews
      frg = ''
            set result (rg --ignore-case --color=always --line-number --no-heading "$argv" |
            fzf --ansi \
                --color 'hl:-1:underline,hl+:-1:underline:reverse' \
                --delimiter ':' \
                --preview "bat --color=always {1} --theme='Solarized (light)' --highlight-line {2}" \
                --preview-window 'up,60%,border-bottom,+{2}+3/3,~3')
        set file (echo $result | cut -d: -f1)
        set linenumber (echo $result | cut -d: -f2)
        if test -n "$file"
            $EDITOR +"$linenumber" "$file"
        end
      '';
    };

    shellInit = ''
      tide configure --auto --style=Lean --prompt_colors='True color' \
                     --show_time='24-hour format' --lean_prompt_height='Two lines' \
                     --prompt_connection=Disconnected --prompt_spacing=Sparse \
                     --icons='Many icons' --transient=Yes
      fzf_configure_bindings --directory=\cf --processes=\cp --git_log=\cl

      set fzf_diff_highlighter delta --paging=never --width=20
    '';
  };

  home.packages = with pkgs.fishPlugins; [
    fzf-fish
    done
    tide
  ];
}

Must be something from the plugins.

In any case, is there something we can augment in Nix to circumvent anyone's config for this? Maybe always default to some shell that's non configurable?

roberth commented 1 day ago

Could you try with https://github.com/NixOS/nix/pull/11021?

nix run github:hercules-ci/nix/issue-11010 -- store info --store ssh://nixie
fzakaria commented 1 day ago

This gets us closer @roberth That fixes the local command but i"m also SSH into nixie where my default is fish there too where it gives.

❯ nix run github:hercules-ci/nix/issue-11010 -- store info --store ssh://nixie.tail9f4b5.ts.net
Store URL: ssh://nixie.tail9f4b5.ts.net
TERM environment variable not set.
error: 'nix-store --serve' protocol mismatch from 'nixie.tail9f4b5.ts.net', got '
       (B

       ��RT'

So the login shell on the other side also needs to be /bin/sh ?

fzakaria commented 1 day ago

Sounds like https://github.com/fish-shell/fish-shell/issues/5394 is how Fish is different than Bash (CC @markrwilliams whose helped me debug this thus far that it's Fish doing something wonky)

nevertheless, I think Nix can harden itself against it.

roberth commented 1 day ago

On the remote end we could get rid of the shell by using an SSH "subsystem", just like sftp does. This does require configuration on the remote, but if you're using NixOS or perhaps even nix-darwin, that shouldn't be an issue. We could make this easy with configuration managers like NixOS/nix-darwin/NixBSD though.