Files
MajorWiki/05-troubleshooting/networking/windows-openssh-wsl-default-shell-breaks-remote-commands.md
majorlinux 5af934a6c6 wiki: update SSH docs with bash.exe default shell fix and Windows admin key auth
- ssh-config-key-management: add Windows OpenSSH admin user key auth section
  (administrators_authorized_keys, BOM-free writing, ACL requirements)
- windows-openssh-wsl-default-shell: add bash.exe as recommended fix (Option 1),
  demote PowerShell to Option 2, add shell-not-found diagnostic tip
- windows-sshd-stops-after-reboot: fix stale wsl.exe reference to bash.exe
- index/README: update Recently Updated table and article descriptions

Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
2026-04-07 22:01:36 -04:00

94 lines
3.8 KiB
Markdown

---
title: "Windows OpenSSH: WSL as Default Shell Breaks Remote Commands"
domain: troubleshooting
category: networking
tags:
- windows
- openssh
- wsl
- ssh
- majorrig
- powershell
status: published
created: 2026-04-03
updated: 2026-04-07T21:55
---
# Windows OpenSSH: WSL as Default Shell Breaks Remote Commands
## Problem
SSH remote commands fail with:
```
Invalid command line argument: -c
Please use 'wsl.exe --help' to get a list of supported arguments.
```
This happens on **every** remote command — `ssh-copy-id`, `ssh user@host "command"`, `scp`, etc. Interactive SSH (no command) may still work if it drops into WSL.
## Cause
Windows OpenSSH's default shell is set to `C:\Windows\System32\wsl.exe`. When SSH executes a remote command, it invokes:
```
<default_shell> -c "<command>"
```
But `wsl.exe` does not accept the `-c` flag. It expects `-e` for command execution, or no flags for an interactive session. Since OpenSSH hardcodes `-c`, every remote command fails.
## Fix — Option 1: Use `bash.exe` (Recommended)
`bash.exe` is a WSL shim that **does** accept the `-c` flag. This gives you a Linux-first SSH experience where both interactive sessions and remote commands work natively.
```powershell
# Find the actual path to bash.exe (it varies by install)
Get-Command bash.exe | Select-Object Source
# Set it as the default shell (elevated PowerShell)
Set-ItemProperty -Path "HKLM:\SOFTWARE\OpenSSH" -Name DefaultShell -Value "C:\Users\<username>\AppData\Local\Microsoft\WindowsApps\bash.exe"
Restart-Service sshd
```
> **Note:** `bash.exe` may not be at `C:\Windows\System32\bash.exe` on all installs. Always verify the path with `Get-Command` first — the Windows Store WSL install places it under `AppData\Local\Microsoft\WindowsApps\`.
### After the fix (bash.exe)
- Interactive SSH sessions land directly in your WSL distro
- Remote SSH commands execute in WSL's bash — Linux commands work natively
- `ssh user@host "uname -s"` returns `Linux`
## Fix — Option 2: Revert to PowerShell
If you need Windows-native command execution over SSH (e.g., for Windows-targeted Ansible or remote PowerShell administration), set the default shell back to PowerShell:
```powershell
Set-ItemProperty -Path "HKLM:\SOFTWARE\OpenSSH" -Name DefaultShell -Value "C:\Windows\System32\WindowsPowerShell\v1.0\powershell.exe"
Restart-Service sshd
```
### After the fix (PowerShell)
- Remote SSH commands execute via PowerShell
- To run Linux commands, prefix with `wsl`:
```bash
ssh user@host "wsl bash -c 'cd /mnt/d/project && git pull'"
```
- Interactive SSH sessions land in PowerShell (type `wsl` to enter Linux)
- `ssh-copy-id` still won't work for WSL's `authorized_keys` — Windows OpenSSH reads from `C:\Users\<user>\.ssh\authorized_keys`, not the WSL home directory
## Key Notes
- This registry key (`HKLM:\SOFTWARE\OpenSSH\DefaultShell`) is the **only** supported way to change the OpenSSH default shell on Windows
- The change persists across reboots and Windows Updates
- `wsl.exe` does **not** support `-c` — never use it as the default shell
- `bash.exe` **does** support `-c` — use it for a Linux-first SSH experience
- The path to `bash.exe` varies by install method — always verify with `Get-Command bash.exe`
- Tools like Ansible, `scp`, `rsync`, and `ssh-copy-id` all depend on `-c` working
- If the shell path in the registry doesn't exist on disk, sshd will reject the user entirely with `User <name> not allowed because shell <path> does not exist` — check `Get-WinEvent -LogName OpenSSH/Operational` to diagnose
## Related
- [Windows OpenSSH Server (sshd) Stops After Reboot](windows-sshd-stops-after-reboot.md) — sshd service startup issues
- [Microsoft Docs: OpenSSH DefaultShell](https://learn.microsoft.com/en-us/windows-server/administration/openssh/openssh-server-configuration#configuring-the-default-shell-for-openssh-in-windows)