feat: Add SSH service for local VSCode Remote-SSH access#2792
feat: Add SSH service for local VSCode Remote-SSH access#2792gpothier wants to merge 2 commits intoOpenHands:mainfrom
Conversation
Add SSH server support to agent-server containers, enabling users to connect via their local VSCode with the Remote-SSH extension. ## Changes ### Dockerfile - Install openssh-server package - Generate SSH host keys (ed25519, rsa, ecdsa) at build time - Configure sshd for non-root operation (port 2222, key-based auth) - Set proper permissions on host keys for openhands group ### SSH Service (ssh_service.py) - New service to manage SSH server lifecycle - Populates ~/.ssh/authorized_keys from OH_SSH_PUBLIC_KEYS env var - Starts sshd as non-root user on port 2222 - Integrated with agent-server startup ### Configuration - Add SSH_PORT (default: 2222) to config - Add OH_SSH_PUBLIC_KEYS environment variable support ## Technical Details - SSH server runs on port 2222 (non-privileged) - Host keys readable by openhands group (mode 640) - PAM disabled (requires root) - Public key authentication preferred - Password authentication available as fallback Co-authored-by: openhands <openhands@all-hands.dev>
|
[Automatic Post]: I have assigned @simonrosenberg as a reviewer based on git blame information. Thanks in advance for the help! |
|
Thank you so much for this! @OpenHands Do a /codereview on this PR. Make sure you read the sister PR too. |
|
I'm on it! enyst can track my progress at all-hands.dev |
enyst
left a comment
There was a problem hiding this comment.
I read this together with the sister PR (OpenHands/OpenHands#13844). I like the overall direction, but I found a few important issues that should be fixed before this ships. The inline comments call out the details.
This review was created by an AI assistant (OpenHands) on behalf of the user.
| mkdir -p /run/sshd; \ | ||
| chmod 755 /run/sshd; \ | ||
| # Generate host keys | ||
| ssh-keygen -A; \ |
There was a problem hiding this comment.
Generating the SSH host keys at image-build time bakes the same private keys into every container built from this image. That defeats host identity verification: VS Code/SSH will see unrelated runtimes as the same host, and anyone with access to the image can impersonate another sandbox's host key. These keys need to be generated per container start (or injected/mounted per runtime), not once in the Dockerfile layer.
| # Allow sshd to run on non-privileged port without root | ||
| sed -i 's/#UsePAM yes/UsePAM no/' /etc/ssh/sshd_config; \ | ||
| # Set password for openhands user (password: "openhands") | ||
| echo "${USERNAME}:openhands" | chpasswd; \ |
There was a problem hiding this comment.
This enables password auth and sets a globally known credential (openhands / openhands). In the sister PR, the SSH endpoint is exposed directly to the user through sandbox.exposed_urls, so there is no app-level auth once someone can reach host:port. That means anyone who can hit the runtime can log in, even when the user configured SSH keys. I think we should disable PasswordAuthentication entirely here and require the per-user public keys instead.
| start_vscode_service(), | ||
| start_desktop_service(), | ||
| start_tool_preload_service(), | ||
| start_ssh_service(), |
There was a problem hiding this comment.
We start the SSH service here, but the shutdown path below still only stops VSCode, desktop, and tool-preload. That leaves sshd unmanaged across FastAPI lifespan restarts/tests and can leak the child process or keep the port bound. Please add a matching stop_ssh_service() in the finally gather(...) block.
Why
With the "Remote - SSH" extension, a local VSCode (or downstream fork) instance can connect to a remote machine and run everything except UI from there: git cloning, running the app, etc. Although the OpenHands UI embeds VSCode, that embedded version can be less useful than the local "desktop" version. For instance, for debugging:
This PR (along with the sister PR in the OpenHands repo) enables one-click opening of a local VSCode window connected to the sandbox:
Summary
Add SSH server support to agent-server containers, enabling users to connect via their local VSCode with the Remote-SSH extension.
There is a "sister" PR in the OpenHands repo that completes this feature with a settings page to add SSH keys and a button to directly open the local VSCode: OpenHands/OpenHands#13844
Changes
Dockerfile
SSH Service (ssh_service.py)
Configuration
Technical Details
Issue Number
How to Test
When both this PR and the sister PR are in use, a new button appears in the Code button's popup (see screenshot above). This button opens a new VSCode window connected to the sandbox through SSH. When the window opens for the first time, VSCode asks to accept the remote SSH host ID, like when one connects to a new SSH host (just type
yes).Video/Screenshots
Type
Notes
There seems to be a bug in VSCode itself with multiple VSCode windows connecting to the same SSH host at different ports, where it wrongly assumes this is the same host. So currently this feature only allows one local VSCode window at a time, at least until this is resolved on the VSCode side.