Sudo doesn't work on zsh

Hello there, It is me once again! This time my problem is, when I change the the default shell to zsh and restart I cant run sudo with it. I mean I can run sudo but sudo can’t run with any other command. It worked fine with bash.

Did you install zsh with programs.zsh.enable = true?

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

To be exact.

Are your packages installed with home-manager or globally? It sounds like root doesn’t have the correct path. Try running your command with sudo -E, this will preserve your environment when running the command.

1 Like

I don’t use home manager, so everything is in my conf.nix. Sudo -E also didn’t work, unfortunately.

I’m not sure then. Are you able to share your configuration?

Sure:

# Edit this configuration file to define what should be installed on
# your system.  Help is available in the configuration.nix(5) man page
# and in the NixOS manual (accessible by running ‘nixos-help’).

{ config, pkgs, ... }:

{
  imports =
    [ # Include the results of the hardware scan.
      ./hardware-configuration.nix
    ];

  # Bootloader.
  boot.loader.systemd-boot.enable = true;
  boot.loader.efi.canTouchEfiVariables = true;
  boot.supportedFilesystems = [ "ntfs" ];

  networking.hostName = "nixos"; # Define your hostname.
  # networking.wireless.enable = true;  # Enables wireless support via wpa_supplicant.

  # Configure network proxy if necessary
  # networking.proxy.default = "http://user:password@proxy:port/";
  # networking.proxy.noProxy = "127.0.0.1,localhost,internal.domain";

  # Enable networking
  networking.networkmanager.enable = true;

  # Set your time zone.
  time.timeZone = "Europe/Istanbul";

  # Select internationalisation properties.
  i18n.defaultLocale = "en_US.UTF-8";

  i18n.extraLocaleSettings = {
    LC_ADDRESS = "en_GB.UTF-8";
    LC_IDENTIFICATION = "en_GB.UTF-8";
    LC_MEASUREMENT = "en_GB.UTF-8";
    LC_MONETARY = "en_GB.UTF-8";
    LC_NAME = "en_GB.UTF-8";
    LC_NUMERIC = "en_GB.UTF-8";
    LC_PAPER = "en_GB.UTF-8";
    LC_TELEPHONE = "en_GB.UTF-8";
    LC_TIME = "en_GB.UTF-8";
  };

  # Enable the X11 windowing system.
  services.xserver.enable = true;

  # Enable the KDE Plasma Desktop Environment.
  services.xserver.displayManager.sddm.enable = true;
  services.xserver.desktopManager.plasma5.enable = true;
  services.xserver.desktopManager.gnome.enable = true;
  services.xserver.windowManager.openbox.enable = true;
  programs.ssh.askPassword = pkgs.lib.mkForce "${pkgs.ksshaskpass.out}/bin/ksshaskpass";

  # Configure keymap in X11
  services.xserver = {
    layout = "--";
    xkbVariant = "";
  };

  services.flatpak.enable = true;

  # Configure console keymap
  console.keyMap = "--";

  # Enable CUPS to print documents.
  services.printing.enable = true;

  # Enable sound with pipewire.
  sound.enable = true;
  hardware.pulseaudio.enable = false;
  security.rtkit.enable = true;
  services.pipewire = {
    enable = true;
    alsa.enable = true;
    alsa.support32Bit = true;
    pulse.enable = true;
    # If you want to use JACK applications, uncomment this
    jack.enable = true;

    # use the example session manager (no others are packaged yet so this is enabled by default,
    # no need to redefine it in your config for now)
    #media-session.enable = true;
  };

  # Enable touchpad support (enabled default in most desktopManager).
  # services.xserver.libinput.enable = true;

  programs.zsh.enable = true;
  users.defaultUserShell = pkgs.zsh;
  environment.shells = with pkgs; [ zsh ];
  
  # Define a user account. Don't forget to set a password with ‘passwd’.
  users.users.user = {
    isNormalUser = true;
    description = "user";
    extraGroups = [ "networkmanager" "wheel" ];
    packages = with pkgs; [
      firefox
      kate
      thunderbird
      mpv
      skypeforlinux
      gnome.gnome-tweaks
      dropbox
      deadbeef
      qview
      shortwave
      selectdefaultapplication
      networkmanagerapplet
      networkmanager
      obconf
      pulsemixer
      libsForQt5.kolourpaint
      marktext
      vscodium
      jetbrains-toolbox
      audacity
      libsForQt5.kfind
      btop
      flameshot
      neofetch
      trash-cli
      virtualbox
      virt-manager
      wine
      xclip
      gtk2fontsel
      protonvpn-gui
      qbittorrent
      zoom-us
      devour
      hunspell
      aspell
      aspellDicts.tr
      alacritty
      zsh
      fff
      dunst
      picom
      polybar
      rofi
      sxhkd
      tint2
      xidlehook
      xob
      nitrogen
      libnotify
      gnome.zenity
      tdrop
      bspwm
      openbox
      qtile
      doomrunner
      lutris
      steam
      stalonetray
      i3lock-color
      nerdfonts
      corefonts
      font-awesome
      google-fonts
      noto-fonts-emoji
      noto-fonts
      terminus_font
      terminus_font_ttf
      terminus-nerdfont
      python311Packages.pip
    ];
  };

environment.gnome.excludePackages = (with pkgs; [
  gnome-photos
  gnome-tour
  gnome-connections
  gnome-console
]) ++ (with pkgs.gnome; [
  cheese
  gnome-calculator
  gnome-contacts
  gnome-clocks
  gnome-maps
  gnome-music
  gnome-terminal
  gnome-weather
  gnome-system-monitor
  gnome-disk-utility
  gnome-logs
  gnome-font-viewer
  gnome-calendar
  nautilus
  yelp
  simple-scan
  gedit
  epiphany
  geary
  evince
  gnome-characters
  totem
  tali
  iagno
  hitori
  atomix
  gedit
  eog
  baobab
  file-roller
  seahorse
]);

environment.plasma5.excludePackages = with pkgs.libsForQt5; [
  elisa
  gwenview
  oxygen
  khelpcenter
  print-manager
];
  # Allow unfree packages
  nixpkgs.config.allowUnfree = true;

  # List packages installed in system profile. To search, run:
  # $ nix search wget
  environment.systemPackages = with pkgs; [
    wget
    micro
    git
    udiskie
    qt5ct
    lxappearance
    flatpak
    python3
    steam-run
    killall
    xorg.xkill
    gnome.dconf-editor
    gnome-extension-manager
	gnomeExtensions.dash-to-dock
	gnomeExtensions.compiz-alike-magic-lamp-effect
	gnomeExtensions.compiz-windows-effect
	gnomeExtensions.just-perfection
	gnomeExtensions.space-bar
  ];

  qt.platformTheme = "qt5ct";

  # Some programs need SUID wrappers, can be configured further or are
  # started in user sessions.
  # programs.mtr.enable = true;
  # programs.gnupg.agent = {
  #   enable = true;
  #   enableSSHSupport = true;
  # };

  # List services that you want to enable:

  # Enable the OpenSSH daemon.
  # services.openssh.enable = true;

  # Open ports in the firewall.
  # networking.firewall.allowedTCPPorts = [ ... ];
  # networking.firewall.allowedUDPPorts = [ ... ];
  # Or disable the firewall altogether.
  # networking.firewall.enable = false;

  # This value determines the NixOS release from which the default
  # settings for stateful data, like file locations and database versions
  # on your system were taken. It‘s perfectly fine and recommended to leave
  # this value at the release version of the first install of this system.
  # Before changing this value read the documentation for this option
  # (e.g. man configuration.nix or on https://nixos.org/nixos/options.html).
  system.stateVersion = "23.05"; # Did you read the comment?

}

