# SSH

> Open a shell in a fresh sandbox with a single ssh command — no SDK, no client install.

Every Watasu sandbox is one `ssh` away. The SSH front door creates a sandbox
from a template and drops you into an interactive shell inside it — from any
machine with an ssh client, with the API credentials you already have. Agents
get the same benefit: anything that can run `ssh` can run code in a sandbox,
no SDK required.

```
$ ssh base@box.watasu.io
(base@box.watasu.io) Watasu API token:
watasu · sandbox s-6231 · template base:2026-06-14 · team myorg · deadline 60m
user@s-6231:/workspace$ python3 -V
Python 3.12.4
user@s-6231:/workspace$ exit

sandbox s-6231 paused · reconnect: ssh s-6231@box.watasu.io
```

On the first connect, paste a Watasu API token at the password prompt — the
same token `watasu login` stores in `~/.netrc`, or any write-capable API key
from the dashboard. Watasu registers your SSH public key during that first
login, so every later connect is passwordless.

Prefer not to paste anything? `watasu ssh base` handles the token for you on
that first connect — and because your key gets registered along the way,
plain `ssh base@box.watasu.io` works from then on.

## Addressing

Everything rides in the SSH username; the host is always `box.watasu.io`.

| Command                                | What it does                                                                             |
| -------------------------------------- | ---------------------------------------------------------------------------------------- |
| `ssh base@box.watasu.io`               | Fresh sandbox from the latest ready build of `base`, in your default team.               |
| `ssh base:2026-06-14@box.watasu.io`    | Pin an exact template build — same `slug:version-or-id-or-tag` syntax as the create API. |
| `ssh python-data:stable@box.watasu.io` | Your own template, resolved by tag.                                                      |
| `ssh myorg/base@box.watasu.io`         | Explicit team, for multi-team accounts.                                                  |
| `ssh s-6231@box.watasu.io`             | Reconnect to sandbox 6231 — resumes it if it is paused.                                  |
| `ssh base@box.watasu.io 'uname -a'`    | Run one command and exit; the exit code is propagated.                                   |
| `ssh ls@box.watasu.io`                 | List templates you can start and your recent sandboxes.                                  |

If you omit the team, Watasu uses your personal team; API keys scoped to a
single team use that team. If your key is scoped to several teams, name one
explicitly with the `team/` prefix.

## Authentication

SSH accepts two credentials:

* **A Watasu API token as the password.** Tokens come from `watasu login`
  (stored in `~/.netrc`) or from the dashboard's API keys page, and must be
  write-capable. Everything tied to the token applies to SSH sessions too:
  team scoping, revocation, and expiry.
* **A registered SSH public key.** Keys are listed and managed in the
  dashboard. During your first token-authenticated connect, Watasu registers
  the public key your ssh client offered (up to 5 auto-registered keys per
  account) and tells you so in the welcome banner. Set
  `-o SetEnv=WATASU_NO_ENROLL=1` to opt out for a connection.

For scripts and agents, `watasu token` prints the stored API token:

```bash
sshpass -p "$(watasu token)" ssh base@box.watasu.io 'echo ready'
```

or skip the plumbing entirely with the built-in wrapper, which handles the
token prompt for you:

```bash
watasu ssh base 'echo ready'
watasu ssh s-6231
```

## Host key

`box.watasu.io` always presents this ed25519 host key — it never changes:

```
ssh-ed25519 AAAAC3NzaC1lZDI1NTE5AAAAIJY3hN9LjzU/0KQRwdmVJbctFLx0HF0gcakLffffyu/I box.watasu.io
SHA256:6gMd8MZ2r3v+/05cX9UhDIsuUfsetY1ysl3APiYc6QE
```

Compare the fingerprint on first connect. `SSHFP` records are also published
in DNS for clients configured with `VerifyHostKeyDNS`.

## Options

Sandbox options are passed as `WATASU_*` environment variables using ssh's
standard env forwarding. Any other variables you send are set in the shell's
environment inside the sandbox, like ordinary ssh.

```bash
ssh -o SetEnv="WATASU_TIMEOUT=4h WATASU_MEMORY=4096" base@box.watasu.io
```

