Skip to main content
SSH into any running training job on Baseten and get a full terminal inside the training container: debug, inspect files, run commands, edit code, or transfer data with scp and sftp. You get the same control you’d have on a local GPU box, running on Baseten-managed hardware. Unlike VS Code and Cursor remote tunnels, SSH is terminal-first and works with any OpenSSH-compatible tool.

Prerequisites

SSH sessions must be enabled for your Baseten workspace. Contact support to request access.
  • Baseten account: Sign up and generate an API key.
  • Baseten CLI: Install the CLI and log in:
    Terminal
  • uv: Training jobs are configured and pushed with the Truss CLI; this guide uses uvx to run it without a separate install step. Log in to Baseten:
    Terminal
  • OpenSSH client: Pre-installed on macOS and Linux. On Windows, use the OpenSSH optional feature or WSL.

Enable SSH on a training job

To enable SSH access on a training job, set session_provider to SSH in your config.py:
config.py
This example sets trigger=ON_STARTUP so the session is available as soon as the job starts running. The default is ON_DEMAND, which activates the session on your first SSH connection; see Trigger modes for all options. Training jobs support H200 and H100 GPUs. For all InteractiveSession fields, see the SDK reference. For supported compute, see Compute resources.

Create a workstation with the CLI

To create an SSH-enabled workstation without writing a config.py, use the truss train workstation command. It configures an interactive session with InteractiveSessionTrigger.ON_STARTUP and runs sleep infinity to keep the container alive:
Terminal
Once the workstation is running, connect using the SSH command provided in the output. See the CLI reference for all available options. For multi-node workstations, pass --node-count instead of --gpu-count: Baseten bootstraps a Slurm cluster across the nodes. See Slurm workstations.

Push an SSH-enabled training job

This walkthrough uses the MNIST PyTorch example to push a training job with SSH enabled, then connects to the container from your terminal.

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.
To set up SSH access:
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.

Clone the example

Clone the cookbook and change into the MNIST training example:
Terminal

Configure and push the job

Edit config.py to add an interactive_session with session_provider=SSH, as shown in Enable SSH on a training job. Then push:
Terminal
The expected output is:
Output
Where:
  • <job_id> is your new training job’s ID. Note it down; you’ll use it to connect in the next step.
  • <project_id> is the Baseten-assigned ID for the training project.

Connect

Once the job is running, find its ID with uvx truss train view, then SSH in:
Terminal
For example, to connect to node 0 of job abc1234:
Terminal
You’re connected when you see a shell prompt like root@baseten-training-job-<job_id>-multinode-0:~#. By default, your source files are extracted to /b10/workspace (available as $BT_WORKING_DIR). If you set enable_baseten_workdir=False, Baseten uses your base image’s WORKDIR instead.

How it works

When you connect to a training-job-*.ssh.baseten.co hostname, the managed ~/.ssh/config block runs the CLI, which calls Baseten’s signing API to issue a short-lived SSH certificate and relays the connection to the correct training job. Certificates refresh automatically on every connection, so you never need to manage keys or tokens manually.

Hostname format

Training hostnames name a job and a node:
Hostname
Examples:
Terminal

IDE integration

Because setup configures standard OpenSSH, tools that speak SSH can connect with the same hostname:
  • VS Code: Install the Remote - SSH extension, then connect to training-job-<job_id>-<node>.ssh.baseten.co.
  • Cursor: Use the built-in SSH remote feature with training-job-<job_id>-<node>.ssh.baseten.co.

Multi-node jobs

For multi-node training jobs, specify the node index in the hostname. Node 0 is the leader:
Terminal

File transfer

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

Multiple workspaces

With the Baseten CLI, connections authenticate with the profile pinned at setup time. To pin a different profile, re-run setup with --profile <name>; to override for a single connection, set BASETEN_PROFILE:
Terminal
With the Truss CLI, include the remote name from ~/.trussrc in the hostname instead: training-job-abc1234-0.<remote>.ssh.baseten.co.

Session management

For how to view session status, change triggers, and extend session expiry, see the Remote access overview.

Troubleshooting

”Invalid job id: must be a valid hash id”

Check that the job ID in the hostname is correct. Find your job ID with uvx truss train view or in the Baseten dashboard.

”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 ---.

Connection refused or job unreachable

SSH requires the training job to be in the RUNNING state. Check with:
Terminal
If the job is running but SSH still fails, the job may not have SSH enabled. Confirm session_provider=InteractiveSessionProvider.SSH is set in your config, as shown in Enable SSH on a training job.

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:
Terminal

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:
Terminal

Missing Python certificates

If ssh fails with a CERTIFICATE_VERIFY_FAILED error, the Python interpreter the proxy script runs under has no SSL root certificates, so it cannot verify TLS connections to Baseten. To fix it, either install certificates for that Python, or re-run setup pointing at a Python that already has them:
Terminal
This is most common on macOS with Python installed from python.org, which ships without certificates until you run its installer:
Terminal
On other platforms, make sure your Python has a root certificate bundle (for example the ca-certificates package on Debian/Ubuntu).

Next steps

SSH is one of several ways into a running job; these pages cover the rest of the remote-access surface: