> ## Documentation Index
> Fetch the complete documentation index at: https://docs.baseten.co/llms.txt
> Use this file to discover all available pages before exploring further.

# SSH access

> Connect to running model deployments directly from your terminal with standard SSH.

SSH into any running model deployment on Baseten and get a full terminal inside the model container: debug, inspect files, run commands, edit code, or transfer data with `scp` and `sftp`. Standard OpenSSH tooling works unchanged, so anything that speaks SSH, from your terminal to your IDE, can reach the container.

## Prerequisites

<Note>
  Inference SSH must be enabled for your organization. [Contact support](mailto:support@baseten.co) to request access.
</Note>

* **Baseten account**: [Sign up](https://app.baseten.co/) and generate an [API key](https://app.baseten.co/settings/account/api_keys).
* **Baseten CLI**: [Install the CLI](/reference/cli/baseten/overview#install) and log in:

  ```sh Terminal theme={"system"}
  baseten auth login
  ```
* **OpenSSH client**: Pre-installed on macOS and Linux. On Windows, use the OpenSSH optional feature or WSL.

## Set up your machine

Run setup once per machine. It generates an SSH keypair and adds a managed block to `~/.ssh/config` that routes `*.ssh.baseten.co` connections through the CLI.

<Tabs>
  <Tab title="Baseten CLI">
    **To set up SSH access**:

    <CodeGroup>
      ```sh Terminal theme={"system"}
      baseten ssh setup
      ```

      ```text Output theme={"system"}
      Generated SSH keypair: /Users/<you>/.ssh/baseten/id_ed25519
      SSH config updated.
      Connect with:
         deployment:    ssh model-<model-id>-<deployment-id>.ssh.baseten.co
         environment:   ssh <environment>.model-<model-id>.ssh.baseten.co
         training job:  ssh training-job-<job-id>-<node>.ssh.baseten.co
      ```
    </CodeGroup>

    Connections authenticate with the profile pinned at setup time. To pin a different profile, pass `--profile <name>`. Re-running setup refreshes the keypair and the managed config block.

    If you previously ran `truss ssh setup`, remove its block (between `# --- baseten-ssh ---` and `# --- end baseten-ssh ---`) from `~/.ssh/config` first; setup refuses to touch a file that already configures `*.ssh.baseten.co` hosts outside its own managed block.
  </Tab>

  <Tab title="Truss CLI">
    **To set up SSH access**:

    <CodeGroup>
      ```sh Terminal theme={"system"}
      uvx truss ssh setup
      ```

      ```text Output theme={"system"}
      SSH keypair: /Users/<you>/.ssh/baseten/id_ed25519
      Proxy script: /Users/<you>/.ssh/baseten/proxy-command.py
      SSH config updated: ~/.ssh/config
      Default remote: <remote>

      SSH access configured. Connect to a running workload with:

        Training job: ssh training-job-<job-id>-<node>.ssh.baseten.co
        Inference model: ssh model-<model-id>-<deployment-id>.ssh.baseten.co
      ```
    </CodeGroup>

    The Truss setup doesn't support the `<environment>.model-<model-id>` hostname form; use the Baseten CLI to connect by environment name.
  </Tab>
</Tabs>

## Enable SSH on a deployment

SSH is enabled per deployment in `config.yaml`:

1. Set [`runtime.remote_ssh.enabled`](/reference/truss-configuration#param-remote-ssh) to `true` in your model's `config.yaml`:

   ```yaml config.yaml {3-5} theme={"system"}
   model_name: my-model

   runtime:
     remote_ssh:
       enabled: true

   resources:
     accelerator: H100
     use_gpu: true
   ```

2. Push the model:

   ```sh Terminal theme={"system"}
   baseten model push
   ```

SSH access is available as soon as the deployment is `ACTIVE`. Re-deploying without this field disables SSH for the new deployment. Active SSH sessions don't block scale-to-zero or scale-down; for longer interactive sessions, set a non-zero `min_replicas` so your replica isn't reclaimed mid-session.

<Note>
  SSH requires the default container user (`app`, uid `60000`). Setting `docker_server.run_as_user_id` to a different value is incompatible with SSH and the push will fail validation.
</Note>

## Connect

**To connect to a running deployment**:

1. Find the model and deployment IDs:

   <CodeGroup>
     ```sh Terminal theme={"system"}
     baseten model deployment list --model-id abc12345
     ```

     ```text Output theme={"system"}
     ID       NAME           ENVIRONMENT  STATUS  INSTANCE                    REPLICAS  CREATED
     def4567  deployment-31  production   ACTIVE  4x16 - 4 vCPUs, 16 GiB RAM  1         2026-07-03T22:03:00Z
     ...
     ```
   </CodeGroup>

   Find model IDs with [`baseten model list`](/reference/cli/baseten/model#list).

2. SSH in with the deployment hostname:

   ```sh Terminal theme={"system"}
   ssh model-abc12345-def4567.ssh.baseten.co
   ```

You're connected when you see a shell prompt inside the model container. Your container runs as the non-root `app` user.

To connect to whatever deployment is currently live in an environment, put the environment name in front of the model ID instead of naming a deployment:

```sh Terminal theme={"system"}
ssh production.model-abc12345.ssh.baseten.co
```

The CLI resolves the environment to its current deployment on every connection, so the same hostname keeps working across promotions. This form requires setup through the Baseten CLI.

## How it works

When you connect to a `*.ssh.baseten.co` hostname, the managed `~/.ssh/config` block runs the CLI. The CLI calls Baseten's signing API to issue a short-lived SSH certificate scoped to that deployment, then relays the connection to a running replica's container. Certificates refresh automatically on every connection, so you never need to manage keys or tokens manually. Authorization uses your existing model permissions, so only users who can manage the model can SSH into it.

## Hostname formats

SSH hostnames take two forms, by deployment or by environment:

```text Hostname theme={"system"}
model-<model_id>-<deployment_id>[-<replica_id>].ssh.baseten.co
<environment>.model-<model_id>.ssh.baseten.co
```

| Segment         | Description                                                                                                 | Example      |
| --------------- | ----------------------------------------------------------------------------------------------------------- | ------------ |
| `model_id`      | Model ID (8 lowercase alphanumeric characters). Find it with `baseten model list` or in the deployment URL. | `abc12345`   |
| `deployment_id` | Deployment ID (7 lowercase alphanumeric characters). Each new push creates a new deployment.                | `def4567`    |
| `replica_id`    | Optional. Suffix that uniquely identifies one replica when the deployment has multiple.                     | `xyz9a`      |
| `environment`   | Environment name. Targets the environment's current deployment; not combinable with a deployment ID.        | `production` |

Examples:

```sh Terminal theme={"system"}
# Connect to any running replica of this deployment
ssh model-abc12345-def4567.ssh.baseten.co

# Connect to a specific replica by suffix
ssh model-abc12345-def4567-xyz9a.ssh.baseten.co

# Connect to the current deployment in the production environment
ssh production.model-abc12345.ssh.baseten.co
```

## IDE integration

Because setup configures standard OpenSSH, tools that speak SSH can connect with the same hostnames:

* **VS Code**: Install the [Remote - SSH](https://marketplace.visualstudio.com/items?itemName=ms-vscode-remote.remote-ssh) extension, then connect to `model-<model_id>-<deployment_id>.ssh.baseten.co`.
* **Cursor**: Use the built-in SSH remote feature with `model-<model_id>-<deployment_id>.ssh.baseten.co`.

## Target a specific replica

Deployments with [autoscaling](/deployment/autoscaling/overview) can have many replicas. By default, Baseten routes your SSH session to one running replica. To pin to a specific replica (useful when reproducing a bug that only appears on one replica), append a unique replica-name suffix to the hostname:

```sh Terminal theme={"system"}
ssh model-abc12345-def4567-xyz9a.ssh.baseten.co
```

Find replica names in the deployment's logs view in the Baseten dashboard or with [`baseten model deployment replica list`](/reference/cli/baseten/model-deployment-replica#list).

<Warning>
  Active SSH sessions don't protect a replica from being scaled down. If the autoscaler removes the replica you're connected to, your session is terminated along with it.
</Warning>

## File transfer

Use `scp` or `sftp` with the same hostname to transfer files:

```sh Terminal theme={"system"}
# Copy a file into the model container
scp ./data.json model-abc12345-def4567.ssh.baseten.co:/tmp/data.json

# Copy a file out of the container
scp model-abc12345-def4567.ssh.baseten.co:/tmp/output.json ./output.json

# Interactive file browser
sftp model-abc12345-def4567.ssh.baseten.co
```

## Multiple workspaces

With the Baseten CLI, connections authenticate with the [profile](/reference/cli/baseten/auth) pinned at setup time. To pin a different profile, re-run setup with `--profile <name>`; to override for a single connection, set `BASETEN_PROFILE`:

```sh Terminal theme={"system"}
BASETEN_PROFILE=staging ssh model-abc12345-def4567.ssh.baseten.co
```

With the Truss CLI, include the remote name from `~/.trussrc` in the hostname instead: `model-abc12345-def4567.<remote>.ssh.baseten.co`.

## Troubleshooting

### "SSH access is not enabled for your organization"

Inference SSH is gated per organization. [Contact support](mailto:support@baseten.co) to request access.

### "ssh proxy rejected the connection; is the workload running with SSH enabled?"

The deployment was pushed without `runtime.remote_ssh.enabled: true`, or it isn't `ACTIVE` with at least one running replica. Add the config field and re-push to create a new deployment with SSH enabled; existing deployments can't be changed in place. If the deployment is scaled to zero, send a request to wake it, or set a non-zero `min_replicas` while debugging.

### "no SSH keypair found; run `baseten ssh setup` first"

Run `baseten ssh setup` to configure your machine.

### "already configures \*.ssh.baseten.co hosts outside the managed block"

Another tool (typically `truss ssh setup`) has already added Baseten SSH entries to `~/.ssh/config`. Remove them and re-run `baseten ssh setup`. The Truss block sits between `# --- baseten-ssh ---` and `# --- end baseten-ssh ---`.

### "baseten was not found on your PATH"

The managed config block invokes `baseten` at connect time. Make sure the binary is on your `PATH` in the environment where you run `ssh` (including inside IDEs, which might launch with a reduced `PATH`).

### Truss CLI: "No api\_key for remote"

Truss 0.17.2 through 0.18.17 stored your API key in the OS keyring, which the Truss SSH proxy can't read. Truss 0.18.18 and later keep the key in `~/.trussrc`. Re-run login on the latest version to move it back:

```sh Terminal theme={"system"}
uvx truss login
```

### Truss CLI: TLS errors

The Truss proxy script requires Python 3.10 or newer. If you see TLS errors, re-run setup with a newer Python interpreter:

```sh Terminal theme={"system"}
uvx truss ssh setup --python $(which python3.12)
```

## Next steps

SSH gives you the fastest loop for debugging a live deployment; pair it with the rest of the deployment tooling:

* [`baseten ssh`](/reference/cli/baseten/ssh): full command reference, including profile pinning and the managed config block.
* [Tune vLLM args over SSH](https://github.com/basetenlabs/truss-examples/tree/main/inference-ssh/tune-vllm-args): edit vLLM arguments and the chat template inside a running container and restart the engine in place, without redeploying.
* [Iterate on a gRPC server over SSH](https://github.com/basetenlabs/truss-examples/tree/main/inference-ssh/grpc-server): edit a deployed gRPC server's code and restart it in place on every change.
* [Autoscaling](/deployment/autoscaling/overview): control replica lifecycle so sessions aren't reclaimed mid-debug.
* [SSH for training jobs](/training/ssh): the same workflow for training containers.