| Variable                         | Effect                                                                            |
| -------------------------------- | --------------------------------------------------------------------------------- |
| `WATASU_TEAM`                    | Team name — alternative to the `team/` username prefix.                           |
| `WATASU_TIMEOUT`                 | Sandbox timeout (`3600`, `90m`, `4h`). Default for SSH-created sandboxes: 1 hour. |
| `WATASU_ON_TIMEOUT`              | `pause` (default) or `kill` — what happens at the deadline.                       |
| `WATASU_CPU` / `WATASU_MEMORY`   | vCPU count / memory in MB, within your plan limits.                               |
| `WATASU_REGION`                  | Region preference for the new sandbox.                                            |
| `WATASU_SNAPSHOT`                | Create the sandbox from a checkpoint id instead of a template.                    |
| `WATASU_USER` / `WATASU_WORKDIR` | Unix user and working directory for the session.                                  |
| `WATASU_QUIET`                   | `1` suppresses informational messages in one-off command mode.                    |
| `WATASU_NO_ENROLL`               | `1` skips SSH key auto-registration for this connection.                          |

A misspelled `WATASU_*` variable fails the connection with a clear error
rather than silently starting a default sandbox.

## One-off commands and piping

Without a terminal request, `ssh` runs a single command with plain
stdin/stdout — so pipes work the way you expect:

```bash
# run and get the exit code
ssh base@box.watasu.io 'python3 -c "print(6*7)"'

# stream a local file in
ssh base@box.watasu.io 'wc -l' < data.csv

# bring results back
ssh s-6231@box.watasu.io 'tar -czf - /workspace/out' > out.tgz
```

Use `-t` when a one-off command needs a real terminal (TUIs, REPLs). For
structured file transfer, use the [files API](https://docs.watasu.io/sandboxes/files-and-commands.md) —
`scp`/`sftp` are not supported yet.

## Session lifecycle

* SSH-created sandboxes default to a 1-hour timeout with
  `on_timeout: pause` — a forgotten session becomes paused storage, not a
  running bill. See [Sandbox Billing](https://docs.watasu.io/sandboxes/billing.md).
* Typing `exit` pauses the sandbox immediately and prints the reconnect
  command. Reconnecting resumes it exactly where it stopped — files,
  processes, and memory state included.
* If the connection drops instead, the sandbox keeps running until its
  deadline; `ssh s-<id>@box.watasu.io` reattaches to the live session,
  including recent scrollback.
* Several SSH sessions can share one sandbox — each extra connection opens
  another shell in the same machine.
* Reconnecting refreshes the sandbox deadline, exactly like `resume` in the
  API.

Sandboxes created over SSH are ordinary sandboxes: they appear in
`GET /v1/sandboxes`, in the dashboard, and in the SDKs, and every
lifecycle operation on them works from anywhere. SSH is a door, not a
separate kind of sandbox.

## Not supported over SSH

* `scp`/`sftp` — use the [files API](https://docs.watasu.io/sandboxes/files-and-commands.md) or pipe
  through a one-off command as shown above.
* Port forwarding (`-L`/`-R`) — expose ports on the sandbox instead; see
  [Networking and Ports](https://docs.watasu.io/sandboxes/networking.md).
* SSH agent forwarding and X11.

Connection and session limits apply per account; sandbox creation over SSH
counts against your team's sandbox quota like any API create.

## Troubleshooting

| Symptom                                    | Fix                                                                                                                                                   |
| ------------------------------------------ | ----------------------------------------------------------------------------------------------------------------------------------------------------- |
| `Permission denied` at the password prompt | The token is invalid, revoked, expired, or read-only. Run `watasu login` again or create a write-capable API key in the dashboard.                    |
| `template '...' not found`                 | Check `ssh ls@box.watasu.io` for the templates visible to your team.                                                                                  |
| `you belong to several teams`              | Add the team prefix: `ssh myorg/base@box.watasu.io`.                                                                                                  |
| `balance is empty`                         | Top up your prepaid balance in the dashboard, then reconnect.                                                                                         |
| `sandbox s-... was destroyed`              | Destroyed sandboxes cannot be reconnected. Start fresh from the template, or restore a [checkpoint](https://docs.watasu.io/sandboxes/checkpoints.md). |
| Host key warning                           | Verify the fingerprint above. If it does not match, disconnect and contact support.                                                                   |

## Related pages

* [Sandboxes Overview](https://docs.watasu.io/sandboxes/overview.md)
* [Templates](https://docs.watasu.io/sandboxes/templates.md)
* [Files and Processes](https://docs.watasu.io/sandboxes/files-and-commands.md)
* [Checkpoints](https://docs.watasu.io/sandboxes/checkpoints.md)
* [Sandbox Billing](https://docs.watasu.io/sandboxes/billing.md)
* [CLI Authentication](https://docs.watasu.io/cli/authentication.md)

[View this page on the web](https://docs.watasu.io/sandboxes/ssh/)
