---
title: SSH
description: Rust SDK - SSH API reference
---

Reach a running sandbox over SSH: open a native in-process SSH client, run exec requests, attach an interactive shell, transfer files over SFTP, or stand up a reusable SSH server endpoint. Requires the `ssh` feature. See [SSH](/sandboxes/ssh) for usage flows.

```toml
microsandbox = { version = "0.5.8", features = ["ssh"] }
```


## Sandbox

#### <span className="msb-recv">sb.</span><span className="msb-hn">ssh()</span>

```rust
fn ssh(&self) -> SandboxSshOps
```

<Accordion title="Example">

```rust
let client = sb.ssh().connect().await?;
```

</Accordion>

Return the SSH namespace for this sandbox. The namespace holds the SSH client and server helpers; nothing connects until you call [`connect`](#ssh-connect) or [`server`](#ssh-server).

<p className="msb-label">Returns</p>

<div className="msb-params">
  <div className="msb-param">
    <div className="msb-param-key"><a className="msb-type" href="#sandboxsshops">SandboxSshOps</a></div>
    <div className="msb-param-desc">SSH namespace for this sandbox.</div>
  </div>
</div>

## SandboxSshOps

<p className="msb-backref">Returned by <a href="#sb-ssh">sb.ssh()</a></p>

SSH operations for a sandbox.

#### <span className="msb-recv">ssh.</span><span className="msb-hn">connect()</span>

```rust
async fn connect(&self) -> MicrosandboxResult<SshClient>
```

<Accordion title="Example">

```rust
let client = sb.ssh().connect().await?;
let out = client.exec("uname -a").await?;
```

</Accordion>

Connect a native in-process SSH client to this sandbox. Generates an ephemeral Ed25519 client and host key pair, stands up an internal server bound to a duplex stream, and authenticates over public key. Uses default client options (user `root`, terminal from `$TERM`, SFTP enabled).

<p className="msb-label">Returns</p>

<div className="msb-params">
  <div className="msb-param">
    <div className="msb-param-key"><a className="msb-type" href="#sshclient">SshClient</a></div>
    <div className="msb-param-desc">Connected SSH client session.</div>
  </div>
</div>

#### <span className="msb-recv">ssh.</span><span className="msb-hn">open_client()</span>

```rust
async fn open_client(&self) -> MicrosandboxResult<SshClient>
```

Alias for [`connect`](#ssh-connect).

<p className="msb-label">Returns</p>

<div className="msb-params">
  <div className="msb-param">
    <div className="msb-param-key"><a className="msb-type" href="#sshclient">SshClient</a></div>
    <div className="msb-param-desc">Connected SSH client session.</div>
  </div>
</div>

#### <span className="msb-recv">ssh.</span><span className="msb-hn">connect_with()</span>

```rust
async fn connect_with(
    &self,
    f: impl FnOnce(SshClientOptionsBuilder) -> SshClientOptionsBuilder,
) -> MicrosandboxResult<SshClient>
```

<Accordion title="Example">

```rust
let client = sb.ssh().connect_with(|opts| opts
    .user("app")
    .term("xterm-256color")).await?;
```

</Accordion>

Connect a native in-process SSH client with custom options. The closure configures the login user, terminal name, and whether SFTP is enabled on the internal server.

<p className="msb-label">Parameters</p>

<div className="msb-params">
  <div className="msb-param">
    <div className="msb-param-key"><code>f</code><a className="msb-type" href="#sshclientoptionsbuilder">FnOnce(SshClientOptionsBuilder)</a></div>
    <div className="msb-param-desc">Configure user, terminal, and SFTP support.</div>
  </div>
</div>

<p className="msb-label">Returns</p>

<div className="msb-params">
  <div className="msb-param">
    <div className="msb-param-key"><a className="msb-type" href="#sshclient">SshClient</a></div>
    <div className="msb-param-desc">Connected SSH client session.</div>
  </div>
</div>

#### <span className="msb-recv">ssh.</span><span className="msb-hn">open_client_with()</span>

```rust
async fn open_client_with(
    &self,
    f: impl FnOnce(SshClientOptionsBuilder) -> SshClientOptionsBuilder,
) -> MicrosandboxResult<SshClient>
```

Alias for [`connect_with`](#ssh-connect_with).

<p className="msb-label">Parameters</p>

<div className="msb-params">
  <div className="msb-param">
    <div className="msb-param-key"><code>f</code><a className="msb-type" href="#sshclientoptionsbuilder">FnOnce(SshClientOptionsBuilder)</a></div>
    <div className="msb-param-desc">Configure user, terminal, and SFTP support.</div>
  </div>
</div>

<p className="msb-label">Returns</p>

<div className="msb-params">
  <div className="msb-param">
    <div className="msb-param-key"><a className="msb-type" href="#sshclient">SshClient</a></div>
    <div className="msb-param-desc">Connected SSH client session.</div>
  </div>
</div>

#### <span className="msb-recv">ssh.</span><span className="msb-hn">server()</span>

<Tooltip tip="Serving with the convenience defaults is not available on microsandbox cloud; supply explicit host-key and authorized-key material, or use the SSH client."><span className="msb-badge-local">Local-only <Icon icon="circle-info" size={11} /></span></Tooltip>

```rust
async fn server(&self) -> MicrosandboxResult<SshServer>
```

<Accordion title="Example">

```rust
let server = sb.ssh().server().await?;
let (client_io, server_io) = tokio::io::duplex(64 * 1024);
server.serve(server_io).await?;
```

</Accordion>

Prepare a reusable SSH server endpoint for this sandbox. Loads or creates the host key and resolves authorized keys from the default authorized-keys file. The returned [`SshServer`](#sshserver) is cloneable and can serve many connections.

<p className="msb-label">Returns</p>

<div className="msb-params">
  <div className="msb-param">
    <div className="msb-param-key"><a className="msb-type" href="#sshserver">SshServer</a></div>
    <div className="msb-param-desc">Reusable SSH server endpoint.</div>
  </div>
</div>

#### <span className="msb-recv">ssh.</span><span className="msb-hn">prepare_server()</span>

<Tooltip tip="Serving with the convenience defaults is not available on microsandbox cloud; supply explicit host-key and authorized-key material, or use the SSH client."><span className="msb-badge-local">Local-only <Icon icon="circle-info" size={11} /></span></Tooltip>

```rust
async fn prepare_server(&self) -> MicrosandboxResult<SshServer>
```

Alias for [`server`](#ssh-server).

<p className="msb-label">Returns</p>

<div className="msb-params">
  <div className="msb-param">
    <div className="msb-param-key"><a className="msb-type" href="#sshserver">SshServer</a></div>
    <div className="msb-param-desc">Reusable SSH server endpoint.</div>
  </div>
</div>

#### <span className="msb-recv">ssh.</span><span className="msb-hn">server_with()</span>

<Tooltip tip="On microsandbox cloud, serving works when you supply explicit host-key and authorized-key material; the convenience defaults are local-only."><span className="msb-badge-limited">Limited on cloud <Icon icon="circle-info" size={11} /></span></Tooltip>

```rust
async fn server_with(
    &self,
    f: impl FnOnce(SshServerOptionsBuilder) -> SshServerOptionsBuilder,
) -> MicrosandboxResult<SshServer>
```

<Accordion title="Example">

```rust
let server = sb.ssh().server_with(|opts| opts
    .authorized_key("ssh-ed25519 AAAAC3Nza...")
    .user("app")
    .sftp(false)).await?;
```

</Accordion>

Prepare a server endpoint with custom host-key, authorization, guest-user, or SFTP options. If no authorized keys are configured, the default authorized-keys file is loaded; an empty key set is an error.

<p className="msb-label">Parameters</p>

<div className="msb-params">
  <div className="msb-param">
    <div className="msb-param-key"><code>f</code><a className="msb-type" href="#sshserveroptionsbuilder">FnOnce(SshServerOptionsBuilder)</a></div>
    <div className="msb-param-desc">Configure host key, authorized keys, guest user, and SFTP.</div>
  </div>
</div>

<p className="msb-label">Returns</p>

<div className="msb-params">
  <div className="msb-param">
    <div className="msb-param-key"><a className="msb-type" href="#sshserver">SshServer</a></div>
    <div className="msb-param-desc">Reusable SSH server endpoint.</div>
  </div>
</div>

#### <span className="msb-recv">ssh.</span><span className="msb-hn">prepare_server_with()</span>

<Tooltip tip="On microsandbox cloud, serving works when you supply explicit host-key and authorized-key material; the convenience defaults are local-only."><span className="msb-badge-limited">Limited on cloud <Icon icon="circle-info" size={11} /></span></Tooltip>

```rust
async fn prepare_server_with(
    &self,
    f: impl FnOnce(SshServerOptionsBuilder) -> SshServerOptionsBuilder,
) -> MicrosandboxResult<SshServer>
```

Alias for [`server_with`](#ssh-server_with).

<p className="msb-label">Parameters</p>

<div className="msb-params">
  <div className="msb-param">
    <div className="msb-param-key"><code>f</code><a className="msb-type" href="#sshserveroptionsbuilder">FnOnce(SshServerOptionsBuilder)</a></div>
    <div className="msb-param-desc">Configure host key, authorized keys, guest user, and SFTP.</div>
  </div>
</div>

<p className="msb-label">Returns</p>

<div className="msb-params">
  <div className="msb-param">
    <div className="msb-param-key"><a className="msb-type" href="#sshserver">SshServer</a></div>
    <div className="msb-param-desc">Reusable SSH server endpoint.</div>
  </div>
</div>

## SshClient

<p className="msb-backref">Returned by <a href="#ssh-connect">ssh.connect()</a>, <a href="#ssh-connect_with">ssh.connect_with()</a></p>

Native in-process SSH client session.

#### <span className="msb-recv">client.</span><span className="msb-hn">exec()</span>

```rust
async fn exec(&self, command: impl Into<String>) -> MicrosandboxResult<SshOutput>
```

<Accordion title="Example">

```rust
let out = client.exec("echo hello").await?;
println!("exit {}: {}", out.status, String::from_utf8_lossy(&out.stdout));
```

</Accordion>

Run an SSH exec request and collect stdout, stderr, and the exit status. The command is run through the sandbox's configured shell (default `/bin/sh -c`). No PTY is requested.

<p className="msb-label">Parameters</p>

<div className="msb-params">
  <div className="msb-param">
    <div className="msb-param-key"><code>command</code><span className="msb-type">impl Into&lt;String&gt;</span></div>
    <div className="msb-param-desc">Command string sent through SSH.</div>
  </div>
</div>

<p className="msb-label">Returns</p>

<div className="msb-params">
  <div className="msb-param">
    <div className="msb-param-key"><a className="msb-type" href="#sshoutput">SshOutput</a></div>
    <div className="msb-param-desc">Captured output and exit status.</div>
  </div>
</div>

#### <span className="msb-recv">client.</span><span className="msb-hn">exec_with()</span>

```rust
async fn exec_with(
    &self,
    command: impl Into<String>,
    f: impl FnOnce(SshExecOptionsBuilder) -> SshExecOptionsBuilder,
) -> MicrosandboxResult<SshOutput>
```

<Accordion title="Example">

```rust
let out = client.exec_with("top -bn1", |opts| opts.tty(true)).await?;
```

</Accordion>

Run an SSH exec request with options. The closure can request a PTY via [`tty`](#sshexecoptionsbuilder); when a PTY is allocated, stderr is folded into stdout.

<p className="msb-label">Parameters</p>

<div className="msb-params">
  <div className="msb-param">
    <div className="msb-param-key"><code>command</code><span className="msb-type">impl Into&lt;String&gt;</span></div>
    <div className="msb-param-desc">Command string sent through SSH.</div>
  </div>
  <div className="msb-param">
    <div className="msb-param-key"><code>f</code><a className="msb-type" href="#sshexecoptionsbuilder">FnOnce(SshExecOptionsBuilder)</a></div>
    <div className="msb-param-desc">Configure exec options.</div>
  </div>
</div>

<p className="msb-label">Returns</p>

<div className="msb-params">
  <div className="msb-param">
    <div className="msb-param-key"><a className="msb-type" href="#sshoutput">SshOutput</a></div>
    <div className="msb-param-desc">Captured output and exit status.</div>
  </div>
</div>

#### <span className="msb-recv">client.</span><span className="msb-hn">attach()</span>

```rust
async fn attach(&self) -> MicrosandboxResult<i32>
```

<Accordion title="Example">

```rust
let code = client.attach().await?;
println!("shell exited with {code}");
```

</Accordion>

Attach the local terminal to an interactive SSH shell. Requests a PTY sized to the current terminal, puts the terminal into raw mode, forwards keystrokes, relays window-resize events, and returns when the shell exits or the default detach key sequence is typed.

<p className="msb-label">Returns</p>

<div className="msb-params">
  <div className="msb-param">
    <div className="msb-param-key"><span className="msb-type">i32</span></div>
    <div className="msb-param-desc">Shell exit code (128 if terminated by signal).</div>
  </div>
</div>

#### <span className="msb-recv">client.</span><span className="msb-hn">attach_with()</span>

```rust
async fn attach_with(
    &self,
    f: impl FnOnce(SshAttachOptionsBuilder) -> SshAttachOptionsBuilder,
) -> MicrosandboxResult<i32>
```

<Accordion title="Example">

```rust
let code = client.attach_with(|opts| opts
    .term("xterm-256color")
    .detach_keys("ctrl-p,ctrl-q")).await?;
```

</Accordion>

Attach an interactive shell with custom terminal and detach-key options.

<p className="msb-label">Parameters</p>

<div className="msb-params">
  <div className="msb-param">
    <div className="msb-param-key"><code>f</code><a className="msb-type" href="#sshattachoptionsbuilder">FnOnce(SshAttachOptionsBuilder)</a></div>
    <div className="msb-param-desc">Configure terminal name and detach keys.</div>
  </div>
</div>

<p className="msb-label">Returns</p>

<div className="msb-params">
  <div className="msb-param">
    <div className="msb-param-key"><span className="msb-type">i32</span></div>
    <div className="msb-param-desc">Shell exit code (128 if terminated by signal).</div>
  </div>
</div>

#### <span className="msb-recv">client.</span><span className="msb-hn">sftp()</span>

```rust
async fn sftp(&self) -> MicrosandboxResult<SftpClient>
```

<Accordion title="Example">

```rust
let sftp = client.sftp().await?;
let mut file = sftp.create("/tmp/hello.txt").await?;
```

</Accordion>

Open an SFTP client session over this SSH connection. Requests the `sftp` subsystem and returns a high-level SFTP session for reading, writing, and listing files inside the guest.

<p className="msb-label">Returns</p>

<div className="msb-params">
  <div className="msb-param">
    <div className="msb-param-key"><a className="msb-type" href="#sftpclient">SftpClient</a></div>
    <div className="msb-param-desc">SFTP client session.</div>
  </div>
</div>

#### <span className="msb-recv">client.</span><span className="msb-hn">close()</span>

```rust
async fn close(self) -> MicrosandboxResult<()>
```

<Accordion title="Example">

```rust
client.close().await?;
```

</Accordion>

Close this native SSH client session. Sends a disconnect and aborts the internal server task. Consumes the client.

## SshServer

<p className="msb-backref">Returned by <a href="#ssh-server">ssh.server()</a>, <a href="#ssh-server_with">ssh.server_with()</a></p>

Reusable SSH server endpoint for a sandbox.

#### <span className="msb-recv">server.</span><span className="msb-hn">serve()</span>

```rust
async fn serve<S>(&self, stream: S) -> MicrosandboxResult<()>
where
    S: AsyncRead + AsyncWrite + Unpin + Send + 'static,
```

<Accordion title="Example">

```rust
let server = sb.ssh().server().await?;
let (client_io, server_io) = tokio::io::duplex(64 * 1024);
tokio::spawn(async move { server.serve(server_io).await });
```

</Accordion>

Serve one SSH connection over an ordered duplex stream. Runs the SSH handshake and session loop to completion. Returns when the connection closes.

<p className="msb-label">Parameters</p>

<div className="msb-params">
  <div className="msb-param">
    <div className="msb-param-key"><code>stream</code><span className="msb-type">S: AsyncRead + AsyncWrite</span></div>
    <div className="msb-param-desc">Ordered duplex SSH transport.</div>
  </div>
</div>

#### <span className="msb-recv">server.</span><span className="msb-hn">serve_connection()</span>

```rust
async fn serve_connection<S>(&self, stream: S) -> MicrosandboxResult<()>
where
    S: AsyncRead + AsyncWrite + Unpin + Send + 'static,
```

Alias for [`serve`](#server-serve).

<p className="msb-label">Parameters</p>

<div className="msb-params">
  <div className="msb-param">
    <div className="msb-param-key"><code>stream</code><span className="msb-type">S: AsyncRead + AsyncWrite</span></div>
    <div className="msb-param-desc">Ordered duplex SSH transport.</div>
  </div>
</div>

## SshStdioStream

<p className="msb-backref">Used by <a href="#server-serve">server.serve()</a></p>

Ordered duplex stream backed by this process's stdin and stdout. Implements `AsyncRead` and `AsyncWrite`.


#### <span className="msb-recv">SshStdioStream::</span><span className="msb-hn">new()</span>

```rust
fn new() -> Self
```

<Accordion title="Example">

```rust
use microsandbox::SshStdioStream;

let server = sb.ssh().server().await?;
server.serve(SshStdioStream::new()).await?;
```

</Accordion>

Create a stdio SSH transport stream backed by this process's stdin and stdout. Implements [`AsyncRead`](#sshstdiostream) and `AsyncWrite`, so it can be passed straight to [`serve`](#server-serve) to bridge an SSH connection over the parent process's standard streams. Also available via `Default`.

<p className="msb-label">Returns</p>

<div className="msb-params">
  <div className="msb-param">
    <div className="msb-param-key"><a className="msb-type" href="#sshstdiostream">SshStdioStream</a></div>
    <div className="msb-param-desc">Duplex stream over stdin/stdout.</div>
  </div>
</div>

## Constants

#### <span className="msb-recv"></span><span className="msb-hn">DEFAULT_SSH_HOST</span>

```rust
pub const DEFAULT_SSH_HOST: &str = "127.0.0.1";
```

Default SSH listener host used by the CLI adapter when binding a sandbox SSH endpoint.

#### <span className="msb-recv"></span><span className="msb-hn">DEFAULT_SSH_PORT</span>

```rust
pub const DEFAULT_SSH_PORT: u16 = 2222;
```

Default SSH listener port used by the CLI adapter when binding a sandbox SSH endpoint.

## SshClientOptionsBuilder


<p className="msb-backref">Used by <a href="#ssh-connect_with">ssh.connect_with()</a></p>

Builder for SSH client options. Defaults: user `root`, terminal from `$TERM` (falling back to `xterm`), SFTP enabled.


#### <span className="msb-recv">client_options.</span><span className="msb-hn">user()</span>

```rust
user()
```

SSH login user. Default `root`.

#### <span className="msb-recv">client_options.</span><span className="msb-hn">term()</span>

```rust
term()
```

Terminal name for interactive sessions.

#### <span className="msb-recv">client_options.</span><span className="msb-hn">sftp()</span>

```rust
sftp()
```

Enable or disable SFTP on the internal server. Default `true`.

#### <span className="msb-recv">client_options.</span><span className="msb-hn">build()</span>

```rust
build()
```

Finalize the options.

## SshExecOptionsBuilder


<p className="msb-backref">Used by <a href="#client-exec_with">client.exec_with()</a></p>

Builder for SSH exec options.


#### <span className="msb-recv">exec_options.</span><span className="msb-hn">tty()</span>

```rust
tty()
```

Request a PTY for the exec channel. Default `false`.

#### <span className="msb-recv">exec_options.</span><span className="msb-hn">build()</span>

```rust
build()
```

Finalize the options.

## SshAttachOptionsBuilder


<p className="msb-backref">Used by <a href="#client-attach_with">client.attach_with()</a></p>

Builder for interactive SSH attach options. Default terminal comes from `$TERM` (falling back to `xterm`); detach keys default to the standard sequence.


#### <span className="msb-recv">attach_options.</span><span className="msb-hn">term()</span>

```rust
term()
```

Terminal name for the shell.

#### <span className="msb-recv">attach_options.</span><span className="msb-hn">detach_keys()</span>

```rust
detach_keys()
```

Detach key sequence.

#### <span className="msb-recv">attach_options.</span><span className="msb-hn">build()</span>

```rust
build()
```

Finalize the options.

## SshServerOptionsBuilder


<p className="msb-backref">Used by <a href="#ssh-server_with">ssh.server_with()</a></p>

Builder for SSH server options. SFTP is enabled by default; when no authorized keys are provided, the default authorized-keys file is loaded.


#### <span className="msb-recv">server_options.</span><span className="msb-hn">host_key_path()</span>

```rust
host_key_path()
```

Override the host private key path.

#### <span className="msb-recv">server_options.</span><span className="msb-hn">host_key()</span>

```rust
host_key()
```

Use an in-memory host private key.

#### <span className="msb-recv">server_options.</span><span className="msb-hn">authorized_keys_path()</span>

```rust
authorized_keys_path()
```

Override the authorized-keys path.

#### <span className="msb-recv">server_options.</span><span className="msb-hn">authorized_key()</span>

```rust
authorized_key()
```

Add one in-memory authorized public key.

#### <span className="msb-recv">server_options.</span><span className="msb-hn">user()</span>

```rust
user()
```

Override the guest user used for exec requests.

#### <span className="msb-recv">server_options.</span><span className="msb-hn">sftp()</span>

```rust
sftp()
```

Enable or disable SFTP. Default `true`.

#### <span className="msb-recv">server_options.</span><span className="msb-hn">build()</span>

```rust
build()
```

Finalize the options.

## SftpClient

<p className="msb-backref">Returned by <a href="#client-sftp">client.sftp()</a></p>

High-level SFTP client session.

```rust
pub type SftpClient = russh_sftp::client::SftpSession;
```

## Types

### SshOutput

<p className="msb-backref">Returned by <a href="#client-exec">client.exec()</a>, <a href="#client-exec_with">client.exec_with()</a></p>

Output from an SSH exec request.

| Field | Type | Description |
|-------|------|-------------|
| `status` | `i32` | Exit status code. |
| `stdout` | `Bytes` | Captured stdout bytes. |
| `stderr` | `Bytes` | Captured stderr bytes (folded into stdout when a PTY is allocated). |
