There’s a common pattern in software development: you’ve got a powerful remote machine — a cloud VM, a production-like server, or a GPU node — and you want to actually use it properly without giving up a decent editor experience. VS Code’s remote development extensions handle this better than anything else available, and if you haven’t explored all three options, you’re probably using a less convenient setup than you need to be.
The Three Extensions
VS Code offers three distinct remote development modes, each solving a different problem.
Remote - SSH connects your VS Code instance to any machine you can reach via SSH. The editor runs locally but all file access, terminal sessions, and extensions run on the remote machine. This is the most flexible option — it works with any Linux or macOS host, any cloud provider, and any network-accessible server. Setup is about two minutes: install the extension, hit Ctrl+Shift+P, type “Connect to Host”, and add your SSH host details. VS Code installs a small server component on the remote machine on first connection.
Dev Containers runs your development environment inside a Docker container. The magic here is the .devcontainer/devcontainer.json file, which describes the container configuration — base image, installed packages, extensions to install, ports to forward, and post-creation commands. Anyone who opens the project in VS Code gets offered the option to reopen it in a container, giving them an identical environment to everyone else on the team. No more “works on my machine.”
Remote Tunnels is the newest and most useful option for developers without a fixed server. You install the VS Code CLI on any machine, run code tunnel, authenticate with your GitHub account, and the machine appears in your VS Code (and on vscode.dev) from anywhere with a browser. No SSH required, no public IP needed, no firewall rules. You can start a tunnel on a cloud VM and access it from a Chromebook, a tablet, or a borrowed laptop.
Remote SSH in Practice
The extension is more powerful than it first appears. You can have multiple remote hosts in your config and switch between them from the status bar. Extensions install on the remote side, which means linters, language servers, and debuggers all run on the host machine rather than sending file contents across the network. This matters a lot for large projects where a local language server would be grinding through gigabytes of code.
A few things that catch people out initially: your local SSH agent forwarding settings affect whether you can clone repos on the remote host using your local keys. Add ForwardAgent yes to your ~/.ssh/config entry for the remote host if you need this. Also, the Remote - SSH extension installs a VS Code Server on the remote machine, which requires a network connection during setup — on air-gapped servers you’ll need to follow the offline installation procedure.
For developers who work with cloud VMs, Remote SSH combined with a persistent tmux session on the server is a powerful setup. The tmux session keeps your terminal processes running even when the VS Code connection drops, and you reconnect to exactly where you left off.
Dev Containers: The Team Standard
Dev containers solve the reproducibility problem. Instead of a README with a long list of “before you start” instructions, you ship a .devcontainer folder that contains everything: the runtime version, the package manager, the required CLI tools, the linter configuration. When a new developer joins the team, they open the project, accept the “reopen in container” prompt, and they have a working environment in minutes.
The devcontainer.json format is straightforward:
{
"name": "Node.js Project",
"image": "mcr.microsoft.com/devcontainers/javascript-node:20",
"features": {
"ghcr.io/devcontainers/features/github-cli:1": {}
},
"postCreateCommand": "npm install",
"extensions": ["dbaeumer.vscode-eslint", "esbenp.prettier-vscode"],
"forwardPorts": [3000]
}
The features field is worth knowing about. The Dev Container Features specification provides pre-built add-ons for common tools — Docker in Docker, GitHub CLI, AWS CLI, Terraform — that you add with a single line rather than a custom Dockerfile layer.
One consideration: dev containers require Docker Desktop (or an alternative like OrbStack on macOS, which is significantly faster). On Linux, Docker Engine is enough. The startup time for the container on first open is longer than opening a local project; after the first build it’s much faster because layers are cached.
Remote Tunnels: The Underrated Option
Remote Tunnels addresses a gap that neither SSH nor dev containers covers well: you want to code on a remote machine from a device that can’t run SSH easily, or you’re behind a firewall that blocks inbound connections, or you just want to be able to pick up work from any browser without any configuration.
Install the VS Code CLI on the machine you want to connect to:
curl -Lk 'https://code.visualstudio.com/sha/download?build=stable&os=cli-alpine-x64' --output vscode_cli.tar.gz
tar -xf vscode_cli.tar.gz
./code tunnel --accept-server-license-terms
After authenticating with GitHub, the tunnel appears in your VS Code under Remote Explorer, and at vscode.dev under your account. The connection is end-to-end encrypted through Microsoft’s relay infrastructure; Microsoft doesn’t have access to your code.
The main limitation is latency. For interactive editing on a server that’s geographically far away, the response can feel sluggish compared to SSH. But for checking on a long-running process, debugging a staging environment, or doing a quick edit from a device without your usual setup, it’s excellent.
Choosing Between Them
Use Remote SSH when you have a persistent remote machine with an SSH daemon, a consistent IP or hostname, and you want full performance with your usual workflow.
Use Dev Containers when team consistency matters, when you want to isolate project dependencies, or when onboarding speed is a priority. It works locally or combined with Remote SSH (you can open a container on a remote machine).
Use Remote Tunnels when you don’t have reliable SSH access, when you need to reach a machine behind NAT or a firewall, or when you want browser-based access from any device.
All three integrate with VS Code’s built-in debugging, source control, and extension ecosystem transparently — which is the reason the remote development workflow in VS Code remains significantly better than comparable setups in other editors.