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

# Sandbox providers

> Every compute provider Merv can provision sandboxes on: credentials, environment variables, and the quirks that bite.

Merv provisions one SSH-reachable runtime per request through a provider-neutral backend. Ten providers are configured **per project** under **Settings → Compute** (save, verify, enable, daily USD limit); Modal only through environment variables on the brain. Self-hosted brains can set any of them by environment variable. Agents pick a provider per request with `sandbox.request(provider=...)`; `sandbox.options` tags every hardware option with the provider that serves it.

Sandbox ids are stored as `<provider>:<native_id>`, so every later operation routes to the owning provider. Terminate a provider's sandboxes before removing it from the configuration — ids of a removed provider become unroutable on purpose (failing loudly beats stranding a billing VM).

| Provider                      | Kind · management                 | Aliases                         | Billing               |
| ----------------------------- | --------------------------------- | ------------------------------- | --------------------- |
| `lambda_labs`                 | VM · management SSH               | `lambda`, `lambdalabs`          | per minute            |
| `thunder_compute`             | VM · management SSH               | `thunder`, `thundercompute`     | per minute            |
| `modal`                       | managed container · provider exec | —                               | as Modal bills        |
| `hyperstack`                  | VM · management SSH               | —                               | per minute            |
| `digitalocean`                | VM · management SSH               | —                               | per hour              |
| `verda` (formerly DataCrunch) | VM · management SSH               | `datacrunch`                    | rounds up to 10 min   |
| `voltage_park`                | VM · management SSH               | `voltagepark`                   | as the provider bills |
| `tensordock`                  | VM · management SSH               | —                               | per second, prepaid   |
| `aws`                         | VM · management SSH               | `ec2`, `amazon`                 | as AWS bills          |
| `gcp`                         | VM · management SSH               | `gce`, `google`, `google_cloud` | as GCP bills          |
| `azure`                       | VM · management SSH               | `az`, `microsoft_azure`         | as Azure bills        |

All VM providers bootstrap the same way: authorize the caller's public key and the brain's management key, install the `rec.sh` transcript wrapper and `merv_run`, then install the ML toolchain in a second phase. Secrets such as `HF_TOKEN` are pushed post-boot over the management SSH channel, never embedded in provider user data.

<Warning>
  On every VM provider a stopped machine still bills its disks. Only termination stops charges — which is what release does.
</Warning>

## Self-host: selecting providers

```bash theme={"theme":{"light":"github-light","dark":"dark-plus"}}
MERV_EXECUTION_BACKEND=lambda_labs                 # one provider (default)
MERV_EXECUTION_BACKENDS=lambda_labs,aws,modal      # a fleet behind one multiplexer
```

## Per-provider details

<AccordionGroup>
  <Accordion title="Lambda Labs — lambda_labs">
    * **Env**: `MERV_LAMBDA_API_KEY` (or `LAMBDA_LABS_API_KEY` / `LAMBDA_API_KEY`); optional `MERV_LAMBDA_REGION`, `MERV_LAMBDA_INSTANCE_TYPE`.
    * **Credentials**: cloud.lambda.ai → API keys → Generate. Pay-as-you-go with a card on file.
    * **Quirks**: fixed SKUs (`gpu_1x_a10`, …); live capacity via the instance-types API; deep A10/A100/H100 stock.
  </Accordion>

  <Accordion title="Thunder Compute — thunder_compute">
    * **Env**: `MERV_THUNDER_API_KEY` (or `THUNDER_COMPUTE_API_KEY` / `TNR_API_TOKEN`).
    * **Quirks**: virtualized GPUs behind a port-forwarded SSH endpoint; bootstrap pushed over SSH. Cheap A100 capacity; prototyping-mode instances can be slow for sustained training.
  </Accordion>

  <Accordion title="Modal — modal">
    * **Env**: `MODAL_TOKEN_ID` + `MODAL_TOKEN_SECRET` on the brain — not configurable in the UI.
    * Managed container driver with a provider-exec management transport; composable GPU/CPU/memory catalog rather than fixed VM SKUs.
  </Accordion>

  <Accordion title="Hyperstack — hyperstack">
    * **Env**: `MERV_HYPERSTACK_API_KEY` (or `HYPERSTACK_API_KEY`) and `MERV_HYPERSTACK_ENVIRONMENT`; optional `MERV_HYPERSTACK_IMAGE` (default `Ubuntu Server 24.04 LTS (Noble Numbat)`), `MERV_HYPERSTACK_FLAVOR`.
    * **Credentials**: console.hyperstack.cloud → add credit → Settings → API Keys. Create an **environment** once (it pins the region) and put its name in `MERV_HYPERSTACK_ENVIRONMENT`.
    * **Quirks**: VMs have zero inbound ports by default — Merv attaches a TCP-22 ingress rule at create. Login user `ubuntu`. `SHUTOFF` still bills.
  </Accordion>

  <Accordion title="DigitalOcean GPU Droplets — digitalocean">
    * **Env**: `MERV_DIGITALOCEAN_TOKEN` (or `DIGITALOCEAN_TOKEN` / `DIGITALOCEAN_ACCESS_TOKEN`); optional `MERV_DIGITALOCEAN_IMAGE` (default `gpu-h100x1-base`), `MERV_DIGITALOCEAN_REGION`.
    * **Credentials**: cloud.digitalocean.com → API → Tokens → full access. GPU sizes stay hidden until the one-time GPU unlock (Create → GPU Droplets).
    * **Quirks**: no A100s (H100/H200/L40S/RTX-Ada); user\_data caps at 64 KiB; hourly billing with monthly cap.
  </Accordion>

  <Accordion title="Verda (DataCrunch) — verda">
    * **Env**: `MERV_VERDA_CLIENT_ID` + `MERV_VERDA_CLIENT_SECRET` (or `DATACRUNCH_CLIENT_ID`/`DATACRUNCH_CLIENT_SECRET`); optional `MERV_VERDA_IMAGE` (default `ubuntu-24.04`), `MERV_VERDA_LOCATION` (e.g. `FIN-01`), `MERV_VERDA_API_BASE`.
    * **Credentials**: cloud.datacrunch.io → Keys → REST API credentials (OAuth2 client id + secret).
    * **Quirks**: SSH keys and the bootstrap script are pre-registered account resources; `offline` instances keep billing their OS volume.
  </Accordion>

  <Accordion title="Voltage Park — voltage_park">
    * **Env**: `MERV_VOLTAGE_PARK_TOKEN` (or `VOLTAGE_PARK_TOKEN`).
    * **Credentials**: dashboard.voltagepark.com → developer settings → API token.
    * **Quirks**: H100-SXM5-only, sold as instant-deploy presets (the preset uuid is the `instance_type`). Stopped VMs still hold storage.
  </Accordion>

  <Accordion title="TensorDock — tensordock">
    * **Env**: `MERV_TENSORDOCK_TOKEN` (or `TENSORDOCK_TOKEN`); optional `MERV_TENSORDOCK_IMAGE` (default `ubuntu2404`).
    * **Credentials**: dashboard.tensordock.com → Developer Settings → API token. Prepaid balance (min \$1).
    * **Quirks**: marketplace of third-party hosts; only locations with a dedicated IP are offered; no billing API, so the provision-time quote is the recorded rate.
  </Accordion>

  <Accordion title="AWS EC2 — aws">
    * **Env**: `AWS_ACCESS_KEY_ID` + `AWS_SECRET_ACCESS_KEY` (or `MERV_AWS_*`), optional `AWS_SESSION_TOKEN`; `MERV_AWS_REGION` (default `us-east-1`); optional `MERV_AWS_IMAGE_ID`, `MERV_AWS_INSTANCE_TYPE`, `MERV_AWS_VOLUME_GIB` (default 200). With no keys set, boto3's default chain applies.
    * **Deps**: `pip install 'merv[aws]'` (boto3; included in the `control` extra).
    * **Quirks**: bootstrap pushed over management SSH (user\_data caps at 16 KiB); default image is the newest Deep Learning Base GPU AMI; a shared `merv-sandbox-ssh` security group is created once. Fresh accounts have a zero vCPU quota for G/P families — request it under Service Quotas. Prices unknown (no EC2 pricing in the API).
  </Accordion>

  <Accordion title="GCP Compute Engine — gcp">
    * **Env**: `MERV_GCP_PROJECT` (or `GOOGLE_CLOUD_PROJECT`); `MERV_GCP_ZONE` (default `us-central1-a`); `GOOGLE_APPLICATION_CREDENTIALS` or ambient ADC; optional `MERV_GCP_MACHINE_TYPE`, `MERV_GCP_IMAGE_PROJECT`/`MERV_GCP_IMAGE_FAMILY`, `MERV_GCP_BOOT_DISK_GIB` (default 200).
    * **Deps**: `pip install 'merv[gcp]'`.
    * **Quirks**: GPU-bundled machine types only (a2/a3/g2); shared `merv-sandbox-allow-ssh` firewall rule created once per project; fresh projects have a zero GPU quota (`GPUS_ALL_REGIONS`). If the default DLVM image family 404s, override `MERV_GCP_IMAGE_FAMILY`.
  </Accordion>

  <Accordion title="Azure — azure">
    * **Env**: `MERV_AZURE_TENANT_ID`, `MERV_AZURE_CLIENT_ID`, `MERV_AZURE_CLIENT_SECRET`, `MERV_AZURE_SUBSCRIPTION_ID` (`AZURE_*` accepted); `MERV_AZURE_LOCATION` (default `eastus`); optional `MERV_AZURE_VM_SIZE`, `MERV_AZURE_IMAGE` (default `microsoft-dsvm:ubuntu-hpc:2204:latest`), `MERV_AZURE_OS_DISK_GIB` (default 200).
    * **Credentials**: `az ad sp create-for-rbac --role Contributor --scopes /subscriptions/<id>`.
    * **Quirks**: each sandbox is its own resource group (`rp-<uid>-rg`), so terminate is one atomic delete. Fresh subscriptions have a zero vCPU quota for GPU families.
  </Accordion>
</AccordionGroup>

Adding a provider to Merv itself: implement one `sandbox/adapters/<provider>.py`, expose one lazy builder, register one `SandboxDriverDescriptor`, and pass the shared conformance tests. See the repo's `merv/docs/SANDBOX_PROVIDERS.md`.
