# SSH

Use standard SSH clients to open a shell inside a sandbox or copy files with `scp`. Sandbox0 terminates SSH at a region-scoped `ssh-gateway`, authenticates the user from uploaded SSH public keys, and bridges the session into the sandbox runtime.

<Callout variant="info">
SSH access targets the sandbox procd runtime in the main sandbox container.
</Callout>

## Connection Model

| Part | Value | Example |
|------|-------|---------|
| Gateway host | Returned by the sandbox detail `ssh.host` field | `aws-us-east-1.ssh.sandbox0.example.com` |
| SSH port | Returned by the sandbox detail `ssh.port` field | `22` |
| SSH username | Target sandbox ID | `rs-abc123-default-x7k9m` |
| Authentication | SSH public key uploaded to the current user | `ssh-ed25519 AAAA...` |
| Session target | Interactive shell or remote command in the sandbox main container | `ssh <sandbox-id>@<host>` |

The gateway uses the SSH username to decide which sandbox to connect to. Your uploaded public key identifies the user, and the platform still enforces normal sandbox authorization before opening the session.

Use `s0 sandbox get` to read the connection info instead of hard-coding a region host:

```bash
s0 sandbox get "$SANDBOX_ID"
```

The table output includes `SSH Host`, `SSH Port`, and `SSH Username` when SSH is available for the sandbox. Use `s0 -o json sandbox get "$SANDBOX_ID"` when you want to script against the same fields.

<Callout variant="warning">
Sandbox0 supports `scp` only when the client uses SFTP-backed mode. [OpenSSH 9.0 and newer](https://www.openssh.com/txt/release-9.0) use this mode by default. Legacy SCP protocol, including `scp -O` and OpenSSH 8.x `scp` clients that default to legacy SCP, is not supported. Use `sftp` or upgrade the OpenSSH client if you are on OpenSSH 8.x.
</Callout>

---

## Manage SSH Public Keys

Upload your SSH public key once, then reuse standard `ssh`, SFTP-backed `scp`, and `sftp` clients.

Create a key if you do not already have one:

```bash
ssh-keygen -t ed25519 -f ~/.ssh/sandbox0_ed25519 -C "sandbox0"
```

Upload the public key with the `s0` CLI:

```bash
s0 user ssh-key add --public-key-file ~/.ssh/sandbox0_ed25519.pub
```

You can also pass the public key inline. Inline keys require an explicit name:

```bash
s0 user ssh-key add --name laptop --public-key "$(cat ~/.ssh/sandbox0_ed25519.pub)"
```

List the keys currently attached to your user:

```bash
s0 user ssh-key list
```

Delete a key you no longer want to trust. Use the key ID from `s0 user ssh-key list`:

```bash
s0 user ssh-key delete "$SSH_KEY_ID"
```

---

## Connect to a Sandbox

Read `SSH Host`, `SSH Port`, and `SSH Username` from `s0 sandbox get`, then connect with a standard SSH client.

Fetch the connection info:

```bash
s0 sandbox get "$SANDBOX_ID"
```

For scripts, extract the same fields from JSON output:

```bash
SANDBOX_JSON="$(s0 -o json sandbox get "$SANDBOX_ID")"
SSH_HOST="$(printf '%s' "$SANDBOX_JSON" | jq -r '.ssh.host')"
SSH_PORT="$(printf '%s' "$SANDBOX_JSON" | jq -r '.ssh.port')"
SSH_USER="$(printf '%s' "$SANDBOX_JSON" | jq -r '.ssh.username')"
ssh -i ~/.ssh/sandbox0_ed25519 -p "$SSH_PORT" "$SSH_USER@$SSH_HOST"
```

Run a one-shot remote command instead of opening an interactive shell:

```bash
ssh -i ~/.ssh/sandbox0_ed25519 -p "$SSH_PORT" "$SSH_USER@$SSH_HOST" 'uname -a'
```

If the sandbox is paused and `auto_resume` is enabled, `ssh-gateway` asks the control plane to resume it before attaching. With `auto_resume: false`, resume it explicitly first. Wake-up takes time and can fail when capacity or retained memory compatibility is unavailable. SSH and SFTP require running guest compute; use the [Files API](/docs/sandbox/files) for persistent file access while compute stays paused.

---

## Copy Files with scp

Use `scp` to upload or download files when your OpenSSH client uses SFTP-backed mode. This is the default in OpenSSH 9.0 and newer. On OpenSSH 8.x, use the `sftp` command instead because its `scp` client speaks the legacy SCP protocol.

Upload a local file:

```bash
scp -i ~/.ssh/sandbox0_ed25519 -P "$SSH_PORT" ./build.log "$SSH_USER@$SSH_HOST:/workspace/build.log"
```

Download a file from the sandbox:

```bash
scp -i ~/.ssh/sandbox0_ed25519 -P "$SSH_PORT" "$SSH_USER@$SSH_HOST:/workspace/output.txt" ./output.txt
```

Because file transfer runs over the SFTP subsystem here, `sftp` clients work too:

```bash
sftp -i ~/.ssh/sandbox0_ed25519 -P "$SSH_PORT" "$SSH_USER@$SSH_HOST"
```

---

## Operational Notes

- SSH authorization stays at the platform layer. You do not manage `authorized_keys` inside each sandbox.
- Uploaded SSH public keys belong to the user account, not to one sandbox.
- A key can access any sandbox that the user is authorized to access in that region.
- SSH is best for human shell access and standard file transfer. For programmatic process control, use [Contexts](/docs/sandbox/contexts), or use [Supervised Sessions](/docs/sandbox/session-supervisor) when reconnect and runtime recovery matter.

---

## Next Steps

<CardGroup>
  <Card title="Network" href="/docs/sandbox/network" cta="Continue">
    Configure outbound network policy, traffic rules, and protocol-aware restrictions.
  </Card>

  <Card title="Egress Proxy" href="/docs/sandbox/proxy" cta="Continue">
    Route allowed TCP egress through a customer-managed SOCKS5 proxy.
  </Card>
</CardGroup>
