visual-studio-codewindows-subsystem-for-linuxvscode-remote

what is different between SSH into WSL and the "Ubuntu" terminal/native app?


Win10, WSL2, Ubuntu vanilla install. I have an SSH daemon listening within the WSL2 instance (on a high-numbered port, in case that's relevant). I just noticed that after installing the VSCode/WSL remote extension, if I execute code . from within the Ubuntu terminal/app/native console (sorry I don't know what this is properly called) it downloads/installs an instance of the VSCode server and at least so far appears to run as I'd expect it to.

### launch the "Ubuntu" applet from the normal windows environment....
[lwobker:/dtop/scripts/jumpstamper]$ code .
Updating VS Code Server to version 899d46d82c4c95423fb7e10e68eba52050e30ba3
Removing previous installation...
Installing VS Code Server for x64 (899d46d82c4c95423fb7e10e68eba52050e30ba3)
Downloading:  66%

BUT - if I ssh into the WSL instance (as the same user) and again type code . then it knows nothing of which I speak, and I get the standard Ubuntu "uh, sorry I'm not quite sure what you mean" response:

### SSH into the WSL2 virtual machine...
[lwobker:/dtop/scripts/fun]$ code .

Command 'code' not found, did you mean:

  command 'node' from deb nodejs (10.19.0~dfsg-3ubuntu1)
  command 'cde' from deb cde (0.1+git9-g551e54d-1.1build1)
  command 'cdde' from deb cdde (0.3.1-1build1)
  command 'tcode' from deb emboss (6.6.0+dfsg-7ubuntu2)
  command 'ode' from deb plotutils (2.6-10build1)

I would have thought (clearly wrongly) that the Ubuntu terminal brought up is the same login shell as the one I'd get using SSH to log into the same virtual machine... but... evidently not?


Solution

  • You're going to run into a couple of things here.

    PATH differences

    First, and what you are running into at the moment, is the difference in $PATH. When you run WSL directly on the host in the terminal, it starts your shell in a fairly "unorthodox" way. At least, it's quite different than if you were running on a normal Linux host.

    "Normally", you'd see something like login called to authenticate your user. login (and ssh) uses PAM, the Plugable Authentication Module system to define what happens during the authentication process. One of the commonly configured modules is pam_env, which can change the environment.

    You can see this defined in WSL/Ubuntu in /etc/pam.d/login and /etc/pam.d/sshd. Both include the line:

    session    required     pam_env.so
    

    You'll see in the man page that pam_env processes /etc/environment, and on Ubuntu 20.04 on WSL, that's defined as:

    PATH="/usr/local/sbin:/usr/local/bin:/usr/sbin:/usr/bin:/sbin:/bin:/usr/games:/usr/local/games:/snap/bin"
    

    That's the PATH you should see when ssh'ing in to your WSL instance, plus any changes made in your shell startup files.

    On the other hand, you may have noticed that WSL doesn't actually require a login when you launch it locally. Since it's running at the same permissions as your Windows account, and you're already logged into Windows, there's really no point in additional authentication here. This is true no matter what WSL user you use.

    WSL launches your shell using /init, it's PID1 init process. /init is responsible for setting up the tight Windows integration, including (among other things):

    In case it's not clear, this is why code isn't found when you login via ssh. Since VSCode is a Windows executable, and in your Windows path, it's only there (by default) when that path is specifically added by /init. It is not there in the /etc/environment PATH used by sshd.

    Remote GUI's in Windows

    But really, even adding it to the path won't help much here.

    I'm not sure of your exact use-case for trying to run VSCode through SSH, but note that running Windows GUI applications through SSH is quite a bit different than X forwarding on Linux. There's really not a one-to-one equivalent.

    By default, even if you provide the full path of the Windows executable, it will not execute through SSH. This is to be expected. Even the Windows OpenSSH server has issues with this since it runs as a service, and services do not have GUI access. See this question for some more information there.

    I'm not sure if there's a way to get the GUI to display on the remote host through WSL. I think it's unlikely, and probably not worthwhile regardless.

    The best scenario I could see would be to use Windows OpenSSH running as a normal user, as documented in that previous question. Then, once logged into your Windows user, run wsl there. Then, you might be able to launch a GUI client on the SSH host itself.

    Remote VSCode

    What you probably want to do is access your WSL instance through VSCode remotely in the first place.

    There are at least three supported solutions for that: