Skip to content

Connect browser SSH through metro-api - #307

Open
sjmiller609 wants to merge 1 commit into
mainfrom
hypeship/ssh-via-metro-api
Open

sjmiller609 wants to merge 1 commit into
mainfrom
hypeship/ssh-via-metro-api

Conversation

@sjmiller609

@sjmiller609 sjmiller609 commented Oct 31, 2026 •

Copy link
Copy Markdown
Contributor

Summary

kernel browsers ssh now tunnels through metro-api's /browser/ssh route instead of the VM's public 2222 endpoint.

  • Derive the SSH URL from the browser's CDP URL: same metro-api host, port, base path and session JWT, with /browser/cdp replaced by /browser/ssh.
  • Use it for the interactive connection and for both --setup-only outputs. The ProxyCommand URL is single-quoted because ssh runs it through a shell and the URL contains ?. The printed ssh command wraps it in double quotes.
  • Guest setup is unchanged: the CLI still starts the websocat bridge on the VM's private 2222, and metro-api forwards to it. The JSON output keeps all its fields, including vm_domain.

Going through metro-api means connecting wakes a browser that's in standby, and an open SSH connection keeps it out of standby, including while the shell is idle.

Rollout

Requires the metro-api /browser/ssh route (kernel/kernel#5144) to be deployed on every metro before release. Older CLI versions keep using public 2222 until it is retired.

--setup-only commands now include the session JWT in the websocat URL, so they're valid only for as long as that JWT is.

Testing

  • go build ./..., go vet ./cmd/... ./pkg/ssh/, go test ./pkg/ssh/ ./cmd/
  • New unit tests cover URL derivation (root and base-path metro URLs, extra query params dropped, missing JWT, unexpected path) and the generated ssh args.
  • Against staging with a headless Hypeman browser and the built CLI:
    • Interactive kernel browsers ssh <id> ran a remote command through /browser/ssh.
    • The printed --setup-only -o json ssh_command, run through bash -c, connected and ran a command.
    • Local forwarding (-L) to the guest's CDP HTTP endpoint returned /json/version.
    • Deleted the browser afterward.
  • Not tested: Unikraft browsers, or anything against production.

Note

Medium Risk
Changes how users reach browser VMs and depends on metro-api /browser/ssh being deployed; setup-only commands now embed session JWTs with limited lifetime.

Overview
kernel browsers ssh no longer opens websocat to the VM’s public :2222 endpoint. It builds a metro-api SSH WebSocket URL from the browser CDP URL (same host, path prefix, and session JWT; /browser/cdp → /browser/ssh) and uses that for the interactive session and for --setup-only / JSON proxy_command / ssh_command output.

Shared helpers ProxyURL, ProxyCommand, and an updated BuildSSHCommand(proxyURL, …) centralize the websocat --binary '…' proxy (single-quoted URL for shell-safe ProxyCommand). VM-side setup is unchanged; metro still forwards to the guest bridge on private 2222. Troubleshooting text now points at metro reachability instead of port 2222.

Unit tests cover URL derivation edge cases and the generated ssh argument list.

Reviewed by Cursor Bugbot for commit 99b92ea. Bugbot is set up for automated code reviews on this repo. Configure here.

@sjmiller609
sjmiller609 marked this pull request as ready for review October 31, 2026 15:27
@sjmiller609
sjmiller609 requested a review from rgarcia October 31, 2026 15:34
@sjmiller609

Copy link
Copy Markdown
Contributor Author

Picked rgarcia to review: recent commits in ssh; 6 pending

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

2 participants