VS Code Remote Development: Complete Guide
Visual Studio Code's Remote Development extension pack is one of the most transformative features Microsoft has shipped for the editor. It allows you to open any folder, container, or remote machine as if it were a local project, running the full VS Code experience — IntelliSense, debugging, terminals, extensions — wherever your code actually lives. This guide walks through everything you need to know to use it effectively.
What Is Remote Development?
Remote Development is a collection of VS Code extensions that let the editor's UI run on your local machine while the actual workspace — file system, language servers, terminals, and extensions — runs somewhere else. VS Code splits itself into a UI client and a server component. The server is a small Node process that VS Code installs automatically on the remote target.
The extension pack includes three core extensions:
- Remote - SSH — connect to any host over SSH.
- Dev Containers — run your project inside a Docker container with a defined environment.
- WSL — integrate with the Windows Subsystem for Linux.
Why It Matters
Developers rarely work in a single, clean environment anymore. You might have a Node service on a cloud VM, a Python pipeline in a Docker container, and a Rust binary on a Raspberry Pi. Without Remote Development, you'd juggle SSH terminals, manual file syncs, and inconsistent tooling. With it, you get a single, consistent editing experience regardless of where the code runs.
Key benefits include:
- Eliminating "works on my machine" issues by developing inside the same container that ships to production.
- Keeping heavy compute and large datasets on remote servers while editing from a lightweight laptop.
- Onboarding new team members in minutes with a version-controlled dev container definition.
- Running Linux-targeted tooling natively from Windows via WSL.
Prerequisites and Installation
Before you start, install the prerequisites for your chosen workflow. All workflows require VS Code itself.
For SSH, you need an OpenSSH-compatible client on your local machine and an SSH server on the remote host. For Dev Containers, you need Docker Desktop or a compatible Docker engine. For WSL, you need WSL 2 installed on Windows.
Install the extension pack from the marketplace:
# From the command palette (Ctrl/Cmd+Shift+P), run:
# "Extensions: Install Extensions" and search for "Remote Development"
# Or via CLI:
code --install-extension ms-vscode-remote.vscode-remote-extension-pack
Connecting Over SSH
Remote - SSH is the most flexible option. It works with any host you can SSH into: a cloud VM, a bare-metal server, or even a Raspberry Pi on your local network.
Start by defining your SSH host in your local SSH config file, typically at ~/.ssh/config:
# ~/.ssh/config
Host dev-server
HostName 203.0.113.42
User ubuntu
IdentityFile ~/.ssh/id_ed25519
ForwardAgent yes
Then connect from VS Code:
# Command Palette > "Remote-SSH: Connect to Host..."
# Select "dev-server" from the list
# Or from the terminal:
code --remote ssh-remote+dev-server /home/ubuntu/projects/myapp
The first connection takes a moment because VS Code downloads and installs its server component to ~/.vscode-server on the remote host. Subsequent connections are much faster. Once connected, the window title bar shows the host name, and every terminal, task, and extension runs remotely.
Working With Dev Containers
Dev Containers let you define your development environment as code. The definition lives in a .devcontainer/devcontainer.json file (optionally with a Dockerfile or docker-compose.yml) at the root of your repository.
Here is a complete example for a Node.js + PostgreSQL project:
// .devcontainer/devcontainer.json
{
"name": "Node + Postgres Dev",
"dockerComposeFile": "docker-compose.yml",
"service": "app",
"workspaceFolder": "/workspace",
"forwardPorts": [5432, 3000],
"postCreateCommand": "npm install",
"customizations": {
"vscode": {
"extensions": [
"dbaeumer.vscode-eslint",
"esbenp.prettier-vscode",
"ms-ossdata.vscode-postgresql"
],
"settings": {
"editor.formatOnSave": true,
"editor.defaultFormatter": "esbenp.prettier-vscode"
}
}
},
"remoteUser": "node"
}
# .devcontainer/docker-compose.yml
version: "3.8"
services:
app:
build:
context: ..
dockerfile: .devcontainer/Dockerfile
volumes:
- ..:/workspace:cached
command: sleep infinity
depends_on:
- db
db:
image: postgres:16
environment:
POSTGRES_USER: dev
POSTGRES_PASSWORD: dev
POSTGRES_DB: appdb
ports:
- "5432:5432"
# .devcontainer/Dockerfile
FROM mcr.microsoft.com/devcontainers/javascript-node:20
RUN apt-get update && apt-get install -y \
postgresql-client \
&& rm -rf /var/lib/apt/lists/*
Open the project folder in VS Code, then run Dev Containers: Reopen in Container from the command palette. VS Code builds the image, starts the compose stack, and reconnects inside the container. The Postgres database is reachable at localhost:5432 from your host machine because of forwardPorts.
Using WSL on Windows
If you develop on Windows but target Linux, WSL integration is essential. Install a Linux distribution via wsl --install -d Ubuntu, then install the WSL extension in VS Code. Open a WSL terminal, navigate to your project, and run:
# Inside WSL
cd /home/$USER/projects/myapp
code .
VS Code launches and connects to WSL automatically. File operations, the integrated terminal, and language servers all run inside Linux, giving you native performance for Linux-targeted toolchains like Docker, Node, Python, and Go.
Managing Extensions Remotely
Extensions are installed per-environment. An extension installed locally does not automatically run remotely, and vice versa. This separation keeps each environment clean but requires deliberate management.
You can force certain extensions to install everywhere by adding them to your user settings:
// settings.json
{
"remote.SSH.defaultExtensions": [
"dbaeumer.vscode-eslint",
"esbenp.prettier-vscode"
]
}
For dev containers, prefer declaring extensions in devcontainer.json so every contributor gets the same set automatically.
Debugging Remotely
Debugging works identically to local development. Launch configurations run on the remote host, and VS Code's debugger attaches over the same channel it uses for everything else. Here is a Node.js launch config that works inside a dev container:
// .vscode/launch.json
{
"version": "0.2.0",
"configurations": [
{
"type": "node",
"request": "launch",
"name": "Debug API",
"skipFiles": ["<node_internals>/**"],
"program": "${workspaceFolder}/src/index.js",
"env": {
"NODE_ENV": "development",
"DATABASE_URL": "postgres://dev:dev@db:5432/appdb"
}
}
]
}
Press F5 and breakpoints hit just as they would locally. The same pattern applies to Python (debugpy), Go (dlv), and Java.
Port Forwarding
When a process inside the remote environment listens on a port, VS Code can automatically forward it to your local machine so you can open it in a browser. You can also forward ports manually:
# Command Palette > "Forward a Port"
# Enter 8080
# Or in the integrated terminal, VS Code detects the port
# and prompts to forward automatically
For persistent forwards in dev containers, list them in forwardPorts in your devcontainer.json. For SSH, add them to your SSH config with LocalForward directives.
Best Practices
- Commit your
.devcontainerfolder. It is part of your project's contract with its developers. Treat it like production infrastructure code. - Pin base images and extension versions. Use specific tags like
node:20.11instead ofnode:latestto avoid surprise breakages. - Keep the remote workspace lean. Avoid installing heavy GUI tools on the remote host; VS Code handles the UI locally.
- Use
postCreateCommandfor setup. Runnpm install,pip install -r requirements.txt, or database migrations here so the environment is ready on first open. - Leverage Docker BuildKit caching. Add a
.dockerignoreand order Dockerfile layers from least to most frequently changing to speed up container rebuilds. - Secure your SSH connections. Use ed25519 keys with passphrases, disable password auth on the server, and consider a jump host for private networks.
- Sync settings with Settings Sync. Enable VS Code Settings Sync so your keybindings, snippets, and themes follow you across local and remote sessions.
- Profile performance when things feel slow. Run Help: Open Process Explorer to see which extension or language server is consuming resources on the remote host.
Troubleshooting Common Issues
If the SSH connection hangs during server installation, check that the remote host has enough disk space in the home directory and that wget or curl is available. You can manually clean a broken install:
# On the remote host
rm -rf ~/.vscode-server
If a dev container fails to build, open the command palette and run Dev Containers: Rebuild Without Cache to rule out stale Docker layers. For compose-based setups, run docker compose -f .devcontainer/docker-compose.yml logs to inspect service output.
If WSL feels slow, make sure your project files live inside the WSL filesystem (for example /home/user/) rather than on the Windows mount (/mnt/c/). Cross-filesystem access incurs significant overhead.
Conclusion
VS Code Remote Development collapses the distance between your editor and your runtime environment. Whether you are SSHing into a production-like VM, spinning up a reproducible dev container, or bridging Windows and Linux through WSL, the same editor, the same keybindings, and the same debugging workflow follow you everywhere. By treating your development environment as versioned infrastructure — defined in devcontainer.json, secured over SSH, and tuned with the best practices above — you eliminate an entire class of setup friction and let your team focus on shipping code instead of fighting their machines.