Networking
Public HTTPS ports, SSH access via the bastion, and the workspace-private network.
Every sandbox gets a private IP on the workspace network and an sshd the bastion can reach. Outbound is unrestricted; inbound is gated by ports and ssh-access tokens.
Ports
A public HTTPS route from https://<label>--<sandbox-slug>.froglet.sh to an internal port inside the sandbox.
$ froglet ports expose demo --internal 8080 --label web exposed :8080 → http://web--demo.froglet.sh
| Flag | Effect |
|---|---|
--internal | Guest port to forward to. Required. |
--label | URL prefix. Reserved labels (api, admin) are rejected. |
--public | Default. No auth on the route. |
--private | Requires an access token. Mint with ports share. |
--ttl | Auto-revoke after N seconds. |
One-time share link:
$ pid=$(froglet ports ls demo --json | jq -r '.[0].id') $ froglet ports share demo "$pid" --ttl 300 token (expires …): eyJhbGciOiJI…
Revoke explicitly with ports revoke <sandbox> <port-full-uuid>.
SSH
The bastion is at ssh.froglet.sh:2222. Auth is a workspace-scoped JWT minted by ssh-access new:
$ froglet ssh-access new demo --name laptop --ttl 4
created access c35d7262-…
ssh -p 2222 eyJhbGciOiJI…@ssh.froglet.sh
expires 2026-05-17T18:00:00.000ZPaste the printed ssh -p 2222 … line into your terminal. The JWT is the username; the bastion validates it and proxies to the sandbox's guest sshd.
| Command | Effect |
|---|---|
ssh-access new <sandbox> | Mint a token. --ttl <hours> controls expiry. |
ssh-access ls <sandbox> | List outstanding tokens. |
ssh-access rm <access-uuid> | Revoke a token (full UUID required). |
PTY
For a browser terminal, mint a 60-second-TTL WebSocket ticket:
$ froglet sb pty-ticket demo wss://…?ticket=eyJhbGciOiJI…
The dashboard's terminal panel uses this; you can plug the URL into xterm.js or similar.
CLI / SDK
CLI · ports + ssh-access; SDK namespaces ports.*, sshAccess.*, plus the per-sandbox helpers sandboxes.exposePort, sandboxes.createSshAccess, sandboxes.ptyTicket.