# Workspaces

> A GPU or CPU development machine with a saved home directory, reached with SSH, VS Code or JupyterLab.

Source: https://nodus-platform-site.pages.dev/docs/guides/workspaces/
Build revision: 211ad9f836655b1c3a2668c4693e442471f28614

A Workspace is your own development machine: a GPU or CPU machine with VS Code in the browser, JupyterLab and SSH. Its home directory, `/home/nodus`, lives on a Volume and is saved every time the Workspace stops, so you can stop it at the end of the day and pick up where you left off. While it is stopped you pay only for the saved files.

You need the `nodus` CLI to connect over SSH ([install it](https://nodus-platform-site.pages.dev/docs/getting-started/) and run `nodus login`). Browser VS Code and JupyterLab need only the console.

## Create a Workspace

Terminal window

```console
$ nodus create workspace lab --gpu H100
$ nodus get workspaces
NAME   PHASE     COMPUTE    HOME       STOP-REASON   COST    AGE
lab    Running   1 × H100   lab-home                 $0.09   3m
```

`--gpu H100:2` asks for two GPUs; `--cpu 8 --memory 32Gi` without `--gpu` creates a CPU Workspace. The home Volume is `lab-home`, created on the first start if it does not exist; set `spec.volume` to use another one. The default image is `nodus/workspace-pytorch-cuda` (PyTorch and CUDA) on NVIDIA GPUs, `nodus/workspace-rocm` on AMD GPUs and `nodus/workspace-cpu` on CPU. Every catalog image has VS Code, JupyterLab, Python and the user `nodus`.

The same Workspace as a manifest, applied with `nodus apply -f workspace.yaml`:

workspace.yaml

```yaml
apiVersion: nodus.dev/v1
kind: Workspace
metadata:
  name: ws-home
spec:
  image: nodus/workspace-cpu
  resources:
    cpu: "2"
    memory: 8Gi
  volume: ws-home-home
  idleTimeout: 30m
```

In the console, **Workspaces › New workspace** shows the GPU picker, the estimate and the same manifest as YAML, CLI and Python before you create it.

## Connect

### SSH

Terminal window

```console
$ nodus login
$ nodus ssh workspace/lab
nodus@lab:~$ nvidia-smi
$ nodus ssh workspace/lab -- python train.py --epochs 1
```

Sign in once with `nodus login` on each computer using an up-to-date CLI and OpenSSH 8.5 or newer. Login creates a dedicated local SSH key for your account, registers only its public key, and configures every existing and future CPU or GPU Workspace in the organizations you selected. New Workspaces need no separate setup. Your private key stays on your computer with owner-only permissions; sign-in does not start or connect to a Workspace.

Each teammate signs in to their own account. Organization roles and project access determine which Workspaces they can enter. Remove a device’s key under **Account › SSH keys** to revoke it. Removing a teammate’s access also prevents their keys from opening that organization’s Workspaces.

`nodus ssh` connects through the Nodus gateway. No port is open on the machine. OpenSSH verifies the Workspace’s host key against the authenticated API on every connection, with strict host-key checking. A missing or revoked identity fails closed; it does not trust a host key on first use.

### VS Code Remote-SSH, Cursor and JetBrains Gateway

After `nodus login`, open **Desktop VS Code** or **Cursor** in the console, or select the Workspace host in your editor’s Remote-SSH connection dialog. The same account key works for all your authorized Workspaces, including ones created later. Signing in to the website alone cannot configure SSH on your computer.

The `.nodus` host is an SSH alias, not a public DNS address. Login records the CLI executable and saved context, so editors do not depend on your terminal’s environment. Plain `ssh`, `scp` and `rsync` use the same connection. `nodus ssh workspace/lab --config` prints the rule; `nodus ssh workspace/lab --setup` is an optional repair command. Neither command starts or connects to a Workspace.

### Browser VS Code and JupyterLab

Open the Workspace in the console and choose **Browser VS Code** or **JupyterLab**. Both open on a private address that only members of your organization can reach after signing in.

## Stop, start and what is saved

Terminal window

```console
$ nodus stop workspace/lab
$ nodus start workspace/lab
```

When a Workspace stops, everything in `/home/nodus` is saved to its home Volume and the machine is released. Everything else is temporary, including the `/workspace` directory (the container’s working directory, which has nothing to do with the Workspace kind) and anything installed outside your home. Install Python packages with `pip install --user` or in a virtual environment under `/home/nodus` to keep them.

The next start restores the saved home on a fresh machine. Use `ephemeral: true` for a Workspace with no home Volume, whose files are deleted on stop.

A Workspace also stops by itself:

|Stop reason|When|How it starts again|
|-|-|-|
|`Idle`|No SSH session, editor traffic or process for `idleTimeout` (default `1h`)|Connect, open a tool, or `nodus start`|
|`Schedule`|At `schedule.stopAt`|The next `schedule.readyBy`, connecting, or `nodus start`|
|`InsufficientCredits`, `BudgetExceeded`, `MaxCostReached`|Money ran out or a limit was reached|Add credits or raise the limit, then connect or `nodus start`|
|`User`|You ran `nodus stop` or chose **Stop**|Only `nodus start` or **Start**|

Connecting to a Workspace that stopped by itself starts it; `nodus ssh` waits and connects when it is ready. The console asks before a connect starts a stopped Workspace and shows the rate it will bill at.

### Schedules

```yaml
spec:
  schedule:
    readyBy: "2026-10-01T09:00:00-07:00"
    stopAt: "2026-10-01T19:00:00-07:00"
```

The Workspace starts 15 minutes before `readyBy` so it is ready on time, and stops at `stopAt`. It records a `ScheduledStart` event, or `ScheduleMissed` when it could not start in time.

## Run a job on your Workspace files

Terminal window

```console
$ nodus run --from workspace/lab -- python train.py
```

The Job runs on a copy of the last saved home, labelled `nodus.dev/workspace=lab`, so the Workspace’s **Jobs from this workspace** list shows it.

## Sessions and billing

Each period a Workspace runs is a session, recorded as an Attempt with its receipt:

Terminal window

```console
$ nodus get attempts -l nodus.dev/workspace=lab
```

* A GPU Workspace bills at the rate shown when it starts, from when its machine is acquired until the machine is released. A session that stops for any reason closes its charge.
* A CPU Workspace bills at the listed CPU rates while it runs.
* Saved files in the home Volume bill as storage after your organization’s included storage.

`maxCostUSD` stops and saves the Workspace when its cost reaches the limit; raising the limit lets it start again.

## Shared access

A Workspace belongs to its project. Every member of the organization with access to the project can see it, start it and connect with their own account and SSH key; `spec.sshKeys` limits SSH to the keys you name.

## When a Workspace fails

A Workspace in the `Failed` phase does not restart. Delete it and create it again with the same name (or the same `spec.volume`): the home Volume keeps your files.

Terminal window

```console
$ nodus delete workspace/lab
$ nodus create workspace lab --gpu H100
```

To delete the saved files too, delete the home Volume (`nodus delete volume/lab-home`), or empty it with `nodus volume clear lab-home`.
