Are you using VirtualBox on Windows for Linux development and experiencing these common frustrations?
"Starting the VM, opening VSCode, establishing SSH connection... the preparation is tedious every time!"
"I created a development profile in VSCode, but it opens with default settings when SSH connecting..."
"I don't use the VM's GUI, but it feels like a waste of resources and windows..."
This article introduces methods to solve these issues and significantly improve your development workflow. We'll guide you through smoothly connecting from your host OS's VSCode-based editor to your guest OS (we'll use Linux Mint as an example, but these steps can be applied to other Linux distributions), ultimately automating the entire process from VM startup (headless), SSH connection, to VSCode launch with just one desktop shortcut.
📌 Prerequisites
Host OS: Windows 11
Guest OS: Linux on VirtualBox (we'll use Linux Mint 22 as an example, but similar steps apply to other Debian-based distributions like Ubuntu)
Editor (Host OS): VSCode or its derivatives (referred to as VSCode in this article)
VirtualBox Guest Additions must be installed on the guest OS.
⚠️ Disclaimer
The content of this article is based on a specific verification environment (laboratory development environment) and may not work similarly in your environment.
When implementing these steps, please take appropriate safety measures such as creating VM snapshots and backing up files according to your environment.
The information in this article is current as of the writing date. Content may become outdated or procedures may change due to version updates of various tools and software.
Please refer to the official documentation of VirtualBox, VSCode, SSH, and your Linux distribution as needed.
☁️ 1. Preparing SSH Connection from VSCode to Guest OS
First, let's set up SSH connection from your host OS's VSCode to your Linux environment on the guest OS.
1.1. Changing VirtualBox Network Settings
To accept SSH connections, we'll set up port forwarding in VirtualBox's network settings.
Open VirtualBox Manager, select your target virtual machine (e.g., Linux Mint), and shut it down.
Open the virtual machine's "Settings" and navigate to the "Network" section.
Configure "Adapter 1" (or your chosen adapter) as follows:
Attached to: NAT
By selecting NAT, the guest OS can share the host OS's IP address for external network access while allowing specific communications from host to guest through port forwarding.
Expand "Advanced" and click the "Port Forwarding" button.
Add a new rule (click the + button on the right) with the following settings (guest IP can be left blank):
Name
Protocol
Host IP
Host Port
Guest IP
Guest Port
SSH
TCP
2222
22
Host Port 2222: The port that will listen for SSH connections on the host OS. You can change this to any number that doesn't conflict with other services.
Guest Port 22: The standard port that the guest OS's SSH server listens on.
1.2. Setting up SSH Server and Auto-start on Guest OS
Next, let's install the SSH server on the guest OS (Linux Mint) and configure it to start automatically.
Start the target virtual machine.
Open the guest OS's terminal and run the following commands to install the OpenSSH server:
Guest OS
If ufw is not installed, install it with sudo apt install ufw and enable it with sudo ufw enable.
1.4. Verifying SSH Connection (from Host OS)
Check if you can establish an SSH connection to the guest OS from your host OS (Windows) terminal (Command Prompt or PowerShell).
Host OS
ssh your_guest_username@localhost -p 22222
Replace your_guest_username with your guest OS username.
-p 22222 is the host port we set in VirtualBox's port forwarding.
On first connection, you'll be asked to verify the fingerprint - type yes, then enter your guest OS user password. If you can log in, it's successful.
1.5. VSCode SSH Connection Setup
Let's configure VSCode for easy SSH connection.
Start VSCode on your host OS.
Install Remote - SSH Extension:
If not already installed, search for and install "Remote - SSH" (ms-vscode-remote.remote-ssh) from VSCode's extension marketplace.
Configure SSH Config File:
Add SSH connection settings to your SSH Config file. This file is typically located in the .ssh folder under your host OS user directory (e.g., C:\Users\[username]\.ssh\config). Create it if it doesn't exist.
Add or create the following content:
.ssh/config
Host your_ssh_alias HostName localhost User your_guest_username Port 22222
your_ssh_alias: Any connection name (e.g., vbox-mint). This will appear in VSCode's connection list.
your_guest_username: Your guest OS username.
Port 22222: The host port we set in VirtualBox's port forwarding.
Connect via SSH from VSCode:
Click the green "Open Remote Window" icon (usually shaped like ><) in the bottom-left corner of VSCode.
Select "Connect to Host..." from the dropdown menu.
Select the your_ssh_alias we configured in the SSH Config file.
On first connection, you might be asked about the OS type. Select "Linux".
A new VSCode window will open, asking for your guest OS user password. If you can connect after entering the password, it's successful. You'll see SSH: your_ssh_alias in the bottom-left corner.
Now you can access the guest OS's file system from your host OS's VSCode and use the guest OS's terminal directly.
Current Challenges:
Password input required for each SSH connection (this can be improved with SSH key authentication, but we won't cover that in this article).
Extra steps needed when you want to use specific VSCode development profiles (extension sets, etc.) for the connection.
Guest OS needs to be started manually from VirtualBox Manager, and the GUI window is displayed.
Let's proceed to the next section to solve these challenges through automation.
🤖 2. Automating Startup and Connection
Our goal is to perform the following processes automatically with just one click on a desktop shortcut:
Start the VirtualBox guest OS in headless mode (no GUI).
Wait for the guest OS's SSH server to start.
Launch VSCode with the specified profile and workspace, connected to the guest OS via SSH.
2.1. Preparing VBoxManage Command Line Tool
To control VirtualBox from the command line, we need to add VBoxManage.exe to the PATH.
Open Windows "Settings" → "System" → "About" and click "Advanced system settings".
Click the "Environment Variables" button.
Select "Path" under "System variables" and click "Edit".
Click "New" and add the VirtualBox installation directory (typically C:\Program Files\Oracle\VirtualBox).
Click OK to close all dialogs, and restart your PC or open a new Command Prompt/PowerShell window to apply the settings.
Run VBoxManage --version in Command Prompt or PowerShell to verify the path is set correctly.
Note down the VM name for use in the automation script:
Host OS
VBoxManage list vms
From the displayed list, note the target VM's name (e.g., "Linux Mint 22" or "MyLinuxVM", including the quotes). We'll refer to this VM name as Your_VM_Name in the following steps.
2.2. Setting up Guest OS SSH Ready Notification
Let's build a mechanism for the guest OS to notify the host OS when it's ready for SSH connection. We'll use VirtualBox's Guest Properties feature.
Start the target virtual machine.
Guest OS: Create SSH Ready Notification Script
Create a script in the guest OS's home directory or similar location to check SSH service startup and set the Guest Property. For example, create ~/bin/set-ssh-ready.sh with the following content. Create the ~/bin directory if it doesn't exist.
set-ssh-ready.sh
set-ssh-ready.sh
#!/bin/bash# Check if SSH service (sshd or ssh) is activeif systemctl is-active --quiet ssh || systemctl is-active --quiet sshd; then # Check if VBoxControl command exists (part of Guest Additions) if command -v VBoxControl >/dev/null 2>&1; then /usr/bin/VBoxControl guestproperty set "/guestinfo/ssh.ready" "true" else echo "VBoxControl not found. Make sure Guest Additions are installed." >&2 fifi
Make the script executable:
Guest OS
$ mkdir -p ~/bin$ chmod +x ~/bin/set-ssh-ready.sh
Guest OS: Create systemd Service File
Create a systemd service unit file to run the above script after network and SSH service startup.
Open an editor with sudo nano /etc/systemd/system/set-ssh-ready.service and add the following content. Replace your_guest_username with your actual guest OS username.
set-ssh-ready.service
Guest OS
[Unit]Description=Set SSH Ready guest property for VirtualBoxAfter=network.target ssh.service sshd.service[Service]User=your_guest_usernameGroup=your_guest_usernameExecStart=/home/your_guest_username/bin/set-ssh-ready.shType=oneshot[Install]WantedBy=multi-user.target
Important: Adjust the ExecStart path according to your actual script location and username.
Adding sshd.service to the After directive helps handle different SSH daemon service names across distributions.
Guest OS: Enable and Verify systemd Service
Make systemd recognize the new service file and enable auto-start:
After reboot, verify that the service ran once (OK if inactive (dead) with status=0/SUCCESS) and the Guest Property was set:
Guest OS
$ systemctl status set-ssh-ready.service# ● set-ssh-ready.service - Set SSH Ready guest property for VirtualBox# Loaded: loaded (/etc/systemd/system/set-ssh-ready.service; enabled; ...)# Active: inactive (dead) since ...# Process: ... ExecStart=/home/your_guest_username/bin/set-ssh-ready.sh (code=exited, status=0/SUCCESS)# Main PID: ... (code=exited, status=0/SUCCESS)$ VBoxControl guestproperty get "/guestinfo/ssh.ready"# Value: true
If it's not showing active (running) in green or Value: true, check the script path, permissions, service file content, and Guest Additions installation status.
Host OS: Verify Guest Property
From the host OS's Command Prompt or PowerShell, verify that the guest OS's property is set correctly. Replace Your_VM_Name with your actual VM name.
Host OS
VBoxManage guestproperty get "Your_VM_Name" "/guestinfo/ssh.ready"# Expected output: Value: true
Creating a workspace file is convenient for opening specific project folders in VSCode. This specifies the folder on the guest OS to open after SSH connection.
Create a file with .code-workspace extension in any location on the host OS (e.g., C:\Users\[username]\Documents\VSCodeWorkspaces).
{ "folders": [ { // "your_ssh_alias" is the SSH host name set in 1.5 // "your_guest_username" is your guest OS username // "your_project_folder" is your project folder name on the guest OS "uri": "vscode-remote://ssh-remote+your_ssh_alias/home/your_guest_username/your_project_folder" } ], "remoteAuthority": "ssh-remote+your_ssh_alias", // Specify SSH host name "settings": { // Add workspace-specific settings if needed }, "tasks": { // Tasks for this workspace (e.g., VM shutdown) "version": "2.0.0", "tasks": [ { "label": "Shutdown Guest VM", "type": "shell", "command": "VBoxManage controlvm \"Your_VM_Name\" poweroff", // Command executed on host OS "problemMatcher": [], "group": "build", "presentation": { "reveal": "always", "close": true } } ] }}
Make sure to set the uri path and remoteAuthority accurately according to your environment.
The VM shutdown task in tasks can be executed from VSCode's command palette (Ctrl+Shift+P) by selecting Tasks: Run Task and then Shutdown Guest VM. Note that this runs as a command on the host OS.
2.4. Host OS: Create PowerShell Script for Auto-start
Let's create a PowerShell script to automate VM startup, SSH ready waiting, and VSCode launch.
Create a .ps1 extension script file in any location on the host OS (e.g., C:\Users\[username]\Scripts).
Add the following script content. Make sure to replace all <...> placeholders with your actual environment settings.
launch-linux-dev-env.ps1
launch-linux-dev-env.ps1
<#.SYNOPSIS Launches VirtualBox VM in headless mode, waits for SSH connection readiness, and starts VSCode with specified profile and workspace..DESCRIPTION 1. Starts the specified VM in headless mode if not already running. 2. Waits for VM startup and Guest Property "/guestinfo/ssh.ready" to be "true". 3. Launches VSCode with specified executable path, profile name, and workspace file..NOTES Author: Riku-Mono Last Updated: 2025-06-07 Requires: VirtualBox command line tools (VBoxManage) in PATH. Guest OS configured to set "/guestinfo/ssh.ready" property.#>[CmdletBinding()]param()#======================================================================# 🔧 Settings (Change these according to your environment)#======================================================================# VirtualBox Settings$VMName = "<Your_VM_Name>" # e.g., "Linux Mint 22" (name from VBoxManage list vms)# VSCode Settings# VSCode executable path. Usually one of these:# $EditorPath = "$env:LOCALAPPDATA\Programs\Microsoft VS Code\Code.exe" # User Installer$EditorPath = "$env:ProgramFiles\Microsoft VS Code\Code.exe" # System Installer (uncomment as needed)# $EditorPath = "<Path_To_Your_VSCode_Executable>" # For other locations$EditorProfile = "<your_vscode_profile_name>" # e.g., "dev-linux" (VSCode profile name. Will be created if doesn't exist)$WorkspacePath = "<Path_To_Your_code-workspace_File>" # e.g., "C:\Users\YourUser\Documents\VSCodeWorkspaces\my-linux-project.code-workspace" (file created in 2.3)# Timeout settings (seconds): Adjust based on your system's performance$VMStartTimeoutSec = 120$SSHReadyTimeoutSec = 120#======================================================================# 🧯 Common Functions#======================================================================function Write-Log { param( [Parameter(Mandatory=$true)] [string]$Message, [ValidateSet("Info", "Success", "Waiting", "Warning", "Error")] [string]$Severity = "Info" ) $Timestamp = Get-Date -Format "yyyy-MM-dd HH:mm:ss" $Prefix = switch ($Severity) { "Info" { "ℹ️ [INFO]" } "Success" { "✅ [SUCCESS]" } "Waiting" { "⏳ [WAITING]" } "Warning" { "⚠️ [WARNING]" } "Error" { "🛑 [ERROR]" } default { " [LOG]" } } Write-Host "$Timestamp $Prefix $Message"}function Exit-Script { param ( [string]$Message = "Exiting script." ) Write-Log $Message -Severity Error Start-Sleep -Seconds 5 # Time to read message exit 1}function Test-VBoxInstalled { try { & VBoxManage --version | Out-Null return $true } catch { Write-Log "VirtualBox (VBoxManage) is not installed or not in PATH." -Severity Error return $false }}function Get-VMState { param ( [Parameter(Mandatory=$true)] [string]$TargetVMName ) try { $VMInfo = VBoxManage showvminfo $TargetVMName --machinereadable | Select-String -Pattern "^VMState=" if ($VMInfo) { return ($VMInfo -split "=")[1].Trim('"') } return "notfound" # VM not found } catch { Write-Log "Failed to get VM '$TargetVMName' state: $($_.Exception.Message)" -Severity Error return "error" }}#======================================================================# 🚀 VM Startup Process#======================================================================function Start-VMHeadless { param( [Parameter(Mandatory=$true)] [string]$TargetVMName ) Write-Log "Starting VM '$TargetVMName' in headless mode..." try { # Reset SSH ready flag (just in case) VBoxManage guestproperty set $TargetVMName "/guestinfo/ssh.ready" "" | Out-Null $Result = & VBoxManage startvm $TargetVMName --type headless 2>&1 if ($LASTEXITCODE -ne 0) { Write-Log "Failed to start VM '$TargetVMName': $Result" -Severity Error return $false } Write-Log "Start command sent for VM '$TargetVMName'." -Severity Info return $true } catch { Write-Log "Error occurred while starting VM '$TargetVMName': $($_.Exception.Message)" -Severity Error return $false }}#======================================================================# ⏳ VM Startup and SSH Ready Wait Process#======================================================================function WaitFor-VMStateAndSSHReady { param( [Parameter(Mandatory=$true)] [string]$TargetVMName, [Parameter(Mandatory=$true)] [string]$DesiredState, # e.g., "running" [int]$VMTimeout, [int]$SSHTimeout ) Write-Log "Waiting for VM '$TargetVMName' to reach '$DesiredState' state... (Timeout: ${VMTimeout} seconds)" $Stopwatch = [System.Diagnostics.Stopwatch]::StartNew() while ($Stopwatch.Elapsed.TotalSeconds -lt $VMTimeout) { $CurrentState = Get-VMState -TargetVMName $TargetVMName if ($CurrentState -eq $DesiredState) { Write-Log "VM '$TargetVMName' reached '$DesiredState' state. (Elapsed: $($Stopwatch.Elapsed.ToString('hh\:mm\:ss')))" -Severity Success $Stopwatch.Stop() break } Write-Log "Current VM state: '$CurrentState'... (Elapsed: $($Stopwatch.Elapsed.ToString('hh\:mm\:ss')))" -Severity Waiting Start-Sleep -Seconds 2 } if ($Stopwatch.IsRunning) { # If timed out $Stopwatch.Stop() Write-Log "Timeout: VM '$TargetVMName' did not reach '$DesiredState' state." -Severity Error return $false } Write-Log "Waiting for guest OS SSH connection readiness... (Timeout: ${SSHTimeout} seconds)" $Stopwatch.Restart() while ($Stopwatch.Elapsed.TotalSeconds -lt $SSHTimeout) { try { $Result = VBoxManage guestproperty get $TargetVMName "/guestinfo/ssh.ready" if ($Result -match "Value: true") { Write-Log "SSH connection ready. (Elapsed: $($Stopwatch.Elapsed.ToString('hh\:mm\:ss')))" -Severity Success return $true } Write-Log "Checking SSH readiness... (Elapsed: $($Stopwatch.Elapsed.ToString('hh\:mm\:ss'))): $Result" -Severity Waiting } catch { Write-Log "Failed to get Guest Property. VM might not be fully started. (Elapsed: $($Stopwatch.Elapsed.ToString('hh\:mm\:ss')))" -Severity Warning } Start-Sleep -Seconds 5 } Write-Log "Timeout: SSH connection readiness not achieved." -Severity Error Write-Log "Shutting down VM '$TargetVMName'." -Severity Warning try { VBoxManage controlvm $TargetVMName poweroff | Out-Null } catch { Write-Log "Error occurred while shutting down VM '$TargetVMName': $($_.Exception.Message)" -Severity Error } return $false}#======================================================================# 🖥️ VSCode Launch Process#======================================================================function Start-VSCode { param( [Parameter(Mandatory=$true)] [string]$EditorExecPath, [string]$TargetProfile, [string]$TargetWorkspacePath ) Write-Log "Launching VSCode..." Write-Log " Executable path: $EditorExecPath" Write-Log " Profile: $TargetProfile" Write-Log " Workspace: $TargetWorkspacePath" if (-not (Test-Path $EditorExecPath -PathType Leaf)) { Write-Log "VSCode executable not found at specified path: $EditorExecPath" -Severity Error return $false } if (-not (Test-Path $TargetWorkspacePath -PathType Leaf) -and $TargetWorkspacePath) { Write-Log "Workspace file not found at specified path: $TargetWorkspacePath" -Severity Warning Write-Log "Continuing without workspace." $TargetWorkspacePath = $null # Launch without workspace } $Arguments = New-Object System.Collections.Generic.List[string] if ($TargetProfile) { $Arguments.Add("--profile") $Arguments.Add "$TargetProfile" } if ($TargetWorkspacePath) { $Arguments.Add "`"$TargetWorkspacePath`"" # Enclose path in quotes } try { Start-Process -FilePath $EditorExecPath -ArgumentList $Arguments Write-Log "VSCode launch command sent." -Severity Info return $true } catch { Write-Log "Failed to launch VSCode: $($_.Exception.Message)" -Severity Error return $false }}#======================================================================# ⭐ Main Process#======================================================================Write-Log "Starting development environment launch script."# 0. Check if VirtualBox is availableif (-not (Test-VBoxInstalled)) { Exit-Script "VirtualBox (VBoxManage) is not ready."}# 1. Check VM state and start if needed$CurrentVMState = Get-VMState -TargetVMName $VMNameif ($CurrentVMState -eq "running") { Write-Log "VM '$VMName' is already running." -Severity Info} elseif ($CurrentVMState -eq "poweroff" -or $CurrentVMState -eq "aborted" -or $CurrentVMState -eq "saved") { Write-Log "VM '$VMName' is currently in '$CurrentVMState' state. Starting..." if (-not (Start-VMHeadless -TargetVMName $VMName)) { Exit-Script "Failed to start VM '$VMName'." }} elseif ($CurrentVMState -eq "notfound") { Exit-Script "VM '$VMName' not found. Please check the VM name."} else { Exit-Script "VM '$VMName' is in an unexpected state ($CurrentVMState). Please check manually."}# 2. Wait for VM startup and SSH readinessif (-not (WaitFor-VMStateAndSSHReady -TargetVMName $VMName -DesiredState "running" -VMTimeout $VMStartTimeoutSec -SSHTimeout $SSHReadyTimeoutSec)) { Exit-Script "VM preparation timed out."}# 3. Launch VSCodeif (-not (Start-VSCode -EditorExecPath $EditorPath -TargetProfile $EditorProfile -TargetWorkspacePath $WorkspacePath)) { Exit-Script "Failed to launch VSCode."}Write-Log "Development environment launch process completed." -Severity SuccessStart-Sleep -Seconds 3 # Time to read completion message
Create Desktop Shortcut:
Right-click on the desktop, select "New" → "Shortcut".
In the "Type the location of the item" field, enter the following. Replace <Path_To_Your_Script_File.ps1> with the full path to the PowerShell script you created above.
Click "Next", give the shortcut any name (e.g., Launch Linux Dev Environment), and click "Finish".
2.5. Testing and Verification
Double-click the desktop shortcut you created to run it.
A PowerShell window will open, showing log messages as the process progresses.
VM starts (no VirtualBox GUI since it's headless).
Waits for SSH readiness.
VSCode launches.
If VSCode launches with the specified profile, connected to the guest OS via SSH (shown as SSH: your_ssh_alias in the bottom-left corner), and opens the specified workspace, it's successful. You might see password input or confirmation dialogs on first connection or with new profiles.
If it doesn't work, check these points:
Verify all paths in the PowerShell script (VM name, VSCode executable path, workspace path).
Check PowerShell execution policy (we're temporarily allowing with -ExecutionPolicy Bypass, but you can check permanent settings with Set-ExecutionPolicy).
Ensure VBoxManage command is in PATH and works correctly.
Verify guest OS's set-ssh-ready.sh script and set-ssh-ready.service settings, permissions, and paths.
Check if Guest Additions is properly installed and working on the guest OS.
Check error messages displayed in the PowerShell window.
💬 Conclusion
With these settings, your development environment is ready with just one desktop shortcut.
Improved Development Workflow Example
Run the created shortcut.
VSCode launches and establishes SSH connection to the guest OS (password input required on first connection or without key setup).
Start coding in VSCode.
Launch development servers (e.g., npm run dev, python manage.py runserver) in VSCode's terminal (this is the guest OS's terminal).
If the development server listens on a specific port (e.g., 3000, 8000) on the guest OS, VSCode's Remote-SSH feature often automatically forwards it to the same port on the host OS's localhost. You can check and manually configure this in the "Ports" tab.
Access http://localhost:3000 or http://localhost:8000 from the host OS's browser to verify operation.
Shut down the VM when done.
From VSCode's command palette (Ctrl+Shift+P), run Tasks: Run Task and select Shutdown Guest VM (task defined in the workspace file from 2.3).
Or use the shutdown shortcut described below.
Additional Useful Tips
SSH Key Authentication Setup:
Strongly recommended to avoid password input every time. Create an SSH key pair on the host OS and register the public key in the guest OS's ~/.ssh/authorized_keys.
Customize Development Server Launch Tasks (.vscode/tasks.json):
Create a .vscode/tasks.json file in your project's root to define tasks for launching multiple development servers from VSCode.
For example, here's how to define a task to launch frontend and backend servers simultaneously (modify content according to your project):
.vscode/tasks.json (place in guest OS project folder)
.vscode/tasks.json
{ "version": "2.0.0", "tasks": [ { "label": "Dev Server: Frontend", "type": "shell", "command": "npm run dev", // Frontend launch command "options": { "cwd": "${workspaceFolder}/frontend" // Frontend directory }, "problemMatcher": [], "isBackground": true // Run in background }, { "label": "Dev Server: Backend", "type": "shell", // Backend launch command (example with virtual environment activation and environment variables) "command": "source ~/venvs/myproject_venv/bin/activate && export DB_USER='<db_user>' && python manage.py runserver 0.0.0.0:8000", "options": { "cwd": "${workspaceFolder}/backend" // Backend directory }, "problemMatcher": [], "isBackground": true }, { "label": "Start All Dev Servers", "dependsOn": ["Dev Server: Frontend", "Dev Server: Backend"], "dependsOrder": "parallel", // Run in parallel "group": { "kind": "build", "isDefault": true // Make this the default build task }, "problemMatcher": [] } ]}
Run from command palette with Tasks: Run Task → Start All Dev Servers.
VM Shutdown Shortcut:
Create a dedicated shortcut on the desktop for quick VM shutdown.
"Right-click on desktop" → "New" → "Shortcut"
In "Type the location of the item", enter the following (replace Your_VM_Name with your actual VM name):
Click "Next", give the shortcut any name (e.g., VM Shutdown), and click "Finish".
Q&A
Q: Some VSCode extensions don't work after Remote-SSH connection.
A: In Remote-SSH, extensions are categorized as "UI Extensions" (run locally) and "Workspace Extensions" (run on the remote SSH server). Check if required extensions are installed on the remote side (guest OS). In the extensions sidebar, check where each extension is installed and select "Install on SSH: your_ssh_alias" if needed.
Q: VSCode doesn't recognize Python interpreter or Node.js on the guest OS.
A: Verify that the VSCode window is connected to the remote server (shown as SSH: your_ssh_alias in the bottom-left corner). Then, from VSCode's command palette, check if the correct version is selected with Python: Select Interpreter or for Node.js, verify with nvm or nodenv in the guest OS terminal. You might need to explicitly specify paths in VSCode settings (settings.json).
This article presents one solution for automation in my environment.
Find the best method for your environment and enjoy a better development life!