Does sudo wget --help work?

Yes it does, although there is no autocompletion but for example sudo nixos-rebuild switch does not.

I’m surprised it finds wget but not nixos-rebuild. Your config suggests they’d both be linked in /run/current-system/sw/bin/.

A PATH suitable for looking up one should support looking up the other. Since you’re invoking through sudo, there shouldn’t be any shell functions in the way. There’s an outside chance aliases could interfere, I guess.

What does type -a sudo wget nixos-rebuild report if you run it from both bash and zsh?

Zsh:

sudo is an alias for nocorrect sudo
sudo is /run/wrappers/bin/sudo
sudo is /run/current-system/sw/bin/sudo
wget is /run/current-system/sw/bin/wget
nixos-rebuild is /run/current-system/sw/bin/nixos-rebuild

Bash:

sudo is /run/wrappers/bin/sudo
sudo is /run/current-system/sw/bin/sudo
wget is /run/current-system/sw/bin/wget
nixos-rebuild is /run/current-system/sw/bin/nixos-rebuild

Well, that explains the autocompletion bit.

I don’t know zsh, but it sounds like this should be fine.

I’m incredulous enough to need to ask: can you provide the exact output of the following two commands in zsh?

  • sudo PAGER=head nixos-rebuild --help
  • sudo wget --version
nixos-rebu... Nixpkgs System Manager's Manual nixos-rebu...

NAME
     nixos-rebuild — reconfigure a NixOS machine

SYNOPSIS
     nixos-rebuild {switch | boot | test | build |
                   dry-build | dry-activate | edit |
                   build-vm | build-vm-with-bootloader}
                   [--upgrade | --upgrade-all]
GNU Wget 1.21.4 built on linux-gnu.

-cares +digest -gpgme +https +ipv6 +iri +large-file -metalink +nls
+ntlm +opie -psl +ssl/openssl

Wgetrc:
    /nix/store/d3kkv9vjb3ljh7hr5v38gls8iykvwkny-wget-1.21.4/etc/wgetrc (system)
Locale:
    /nix/store/d3kkv9vjb3ljh7hr5v38gls8iykvwkny-wget-1.21.4/share/locale

Copyright (C) 2015 Free Software Foundation, Inc.
License GPLv3+: GNU GPL version 3 or later
<http://www.gnu.org/licenses/gpl.html>.
This is free software: you are free to change and redistribute it.
There is NO WARRANTY, to the extent permitted by law.

Originally written by Hrvoje Niksic <hniksic@xemacs.org>.
Please send bug reports and questions to <bug-wget@gnu.org>.

That’s what I’d expect, though I’m not sure how it squares with your earlier statement:

What happens if you run neofetch and sudo neofetch in both bash and zsh?

Neofetch does run in every four situations. sudo nixos-rebuild switch doesn’t run in zsh. Also, the auto-completion thing might be on my part since I have my own (stolen) script for that.
Here is that script:

# completion system

# called later (via is4 && grmlcomp)
# note: use 'zstyle' for getting current settings
#         press ^xh (control-x h) for getting tags in context; ^x? (control-x ?) to run complete_debug with trace output
function grmlcomp () {
    # TODO: This could use some additional information

    # Make sure the completion system is initialised
    (( ${+_comps} )) || return 1

    # allow one error for every three characters typed in approximate completer
    zstyle ':completion:*:approximate:'    max-errors 'reply=( $((($#PREFIX+$#SUFFIX)/3 )) numeric )'

    # don't complete backup files as executables
    zstyle ':completion:*:complete:-command-::commands' ignored-patterns '(aptitude-*|*\~)'

    # start menu completion only if it could find no unambiguous initial string
    zstyle ':completion:*:correct:*'       insert-unambiguous true
    zstyle ':completion:*:corrections'     format $'%{\e[0;31m%}%d (errors: %e)%{\e[0m%}'
    zstyle ':completion:*:correct:*'       original true

    # activate color-completion
    zstyle ':completion:*:default'         list-colors ${(s.:.)LS_COLORS}

    # format on completion
    zstyle ':completion:*:descriptions'    format $'%{\e[0;31m%}completing %B%d%b%{\e[0m%}'

    # automatically complete 'cd -<tab>' and 'cd -<ctrl-d>' with menu
    # zstyle ':completion:*:*:cd:*:directory-stack' menu yes select

    # insert all expansions for expand completer
    zstyle ':completion:*:expand:*'        tag-order all-expansions
    zstyle ':completion:*:history-words'   list false

    # activate menu
    zstyle ':completion:*:history-words'   menu yes

    # ignore duplicate entries
    zstyle ':completion:*:history-words'   remove-all-dups yes
    zstyle ':completion:*:history-words'   stop yes

    # match uppercase from lowercase
    zstyle ':completion:*'                 matcher-list 'm:{a-z}={A-Z}'

    # separate matches into groups
    zstyle ':completion:*:matches'         group 'yes'
    zstyle ':completion:*'                 group-name ''

    if [[ "$NOMENU" -eq 0 ]] ; then
        # if there are more than 5 options allow selecting from a menu
        zstyle ':completion:*'               menu select=5
    else
        # don't use any menus at all
        setopt no_auto_menu
    fi

    zstyle ':completion:*:messages'        format '%d'
    zstyle ':completion:*:options'         auto-description '%d'

    # describe options in full
    zstyle ':completion:*:options'         description 'yes'

    # on processes completion complete all user processes
    zstyle ':completion:*:processes'       command 'ps -au$USER'

    # offer indexes before parameters in subscripts
    zstyle ':completion:*:*:-subscript-:*' tag-order indexes parameters

    # provide verbose completion information
    zstyle ':completion:*'                 verbose true

    # recent (as of Dec 2007) zsh versions are able to provide descriptions
    # for commands (read: 1st word in the line) that it will list for the user
    # to choose from. The following disables that, because it's not exactly fast.
    zstyle ':completion:*:-command-:*:'    verbose false

    # set format for warnings
    zstyle ':completion:*:warnings'        format $'%{\e[0;31m%}No matches for:%{\e[0m%} %d'

    # define files to ignore for zcompile
    zstyle ':completion:*:*:zcompile:*'    ignored-patterns '(*~|*.zwc)'
    zstyle ':completion:correct:'          prompt 'correct to: %e'

    # Ignore completion functions for commands you don't have:
    zstyle ':completion::(^approximate*):*:functions' ignored-patterns '_*'

    # Provide more processes in completion of programs like killall:
    zstyle ':completion:*:processes-names' command 'ps c -u ${USER} -o command | uniq'

    # complete manual by their section
    zstyle ':completion:*:manuals'    separate-sections true
    zstyle ':completion:*:manuals.*'  insert-sections   true
    zstyle ':completion:*:man:*'      menu yes select

    # Search path for sudo completion
    zstyle ':completion:*:sudo:*' command-path /usr/local/sbin \
                                               /usr/local/bin  \
                                               /usr/sbin       \
                                               /usr/bin        \
                                               /sbin           \
                                               /bin            \
                                               /usr/X11R6/bin

    # provide .. as a completion
    zstyle ':completion:*' special-dirs ..

    # run rehash on completion so new installed program are found automatically:
    function _force_rehash () {
        (( CURRENT == 1 )) && rehash
        return 1
    }

    ## correction
    # some people don't like the automatic correction - so run 'NOCOR=1 zsh' to deactivate it
    if [[ "$NOCOR" -gt 0 ]] ; then
        zstyle ':completion:*' completer _oldlist _expand _force_rehash _complete _files _ignored
        setopt nocorrect
    else
        # try to be smart about when to use what completer...
        setopt correct
        zstyle -e ':completion:*' completer '
            if [[ $_last_try != "$HISTNO$BUFFER$CURSOR" ]] ; then
                _last_try="$HISTNO$BUFFER$CURSOR"
                reply=(_complete _match _ignored _prefix _files)
            else
                if [[ $words[1] == (rm|mv) ]] ; then
                    reply=(_complete _files)
                else
                    reply=(_oldlist _expand _force_rehash _complete _ignored _correct _approximate _files)
                fi
            fi'
    fi

    # command for process lists, the local web server details and host completion
    zstyle ':completion:*:urls' local 'www' '/var/www/' 'public_html'

    # Some functions, like _apt and _dpkg, are very slow. We can use a cache in
    # order to speed things up
    if [[ ${GRML_COMP_CACHING:-yes} == yes ]]; then
        GRML_COMP_CACHE_DIR=${GRML_COMP_CACHE_DIR:-${ZDOTDIR:-$HOME}/.cache}
        if [[ ! -d ${GRML_COMP_CACHE_DIR} ]]; then
            command mkdir -p "${GRML_COMP_CACHE_DIR}"
        fi
        zstyle ':completion:*' use-cache  yes
        zstyle ':completion:*:complete:*' cache-path "${GRML_COMP_CACHE_DIR}"
    fi

    # host completion
    if is42 ; then
        [[ -r ~/.ssh/config ]] && _ssh_config_hosts=(${${(s: :)${(ps:\t:)${${(@M)${(f)"$(<$HOME/.ssh/config)"}:#Host *}#Host }}}:#*[*?]*}) || _ssh_config_hosts=()
        [[ -r ~/.ssh/known_hosts ]] && _ssh_hosts=(${${${${(f)"$(<$HOME/.ssh/known_hosts)"}:#[\|]*}%%\ *}%%,*}) || _ssh_hosts=()
        [[ -r /etc/hosts ]] && [[ "$NOETCHOSTS" -eq 0 ]] && : ${(A)_etc_hosts:=${(s: :)${(ps:\t:)${${(f)~~"$(grep -v '^0\.0n.0.\.0\|^127\.0\.0\.1\|^::1 ' /etc/hosts)"}%%\#*}##[:blank:]#[^[:blank:]]#}}} || _etc_hosts=()
    else
        _ssh_config_hosts=()
        _ssh_hosts=()
        _etc_hosts=()
    fi

    local localname
    localname="$(uname -n)"
    hosts=(
        "${localname}"
        "$_ssh_config_hosts[@]"
        "$_ssh_hosts[@]"
        "$_etc_hosts[@]"
        localhost
    )
    zstyle ':completion:*:hosts' hosts $hosts
    # TODO: so, why is this here?
    #  zstyle '*' hosts $hosts

    # use generic completion system for programs not yet defined; (_gnu_generic works
    # with commands that provide a --help option with "standard" gnu-like output.)
    for compcom in cp deborphan df feh fetchipac gpasswd head hnb ipacsum mv \
                   pal stow uname ; do
        [[ -z ${_comps[$compcom]} ]] && compdef _gnu_generic ${compcom}
    done; unset compcom

    # see upgrade function in this file
    compdef _hosts upgrade
}

function is42 () {
    [[ $ZSH_VERSION == 4.<2->* || $ZSH_VERSION == <5->* ]] && return 0
    return 1
}

grmlcomp

Since this thread started with the assertion that sudo can’t run other commands from zsh, can you clarify what exact failure you’re describing when you say:

Both quasigod and I are interpreting this as being about PATH/command-not-found errors, but the output included in your previous response for sudo PAGER=head nixos-rebuild --help indicates that the command is available and the PATH is set correctly.

Sorry since nixos-rebuld didn’t work and I haven’t tried anything else at the time I just assumed that was the case for anything.

Can you share exactly the output you get when trying to run sudo nixos-rebuild switch in zsh? We both assumed it was not in your path, but that doesn’t appear to be the case.