---
id: platform/ssh
title: SSH and web shell
description: Open a shell on a running Bex service, register a public key, select an instance, and understand access and persistence limits.
keywords: [bex, ssh, shell, debugging, instances]
last_updated: 2026-09-23
---

Use SSH or the dashboard shell to inspect a running service instance. Commands
execute in the live workload and can read its environment, secrets, and data.
Use [logs](./logging.md) first when a shell is unnecessary.

## Requirements

Shell access is available for eligible **paid web services, private services,
and background workers**. The service must be unsuspended, running a live image,
and have a Ready instance. Static sites, cron jobs, free services, and managed
datastores do not use this running-service shell workflow.

The installation needs its SSH/web-shell gateway configured. Your account needs
sensitive-resource access, normally developer/admin, plus any applicable policy
checks. Permission to restart a service is insufficient. Uploading an SSH key
also does not grant access to a workspace you cannot otherwise use.

The application image must contain the shell or executable you want to run.
A minimal image without a shell will not become a full Linux toolbox merely
because the gateway is reachable.

## Register a public key

Use your dashboard account's SSH key settings to add an existing public key,
or generate a dedicated pair locally if needed:

```bash
ssh-keygen -t ed25519 -f ~/.ssh/bex_service -C bex-service-access
```

Choose a new filename rather than overwriting an existing key. Upload only the
`.pub` file; keep the private key on your machine.

The API provides `GET /v1/ssh-keys`, `POST /v1/ssh-keys` with `name` and
`publicKey`, and `DELETE /v1/ssh-keys/{id}`. Key enrollment is restricted to
eligible direct human callers. A machine API key or third-party OAuth agent
cannot enroll another durable credential for itself. See [API authentication](./api.md).

## Connect to the service

After [CLI login](../cli.md), choose your workspace and use a returned service ID:

```bash
bex workspace set YOUR_WORKSPACE_ID
bex ssh YOUR_SERVICE_ID
```

For a direct OpenSSH connection, use the service's returned
`serviceDetails.sshAddress`, not a hostname inferred from its display name or
public web URL. Supply your private key with `ssh -i` if it is not already
selected by your SSH configuration or agent. Verify an unfamiliar gateway's host
key through the platform operator; do not disable host-key checking to bypass a
connection error.

A bare service target can select any Ready replica. Inspect
`GET /v1/services/{id}/instances` and use the returned instance identifier when
you need a particular replica. Instances can disappear during deployments or
scaling, so refresh the list if a target is no longer available.

## Use the dashboard shell

Open the service's Shell view and select an instance when offered. The dashboard
obtains a short-lived connection ticket and the gateway checks access again
when opening the session. No private SSH key needs to be pasted into the browser.

If a ticket expires before connection, reopen the shell to obtain a fresh one.
Do not reuse a captured ticket as a permanent automation credential or share it
in a support report.

## Session limits and troubleshooting

Shell changes to the container filesystem are ephemeral unless written to a
mounted [persistent disk](./persistent-disks.md) or an external datastore. Such
persistent writes affect real application data. Make durable code/configuration
changes in the repository or platform settings and deploy them normally.

Running-service SSH is not a generic bastion: App targets do not provide SFTP
subsystems or a general forwarding service. Do not infer support for ephemeral
instances or hosted one-off jobs from imported CLI options. Agent-session
sandboxes are a separate product with different capabilities.

| Symptom | Check |
| --- | --- |
| Permission denied | Uploaded public key, local private-key selection, account role, and resource access. |
| No SSH address or service not eligible | Plan, type, suspension, live revision, and gateway configuration. |
| No Ready instance | Deployment and health-check state; inspect logs before reconnecting. |
| Shell executable missing | The final application image and available executable paths. |
| Session disconnects during a deploy | Instance replacement; reconnect to a current Ready instance. |

For database access, use [Postgres connections](./postgres.md) or
[Key Value connections](./key-value.md). For a command that should gate each
release, use a [pre-deploy command](./pre-deploy-commands.md).
