# Enterprise GPU Rental | H100, A100, B200, B300 On-Demand | Spheron Docs > Rent NVIDIA H100, A100, B200 GPUs from $0.72/hr. No contracts. Instant deployment from Tier 3/4 data centers. Perfect for AI training, LLM inference & ML workloads. 99% uptime. ## API reference This page covers the Spheron AI REST API for programmatic access to GPU instances, SSH keys, volumes, and account balance. :::tip[Using an AI agent?] Hand this API to Claude, ChatGPT, or any LLM with the ready-made [API skill for AI agents](/api-skill). The agent learns the full deploy flow, parameter rules, and error handling, and knows to request an API key. Download the skill file. ::: ### Table of contents * [Quick start](#quick-start) * [Authentication](#authentication) * [Endpoints](#endpoints) * [Providers](#get-providers) * [GPU offers](#get-gpu-offers) * [CPU offers](#cpu-offers) * [Deployments](#deployments) * [Instance lifecycle](#instance-lifecycle) * [SSH keys](#ssh-keys) * [Volumes](#volumes) * [Teams](#teams) * [Error reference](#error-reference) * [Status values](#status-values) * [Rate limits](#rate-limits) * [Security](#security) * [Common workflows](#common-workflows) ### Quick start #### 1. Get your API key Generate an API key from your [Spheron dashboard](https://app.spheron.ai/settings). #### 2. Make your first API call Test your connection by listing available providers: ```bash curl -H "Authorization: Bearer " \ https://app.spheron.ai/api/providers ``` #### 3. List available GPUs ```bash curl -H "Authorization: Bearer " \ "https://app.spheron.ai/api/gpu-offers?limit=5" ``` #### 4. Deploy your first instance ```bash curl -X POST "https://app.spheron.ai/api/deployments" \ -H "Authorization: Bearer " \ -H "Content-Type: application/json" \ -d '{ "provider": "spheron-ai", "offerId": "rtx-4090-spheron-ai-1", "gpuType": "rtx-4090", "gpuCount": 1, "region": "us-east-1", "operatingSystem": "ubuntu-22.04", "instanceType": "DEDICATED", "sshKeyId": "your_ssh_key_id" }' ``` ### Base URL ``` https://app.spheron.ai ``` ### Authentication Include your API key in the Authorization header for all authenticated requests: ```bash Authorization: Bearer ``` **Security note:** Treat API keys like passwords. Never expose them in client-side code or public repositories. See [Security best practices](/security) for more information. ### Endpoints #### Get providers Get a list of all available GPU providers (public endpoint). Returns the subset of providers currently configured on the server. **Method:** `GET` **Path:** `/api/providers` **Response example:** ```json [ "data-crunch", "massed-compute", "sesterce", "spheron-ai", "spheron-es", "spheron-ms", "spheron-am" ] ``` *** #### Get GPU offers Get available offers with filtering and pagination. Authenticate to see team discounts. This endpoint returns both GPU offers and the single CPU Node row. Use `computeType` to narrow it to one or the other. See [CPU offers](#cpu-offers) for the CPU-specific shape. **Method:** `GET` **Path:** `/api/gpu-offers` **Headers:** * `Authorization`: Bearer `` (optional) **Parameters:** | Name | Type | Required | Description | | :------------- | :----- | :------- | :----------------------------------------------------------------------------------------------------------------- | | `page` | number | No | Page number (default: 1) | | `limit` | number | No | Items per page (default: 10) | | `search` | string | No | Search term for GPU models | | `sortBy` | string | No | Sort field (default: popularity) | | `sortOrder` | string | No | asc or desc (default: asc) | | `instanceType` | string | No | Filter by type: 'SPOT', 'DEDICATED', or 'CLUSTER' (case-insensitive) | | `computeType` | string | No | Filter by silicon: `cpu` returns only the CPU Node row, `gpu` returns only GPU offers. Omit to list both (default) | **Response example:** ```json { "data": [ { "gpuType": "rtx-4090", "gpuModel": "RTX 4090", "baseGpuType": "rtx-4090", "interconnectVariants": ["PCIe"], "hasMultipleVariants": false, "displayName": "RTX 4090", "popularity": 85, "totalAvailable": 12, "lowestPrice": 0.45, "highestPrice": 0.65, "averagePrice": 0.55, "providers": ["massed-compute", "spheron-ai"], "offers": [ { "provider": "massed-compute", "offerId": "rtx-4090-massed-compute-1-dedicated", "name": "RTX 4090", "description": "High-performance gaming and AI GPU", "vcpus": 8, "memory": 32, "storage": 100, "gpuCount": 1, "price": 0.50, "available": true, "clusters": ["us-east-1", "us-west-2"], "gpu_memory": 24, "os_options": ["ubuntu-20.04", "ubuntu-22.04"], "maintenance": false, "interconnectType": "PCIe", "interconnectDescription": "PCIe interface", "instanceType": "DEDICATED", "supportsCloudInit": true, "extras": { "deployment_type": "vm", "networking_type": "standard" } }, { "provider": "data-crunch", "offerId": "rtx-4090-data-crunch-1-spot", "name": "RTX 4090 SPOT", "description": "Cost-effective SPOT instance (lower price, may be interrupted)", "vcpus": 8, "memory": 32, "storage": 100, "gpuCount": 1, "price": 0.25, "spot_price": 0.25, "available": true, "clusters": ["us-east-1", "eu-west-1"], "gpu_memory": 24, "os_options": ["ubuntu-20.04", "ubuntu-22.04"], "maintenance": false, "interconnectType": "PCIe", "interconnectDescription": "PCIe interface", "instanceType": "SPOT", "supportsCloudInit": true, "extras": { "deployment_type": "vm", "networking_type": "standard" }, "note": "For SPOT instances: price = spot_price (discounted rate with possible interruption)" }, { "provider": "spheron-ai", "offerId": "baremetal_h100_sxm5_8", "name": "H100 SXM5 8x GPU Bare Metal", "description": "8x H100 SXM5 GPUs, 832 vCPUs, 8192GB RAM, 144000GB Storage. Bare Metal with NVLink between GPUs.", "vcpus": 832, "memory": 8192, "storage": 144000, "gpuCount": 8, "price": 15.84, "available": true, "clusters": ["dalas-united states"], "region": "dalas-united states", "gpu_memory": 80, "os_options": ["Ubuntu 20.04 LTS", "Ubuntu 22.04 LTS"], "maintenance": false, "interconnectType": "NVLink", "interconnectDescription": "NVLink high-speed GPU interconnect", "instanceType": "CLUSTER", "supportsCloudInit": true, "extras": { "deployment_type": "cluster", "networking_type": "ethernet" } } ] } ], "total": 50, "page": 1, "limit": 10, "totalPages": 5 } ``` :::info[Discount information (authenticated only)] **Without authentication:** Only the `price` field is included (original undiscounted price). No discount fields are returned. **With authentication (your team):** Additional discount fields are included in each offer: * `price`: Original undiscounted price per hour * `originalPrice`: Same as `price` (for reference) * `discountedPrice`: Final price after your team's best discount is applied (5-50%) * `discountPercentage`: Your team's actual discount percentage * `hasDiscount`: Whether your team has an active discount Discounts are either volume-based or admin-assigned. The higher of the two is automatically applied. ::: :::info[Lifecycle and deployment shape] * `pauseUnsupportedReason`: Present on every offer. It is `null` when an instance from this offer can be stopped, and otherwise carries the reason it cannot, ready to show to a user. Read it before you promise a Stop control. See [Instance lifecycle](/concepts/instance-lifecycle). * `extras.deployment_type`: `vm`, `baremetal`, or `cluster`. A bare metal offer supports neither stopping nor restarting. ::: *** #### CPU offers CPU Node is a CPU-only instance with no GPU attached. It is served by the same `/api/gpu-offers` endpoint as a single row, not as one entry per provider. **Filter to CPU only:** ```bash curl -H "Authorization: Bearer " \ "https://app.spheron.ai/api/gpu-offers?computeType=cpu" ``` `?search=cpu` returns the same row. Passing `computeType=gpu` excludes it, and omitting the parameter lists both. **What the row looks like:** * `gpuType` is `"CPU"` and `displayName` is `"CPU NODE"`. * Every entry in `offers[]` reports `gpuCount: 0` and `gpu_memory: 0`. * Size is described by `vcpus` and `memory` rather than a GPU model. * `clusters` holds the region, `os_options` holds the deployable images, and `offerId` is what a deployment takes. **Response example (one offer from the CPU Node row):** ```json { "data": [ { "gpuType": "CPU", "gpuModel": "", "baseGpuType": "CPU", "displayName": "CPU NODE", "totalAvailable": 29, "lowestPrice": 0.0862, "providers": ["sesterce", "data-crunch", "spheron-ai"], "offers": [ { "provider": "data-crunch", "offerId": "CPU.4V.16G_FIN-01_200_spot", "name": "0x AMD EPYC", "description": "0x AMD EPYC, 4 vCPUs, 16GB RAM.", "vcpus": 4, "memory": 16, "storage": 200, "gpuCount": 0, "gpu_memory": 0, "price": 0.0862, "spot_price": 0.0862, "available": true, "clusters": ["Finland 1"], "os_options": ["Jupyter", "Ubuntu 22.04", "Ubuntu 24.04"], "maintenance": false, "instanceType": "SPOT", "supportsCloudInit": true, "extras": { "deployment_type": "vm" } } ] } ], "total": 1, "page": 1, "limit": 10, "totalPages": 1 } ``` **Deploy a CPU offer:** Send `gpuType: "CPU"` with `gpuCount: 0` to `POST /api/deployments`. Every other parameter works the way it does for a GPU offer. ```bash curl -X POST "https://app.spheron.ai/api/deployments" \ -H "Authorization: Bearer " \ -H "Content-Type: application/json" \ -d '{ "provider": "data-crunch", "offerId": "CPU.4V.16G_FIN-01_200_spot", "gpuType": "CPU", "gpuCount": 0, "region": "Finland 1", "operatingSystem": "Ubuntu 22.04", "instanceType": "SPOT", "sshKeyId": "your_ssh_key_id" }' ``` Deployments created this way are stored as CPU nodes, so responses and usage records report a CPU node rather than an unnamed GPU. :::warning[gpuType must match the offer] Sending a GPU model name against a CPU `offerId` returns a `400` validation error naming the mismatch. Send `"CPU"`, or omit `gpuType` and let the platform resolve it from the offer. ::: See [CPU Nodes](/concepts/cpu-nodes) for sizes, regions, and the dashboard flow. ### Deployments #### Create deployment Create a new GPU instance deployment. **Method:** `POST` **Path:** `/api/deployments` **Headers:** * `Authorization`: Bearer `` * `Content-Type`: application/json **Parameters:** | Name | Type | Required | Description | | :---------------- | :-------- | :------- | :-------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- | | `provider` | string | Yes | Provider name (e.g., `data-crunch`, `massed-compute`, `sesterce`, `spheron-ai`, `spheron-es`, `spheron-ms`, `spheron-am`). Call `GET /api/providers` for the live list of configured providers. | | `offerId` | string | Yes | Unique offer ID from the GPU offers endpoint | | `gpuType` | string | Yes | GPU type identifier (e.g., rtx-4090, h100). Send `CPU` for a [CPU Node offer](#cpu-offers). | | `gpuCount` | number | Yes | Number of GPUs to deploy. Send `0` for a CPU Node offer. | | `region` | string | Yes | Deployment region or cluster. Send the offer's `clusters` value back unchanged. | | `operatingSystem` | string | Yes | Operating system (e.g., ubuntu-20.04, ubuntu-22.04) | | `instanceType` | string | Yes | Instance type: 'SPOT', 'DEDICATED', or 'CLUSTER' (case-insensitive) | | `sshKeyId` | string | No | SSH key ID from your saved keys (either this or ssh\_public\_key required) | | `ssh_public_key` | string | No | Inline SSH public key content (either this or sshKeyId required). A temporary key will be created. | | `teamId` | string | No | Team ID for team deployments (optional) | | `name` | string | No | Optional name for the deployment | | `cloudInit` | object | No | Cloud-Init configuration object. Supports fields: runcmd (string\[]), packages (string\[]), writeFiles (array of `{ path, content, owner?, permissions? }`). | | `volumeIds` | string\[] | No | IDs of persistent volumes to attach at launch. Each volume must match the deployment's provider and region. Per-provider rules: Sesterce: single-item array, volumes attach at instance creation and cannot be attached or detached afterwards; Spheron AI: up to 10 volumes per instance, each volume can only be attached to one instance at a time (hot-detach and re-attach supported post-launch); Verda: up to 10 volumes per instance, each volume can be shared across multiple instances; Spheron ES: multiple volumes per instance, each volume can be shared across multiple instances read-write or read-only, and attaching at deploy time avoids the VM restart that a hot-attach causes; Spheron MS: single-item array, and the volume's region must equal the offer's region or the request is rejected before anything is created; Spheron AM: volumes are not available, and a request carrying `volumeIds` is rejected rather than created without them. | **Request body example:** ```json { "provider": "massed-compute", "offerId": "rtx-4090-spheron-ai-1", "gpuType": "rtx-4090", "gpuCount": 1, "region": "us-east-1", "operatingSystem": "ubuntu-20.04", "instanceType": "DEDICATED", "sshKeyId": "ssh_key_id_here", "teamId": "team_id_optional", "name": "My GPU Instance", "note": "Alternatively, use 'ssh_public_key' instead of 'sshKeyId' to create a temporary SSH key", "cloudInit": { "runcmd": [ "echo 'Hello from cloud-init'", "apt-get update" ], "packages": ["curl", "git"], "writeFiles": [ { "path": "/etc/motd", "content": "Welcome to your instance!", "owner": "root:root", "permissions": "0644" } ] }, "volumeIds": ["vol_abc123"] } ``` **Response example:** ```json { "id": "deployment_id", "name": "My GPU Instance", "userId": "user_id", "teamId": "team_id", "gpuModelId": "rtx-4090-rtx-4090-spheron-ai-1", "gpuType": "rtx-4090", "offerId": "rtx-4090-spheron-ai-1", "providerId": "spheron-ai", "gpuCount": 1, "region": "us-east-1", "operatingSystem": "ubuntu-20.04", "instanceType": "DEDICATED", "sshKeyId": "ssh_key_id_here", "tempSshKeyId": null, "sshKeyName": "My SSH Key", "sshKeyFingerprint": "SHA256:abc123...", "ipAddress": null, "user": null, "status": "deploying", "startedAt": null, "stoppedAt": null, "lastCreditDeduction": null, "totalCost": 0, "hourlyRate": 0.50, "originalHourlyRate": 0.50, "discountPercentage": 0, "hasDiscount": false, "vcpus": 8, "memory": 32, "storage": 100, "sshCommand": null, "sshPort": null, "portForwards": [], "createdAt": "2024-01-15T10:30:00Z" } ``` #### Get deployments Get a list of your deployments with optional filtering. **Method:** `GET` **Path:** `/api/deployments` **Headers:** * `Authorization`: Bearer `` **Parameters:** | Name | Type | Required | Description | | :------- | :----- | :------- | :---------------------------------------------------------------------------------------------------------------------------------------------------------------------------- | | `userId` | string | No | Filter by user ID (must be your own) | | `teamId` | string | No | Filter by team ID | | `status` | string | No | Filter by status: `active` (running/deploying/stopped), `inactive` (terminated/failed), or a specific status value: `running`, `deploying`, `stopped`, `terminated`, `failed` | **Response example:** ```json [ { "id": "deployment_id", "name": "My GPU Instance", "userId": "user_id", "teamId": "team_id", "gpuModelId": "rtx-4090-spheron-ai-1", "gpuType": "rtx-4090", "offerId": "rtx-4090-spheron-ai-1", "providerId": "spheron-ai", "gpuCount": 1, "region": "us-east-1", "operatingSystem": "ubuntu-20.04", "instanceType": "DEDICATED", "sshKeyId": "ssh_key_id_here", "tempSshKeyId": null, "sshKeyName": "My SSH Key", "sshKeyFingerprint": "SHA256:abc123...", "ipAddress": "192.168.1.100", "user": "ubuntu", "status": "running", "startedAt": "2024-01-15T10:30:00Z", "stoppedAt": null, "lastCreditDeduction": "2024-01-15T11:30:00Z", "totalCost": 12.50, "hourlyRate": 0.50, "stoppedHourlyRate": null, "pausedAt": null, "totalPausedHours": 0, "supportsPause": true, "supportsRestart": true, "pauseUnsupportedReason": null, "providerMinimumRuntimeMinutes": null, "hasDiscount": false, "discountPercentage": 0, "originalHourlyRate": 0.50, "vcpus": 8, "memory": 32, "storage": 100, "sshCommand": "ssh ubuntu@192.168.1.100", "sshPort": 22, "portForwards": [], "createdAt": "2024-01-15T10:30:00Z" } ] ``` :::info[Lifecycle fields] * `stoppedHourlyRate`: What the instance costs while stopped. `null` until it has been stopped at least once. * `pausedAt`: When the instance was last stopped, or `null` if it is not stopped. * `totalPausedHours`: Hours spent stopped across every stop and start cycle so far. * `supportsPause` / `supportsRestart`: Whether this specific instance can be stopped or restarted, narrowed by its machine type and region. * `pauseUnsupportedReason`: Why stopping is unavailable, or `null` when it is available. Show this to the user rather than deriving your own message. * `providerMinimumRuntimeMinutes`: The machine type's own minimum reservation, when it declares one. `null` otherwise. The binding minimum is whichever is longer, this or your account's minimum. See [Instance lifecycle](#instance-lifecycle) for the endpoints that use these fields. ::: #### Get deployment details Get details of a specific deployment by ID. **Method:** `GET` **Path:** `/api/deployments/{deploymentId}` **Headers:** * `Authorization`: Bearer `` **Parameters:** | Name | Type | Required | Description | | :------------- | :----- | :------- | :------------ | | `deploymentId` | string | Yes | Deployment ID | **Response example:** ```json { "id": "deployment_id", "name": "My GPU Instance", "userId": "user_id", "teamId": "team_id", "gpuModelId": "rtx-4090-spheron-ai-1", "gpuType": "rtx-4090", "offerId": "rtx-4090-spheron-ai-1", "providerId": "spheron-ai", "gpuCount": 1, "region": "us-east-1", "operatingSystem": "ubuntu-20.04", "instanceType": "DEDICATED", "sshKeyId": "ssh_key_id_here", "tempSshKeyId": null, "sshKeyName": "My SSH Key", "sshKeyFingerprint": "SHA256:abc123...", "ipAddress": "192.168.1.100", "user": "ubuntu", "status": "running", "startedAt": "2024-01-15T10:30:00Z", "stoppedAt": null, "lastCreditDeduction": "2024-01-15T11:30:00Z", "totalCost": 12.50, "hourlyRate": 0.50, "hasDiscount": false, "discountPercentage": 0, "originalHourlyRate": 0.50, "vcpus": 8, "memory": 32, "storage": 100, "sshCommand": "ssh ubuntu@192.168.1.100", "sshPort": 22, "portForwards": [], "extras": {}, "createdAt": "2024-01-15T10:30:00Z" } ``` #### Rename deployment Update the display name of an existing deployment. Only the `name` field is mutable. Provider, region, GPU type, instance type, SSH key, attached volumes, and every other deployment attribute are immutable after creation. To change anything else, terminate this deployment and create a new one. The response is the full updated deployment in the same shape returned by `GET /api/deployments/{deploymentId}`. **Method:** `PATCH` **Path:** `/api/deployments/{deploymentId}` **Headers:** * `Authorization`: Bearer `` * `Content-Type`: application/json **Parameters:** | Name | Type | Required | Description | | :------------- | :----- | :------- | :---------------------- | | `deploymentId` | string | Yes | Deployment ID to update | **Request body example:** ```json { "name": "Renamed Instance" } ``` :::info[Update rules] Only `name` is read from the body; any other fields are silently ignored. A request with no `name` is rejected with `404 Nothing to update`. The name is stored verbatim and returned on subsequent `GET` responses. There is no character or length restriction at update time. ::: **Response example:** ```json { "id": "deployment_id", "name": "Renamed Instance", "userId": "user_id", "teamId": "team_id", "gpuModelId": "rtx-4090-rtx-4090-massed-compute-1", "gpuType": "rtx-4090", "offerId": "rtx-4090-massed-compute-1", "providerId": "massed-compute", "gpuCount": 1, "region": "us-east-1", "operatingSystem": "ubuntu-20.04", "instanceType": "DEDICATED", "sshKeyId": "ssh_key_id_here", "tempSshKeyId": null, "sshKeyName": "My SSH Key", "sshKeyFingerprint": "SHA256:abc123...", "ipAddress": "192.168.1.100", "user": "ubuntu", "status": "running", "startedAt": "2024-01-15T10:30:00Z", "stoppedAt": null, "lastCreditDeduction": "2024-01-15T11:30:00Z", "totalCost": 12.50, "hourlyRate": 0.50, "hasDiscount": false, "discountPercentage": 0, "originalHourlyRate": 0.50, "vcpus": 8, "memory": 32, "storage": 100, "sshCommand": "ssh ubuntu@192.168.1.100", "sshPort": 22, "portForwards": [], "createdAt": "2024-01-15T10:30:00Z" } ``` #### Terminate deployment Terminate a deployment and its associated cloud instance. **Method:** `DELETE` **Path:** `/api/deployments/{deploymentId}` **Headers:** * `Authorization`: Bearer `` **Parameters:** | Name | Type | Required | Description | | :------------- | :----- | :------- | :------------------------- | | `deploymentId` | string | Yes | Deployment ID to terminate | **Response example:** ```json { "message": "Instance destruction initiated", "deployment": { "id": "deployment_id", "status": "terminated", "stoppedAt": "2024-01-15T12:30:00Z" } } ``` #### Check if deployment can be terminated Check whether a deployment has met the minimum runtime and can be safely terminated. Use this before calling the terminate endpoint to avoid rejected requests. **Method:** `GET` **Path:** `/api/deployments/{deploymentId}/can-terminate` **Headers:** * `Authorization`: Bearer `` **Parameters:** | Name | Type | Required | Description | | :------------- | :----- | :------- | :--------------------- | | `deploymentId` | string | Yes | Deployment ID to check | **Response example:** ```json { "canTerminate": true, "runtime": 25, "timeRemaining": 0, "minimumRuntime": 20 } ``` :::info[Response fields] * `canTerminate`: Whether the deployment can be terminated now * `runtime`: Minutes since the deployment started * `timeRemaining`: Minutes remaining until the minimum runtime is met * `minimumRuntime`: Minimum runtime required before termination is allowed, in minutes When `canTerminate` is `false`, a `reason` field explains why (e.g., "Instance status is deploying, not running" or "Minimum runtime not met"). `minimumRuntime` is the minimum that applies to this specific deployment: whichever is longer, your account's minimum (20 minutes by default) or the machine type's own `providerMinimumRuntimeMinutes`. Some providers hold a machine for a minimum reservation and charge it in full even when you terminate early, so this varies by machine type rather than by provider. Read it from the response rather than assuming 20. Minimum runtime counts time actually spent running. Stopping an instance freezes that clock rather than advancing it. ::: ### Instance lifecycle Stop an instance to pause GPU billing while keeping its disk, start it again, or reboot it in place. Support varies by provider, machine type, and region. See [Instance lifecycle](/concepts/instance-lifecycle) for the support matrix and the billing rules. Every endpoint below acts on a deployment you own or that belongs to your team. Asking a provider for an action it cannot perform returns an error that names the limit rather than a generic failure. #### Quote a stop Return the current rate, the stopped rate, and the breakdown behind it. This endpoint changes nothing, so call it before `pause` to show the user the same number the stop will apply. **Method:** `GET` **Path:** `/api/deployments/{deploymentId}/pause-quote` **Headers:** * `Authorization`: Bearer `` **Parameters:** | Name | Type | Required | Description | | :------------- | :----- | :------- | :------------------ | | `deploymentId` | string | Yes | Deployment to quote | **Response example:** ```json { "hourlyRate": 0.0412, "originalHourlyRate": 0.0412, "currentHourlyRate": 2.45, "breakdown": [ { "label": "Root disk (512 GB)", "amount": 0.0362 }, { "label": "Public IP (retained)", "amount": 0.005 } ] } ``` :::info[Response fields] * `hourlyRate`: What the instance costs per hour while stopped, after any account discount * `originalHourlyRate`: The stopped rate before any discount * `currentHourlyRate`: What the instance costs per hour right now * `breakdown`: Itemised list of what is still charged while stopped ::: *** #### Stop deployment Stop the instance. The GPU is released, the disk and its contents are preserved, and billing drops to the stopped rate. Only a running instance can be stopped. **Method:** `POST` **Path:** `/api/deployments/{deploymentId}/pause` **Headers:** * `Authorization`: Bearer `` **Example request:** ```bash curl -X POST "https://app.spheron.ai/api/deployments//pause" \ -H "Authorization: Bearer " ``` **Response:** The updated deployment object, with `status` set to `stopped` and `stoppedHourlyRate` populated. :::warning[A stop can outlive the request] Writing a machine's memory to disk routinely takes longer than the HTTP request allows. A timeout usually means the stop was accepted and is still running. Poll the deployment rather than retrying the stop. ::: *** #### Start deployment Start a stopped instance. It comes back on the same disk with the same contents and the same public IP. Only a stopped instance can be started. **Method:** `POST` **Path:** `/api/deployments/{deploymentId}/resume` **Headers:** * `Authorization`: Bearer `` **Example request:** ```bash curl -X POST "https://app.spheron.ai/api/deployments//resume" \ -H "Authorization: Bearer " ``` **Response:** The updated deployment object. A start can be refused when the provider released the hardware while the instance was stopped and the machine type is currently out of stock. The refusal is not destructive: the instance and its disk are unchanged, so retry when stock returns. *** #### Restart deployment Reboot the instance in place. Billing does not change and the instance keeps its status. This is a hard reboot, so anything held in memory is lost. Only a running instance can be restarted. **Method:** `POST` **Path:** `/api/deployments/{deploymentId}/restart` **Headers:** * `Authorization`: Bearer `` **Example request:** ```bash curl -X POST "https://app.spheron.ai/api/deployments//restart" \ -H "Authorization: Bearer " ``` **Response:** The updated deployment object. *** #### Get restart progress Report whether a reboot is still in flight, asked of the provider rather than read from a cached record. Poll this while a restart runs. **Method:** `GET` **Path:** `/api/deployments/{deploymentId}/reboot-status` **Headers:** * `Authorization`: Bearer `` **Response example:** ```json { "restarting": true, "since": "2026-09-08T10:31:04Z" } ``` `restarting` is `false` and `since` is absent when no reboot is in flight. *** #### Lifecycle errors | Status | Meaning | What to do | | ------ | --------------------------------------------------------------------------------------------------------------- | ------------------------------------------------------------------ | | `400` | The provider, machine type, or region cannot perform this action, or the instance is in the wrong status for it | Read `error` for the specific limit. Do not retry. | | `403` | The deployment belongs to another user or team | Check the deployment ID. | | `404` | No deployment with that ID | Check the deployment ID. | | `409` | Another change is still in flight on this instance, such as a volume change or an earlier restart | Wait a few minutes and retry. | | `502` | The provider refused the action, or its stopped rate could not be determined | Read `error`. Nothing was changed. | | `503` | A start was refused, usually because the machine type is out of stock | Retry later. The instance and its data are intact. | | `504` | The provider is taking longer than usual | The request went through. Poll the deployment instead of retrying. | Check `supportsPause`, `supportsRestart`, and `pauseUnsupportedReason` on the deployment object before offering a control, so a user is never shown a button that always fails. ### SSH keys #### Get SSH keys Get a list of your SSH keys. **Method:** `GET` **Path:** `/api/ssh-keys` **Headers:** * `Authorization`: Bearer `` **Parameters:** | Name | Type | Required | Description | | :------- | :----- | :------- | :----------------------------------- | | `userId` | string | No | Filter by user ID (must be your own) | | `teamId` | string | No | Filter by team ID | **Response example:** ```json [ { "id": "ssh_key_id", "userId": "user_id", "teamId": "team_id", "name": "My SSH Key", "publicKey": "ssh-rsa AAAAB3NzaC1yc2EAAAADAQABAAAB...", "fingerprint": "sha256:abc123def456...", "createdAt": "2024-01-15T10:30:00Z" } ] ``` #### Add SSH key Add a new SSH key. **Method:** `POST` **Path:** `/api/ssh-keys` **Headers:** * `Authorization`: Bearer `` * `Content-Type`: application/json **Request body:** ```json { "name": "My SSH Key", "publicKey": "ssh-rsa AAAAB3NzaC1yc2EAAAADAQABAAAB... user@hostname", "teamId": "team_id_optional" } ``` **Response example:** ```json { "id": "ssh_key_id", "userId": "user_id", "teamId": "team_id", "name": "My SSH Key", "publicKey": "ssh-rsa AAAAB3NzaC1yc2EAAAADAQABAAAB...", "fingerprint": "sha256:abc123def456...", "createdAt": "2024-01-15T10:30:00Z" } ``` #### Get SSH key details Get a specific SSH key by ID. **Method:** `GET` **Path:** `/api/ssh-keys/{id}` **Headers:** * `Authorization`: Bearer `` **Parameters:** | Name | Type | Required | Description | | :--- | :----- | :------- | :---------- | | `id` | string | Yes | SSH key ID | **Response example:** ```json { "id": "ssh_key_id", "userId": "user_id", "teamId": "team_id", "name": "My SSH Key", "publicKey": "ssh-rsa AAAAB3NzaC1yc2EAAAADAQABAAAB...", "fingerprint": "sha256:abc123def456...", "createdAt": "2024-01-15T10:30:00Z" } ``` #### Delete SSH key Delete an SSH key. **Method:** `DELETE` **Path:** `/api/ssh-keys/{id}` **Headers:** * `Authorization`: Bearer `` **Parameters:** | Name | Type | Required | Description | | :--- | :----- | :------- | :------------------- | | `id` | string | Yes | SSH key ID to delete | **Response example:** ```json { "success": true } ``` ### Volumes Supported providers: `data-crunch`, `sesterce`, `spheron-ai`, and `spheron-es`. Each provider has different rules around size limits, regions, attachment, and mutability. Before creating a volume, call `GET /api/volumes/regions?provider=` to discover valid regions (and for Sesterce, the required `cloudId`). #### List volumes List all persistent storage volumes for a team with pagination and status filtering. **Method:** `GET` **Path:** `/api/volumes` **Headers:** * `Authorization`: Bearer `` **Parameters:** | Name | Type | Required | Description | | :------- | :----- | :------- | :------------------------------------------------------------------ | | `teamId` | string | No | Filter by team ID (defaults to current team) | | `page` | number | No | Page number (default: 1) | | `limit` | number | No | Items per page (default: 20) | | `status` | string | No | Filter by status: 'available', 'attached', 'deleting', or 'deleted' | **Response example:** ```json { "volumes": [{ "id": "volume_internal_id", "volumeId": "vol_abc123", "name": "my-data-volume", "userId": "user_id", "teamId": "team_id", "providerId": "data-crunch", "sizeInGb": 100, "usedCapacityBytes": 52428800000, "virtualIp": "192.168.100.50", "attachedToDeploymentIds": ["deployment_id_1"], "attachedToOrderIds": ["order_123"], "status": "attached", "hourlyRate": 0.0137, "lastPriceUpdate": "2026-02-07T10:30:00Z", "createdAt": "2026-02-07T10:00:00Z", "lastAttachedAt": "2026-02-07T10:15:00Z" }], "total": 5, "page": 1, "limit": 20, "totalPages": 1 } ``` #### Create volume Create a new persistent storage volume. Supported providers: `data-crunch`, `sesterce`, `spheron-ai`, `spheron-es`, `spheron-ms`. Optionally attach to an existing deployment during creation for `data-crunch`, `spheron-ai`, and `spheron-es`. Attaching a Spheron ES volume to a running instance restarts the VM. Sesterce and Spheron MS volumes bind at instance launch only, so they cannot be passed a `deploymentId` here and require a `region`. **Method:** `POST` **Path:** `/api/volumes` **Headers:** * `Authorization`: Bearer `` * `Content-Type`: application/json **Parameters:** | Name | Type | Required | Description | | :------------- | :----- | :---------- | :------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------ | | `name` | string | Yes | Volume name (lowercase alphanumeric with hyphens/underscores, max 60 chars) | | `sizeInGb` | number | Yes | Volume size in GB. Per-provider limits: data-crunch 1-10000, sesterce 50-10000, spheron-ms 1-16000, spheron-es up to 262144 (256 TiB), spheron-ai up to 51200 (the cap can vary by region. Call `GET /api/volumes/regions?provider=spheron-ai` to read minSizeGb/maxSizeGb for the region you intend to use). | | `provider` | string | Yes | Provider name: `data-crunch`, `sesterce`, `spheron-ai`, `spheron-es`, or `spheron-ms` | | `region` | string | Conditional | Region for the volume. Required for `data-crunch`, `sesterce`, `spheron-ai`, `spheron-es`, and `spheron-ms`. Spheron MS has no default region, and a volume can only be mounted by an instance in the same region. Use `GET /api/volumes/regions?provider=` to list available options per provider. | | `cloudId` | string | Conditional | Cloud provider identifier (required for Sesterce only). Use `GET /api/volumes/regions?provider=sesterce` to list available cloud providers. | | `teamId` | string | No | Team ID (defaults to current team) | | `deploymentId` | string | No | Deployment ID to attach to during creation. Supported for `data-crunch`, `spheron-ai`, and `spheron-es`. Attaching a Spheron ES volume to a running instance restarts the VM. Not supported for `sesterce` or `spheron-ms`. | :::info[Size limits by provider] * `data-crunch`: 1 to 10000 GB * `sesterce`: 50 to 10000 GB * `spheron-ai`: up to 51200 GB (varies by region; check `minSizeGb`/`maxSizeGb` from `GET /api/volumes/regions?provider=spheron-ai`) * `spheron-es`: up to 262144 GB (256 TiB) * `spheron-ms`: 1 to 16000 GB ::: **Request body example:** ```json { "name": "my-data-volume", "sizeInGb": 100, "provider": "data-crunch", "teamId": "team_id_optional", "deploymentId": "deployment_id_optional", "note": "For data-crunch: add 'region' (e.g. 'FIN-01'). For spheron-ai: add 'region' (e.g. 'CANADA-1', 'MON1', 'OSL1'). For sesterce: add 'region' and 'cloudId'. Use GET /api/volumes/regions to discover valid values." } ``` **Response example:** ```json { "id": "volume_internal_id", "volumeId": "vol_abc123", "name": "my-data-volume", "userId": "user_id", "teamId": "team_id", "providerId": "data-crunch", "sizeInGb": 100, "usedCapacityBytes": 0, "virtualIp": "192.168.100.50", "attachedToDeploymentIds": [], "attachedToOrderIds": [], "status": "available", "hourlyRate": 0.0137, "lastPriceUpdate": "2026-02-07T10:00:00Z", "createdAt": "2026-02-07T10:00:00Z" } ``` :::info[Provider-specific response fields] * **Verda**: Response includes the NFS endpoint and pseudopath needed for mounting. * **Spheron AI**: Response includes `extras.volumeType` (e.g. `Cloud-SSD`). ::: #### Get volume details Get volume details with fresh usage data from the provider. **Method:** `GET` **Path:** `/api/volumes/{volumeId}` **Headers:** * `Authorization`: Bearer `` **Parameters:** | Name | Type | Required | Description | | :--------- | :----- | :------- | :-------------------- | | `volumeId` | string | Yes | Volume ID to retrieve | **Response example:** ```json { "id": "volume_internal_id", "volumeId": "vol_abc123", "name": "my-data-volume", "userId": "user_id", "teamId": "team_id", "providerId": "data-crunch", "sizeInGb": 100, "usedCapacityBytes": 52428800000, "virtualIp": "192.168.100.50", "attachedToDeploymentIds": ["deployment_id_1"], "attachedToOrderIds": ["order_123"], "status": "attached", "hourlyRate": 0.0137, "lastPriceUpdate": "2026-02-07T10:00:00Z", "createdAt": "2026-02-07T10:00:00Z", "lastAttachedAt": "2026-02-07T10:15:00Z" } ``` #### Update volume Update volume properties. Per-provider rules: `data-crunch` and `spheron-es` support size expansion (no shrinking); `spheron-ai` does not support rename or resize. The volume is immutable after creation, so create a new larger volume and migrate your data instead. Sesterce and Spheron MS volumes are immutable and reject all updates after creation. **Method:** `PATCH` **Path:** `/api/volumes/{volumeId}` **Headers:** * `Authorization`: Bearer `` * `Content-Type`: application/json **Parameters:** | Name | Type | Required | Description | | :--------- | :----- | :------- | :------------------ | | `volumeId` | string | Yes | Volume ID to update | **Request body example:** ```json { "name": "renamed-volume", "sizeInGb": 200 } ``` :::info[Update rules by provider] * **Verda**: Supports rename and size expansion. Volumes cannot be shrunk. * **Spheron ES**: Supports in-place size expansion without recreation or data migration. Volumes cannot be shrunk. * **Spheron AI**: Does not support rename or resize. Volumes are immutable after creation. To change size, create a new larger volume and migrate data. * **Spheron MS**: Does not support rename or resize. Size and name are fixed at creation. To change either, create a new volume and migrate data. * **Sesterce**: Immutable. All update requests are rejected after creation. All fields are optional. Only specify fields you want to update. ::: **Response example:** ```json { "id": "volume_internal_id", "volumeId": "vol_abc123", "name": "renamed-volume", "sizeInGb": 200, "virtualIp": "192.168.100.50", "hourlyRate": 0.0274, "lastPriceUpdate": "2026-02-07T11:00:00Z" } ``` #### Delete volume Delete a volume. The volume must not be attached to any active deployments. Terminate the instance first, then delete the volume. This applies to all providers including Sesterce. **Method:** `DELETE` **Path:** `/api/volumes/{volumeId}` **Headers:** * `Authorization`: Bearer `` **Parameters:** | Name | Type | Required | Description | | :--------- | :----- | :------- | :------------------ | | `volumeId` | string | Yes | Volume ID to delete | **Response example:** ```json { "success": true } ``` #### Attach volume Attach a volume to a running deployment. Volume and deployment must be from the same provider and region. :::info[Attachment rules by provider] * **Verda**: Up to 10 volumes per instance. Each volume can be shared across multiple instances. Volumes and instances must be in the same region (`FIN-01`, `FIN-02`, or `FIN-03`). Cross-region attachment fails silently: the volume appears attached but data is not accessible. Always create the volume and deploy the instance in the same Verda region. * **Spheron AI**: Up to 10 volumes per instance. Each volume can be attached to only one instance at a time. Hot-detach and re-attach is supported post-launch. * **Spheron ES**: Multiple volumes per instance. A volume can be mounted on multiple instances simultaneously, read-write or read-only, within the same region. Hot-attach and hot-detach are supported but restart the VM; data is preserved. Attach at deploy time via `volumeIds` to avoid the restart. * **Sesterce**: 1 volume per instance. Cannot be hot-attached via this endpoint; volumes must be selected at instance creation via `volumeIds` on `POST /api/deployments`. Calling this endpoint for a Sesterce volume returns 400. * **Spheron MS**: 1 volume per instance, selected at instance creation via `volumeIds` on `POST /api/deployments`. There is no attach or detach for a running instance, so calling this endpoint for a Spheron MS volume returns an error. The volume's region must equal the offer's region, or the deployment is rejected before anything is created. Terminating the instance releases the volume for the next deployment. ::: **Method:** `POST` **Path:** `/api/volumes/{volumeId}/attach` **Headers:** * `Authorization`: Bearer `` * `Content-Type`: application/json **Parameters:** | Name | Type | Required | Description | | :--------- | :----- | :------- | :------------------ | | `volumeId` | string | Yes | Volume ID to attach | **Request body example:** ```json { "deploymentId": "deployment_id_here" } ``` **Response example:** ```json { "id": "volume_internal_id", "volumeId": "vol_abc123", "status": "attached", "virtualIp": "192.168.100.50", "attachedToDeploymentIds": ["deployment_id_here"], "attachedToOrderIds": ["order_123"], "lastAttachedAt": "2026-02-07T12:00:00Z" } ``` #### Detach volume Detach a volume from a deployment. Volume data is preserved and the volume can be attached to another deployment. Per-provider rules: Sesterce does not allow manual detach. The volume is released automatically when the instance terminates. Manual detach is only permitted for Sesterce if the deployment is in a terminal state (`failed`, `terminated`, or `terminated-provider`) so a stranded volume can be recovered. :::info[Detach rules by provider] **Sesterce** does not allow manual detach. Volumes are released automatically when the instance terminates. Manual detach is only permitted for Sesterce if the deployment is in a terminal state (`failed`, `terminated`, or `terminated-provider`) so a stranded volume can be recovered. ::: **Method:** `POST` **Path:** `/api/volumes/{volumeId}/detach` **Headers:** * `Authorization`: Bearer `` * `Content-Type`: application/json **Parameters:** | Name | Type | Required | Description | | :--------- | :----- | :------- | :------------------ | | `volumeId` | string | Yes | Volume ID to detach | **Request body example:** ```json { "deploymentId": "deployment_id_here" } ``` **Response example:** ```json { "id": "volume_internal_id", "volumeId": "vol_abc123", "status": "available", "virtualIp": "192.168.100.50", "attachedToDeploymentIds": [], "attachedToOrderIds": [], "lastDetachedAt": "2026-02-07T13:00:00Z" } ``` #### Get volume pricing Get storage pricing per GB per hour for a provider. The rate can vary by region. Pass `region` to get the rate for the specific region you intend to use; omitting it returns the provider's default rate. For Sesterce, also pass `cloudId` alongside `region` (Sesterce pricing varies significantly by AZ). Note: `GET /api/volumes/regions` already embeds `hourlyRatePerGb` on each region entry, so this endpoint is mainly useful when you don't need the full region list (e.g. lightweight provider-level price lookups or Sesterce per-cloudId rate refreshes). **Method:** `GET` **Path:** `/api/volumes/pricing` **Headers:** * `Authorization`: Bearer `` **Parameters:** | Name | Type | Required | Description | | :--------- | :----- | :------- | :------------------------------------------------------------------------------------------------------------------------------------------------------ | | `provider` | string | No | Provider name: `data-crunch`, `sesterce`, `spheron-ai`, or `spheron-es`. Pass it explicitly to select the provider whose regions you want. | | `cloudId` | string | No | Cloud provider identifier (Sesterce only). Use alongside `region` to fetch the rate for a specific AZ. | | `region` | string | No | Region identifier. Pass this when the provider's rate varies by region (e.g. `spheron-ai`). For Sesterce: use alongside `cloudId` for AZ-specific rate. | **Response example:** ```json { "provider": "data-crunch", "hourlyRatePerGb": 0.000137 } ``` #### Get volume regions Get available regions and volume tiers for a given storage provider. Required before creating `data-crunch`, `sesterce`, `spheron-ai`, or `spheron-es` volumes to pick a valid region (and cloud) value. Each region entry includes `minSizeGb`, `maxSizeGb`, and `hourlyRatePerGb`, so if you're already listing regions you don't need to also call `GET /api/volumes/pricing`. `hasGpuOffers` indicates whether any GPU offers exist in that region; the top-level `hasAnyOffers` flag is true when the provider has any live GPU offers at all. **Method:** `GET` **Path:** `/api/volumes/regions` **Headers:** * `Authorization`: Bearer `` **Parameters:** | Name | Type | Required | Description | | :--------- | :----- | :------- | :---------------------------------------------------------------------------------------------------------------------------------------------------------------------- | | `provider` | string | No | Provider name: `data-crunch`, `sesterce`, `spheron-ai`, or `spheron-es`. Pass it explicitly to select the provider whose regions you want. Unknown values return a 400. | All providers return the same shape. Sesterce entries also include `cloudId` and `cloudName`: pass both `region` (the `id`) and `cloudId` when creating a Sesterce volume. `hasGpuOffers` is per region; `hasAnyOffers` is true if at least one region has offers. **Response example (`data-crunch`):** ```json { "hasAnyOffers": true, "regions": [ { "id": "Texas", "name": "Dallas, TX", "country_code": "US", "types": ["NFS"], "hasGpuOffers": true, "minSizeGb": 1, "maxSizeGb": 64000, "hourlyRatePerGb": 0.000137 } ] } ``` **Response example (`?provider=data-crunch`):** ```json { "hasAnyOffers": true, "regions": [ { "id": "FIN-01", "name": "Finland 1", "country_code": "FI", "types": ["NVMe_Shared"], "hasGpuOffers": true, "minSizeGb": 1, "maxSizeGb": 10000, "hourlyRatePerGb": 0.000196 }, { "id": "FIN-02", "name": "Finland 2", "country_code": "FI", "types": ["NVMe_Shared"], "hasGpuOffers": true, "minSizeGb": 1, "maxSizeGb": 10000, "hourlyRatePerGb": 0.000196 }, { "id": "FIN-03", "name": "Finland 3", "country_code": "FI", "types": ["NVMe_Shared"], "hasGpuOffers": false, "minSizeGb": 1, "maxSizeGb": 10000, "hourlyRatePerGb": 0.000196 } ] } ``` **Response example (`?provider=sesterce`):** Sesterce entries include `cloudId` and `cloudName`. Pass both `region` (the `id`) and `cloudId` when creating a Sesterce volume. ```json { "hasAnyOffers": true, "regions": [ { "id": "eu-west-1", "name": "EU West 1", "cloudId": "668f9d8df664e3c028ce5de9", "cloudName": "Sesterce EU", "types": ["block-storage"], "hasGpuOffers": true, "minSizeGb": 50, "maxSizeGb": 10000, "hourlyRatePerGb": 0.000150 }, { "id": "us-east-1", "name": "US East 1", "cloudId": "77af9d8df664e3c028ce5ef0", "cloudName": "Sesterce US", "types": ["block-storage"], "hasGpuOffers": true, "minSizeGb": 50, "maxSizeGb": 10000, "hourlyRatePerGb": 0.000175 } ] } ``` **Response example (`?provider=spheron-ai`):** Spheron AI exposes several regions; capacity and rate can vary by region and are returned per region in this response. ```json { "hasAnyOffers": true, "regions": [ { "id": "CANADA-1", "name": "Canada 1", "types": ["Cloud-SSD"], "hasGpuOffers": true, "minSizeGb": 1, "maxSizeGb": 40960, "hourlyRatePerGb": 0.000109 }, { "id": "NORWAY-1", "name": "Norway 1", "types": ["Cloud-SSD"], "hasGpuOffers": false, "minSizeGb": 1, "maxSizeGb": 40960, "hourlyRatePerGb": 0.000109 }, { "id": "MON1", "name": "Montreal 1", "country_code": "CA", "types": ["NVME"], "hasGpuOffers": true, "minSizeGb": 1, "maxSizeGb": 51200, "hourlyRatePerGb": 0.000168 }, { "id": "OSL1", "name": "Oslo 1", "country_code": "NO", "types": ["NVME"], "hasGpuOffers": false, "minSizeGb": 1, "maxSizeGb": 51200, "hourlyRatePerGb": 0.000168 } ] } ``` ### Teams #### Get balance Get account balance. Returns all teams by default. **Method:** `GET` **Path:** `/api/balance` **Headers:** * `Authorization`: Bearer `` **Parameters:** | Name | Type | Required | Description | | :------- | :------ | :------- | :------------------------------------------------------ | | `teamId` | string | No | Get balance for a specific team ID only | | `all` | boolean | No | Set to 'false' to get current team only (default: true) | **Response example:** ```json { "teams": [ { "teamId": "team_1", "teamName": "My Personal Team", "balance": 25.50, "isCurrentTeam": true, "role": "owner" }, { "teamId": "team_2", "teamName": "Company Team", "balance": 150.75, "isCurrentTeam": false, "role": "admin" } ], "currency": "USD" } ``` #### List teams List every team the authenticated caller belongs to, with each team's members, plan, owner, and real-time balance. If the caller has no team yet, a default personal team is created on first call and returned in the response, so this endpoint is safe to call after sign-up without a separate bootstrap step. Use the team `id` field when passing `teamId` into deployment, volume, or balance endpoints. **Method:** `GET` **Path:** `/api/teams` **Headers:** * `Authorization`: Bearer `` **Response example:** ```json [ { "id": "team_id_1", "name": "My Personal Team", "slug": "my-personal-team-1707307200000", "ownerId": "user_id", "balance": 25.50, "members": [ { "userId": "user_id", "email": "owner@example.com", "name": "Owner Name", "role": "owner", "joinedAt": "2024-01-15T10:30:00Z" } ], "createdAt": "2024-01-15T10:30:00Z" } ] ``` :::info[Response fields] * `balance` is computed in real time and reflects the team's current USD credit balance after pending deductions. * `members[].role` is one of `owner`, `admin`, or `member`. ::: #### Get team details Fetch a single team by ID. The authenticated caller must be a member of the team (owner, admin, or member); otherwise the request is rejected with `403`. Returns the same team shape that `GET /api/teams` returns for entries in its array, with one exception: the stored `balance` is returned as-is and is NOT recomputed in real time. For an up-to-date balance, use `GET /api/balance?teamId=` instead. **Method:** `GET` **Path:** `/api/teams/details/{teamId}` **Headers:** * `Authorization`: Bearer `` **Parameters:** | Name | Type | Required | Description | | :------- | :----- | :------- | :---------------------------------------------- | | `teamId` | string | Yes | Team ID to fetch. Obtain from `GET /api/teams`. | **Response example:** ```json { "id": "team_id", "name": "My Personal Team", "slug": "my-personal-team-1707307200000", "ownerId": "user_id", "balance": 25.50, "members": [ { "userId": "user_id", "email": "owner@example.com", "name": "Owner Name", "role": "owner", "joinedAt": "2024-01-15T10:30:00Z" } ], "createdAt": "2024-01-15T10:30:00Z" } ``` ### Error reference All error responses follow this format: ```json { "error": "Error message", "code": "ERROR_CODE", "details": {} } ``` #### Common HTTP status codes **200 OK**: Request succeeded **201 Created**: Resource created successfully **400 Bad Request**: Invalid parameters or request body ```json { "error": "Missing required field: gpuType", "code": "VALIDATION_ERROR" } ``` **401 Unauthorized**: Invalid or missing API key ```json { "error": "Invalid API key", "code": "UNAUTHORIZED" } ``` **403 Forbidden**: Insufficient permissions ```json { "error": "Insufficient permissions to access this resource", "code": "FORBIDDEN" } ``` **404 Not Found**: Resource does not exist ```json { "error": "Deployment not found", "code": "NOT_FOUND" } ``` **429 Too Many Requests**: Rate limit exceeded ```json { "error": "Rate limit exceeded. Try again in 15 minutes", "code": "RATE_LIMIT_EXCEEDED" } ``` **500 Internal Server Error**: Server error ```json { "error": "Internal server error", "code": "INTERNAL_ERROR" } ``` ### Status values #### Deployment statuses **deploying**: Instance is being provisioned. Usually takes 30-60 seconds. **running**: Instance is active and accessible via SSH. **stopped**: Instance is parked. The GPU is released, the disk and its contents are preserved, and billing runs at `stoppedHourlyRate`. A stopped instance is part of the live set, so `?status=active` includes it. Start it with the [resume endpoint](#start-deployment). **failed**: Deployment failed. Check error details in the deployment object. **terminated**: Instance has been terminated by the user and is no longer accessible. **terminated-provider**: Instance was reclaimed or stopped by the provider (e.g., a Spot instance was interrupted). No further action is needed. #### Status lifecycle ``` deploying → running ⇄ stopped → terminated ↓ ↓ failed terminated-provider ``` **Transitions:** * `deploying` to `running`: Successful deployment * `deploying` to `failed`: Deployment error * `running` to `stopped`: Stopped by the user, or parked by the provider * `stopped` to `running`: Started again by the user * `running` or `stopped` to `terminated`: Manual termination by user * `running` to `terminated-provider`: Provider reclaimed the instance (Spot interruption) * Any status can transition to `failed` if errors occur A restart does not change the status. The instance stays `running` throughout, and [reboot-status](#get-restart-progress) reports whether the reboot is still in flight. ### Rate limits All API endpoints are subject to rate limiting to ensure fair usage and system stability. Rate limits are tracked per IP address for unauthenticated requests and per user (Firebase UID) for authenticated requests. #### Rate limit headers All responses include these headers: ```http X-RateLimit-Limit: 250 X-RateLimit-Remaining: 245 X-RateLimit-Reset: 2025-12-29T14:00:00.000Z ``` #### Rate limits by endpoint ##### GPU offers and providers ``` GET /api/providers GET /api/gpu-offers ``` * **Limit**: 250 requests per 15 minutes * **Scope**: Per IP address * **Authentication**: Optional (authenticated users see team discounts) ##### Deployments ``` POST /api/deployments ``` * **Default limit**: 10 deployments per 15 minutes * **Scope**: Per authenticated user * **Custom limits**: Admins can increase limits for enterprise users * **Authentication**: Required ``` GET /api/deployments GET /api/deployments/{deploymentId} PATCH /api/deployments/{deploymentId} DELETE /api/deployments/{deploymentId} GET /api/deployments/{deploymentId}/can-terminate ``` * **Limit**: 250 requests per 15 minutes * **Scope**: Per IP address * **Authentication**: Required ##### SSH keys ``` GET /api/ssh-keys GET /api/ssh-keys/{id} POST /api/ssh-keys DELETE /api/ssh-keys/{id} ``` * **Limit**: 250 requests per 15 minutes * **Scope**: Per IP address * **Authentication**: Required ##### Balance and teams ``` GET /api/balance GET /api/teams GET /api/teams/details/{teamId} ``` * **Limit**: 250 requests per 15 minutes * **Scope**: Per IP address * **Authentication**: Required #### Rate limit response When the rate limit is exceeded (HTTP 429): ```json { "error": "Too many requests", "message": "Too many requests from this IP, please try again later.", "retryAfter": 900 } ``` #### Custom rate limits (enterprise) Enterprise customers can request custom deployment creation limits: * Contact: [info@spheron.ai](mailto\:info@spheron.ai) * Configurable: Deployment creation limit (default: 10 per 15 min) * Options: Custom limit or unlimited deployments #### Quick reference | Endpoint | Rate Limit | Window | Scope | Custom Limits | | ----------------------- | ------------ | ------ | ----- | ------------- | | General API | 250 requests | 15 min | IP | No | | Deployment Creation | 10 requests | 15 min | User | Yes | | All Other API Endpoints | 250 requests | 15 min | IP | No | ### Security #### Best practices Treat API keys like passwords: * Never expose keys in client-side code * Do not commit keys to version control * Use environment variables for credentials * Rotate keys regularly Key management: * Generate keys from [dashboard settings](https://app.spheron.ai/settings) * Set expiry dates for keys * Revoke compromised keys immediately * Use separate keys for different environments Connection security: * All API requests must use HTTPS * Verify SSL certificates * Do not disable certificate validation For comprehensive security guidelines, see [Security best practices](/security). ### Common workflows #### Complete deployment flow ```bash # 1. Check available GPU offers curl -H "Authorization: Bearer " \ "https://app.spheron.ai/api/gpu-offers?search=rtx-4090&limit=5" # 2. Add SSH key (if not already added) curl -X POST "https://app.spheron.ai/api/ssh-keys" \ -H "Authorization: Bearer " \ -H "Content-Type: application/json" \ -d '{"name": "My Key", "publicKey": "ssh-rsa AAA..."}' # 3. Deploy instance curl -X POST "https://app.spheron.ai/api/deployments" \ -H "Authorization: Bearer " \ -H "Content-Type: application/json" \ -d '{ "provider": "spheron-ai", "offerId": "rtx-4090-spheron-ai-1", "gpuType": "rtx-4090", "gpuCount": 1, "region": "us-east-1", "operatingSystem": "ubuntu-22.04", "instanceType": "DEDICATED", "sshKeyId": "your_ssh_key_id" }' # 4. Monitor deployment status curl -H "Authorization: Bearer " \ "https://app.spheron.ai/api/deployments/deployment_id" # 5. Terminate when done curl -X DELETE "https://app.spheron.ai/api/deployments/deployment_id" \ -H "Authorization: Bearer " ``` ### What's next * [Getting Started](/getting-started): Account setup and first deployment * [Security best practices](/security): API key management and security * [Connecting to instances](/connecting): SSH and networking setup * [Billing](/billing): Credits and usage monitoring ## API skill for AI agents This page gives you a ready-made skill file that teaches an AI agent how to use the [Spheron GPU API](/api-reference). Hand it to Claude or ChatGPT, and the agent understands the full deployment flow: which endpoint to call, in what order, how each parameter works, and how to handle errors, provider rules, and instance lifecycles. The skill is one self-contained Markdown file. It works as a Claude Agent Skill, a ChatGPT custom GPT instruction set, or a system prompt for any LLM that can make HTTP requests. Download spheron-gpu-api-skill.md ### What the skill teaches the agent * The full deploy flow: providers, GPU offers, SSH keys, deployment, status polling, stopping, restarting, and termination. * A decision framework that maps a user request to the correct endpoint and call order. * How every deployment parameter works, including which fields must all come from the same offer. * How to deploy a [CPU Node](/concepts/cpu-nodes) when the workload never touches a GPU, and when to suggest one. * Provider-specific rules for volumes and instance types. * When an instance can be [stopped or restarted](/concepts/instance-lifecycle), how to quote the stopped rate first, and why a restart is never emulated with a stop and a start. * Status values, the deployment lifecycle, error codes, and rate limits. * That an API key is required, and that access comes from the [dashboard](https://app.spheron.ai/settings) or by contacting [info@spheron.ai](mailto\:info@spheron.ai). ### Prerequisites * A Spheron API key. Generate one from your [dashboard settings](https://app.spheron.ai/settings). If you do not have API access yet, request it from [info@spheron.ai](mailto\:info@spheron.ai). * An AI agent that can make HTTPS requests, or that you supply request output to manually. :::warning The skill instructs the agent to spend real money on your account when it deploys instances or creates volumes. Keep confirmation steps enabled and review any deploy or terminate action before approving it. ::: ### Use the skill with Claude Choose the option that matches how you run Claude. #### Claude Code or the Claude Agent SDK 1. Download spheron-gpu-api-skill.md. 2. Create a skill folder and rename the file to `SKILL.md` inside it: ```bash mkdir -p ~/.claude/skills/spheron-gpu-api mv spheron-gpu-api-skill.md ~/.claude/skills/spheron-gpu-api/SKILL.md ``` 3. Start Claude Code. The skill loads automatically when your request matches its description (renting or managing GPUs on Spheron). 4. Save your API key once on your local system so the agent reads it automatically on every run instead of asking again: ```bash # Persist the key for future shells echo 'export SPHERON_API_KEY=""' >> ~/.zshrc ``` The skill instructs the agent to read `SPHERON_API_KEY` (or a local `~/.spheron/credentials` file) before each authenticated call. #### Claude apps and Projects 1. Download the file. 2. Add it to a Project's knowledge, or paste its contents into the custom instructions or the start of a conversation. 3. Tell Claude your goal, for example: "Deploy a single H100 on Spheron and give me the SSH command." Provide your API key when asked. ### Use the skill with ChatGPT #### Custom GPT 1. Open the GPT builder and go to Configure. 2. Open `spheron-gpu-api-skill.md`, copy its full contents, and paste them into the Instructions field. 3. Optionally enable Actions and import the API so the GPT can call endpoints directly. Add your API key as a Bearer token in the authentication settings. #### Standard chat 1. Paste the contents of the file as your first message, or save it as a custom instruction. 2. Add your goal and your API key in the same conversation. ### Use the skill with any LLM agent The file is plain Markdown with no tool-specific syntax. Load it as the system prompt for any agent framework that can issue HTTPS requests to `https://app.spheron.ai`. The agent then follows the decision framework and parameter rules in the file. ### Keep the skill current The skill mirrors the [API reference](/api-reference). When the API changes, download the file again so your agent uses the latest endpoints, parameters, and provider rules. ### What's next * [API reference](/api-reference): the complete endpoint documentation the skill is based on. * [Getting started](/getting-started): account setup and your first deployment. * [Security best practices](/security): how to store and rotate your API key safely. * [Instance types](/concepts/instance-types): the difference between SPOT, DEDICATED, and CLUSTER. * [CPU nodes](/concepts/cpu-nodes): CPU-only instances the skill can deploy with `gpuType: "CPU"`. * [Instance lifecycle](/concepts/instance-lifecycle): the stop, start, and restart endpoints the skill calls. ## Billing Manage credits, monitor usage, and track spending for GPU instances. ### Credit system **How it works:** * 1 Credit = $1 USD of GPU usage * Credits never expire * Credits are shared across team members * Pay-per-second billing: credits are deducted continuously based on your hourly rate, so you pay only for the exact time your instance runs * Your hourly rate tracks the provider's current price for the whole life of an instance. If the underlying price moves, charges from that point onward use the new rate. Usage already billed is never recalculated, and any discount on your account continues to apply **Requirements:** * Minimum deposit: $15 * Instant credit delivery ### Dashboard overview The Overview section shows your balance and live GPU usage at a glance. ![Billing Dashboard](/billing.png) **Cards:** * **Available Balance**: Credits ready to spend on GPU deployments. An account-status indicator (for example, "Account in good standing") sits below the value. * **Total Spent**: All-time GPU and storage spend for the team. * **Active**: Number of GPU instances currently running. * **Burn Rate**: Current hourly cost across all running instances. * **Est. Runtime**: Estimated time remaining at the current burn rate. Shows **N/A** when there is no active spending. ### Adding credits ![Payment Methods](/billing2.png) #### Payment methods **Card payment** (powered by Stripe) * Visa, Mastercard, and major cards accepted * Secure processing via Stripe * Instant delivery **Stables payment** (powered by CopperX) * USDC and USDT accepted * Blockchain-secured transactions * Instant delivery #### Preset packages | Amount | Credits | Rate | | -------- | ------- | ---------------------------- | | **$100** | **100** | **$1.00 / credit** (Popular) | | $1,000 | 1,000 | $1.00 / credit | | $5,000 | 5,000 | $1.00 / credit | #### Custom amount Enter any amount between $15 (minimum) and $5,000 (maximum) for instant delivery. ### Usage analytics Track deployments, GPU spend, and volume costs in one place. ![Usage Analytics](/billing3.png) A time-range selector at the top of the panel (default: **All Time**) filters every metric and the deployment list below. **Summary metrics:** * **Deployments**: Total deployments in the selected range * **GPU Spend**: GPU compute spend in the selected range (also shows the billed-instance count) * **Active Volumes**: Currently active persistent volumes (also shows the total volumes ever created) * **Volume Cost**: Accumulated storage spend in the selected range **Per-deployment details:** * GPU model, count, VRAM, and hourly rate (for example, `1x L40S PCIe - 48GB GDDR6 - $1.07/hr`) * Instance ID * Provider and region * Duration and timestamp * Total cost and status (active or terminated) Use the analytics view for: * Cost analysis by GPU type * Spending pattern review across time ranges * Project cost tracking * Usage optimization ### Billing for a stopped instance Stopping an instance keeps it and its disk while releasing the GPU. You are billed for the disk, not the GPU, for as long as it stays stopped. * The stopped rate comes from the provider and covers the retained disk, plus the public IP where the provider charges for one. * Any discount on your account applies to the stopped rate exactly as it does to the running rate. * Charges run on a five minute cycle. Stopping and starting both settle the elapsed time at the outgoing rate first, so a stop landing mid-cycle is not billed at the wrong rate for that slice. * Usage figures, invoices, and the deployment list pick stopped periods up with no change. * When a provider parks your machine from its side, you are charged the stopped rate for that period, not the running rate. Stopped rates are shown to four decimal places. At two decimal places most of them round to $0.00 and read as free, which they are not. :::warning[Stopping is not the same as terminating] A team that runs out of credit has every instance destroyed, stopped ones included. Stopping reduces the burn rate; it does not protect an instance indefinitely. Terminate an instance you have finished with. See [Instance lifecycle](/concepts/instance-lifecycle) for which providers support stopping. ::: ### Deposit history View all credit deposits and top-ups for your team. ![Deposit History](/billing4.png) A time-range selector at the top (default: **All Time**) filters the summary metrics and the deposit list. **Summary metrics:** * **Total Deposited**: All-time deposit amount across the team * **Avg Deposit**: Average value across completed deposits * **Total Deposits**: Count of all deposits with a completed-vs-pending breakdown **Per-deposit details:** * Status badge: **Pending** or **Completed** * Date and time of the deposit * Source label: `Custom $X`, a preset package (e.g., `$100 Package`), or `Auto Top-Up` * Payment provider: **Stripe** (card) or **CopperX** (stables) * Amount in USD and the credits awarded * **Receipt** button on completed deposits for downloading the invoice A deposit that gets stuck pending because a confirmation was delayed or missed is detected and credited to your balance automatically, with no need to contact support. Deposits that were genuinely abandoned or expired are cleared from the list instead of lingering as pending. Use the deposit history for: * Payment verification * Expense tracking * Receipt downloads for accounting records ### Low-balance warnings Warnings are based on how much runtime your balance buys at your current burn rate, not on a fixed dollar figure. The same alert means the same thing whether you run one small GPU or a large cluster. Spheron emails you as your estimated remaining runtime crosses each of these thresholds: | Band | Thresholds | | ------- | --------------------- | | Hours | 12 h, 6 h, 3 h, 1 h | | Minutes | 30 min, 15 min, 5 min | A balance-exhaustion notice follows if the balance actually runs out. These emails are always sent and are not affected by the marketing toggle in [User settings](/user-settings#notifications). Enable [auto top-up](#auto-top-up) to recharge automatically instead of relying on the warnings. ### Auto top-up Auto top-up prevents unexpected instance termination by automatically recharging your account when credits run low. ![Auto Top-Up](/billing5.png) **Configure auto top-up:** 1. Add a payment card from the **Add Credits** tab. Once saved, it appears in the **Saved Card** panel under Auto-Pay. 2. Set **Top up when below** between $5 and $500 (for example, $10) 3. Set **Amount per top-up** between $15 and $5,000 (for example, $50) 4. Toggle **Enable auto top-up** on **How charges work:** * When your balance falls below the threshold, the platform charges your saved card for the top-up amount. * A 5-minute cooldown between charges prevents duplicate billing. * If a charge fails, the platform disables auto top-up and emails you a notification. * Auto top-up charges appear in Deposit History labeled **"Auto Top-Up"**. For long training runs, auto top-up prevents instance termination due to insufficient credits mid-job. ### Billing details Add your company name, registered address, and tax ID to your account so they appear on every future card-payment invoice automatically. Stripe stores this information once and applies it to all subsequent charges. ![Billing Details](/billing6.png) :::info[Card payments only] Billing details apply to card payments processed by Stripe. Stables payments (USDC/USDT via CopperX) are settled on-chain and do not generate invoices through this flow. ::: **Use billing details for:** * Issuing invoices with proper legal entity information for accounting and procurement * Tax compliance: VAT, GST, EIN, or other regional tax identifiers * Expense reimbursement and audit trails that require the registered business name and address #### Configure billing details :::steps ##### Open the Billing page In the Spheron dashboard, navigate to **Billing**. Scroll to the **Billing Details** card (step 03 in the billing settings). ##### Open the Stripe billing portal Click **Manage on Stripe**. Stripe hosts the form and stores the data on its own systems; Spheron does not store company billing details directly. ##### Enter your business information Fill in the four fields: | Field | Description | | -------- | ------------------------------------------------- | | Company | Legal entity name shown on the invoice | | Address | Registered business address | | Tax ID | VAT, GST, EIN, or other applicable tax identifier | | Invoices | Email address that receives each invoice | ##### Save the changes Save in Stripe. The portal links these details to your Spheron customer record. Every subsequent card-payment invoice includes the company name, address, tax ID, and is sent to the configured invoice email automatically. ::: #### Update or remove details Click **Manage on Stripe** at any time to change company information, update the address, swap the tax ID, or change the invoice email. Updates apply to **future invoices only**; previously issued invoices are not retroactively modified. #### Access past invoices Stripe emails each invoice to the configured invoice email address. Past invoices are also available in the Stripe billing portal via the same **Manage on Stripe** button. ### Team discounts Volume-based and admin-assigned discounts apply automatically. The discounted price appears directly in the GPU listings on the dashboard when your team has an active discount. * The higher of volume-based or admin-assigned discounts is applied automatically * No action is required; discounts apply as long as you are authenticated To inquire about discount eligibility for high-volume usage, use the chat widget on [app.spheron.ai](https://app.spheron.ai) or email [info@spheron.ai](mailto\:info@spheron.ai). ### Best practices **Credit management:** * Start with $50-$100 to understand usage patterns * Monitor balance regularly for long-running instances * Enable Auto Top-Up to avoid unexpected terminations * Watch for the [low-balance warning emails](#low-balance-warnings) as your runtime drops * Use custom amounts for precise budgeting **Cost optimization:** * Review usage analytics to identify expensive deployments * Terminate unused instances promptly * Stop an instance you will come back to, so the GPU stops billing while the disk is preserved * Use [Reserved GPUs](/reserved-gpus) for long-term workloads (30-50% savings) * See [Cost Optimization](/cost-optimization) for GPU tier selection and Spot strategies **Security:** * Card payments are Stripe-encrypted and PCI compliant * Stables payments are settled on-chain via CopperX * Card data is never stored on Spheron servers ### Frequently asked questions **Q:** What happens if I run out of credits? **A:** Instances terminate automatically to prevent overcharges. Add credits to resume. **Q:** Does a stopped instance still cost credits? **A:** Yes, at the stopped rate, which covers the retained disk and public IP rather than the GPU. See [Billing for a stopped instance](#billing-for-a-stopped-instance). **Q:** Do credits expire? **A:** No. Credits never expire and remain available indefinitely. **Q:** Can team members share credits? **A:** Yes. Credits are shared across all team members. **Q:** How quickly are credits delivered? **A:** Instantly upon payment confirmation, for both card and stables payments. **Q:** What are the deposit limits? **A:** Minimum: $15 per deposit. Maximum: $5,000 per deposit. **Q:** Are there hidden fees? **A:** No. 1 credit = $1 USD of GPU usage. No additional fees. **Q:** Can I get a refund? **A:** Credits do not expire, so they retain value. Contact support for specific refund inquiries. ### What's next * [Getting Started](/getting-started): Deploy your first instance * [Reserved GPUs](/reserved-gpus): Long-term GPU reservations * [User Settings](/user-settings): Configure billing alerts * [Cost Optimization](/cost-optimization): Reduce GPU spend * [Instance Lifecycle](/concepts/instance-lifecycle): Stop an instance to pause GPU billing * [API Reference](/api-reference): Programmatic billing access ## Changelog All notable changes to **Spheron AI** will be documented in this file. Track new features, improvements, bug fixes, and breaking changes across all releases. This changelog is automatically updated with each deployment to ensure you always have the latest information about platform updates and enhancements. :::steps ### `v1.29.0` • 2026-09-10 #### AMD Instinct Arrives on the Marketplace > Every GPU on the marketplace has been NVIDIA until today. Spheron AM is live with AMD Instinct MI300X, 192 GB of HBM3e per GPU, and offers now say which vendor made the silicon you are renting. **Expansion** * **AMD Instinct MI300X, the first AMD silicon in the catalogue.** Each GPU carries 192 GB of HBM3e, and the catalogue publishes 1x, 2x and 4x GPU configurations. They sort, filter, and deploy through the same wizard as everything else, so choosing AMD is a choice about the hardware and not about learning a second workflow. * **A new provider: Spheron AM.** It appears in Choose Provider alongside the others, with hourly rates in USD. A machine that is out of stock reads as sold out rather than disappearing, so you can set an availability alert instead of wondering where it went. * **A new region in Michigan, United States.** **UX Improvements** * **Offers and instance cards name the silicon vendor.** AMD, NVIDIA, and Intel each carry their own mark. A catalogue with more than one vendor in it should not make you infer the manufacturer from a model string, and a part we cannot place keeps a neutral icon rather than wearing the wrong vendor's logo. * **The deploy wizard tells you when the provider sets the minimum runtime.** Some machine types are held for a minimum reservation that is longer than the platform's own floor. Where that happens, the wizard names the provider and shows the longer number before you deploy, and that is the same number enforced when you come to terminate. **Behaviour Notes** * **Spheron AM machines ship one image, Ubuntu with ROCm.** There is no image picker, because the machine type determines what it boots. * **The boot disk comes with the machine type.** Its size is shown on the offer rather than being something you set. * **Restart is available. Stopping is not.** A Spheron AM instance bills at the full hourly rate until it is destroyed, so there is no stopped state that costs less. An instance you have finished with should be terminated. * **Volumes are not available on Spheron AM.** A deployment that asks for one is refused rather than created without it. * **Each machine type carries a minimum reservation, and it is charged in full.** Terminating early does not reduce it. The figure is shown in the wizard before you deploy. * **Spheron AM is on-demand only.** There is no spot option for these offers. **API** * `GET /api/gpu-offers-with-reserved?providers=spheron-am` returns Spheron AM offers. Send an offer's `region` value back unchanged as `region` on the deployment. * `POST /api/deployments` rejects `volumeIds` for Spheron AM rather than ignoring it. * Deployments carry `providerMinimumRuntimeMinutes` when the machine type declares one. `GET /api/deployments/:deploymentId/can-terminate` reports `minimumRuntime` as whichever is longer, the platform floor or that value, and refuses until it is met. * `POST /api/deployments/:deploymentId/restart` is supported on Spheron AM. `POST /api/deployments/:deploymentId/pause` returns an error naming the reason. ### `v1.28.0` • 2026-09-06 #### A New Provider: Spheron MS > A new GPU provider is live on the marketplace. Spheron MS brings a large catalogue across regions the marketplace has not covered before, with storage you attach at deployment time and a restart you can reach from the instance card. **Expansion** * **Spheron MS appears in Choose Provider.** Its offers sit alongside every other provider, sorted and filtered the same way, with hourly rates in USD. A machine that is out of stock shows as sold out rather than disappearing, so you can set a notification instead of wondering where a GPU went. * **New regions.** Spheron MS lists GPUs in regions the marketplace has not offered before. Each offer names its region, and the region on the offer is the region you deploy into. * **Bare metal alongside virtual machines.** Where an offer is a full physical server it is listed as bare metal and labelled on the card. **New Features** * **Volumes attach when you deploy.** Create a volume in the region you are about to deploy into, then pick it in the deployment wizard. It is mounted before the machine boots, so your data is there the first time you connect. * **Restart from the instance card.** A restart reboots the machine in place. Your billing does not change and the instance keeps its status. **Behaviour Notes** * **A Spheron MS volume is chosen at deployment time, and only then.** There is no attach or detach for a machine that is already running. Terminating the instance releases the volume, and you can then select it for your next deployment. * **One volume per instance on Spheron MS.** * **Volume size and name are fixed at creation.** Spheron MS volumes cannot be resized or renamed afterwards. Create a new volume at the size you need and copy your data across. * **A volume and its instance must be in the same region.** A volume created in one region cannot be attached to an instance in another, and the wizard will not offer it. * **The boot disk comes with the machine type.** Each Spheron MS machine type ships a fixed boot disk, so its size is shown on the offer rather than being something you set. Pick a machine type with the disk you need, or attach a volume for the rest. * **Stopping is not available on Spheron MS.** Restart is, on virtual machines. Bare metal instances support neither. An instance you have finished with should be terminated. **API** * `GET /api/gpu-offers-with-reserved?providers=spheron-ms` returns Spheron MS offers. Send an offer's `region` value back unchanged as `region` on the deployment. * `POST /api/deployments` accepts `volumeIds` with exactly one volume for Spheron MS. The volume's region must equal the offer's region, or the request is rejected before anything is created. * `POST /api/volumes` requires `region` for Spheron MS and has no default. `PATCH /api/volumes/:volumeId` and `POST /api/volumes/:volumeId/attach` return an error for Spheron MS volumes. * `POST /api/deployments/:deploymentId/restart` is supported on Spheron MS virtual machines. `POST /api/deployments/:deploymentId/pause` returns an error. ### `v1.27.2` • 2026-09-05 #### Sold-Out GPUs Stay on the Page > A GPU that is out of stock should read as sold out, not as something the provider never offered. Four ways it could vanish instead. **Bug Fixes** * **A sold-out variant no longer takes its Spot tile with it.** On Spheron ES the published floor price for L40S was worked out after the live quote and inside the same guard, so a failed quote lost the fallback and the Spot option disappeared from the L40S page entirely. The floor is applied first now, and only where a price has never been quoted, so a live price is never replaced by it. * **A GPU that is out of stock everywhere keeps its provider listed.** A model with no stock anywhere has no cache row to carry forward, so one quiet fetch from an upstream erased that brand from Choose Provider while every other provider still showed it as sold out. Sold-out offers are merged with what is already known and held for 7 days after they were last seen. * **Sold-out offers name the provider by brand.** Rows served from the sold-out cache carried raw upstream ids rather than the brand names used everywhere else in the same response. **UX Improvements** * **The CPU vendor is named on the configuration card.** Spheron ES ships L40S on both Intel and AMD hosts and separates them only by a slug you never see, so the host you found after connecting was not necessarily the host you picked. ### `v1.27.1` • 2026-09-05 #### Deployment Emails and Interface Repairs > The deployment ready email printed markup at people and named GPUs that do not exist. Alongside it, a set of repairs to the surfaces this release touched. **Bug Fixes** * **The deployment ready email prints the path, not the markup.** The private key placeholder was escaped by hand and then again by the renderer, so the mail showed the escape sequence instead of the placeholder. Its plain text copy was run through the HTML renderer as well. * **The email names the GPU you deployed.** The type was read out of the deployment name, which is `-x-` only when you did not choose a name yourself. Call an instance `my-training-box` and the email announced a GPU called `MY`. It uses the stored GPU type now, formatted the way the dashboard formats it, so the mail says `L40S PCIE`. * **Cards in a grid no longer wear a pale band.** The card border is a padded wrapper, so the shortest card in a stretching row left a hairline of it uncovered along the bottom. * **Instance and volume rows use one button.** Each action row built its own, so a row could hand off to a confirmation dialog styled like a different product. Both rows use the same button at one height, so labelled buttons and icon triggers cannot drift apart. * **The SSH step gives its space to the fields.** The upload zone, the key fields, and the empty volumes state gave their largest blocks of space to their smallest jobs. ### `v1.27.0` • 2026-09-05 #### Stop an Instance Without Losing It > Stopping an instance used to mean destroying it. Now it parks: the GPU stops billing, the disk and everything on it stays exactly where it was, and you start it again when you want it. Restart arrives alongside, for a machine that needs a reboot rather than a rebuild. Neither is available on every provider, and the two do not line up with each other, so the controls show up only where the upstream can actually honour them. **New Features** * **Stop and Start, on the card and in the details panel.** Stop parks the machine and keeps its disk. Start brings it back with the same disk, the same contents, and the same public IP, so the connection details you saved still work. * **The stop dialog quotes both rates before you commit.** It shows what the instance costs running, what it will cost stopped, the saving as a percentage, a monthly figure for leaving it that way, and an itemised list of what is still being charged. Stopped rates are printed to four decimal places, because at two most of them round to $0.00 and read as free. * **Restart, as a reboot.** A restart reboots in place. Your billing does not change and the instance keeps its status. It is offered only where the provider has a real reboot operation, which is a different list from the providers that can stop: Spheron AI reboots and Spheron ES does not, so restart is absent on Spheron ES even though stopping works there. It is never synthesised from a stop followed by a start, because that releases the GPU and carries a completely different risk under the same label. * **Controls appear only where the provider can honour them.** Stopping is available on Spheron AI and Spheron ES, and nowhere else. On Spheron AI it also depends on the machine type and the region: roughly half of one upstream's catalog cannot hibernate, and one region refuses to shut instances down at all. Verda and Sesterce keep charging in full for a shut down instance, so the control is absent there. The deploy summary and the instance panel say which of the three is the reason, since the remedy differs: another machine type, another region, or another provider. * **A warning where starting again depends on stock.** Some providers release the hardware while an instance is stopped, so a start can be refused while that machine is out of stock. The dialog says so before you commit, and how strongly depends on the provider. A refusal is not destructive: the instance and its disk stay as they are and you try again when stock returns. **Billing** * **A stopped instance is billed for its disk, not its GPU.** The stopped rate comes from the provider, read back from the upstream where it publishes one and quoted from the live pricebook where it does not. It covers the retained disk, plus the public IP where the provider charges for one. Any discount on your account applies exactly as it does while running. * **The switch is settled at the rate you were on.** Charges run on a five minute cycle, so a stop landing mid-cycle would otherwise bill the whole slice at whichever rate happened to be stored when the cycle fired. Stopping and starting both settle the elapsed time at the outgoing rate first. Usage figures, invoices, and the billing page pick stopped periods up with no change. * **A stop from the provider's side is billed as a stop.** When a provider parks your machine, the dashboard says stopped and you are charged the stopped rate. Previously the instance read as running at the full rate for hours and then vanished as a termination while the VM was still alive upstream. Where the stopped rate cannot be determined you are charged nothing rather than guessed at. **Reliability** * **A stopped instance is not cleaned up as an orphan.** Several sweeps decided what was alive from a list that meant running or deploying only. A stopped instance would have been destroyed about fifteen minutes in. * **Rebooting is no longer mistaken for a preemption.** A reboot looks exactly like a stop from outside, and the existing protection covered dedicated instances only, so restarting a spot instance would have destroyed it. A restart now arms a guard that covers the boot, and the dashboard leaves RESTARTING as soon as the machine reports back rather than waiting out a fixed window. * **A deliberate stop is never stalled out.** A machine wedged in a stopped state is closed out after three hours, which is right for a stuck VM and wrong for one you parked yourself. A stop you asked for is exempt. A provider side stop still starts that clock, so nothing can sit there forever. * **A start no longer bounces back to stopped.** A freshly started instance can still report as stopped for a cycle or two, which read as the provider having parked it and flipped the instance straight back. The provider is believed only when it reports a settled state, and never in the tail of a start we asked for. * **A stop still in progress is not reported as a failure.** Writing a machine's memory to disk routinely outlives the request, so a timeout usually means the work was accepted and is still running. It now says the request went through and to check back. * **Failures say what went wrong.** A failed stop or start carries the provider's own words where they are safe to show, for example that a machine type has no hibernation or that an instance has not finished stopping yet. The full cause is logged with the deployment, instance, provider, and region. **UX Improvements** * **Buttons that would fail are not offered.** Stopping and starting take minutes upstream, and the provider refuses the opposite action throughout. The control reads Stopping, Start, or Starting, driven by when the provider confirmed the change settled rather than by a guess, and explains the wait on hover. * **A stopped instance reads as stopped everywhere.** The badge is amber, between the running blue and the terminated grey, because a stopped instance is neither working nor gone and still costs something. The card and the details panel each carried their own copy of the rate and status logic and had drifted, so one instance could show its stopped rate on the card and the running rate, nearly ten times higher, in the panel. There is one copy now. * **Sub-dollar rates are legible.** The price tile sets dollars large and cents small, which reads well for $1.29 and inverts below a dollar: every significant digit landed in the small text and the one large glyph was a zero. A stopped instance is always sub-dollar, so a paying instance read as free at a glance. * **The public IP is shown while stopped.** The address is kept through a stop, so hiding it forced people to start an instance just to read it back. The SSH command stays hidden until the machine is running, since it will not connect otherwise. * **Destroy stays available while stopped.** Starting an instance first, purely to earn the right to stop paying for it, would be backwards. * **The stop dialog names the one way stopping can lose an instance.** A stopped instance still costs something, and a team that runs out of credit has every instance destroyed, stopped ones included. The dialog says so, and points at destroying the instance instead when you are finished with it. * **Restart asks first.** It is a hard reboot on every provider we can verify, so anything held in memory is lost. Restart confirms and says that, where stop leads with the rates because that decision is about money. **API** * `POST /api/deployments/{id}/pause`, `POST /api/deployments/{id}/resume` and `POST /api/deployments/{id}/restart` stop, start, and reboot an instance. Asking a provider that cannot do one of them returns a refusal that names the limit rather than a generic failure. * `GET /api/deployments/{id}/pause-quote` returns the current rate, the stopped rate, and the breakdown behind it, without changing anything. * `GET /api/deployments/{id}/reboot-status` reports whether a reboot is still in flight. * A stopped instance reports `status: "stopped"` and is part of the live set. It is included in `?status=active`, and `?status=stopped` narrows to the stopped ones. The unpaginated listing filtered on an exact status match, so a stopped instance disappeared from the live set without appearing in the terminated one. ### `v1.26.0` • 2026-08-13 #### Light Mode > The whole console can now be read on a light background. Choosing the theme meant walking every page, so a long list of smaller repairs came with it. **New Features** * **Light mode, with the switch in the sidebar.** Sit the console on paper instead of black. Your choice is remembered and applied before the first paint, so a page no longer flashes the wrong theme while it loads. The switch is in the sidebar whether or not you are signed in, and on a phone it sits in the navigation drawer. **UX Improvements** * **One card for your discount.** The Discounts section on Billing stated the same code, percentage, and expiry twice. It is one card now. * **The redeem box is offered only when a code can be redeemed.** A team holds one discount at a time, but the form took a code anyway, called it valid, and then failed. While a discount is running, the section names the code and the date you can redeem another. * **Attached volumes and attached instances match.** The two lists describe one relationship from opposite ends and were drawn differently. They share a layout now: volume rows gained the status badge they were missing, and instance rows gained the hourly rate. * **Copying confirms itself.** Copy buttons in the instance panel wrote to the clipboard silently, so nothing distinguished a copy from a dead button. They confirm the way the volume panel already did. * **vCPU counts are labelled vCPU.** The instance panel quoted a vCPU count in cores, which is a different unit. * **Docs reachable before you sign in.** The link sat in the navigation bar only once you had an account. **Bug Fixes** * **The copy icon no longer disappears when you point at it.** Hovering anywhere on a card turned the icon the colour of the button beneath it. * **Badges no longer react to the pointer.** Every status chip lit up on hover as though it could be clicked. None of them can. * **Destroy and delete warnings are readable.** The warning panel on those confirmations filled with a strong pink that pulled its own text to an uncomfortable contrast. * **Wizards fit an iPad again.** At 1024px the deploy pages split to seat the order summary while the catalog kept the column count it chose for a full window. GPU offer cards, provider cards, and the reserved GPU heading were all squeezed, and the heading broke across four lines. * **Back buttons sized on mobile.** Previous in the volume and reserved GPU wizards sat at content width beneath a full width primary button. * **Voltage Park removed from the API reference.** The docs listed a provider that is no longer offered, along with the Kubernetes add-on that ran only on it. ### `v1.25.3` • 2026-08-11 #### Keep Your Filters > Everything you set in the catalog toolbar survives a refresh and travels in the link. **New Features** * **Filters persist and can be shared.** Your search, sort, providers, and regions are kept in the address bar. Refreshing keeps the view you were looking at, and the link you copy opens the same filtered catalog for a teammate. Only what you changed appears in the link. **Bug Fixes** * **Search matches the name on the card.** Any search containing a space came back empty, so searching a full name such as `H100 SXM5` found nothing. Search now matches the name shown on the card, so multi word searches work. * **Collapse label sized like the rest of the sidebar.** The Collapse control at the bottom of the sidebar was set smaller and in a different face from API Docs and Changelog above it, so it read as a heading rather than the third item in the list. ### `v1.25.2` • 2026-08-11 #### Deployment Emails, Volume Attach and Detach > Deployment emails reach the people who asked for them, attaching and detaching a volume shows up straight away, and the catalog lists every provider again. **Bug Fixes** * **Deployment emails are sent to everyone who opted in.** Users who had turned on deployment notifications were not receiving them. Notification preferences are now honoured when a deployment succeeds or fails. * **Attach and detach show immediately.** After attaching a volume to an instance, or detaching it, the volume panel kept showing the previous state until the page was reloaded. It updates as soon as the change completes. * **Instances are named in the attach picker.** Choosing an instance to attach a volume to listed entries that were hard to tell apart. Each option now names the instance and what it is. * **All providers listed in the catalog filter.** The provider filter could show only Spheron AI while offers from other providers were visible in the catalog behind it. Every provider with live offers is listed again. * **Deployment progress heading readable.** The heading on the deployment progress card sat too dark against its own background to read comfortably. ### `v1.25.1` • 2026-08-10 #### Monthly Costs and a Tidier Interface > The order summary quotes a month rather than a week, and the instance and volume panels have been evened out. **UX Improvements** * **Costs quoted per month.** The order summary projected spend for a week, which is rarely the unit anyone budgets in. It now quotes a full month, calculated from the hourly rate. * **Usage on one line.** Instance usage was spread over several rows in the details panel and now reads as a single compact line. * **Consistent panel typography.** Headings and body text in the instance and volume panels were larger than the rest of the interface and did not match each other. Both panels now use the same sizes. * **Square corners throughout.** Several panels kept rounded corners that did not match the rest of the interface. * **Cleaner copy.** Punctuation in the marketplace text has been made consistent. **Reserved GPUs** * **Reservation requests are for bulk capacity.** Reserved GPU requests now hold to a minimum quantity, so the form reflects what a reservation is actually for. ### `v1.25.0` • 2026-08-09 #### Not Every Job Needs a GPU > Some workloads just need cores. Build steps, data prep, schedulers, API workers, control planes: none of them touch a GPU, and until now you had to rent one anyway. CPU Node has its own page in the sidebar, its own wizard, and prices from $0.09 per hour. **New Features** * **A Deploy CPU page.** CPU Node sits in the sidebar under Compute, next to Deploy GPUs, and opens whether or not you are signed in. There is no catalog to page through and nothing to search for. Every provider's CPU offer collapses onto a single option, so the page selects it for you and goes straight to the configuration. * **Configuration first.** Step 1 asks for spot or dedicated, then the provider, then the instance size, then the region and operating system. GPU count, cluster networking, and the deployment type picker are absent, because a CPU node has no answer for any of them. Step 2 is unchanged: the SSH key, startup script, volumes, and order summary are the same ones the GPU wizard uses, so the two flows cannot drift apart. * **Every CPU size in one place.** CPU Node collects the CPU instances from Verda, Spheron AI, and Sesterce into a single option rather than one entry per provider. Sizes run from 4 vCPU with 4 GB of memory up to 360 vCPU with 1440 GB, and the wizard shows the lowest available price for each size before you commit. * **Spot pricing on CPU.** Verda CPU instances are available at spot rates as well as on demand, currently from $0.09 per hour. The spot and on demand toggle works exactly as it does for GPU offers. * **Regions.** CPU Node is available in Finland 1, Finland 2, and Finland 3 on Verda, Norway 1 and Canada 1 on Spheron AI, and Austin, Oslo, and Montreal on Sesterce. Availability varies by size and region, and the wizard only offers sizes that a region can actually serve. **UX Improvements** * **The GPU catalog lists GPUs only.** CPU Node is deployed from its own page, so the catalog asks the server for GPU offers rather than filtering them out after they arrive. The result count and the number of pages are honest again. * **No GPU driver images on a CPU instance.** The operating system list for a CPU node offered CUDA and other GPU driver images that cannot be used without a GPU. Only images that make sense on a CPU instance are listed. * **CPU instances state their size.** Where a GPU instance names its model, a CPU instance names its vCPU and memory. This applies on the offer card, in the configuration and order summaries, on the instance card, in the details panel, and in the confirmation shown before terminating an instance. GPU count and video memory are left out entirely rather than shown blank. * **Hardware is marked by an icon.** Instance cards carry a mark for the hardware they run on, so a CPU node and an accelerator can be told apart at a glance. * **Even specification grid.** The machine configuration panel left gaps where a value was missing. It now lays out as a consistent grid. * **Topping up mid deploy brings you back to Deploy CPU.** If your balance is short, the configuration you had built is held while you top up and restored when you return, the way it already worked for GPUs. **Bug Fixes** * **Two choices made at once no longer overwrite each other.** Every selection in the deploy wizard rewrote the whole configuration from a copy taken earlier in the render, so when two selections landed together one of them was dropped. A step's own default is applied before the page's, which meant the dropped one was reliably yours. Each choice now writes only the field it changed. * **A deliberate choice of Spot is never overridden.** Where an offer is sold both ways, a default now fills an empty selection only. Where an offer is sold one way, a selection that cannot be deployed is still corrected for you. * **The signed out wizard no longer flickers.** Moving between the GPU and CPU pages while signed out wrote to browser storage in a loop. It settles at once now. **API** * `GET /api/gpu-offers` lists CPU Node alongside the GPU offers, as a single row with `gpuType: "CPU"` and `displayName: "CPU NODE"`. Narrow the catalog to that row with `?search=cpu`. Every entry in its `offers` array reports `gpuCount: 0` and carries the `offerId` a deployment takes, along with `vcpus`, `memory`, `storage`, `price`, `os_options`, and the region in `clusters`. * `POST /api/deployments` accepts CPU offers. Send `gpuType: "CPU"` with `gpuCount: 0`. Deployments created this way are stored with the same values, so responses and usage records report a CPU node rather than an unnamed GPU. ### `v1.24.1` • 2026-07-30 #### Rates That Track the Provider, Plus Deploy Wizard Fixes > Your hourly rate now follows the provider's price for the whole life of an instance, not just at launch. Deploying a GPU alongside a volume no longer fails with a region you never picked, spot configurations are priced on the rate you actually pay, and the setup you return to after adding balance is re-checked against live offers. **Billing** * **Rates Track Current Provider Pricing:** Your hourly rate now stays in line with the provider's current price for a GPU you are already running. Previously this applied on only some providers, so an instance could hold its launch-day rate for its entire life even after the underlying price moved. Charges are calculated from the point the price changes onward, so usage you have already been billed for is never recalculated, and any discount on your account continues to apply **Bug Fixes** * **Correct Region When Deploying With a Volume:** Setting up an instance and a volume in the same region could fail with an error naming a region you never selected, for example reporting an offer in `EU North 1` when everything was set to `EU West 1`. This happened when two regions shared the same price. The wizard now keeps your selected region and the selected configuration in step, on Spheron ES and Verda alike * **Cheapest Spot Region Selected by Default:** Spot configurations were ranked using the on-demand price rather than the spot price you are billed. The region chosen for you was not always the cheapest, and the region list could appear out of order against the prices shown next to it. Both now use the spot price * **Setup Re-Checked When You Come Back:** After adding balance or signing in part-way through setup, the wizard could still show the price and availability from when you started. Your configuration is now re-checked against live offers when you return, so the order summary matches what you are charged. If the provider has withdrawn that configuration in the meantime, you are told directly instead of finding out when the deploy fails *** ### `v1.24.0` • 2026-07-14 #### Reboot-Proof Dedicated GPUs, Earlier Low-Balance Warnings & B300 on Spheron ES > A dedicated GPU that reboots on the provider side now stays alive and recovers on its own, instead of being torn down while you are still using it. Low-balance warnings start hours earlier, Spheron ES adds B300 GPUs with visible memory specs, and a malformed SSH key now fails fast with a clear message. **Expansion** * **B300 Now on Spheron ES:** Spheron ES offers now include the B300 SXM. It is identified correctly in the deploy wizard, on GPU cards, and in the API, instead of surfacing under an unrecognized name * **GPU Memory on More Offers:** Every Spheron ES and Spheron AI offer now shows its per-GPU memory (VRAM) on the GPU cards and in the order summary, matching the other providers. Offers that previously left memory blank now display it **Reliability** * **Dedicated GPUs Survive Provider Reboots:** When a dedicated GPU instance reboots on the provider side and briefly reports as stopped or offline, it is no longer terminated automatically. It stays running and recovers on its own once it comes back online, so a routine provider reboot can no longer destroy a machine you are still using. Spot instances keep their existing behavior * **Cleaner Handling of Stuck Spheron ES Instances:** On Spheron ES, a dedicated instance that never actually started, or that stays stopped for an extended period, is now cleaned up instead of lingering, while genuine short reboots keep the instance alive * **Steadier Sign-In:** Fixed a rare sign-in failure that could hit a brand-new account created from two near-simultaneous requests. Returning to the app after a page refresh is also faster, because it no longer re-runs the full sign-in flow **Notifications** * **Earlier Low-Balance Warnings:** Low-balance warnings now begin sooner, at roughly 12, 6, and 3 hours of estimated remaining runtime, on top of the existing 1 hour, 30, 15, and 5 minute alerts. You get more lead time to top up before your instances are affected, and the balance-exhaustion notice is unchanged **API** * **Clear Error for Invalid SSH Keys:** Creating a deployment with an `ssh_public_key` that is not a string (for example an object) now returns a `400` error that names the problem up front, instead of a generic provider failure reported after a dead deployment record was already created. Valid keys are unaffected *** ### `v1.23.0` • 2026-06-30 #### Faster Dashboards, Automatic Deposit Recovery & Consistent Rate Limits > Your billing, instances, and volumes pages now load noticeably faster, deposits that get stuck pending are recovered or cleared on their own, and API rate limits are enforced consistently no matter how busy the service is. **UX Improvements** * **Faster Billing and Dashboard Loads:** The billing analytics, instances, and volumes pages now load noticeably faster, especially on repeat visits, so you spend less time waiting on spinners. Data still refreshes in the background, and if a fresh result is ever unavailable the page falls back to live data, so what you see stays accurate **Reliability** * **Automatic Recovery of Stuck Deposits:** If a credit deposit you paid for ever gets stuck in a pending state because a confirmation was delayed or missed, it is now detected and credited to your balance automatically, with no need to contact support. Deposits that were genuinely abandoned or expired are cleared from your history instead of lingering as pending forever. Automatic top-ups are unaffected and keep their own retry behavior **API** * **Consistent Rate-Limit Enforcement:** API rate limits are now enforced consistently across the entire service. The documented limits hold accurately even under heavy concurrent traffic, so requests above a limit are reliably throttled instead of occasionally slipping through *** ### `v1.22.0` • 2026-06-17 #### Email Notification Controls, Time-Based Low-Balance Alerts & Billing Fixes > You now decide which marketing emails you receive, while account and billing emails always reach you. Low-balance warnings tell you how much runtime you have left instead of a flat dollar figure, and expired volume discounts correctly drop back to the standard rate. **New Features** * **Email Notification Preferences:** A new Notifications tab in Settings lets you turn marketing emails on or off. You are subscribed by default. Flip the toggle off and you stop receiving product and offer emails, while account and billing emails (deployment status, low-balance warnings, payment receipts) keep coming. Those essential emails are always on and the toggle does not affect them * **One-Click Unsubscribe:** Every marketing email now carries an unsubscribe link that opens the Notifications tab directly, along with a short note explaining why you received it **Notifications** * **Time-Based Low-Balance Alerts:** Low-balance and balance-exhaustion warnings are now based on how much runtime you have left, not a fixed dollar amount. Spheron estimates your remaining time from your balance and current hourly burn rate, then warns you as you cross roughly 60, 30, 15, and 5 minutes of runtime. The same alert now means the same thing whether you run a single small GPU or a large cluster **Bug Fixes** * **Expired Volume Discounts Revert:** When a team's discount expires, volumes now return to their standard hourly rate on the next billing cycle, the same way instances already did. Previously an expired discount could keep applying to a volume's billed rate after it had lapsed *** ### `v1.21.6` • 2026-06-04 #### Out-of-Stock Notify-Me for Spot GPUs & Cleaner GPU Cards > Out-of-stock notify-me now covers spot GPUs too, so a sold-out spot configuration sends you to the Notify CTA instead of a dead form. The same GPU no longer splits into duplicate cards, and the order summary now shows GPU memory. **Notify-Me for Spot** * **Spot Out-of-Stock Cards:** When a spot GPU is fully out of stock, the deploy wizard now hides Region and OS and shows the same Notify CTA you already get for dedicated GPUs, instead of dropping you into a half-configured flow that reported "No OS options available for this region" * **Surfaces Right Away:** Spot configurations that had already sold out now show the Notify CTA immediately, with no waiting for the next stock refresh **Cleaner GPU Cards** * **No More Duplicate Cards:** The same GPU no longer fragments into duplicate cards or shows a doubled form-factor suffix. Listings like "A100 80G SXM4 SXM4", or "A30" and "A30 PCIE" appearing as two separate cards, are now collapsed into one * **Sold-Out Counts Stay Actionable:** When a specific GPU count on Verda is out of stock, the wizard keeps the Notify-me CTA reachable and hides the storage selector, instead of dropping you into a dead configuration flow * **GPU Memory on the Order Summary:** The order summary now shows each GPU's VRAM next to its name * **Accurate Availability Header:** The available and guaranteed header copy now tracks live capacity, so it agrees with the GPU Count and Region sections *** ### `v1.21.5` • 2026-06-02 #### Accurate GPU Pricing & Broader SSH Key Support > GPU prices in the deploy wizard and the API now reflect the right offer, with no sold-out offer undercutting the best available price. Deploys with ECDSA and FIDO security keys now work on Massed Compute and Verda. **Accurate Pricing** * **Correct Spot and Dedicated Counts:** Spot and dedicated offers are no longer double-counted against each other, so the lowest spot price, lowest dedicated price, and availability counts are accurate * **Best Available Price Ignores Sold-Out Offers:** The best-price figure on a GPU card now comes from in-stock offers only, so a stale out-of-stock price can no longer win and mislead you * **Cleaner Public API:** `GET /api/gpu-offers` no longer returns internal out-of-stock offers. Existing fields are unchanged, so existing integrations keep working **Broader SSH Key Support** * **ECDSA & FIDO Keys Now Work:** Deploying to Massed Compute or Verda with an ECDSA (`ecdsa-sha2-...`) or FIDO security key (`sk-ssh-ed25519@openssh.com`, `sk-ecdsa-...`) now succeeds. Previously only RSA and Ed25519 keys were accepted and other types failed with "SSH Key does not exist". Spheron AI, Spheron ES, Sesterce, and Voltage Park already accepted every key type *** ### `v1.21.4` • 2026-06-02 #### Billing: Cost-Saving Intelligence & Spend Visibility > The billing page is now an actionable cost dashboard. See where you can save against other providers and the big hyperscalers, spot idle resources, and track spend trends and anomalies at a glance. **Cost-Saving Signals** * **Cross-Provider Price Comparison:** Each deployment row shows whether you are on the cheapest provider for that GPU, or how much more you are paying per hour than the cheapest option (`+$X/hr vs `) * **Hyperscaler Comparison:** A line under each deployment compares your Spheron rate against AWS, GCP, and Azure list prices, with the percentage you are saving * **Long-Running and Idle Flags:** An amber chip marks deployments running 7+ days, a callout flags volumes left unattached for 30+ days, and volume rows now show the cost accrued so far **Spend Visibility** * **Daily Spend Trend:** A sparkline of daily spend across the selected period, so trends are visible at a glance * **Spend Breakdown:** Mini-charts break your spend down by GPU model, by provider, and by spot versus dedicated * **Blended Rate and Month Projection:** New cards show your blended cost per GPU per hour and a projected total for the current month * **Top Spenders and Reserved Hint:** A top-three deployments-by-spend callout, plus a hint when a GPU type's spend suggests a reserved commitment could save you money **Discounts and Anomalies** * **Discount Savings:** A running total of what your active discounts have saved you across the period * **Spend Anomaly Alert:** An amber banner when a single day's spend spikes far above your recent average *** ### `v1.21.3` • 2026-05-29 #### Out-of-Stock Notify-Me Cards, Interconnect Display & UX Polish > Sold-out GPUs now stay on screen as notify-me cards instead of disappearing, the GPU spec strip shows the interconnect bus, and a few rough edges around volume errors and confirmation dialogs are smoothed out. **Out-of-Stock Notify-Me Cards** * **Sold-Out GPUs Stay Visible:** Across Verda, Massed Compute, Spheron ES, Sesterce, and Voltage Park, out-of-stock GPUs now appear as dimmed "Out of stock" cards with a Notify-me CTA, instead of vanishing from the wizard * **Sold-Out Offers Carry Forward:** Offers that briefly disappear upstream are remembered for up to 7 days, so a sold-out GPU still surfaces as a notify-me card rather than dropping off the marketplace entirely **Interconnect Display** * **Bus on the Spec Strip:** GPU cards now show the interconnect bus (NVLink, SXM, or PCIe) on the spec strip, so you can pick the interconnect that matches your workload * **Clearer NVLink Labels:** NVLink-bridged GPUs are flagged consistently, and NVL models no longer carry a redundant "PCIE" suffix in their title * **RTX PRO 6000 Corrected to Blackwell:** The RTX PRO 6000 now reads as Blackwell architecture, so you install the right driver **UX Polish** * **Dialogs Behave as Expected:** Confirmation dialogs now dismiss the way you expect, closing when you click outside them just like every other modal in the app, so they no longer trap you when you click away. They still stay open while an action is in progress, so you cannot dismiss one mid-operation *** ### `v1.21.2` • 2026-05-26 #### Billing & Volume Reliability > Auto top-up now gets a chance to recover your balance before any instance is terminated for low credit, and a terminated instance's volumes return to Available instead of staying stuck, so you can reattach them. **Billing** * **Auto Top-Up Recovers Before Termination:** When your balance runs low, auto top-up is given time to charge your saved card and restore credit before instances are terminated. A momentary dip no longer costs you a running deployment **Volumes** * **Volumes No Longer Stick to Terminated Instances:** When an instance is torn down, its volumes return to Available so you can reattach them right away, instead of staying marked Attached to an instance that no longer exists *** ### `v1.21.1` • 2026-05-24 #### Confidential Compute on Verda RTX PRO 6000 > Verda's RTX PRO 6000 now offers a Confidential Compute variant that keeps your VM and GPU memory encrypted while in use. **New** * **Confidential Compute Variant:** Verda's RTX PRO 6000 now lists a separate Confidential Compute (CC) option alongside the standard card, so you can choose it directly in the deploy wizard * **Confidential Compute Notice:** When you select the CC variant, the order summary explains that VM and GPU memory are encrypted in use and isolated from the hypervisor and the cloud provider itself *** ### `v1.21.0` • 2026-05-21 #### Mobile-Responsive Marketplace: Sidebar Drawer, Fluid Layouts, and Polished Wizards > The marketplace is now usable on a phone. The desktop sidebar collapses behind a hamburger drawer on small screens, the deploy wizard reorders so the order summary stays in view above the form, instance and volume detail panels open full-screen on mobile, and every page (billing, API docs, volumes, settings, top nav) has been retuned so cards, headers, and dialogs reflow without horizontal overflow. **Mobile Navigation** * **Hamburger Sidebar Drawer:** On phones and small tablets the persistent sidebar is replaced by a hamburger button in the top nav. Tapping it slides a full nav drawer in from the left with an overlay dim. Tapping the overlay, hitting a nav item, or navigating away closes it. Background scrolling is locked while the drawer is open * **One Source of Truth for Nav Links:** Desktop sidebar and mobile drawer now share the same nav definition, so a route added in one shows up in both * **Resize-Aware:** Resizing the window from mobile to desktop closes the drawer, restores the desktop sidebar, and re-applies the layout without a reload **Deploy Wizard on Mobile** * **Order Summary at the Top:** On mobile the order summary now stacks above the configuration form (instead of being pinned to the right rail) so the running price and selected GPU stay visible without scrolling back up * **Full-Width Step Buttons:** Next, Back, and Deploy buttons go full-width on mobile. The Back/Deploy pair stacks vertically with Deploy on top, so the primary action is always under your thumb * **Truncating GPU Cards:** GPU offer cards truncate long titles and the results counter clips its parenthetical detail on narrow screens, so cards no longer push the layout sideways **Instance and Volume Detail Drawers** * **Full-Screen on Mobile:** Tapping an instance or volume card now opens its detail panel as a full-screen sheet (instead of a fixed-width side drawer that ran off the viewport). The panel reverts to the familiar right-side drawer on tablet and desktop * **Safer Height on iOS:** Detail drawer height now accounts for Safari's dynamic address bar, so the bottom of the content is no longer covered **Billing, API Docs, and Volumes** * **Billing Page Reflow:** Balance cards, deposit packages, and the mini-metrics grid now stack cleanly on small screens, step up to a tighter grid on tablets, and keep the full layout on desktop. The tabs row scrolls horizontally on narrow screens instead of wrapping, and the saved-card section reflows for small viewports * **API Docs Reflow:** Endpoint accordions, curl commands, the base URL section, and the quick-test panel all reflow on mobile without horizontal scroll. Long URLs and code blocks now wrap or scroll inside their cards * **Volumes and Instances Pages:** Page headers, load-more buttons, attach/detach dialogs, and the create-volume wizard reflow for mobile widths. The load-more button is full-width on mobile and capped to a comfortable size on tablets and up **Miscellaneous Polish** * **Top Nav:** Logo, balance display, team switcher, deposit dialog, and user menu all retuned for narrow viewports so the bar stays single-line without overflow * **Feature Announcement Modal:** Modal width adapts to the viewport on mobile instead of bleeding off the edge * **Wizard Headers:** Pipe separators between header chips are hidden on narrow screens so you no longer see orphaned `│` characters * **Reserved GPU Wizard, SSH Keys, Team Overview, GPU Alerts, Usage Analytics:** All retuned to flow into a single column on mobile with appropriately stacked actions and headers **Accessibility** * **Drawer Trigger:** The hamburger button now announces whether the drawer is open or closed for screen readers * **Defensive Rendering:** The credit-package grid now guards against an empty package list, so an empty config never throws while the page is mid-render *** ### `v1.20.0` • 2026-05-15 #### GPU Availability Alerts, Smarter Stock Signals & Faster Capacity Refresh > Never refresh the marketplace waiting for a GPU again. Subscribe to a sold-out GPU configuration directly from the deploy wizard and Spheron emails you the moment that exact GPU, count, and instance type is back in stock. The wizard now lets you navigate sold-out variants instead of hiding them, Spheron ES regions surface live stock signals before you commit, Spheron AI multi-GPU placements stay hidden while supply is too thin to deploy, and stock-out errors anywhere on the marketplace clear from the catalogue immediately instead of trailing the next user. **New Features** * **GPU Availability Alerts:** Subscribe to a sold-out GPU configuration directly from the configure step in the deploy wizard. You receive an email the moment that exact configuration (GPU type, count, provider brand, spot or dedicated) is back in stock. An optional price ceiling keeps the email scoped to your budget so you only get pinged when the offer is actually affordable * **Alerts Tab in Settings:** A new Alerts tab under Settings lists every alert you have ever created. Unsubscribe a pending alert with one click, or Resubscribe a previously notified alert if you missed the window the first time * **Brand-Wide Alert Coverage:** An alert scoped to a brand fires when any region under that brand has matching capacity. You do not have to pick a specific region to subscribe; one alert covers the entire brand * **Navigate Sold-Out Configurations in the Wizard:** Sold-out GPU configurations now appear in the deploy wizard as dimmed cards instead of being suppressed entirely. Click through to inspect the count, networking, and provider options that are temporarily unavailable, then either subscribe to an alert or pick a live alternative without restarting the flow **UX Improvements** * **Per-Region Stock Signals on Spheron ES:** The region picker in the deploy wizard now shows a tiered stock pill (high, healthy, low, critical) next to each Spheron ES region, so you can see how thin supply is before committing to a region * **Spheron ES Spot Listings Hide Low-Stock Configurations:** Spheron ES spot offers with too little stock to deploy reliably are no longer listed. This removes the failure path where a listing claimed availability but the deploy refused to allocate * **Spheron AI Multi-GPU Stock Floor:** Spheron AI 4x and 8x configurations are only listed when the region has enough stock to fulfil them. Below the floor the configurations are hidden, so you no longer pick a placement that fails at create time * **Collapsible Sidebar with Persisted State:** The navigation sidebar now collapses to an icon rail and remembers its state across reloads. Tooltips appear on hover when collapsed, so you can reclaim horizontal space for the dashboard, instance cards, and the deploy wizard without losing navigation * **Reserved GPU Catalogue Updates:** The reserved GPU catalogue now includes R100 and GH200, and the GPU memory field is optional on request submissions **Reliability** * **Faster Capacity Detection on Dedicated Offers:** Dedicated GPU availability now refreshes every 5 minutes, so the deploy wizard and dashboard reflect real stock within minutes of an inventory change. When a pending alert exists, the marketplace forces an early refresh so the email lands while capacity is still live * **Cache Refresh on Stock-Out Errors:** Deploy failures that signal out-of-stock now invalidate the marketplace's offer cache immediately. The next user no longer sees a just-sold-out GPU listed as available while the cache walks down its TTL * **Availability Alert Emails:** Notification emails include a per-region capacity breakdown with brand labels, are tone-shaped for spot vs dedicated copy, and ship in both HTML and plain-text bodies so they render correctly in every client *** ### `v1.19.0` • 2026-05-11 #### Spheron ES (Spheron Extra Supply) Provider Launch, Spot Reliability & Faster Deployment Status > Meet **Spheron ES** (Spheron Extra Supply), a new GPU provider on the marketplace with B200 SXM6, H100 SXM5, H200 SXM5, L40S, and RTX Pro 6000 across Finland, France, Middle East, and the United States. Both on-demand and spot are supported, and persistent volumes ship on day one with multi-instance attach, in-place resize, and a 256 TiB ceiling per volume. Alongside the launch, spot deployments now stay correctly labelled across the dashboard, preempted instances are reaped in seconds instead of minutes, and freshly created deployments flip to "Running" the moment the VM is live. **New Provider** * **Spheron ES (Spheron Extra Supply):** A new GPU provider is now live on the marketplace. Inventory currently spans B200 SXM6, H100 SXM5, H200 SXM5, L40S, and RTX Pro 6000 * **On-Demand and Spot:** Both instance types are available. Spot offers the same GPU configurations at a lower price with no uptime guarantee * **Multiple Regions:** Spheron ES regions span Finland (EU North 1), France (EU West 1), Middle East (ME West 1), and the United States (US Central 1). They show up in the deployment and volume wizards, and in regions listings on the API * **Country Filter Picks Up New Regions:** The country filter in the deployment wizard correctly groups EU North under Finland, EU West under France, and ME West. * **Tier 3 DC Compliance Badge:** Spheron ES is flagged with the same Tier 3 DC compliance badge as the rest of the family **Persistent Volumes on Spheron ES** * **Volumes on Spheron ES:** Spheron ES is a supported volume provider from day one. Create and manage persistent storage from the `/volumes` dashboard with the same UX as the existing volume providers * **Multi-Instance Attach:** A single Spheron ES volume can be attached to multiple instances at once, so a dataset can be fanned out across a cluster without duplication * **Attach at Deploy Time Without Restart:** Pick a Spheron ES volume in the deployment wizard and it is wired into the instance before the VM boots. No post-boot mount step, no restart * **Hot-Attach and Hot-Detach Supported:** Attach or detach a volume on a running instance from the dashboard or API. The instance briefly stops and restarts to apply the change; data is preserved * **In-Place Resize:** Grow a Spheron ES volume after creation without recreating it or migrating data (shrinking is not supported) * **Up to 256 TiB per Volume:** Spheron ES volumes can be created up to **256 TiB** in a single volume (`sizeInGb: 262144` on the API). The size slider in the wizard adapts to match * **Volume Rules Dialog for Spheron ES:** The "Volume Rules" dialog accessible from the create-volume and attach flows now covers Spheron ES, spelling out the at-deploy attach, restart-on-hot-attach behaviour, multi-attach semantics, resize policy, and the no-rename restriction * **Mount Tag on the Volume Card:** Each Spheron ES volume card now shows the mount tag for shared-filesystem volumes with a one-click copy, so you can grab it without opening the detail panel **Reliability & UX** * **Spot Type Preserved End-to-End:** Spot deployments created via the API or dashboard are now consistently labelled "Spot" on the instances page and across deployment responses. Previously a spot VM could fall through to "Dedicated" in the dashboard when the client did not pass `instanceType`. Commission, billing, and the instance card badge all derive the type from the offer catalog now * **Faster Status Flip on New Deployments:** Newly created deployments now flip from "Deploying" to "Running" within seconds of the VM coming online, instead of the previous 30-90 second wait. The runtime counter on the dashboard tracks usage accurately from the first second * **Faster Preemption Detection:** Spot instances that get preempted are now detected within \~10 seconds (one monitor cycle), down from the previous \~30 seconds. This shrinks the window where you might still be charged for a preempted VM's allocated disk and IP * **Orphan VM Cleanup for Failed Spot Starts:** If a spot VM is preempted or fails to ever reach Running (for example when capacity is exhausted mid-create), the upstream VM is now reliably destroyed during cleanup. Previously the deployment was marked terminated on the marketplace side but the VM could linger and continue billing for disk and IP allocation * **Safer Concurrent Volume Operations:** Attaching and detaching volumes back-to-back on the same instance is now race-safe. The instance monitor no longer flips a healthy VM to "Terminated" if it observes a transient stopped state during a hot-attach or hot-detach cycle **API** * **New `provider: "spheron-es"` Value Accepted:** `POST /api/volumes` and `POST /api/deployments` now accept `spheron-es` alongside the existing brand values. Use `GET /api/gpu-offers?providers=spheron-es` (note: `providers` is plural and comma-separated) to list GPU offers, and `GET /api/volumes/regions?provider=spheron-es` to discover regions at runtime * **Storage Pricing on Spheron ES:** `GET /api/volumes/pricing?provider=spheron-es` returns the current hourly rate per GB. The endpoint accepts an optional `region` parameter for forward compatibility, but Spheron ES rates are currently flat across all regions * **Multi-Instance Attach on `POST /api/volumes/{volumeId}/attach`:** Spheron ES volumes can be attached to multiple deployments concurrently. Each successful call adds the deployment to `attachedToDeploymentIds`; the same volume id can be reused on a different deployment without detaching first * **`volumeIds` Wired in at Create:** When `volumeIds` is passed to `POST /api/deployments` for a Spheron ES deployment, the volumes are mounted as part of the create call rather than after the VM reaches Running. The response returns with the volume already marked attached * **Volume Size Ceiling for Spheron ES:** `POST /api/volumes` accepts `sizeInGb` up to `262144` on Spheron ES (256 TiB). Read `maxSizeGb` from `GET /api/volumes/regions?provider=spheron-es` for the current cap * **Correct `instanceType` on Deployment Responses:** `GET /api/deployments` and `GET /api/deployments/{deploymentId}` now return the correct `instanceType` for every deployment even when the client did not pass the field on create. The value is derived from the offer catalog and resolves to one of `SPOT`, `DEDICATED`, `BARE_METAL`, or `CLUSTER`. Existing fields are unchanged so existing integrations continue to work *** ### `v1.18.0` • 2026-05-07 #### More Spheron AI GPUs, More Regions, Per-Region Storage Pricing > Spheron AI now ships with more GPU choices, more regions, and a larger storage ceiling. The volume wizard adapts size limits and price to the region you pick, region names read clearly across the dashboard, deployment failure messages are easier to act on, and Verda and Voltage Park now show the same post-create rules modal that Sesterce and Spheron AI already had. **Expansion** * **More Spheron AI GPUs:** Spheron AI offers now span a wider GPU lineup, including new H100 (SXM5, NVL, PCIE), A100 80GB (NVL, PCIE), A6000, RTX 4090, RTX 5090, L40, and L40S options. They appear in the deployment wizard and on `GET /api/gpu-offers` automatically with no client changes * **More Spheron AI Regions:** Two new regions are available alongside Canada 1 and Norway 1: **Montreal 1** and **Oslo 1**. They show up in the deployment and volume wizards, and in regions listings on the API * **Larger Volume Ceiling:** Spheron AI volumes can now be created up to **50 TB** in the new regions (up from 40 TB). The wizard adjusts the size slider's maximum based on the region you pick **UX Improvements** * **Friendlier Region Names:** Region picks across the deployment wizard, volume wizard, instance cards, and volume cards now display as "Canada 1", "Norway 1", "Montreal 1", "Oslo 1" instead of raw region codes * **Country Filter Recognises New Regions:** The country filter in the deployment wizard correctly groups the new Montreal region under Canada and Oslo under Norway * **Per-Region Storage Pricing in the Wizard:** When you change region in the create-volume wizard, the displayed hourly rate and the size slider's range update to match that region. No more clicking through and getting surprised at checkout * **Volume Created Modal for Verda and Voltage Park:** Creating a volume on Verda or Voltage Park now shows the same post-create confirmation modal that Sesterce and Spheron AI already had. Each provider's modal summarises that provider's specific attachment and lifecycle rules and offers a one-click "Deploy GPU" shortcut to jump straight into the deployment wizard * **Cleaner Failure Messages:** Deployment failure reasons and error messages across the dashboard, toast notifications, and deployment-failure emails now surface a single clean line instead of dense JSON payloads and status codes. The full original error is still retained internally for support requests **Bug Fixes & Reliability** * **Clearer Out-of-Stock Errors:** When a GPU is sold out in the chosen region, the deployment failure message now says so directly instead of returning a generic provider error * **Friendlier 409 / Conflict Errors:** Volume delete and deployment errors that come back as a 409 (the volume is still attached, or it is being released after recent activity) now show an actionable next step instead of a generic conflict message * **Region Switch Updates Size Cap:** Switching to a region with a different storage ceiling now resets the size slider correctly. Previously a stale cap could carry over from the previously selected region * **Correct Volume Size Cap Per Region:** The create-volume slider now reads the maximum size of the region you actually picked. Previously the slider showed the brand's widest possible cap (50 TB) on every region, including regions that only support up to 40 TB * **Consistent Provider Label in Errors:** Volume and deployment error toasts always show the Spheron AI label, including in a handful of rarer error paths where the wording previously slipped * **Custom Deployment Names No Longer Fail at Create Time:** Deployments created via the API with a custom `name` (containing spaces, dots, emoji, or anything beyond letters and digits) no longer fail with a name-validation error at deploy time. Your `name` is preserved exactly as you sent it on `GET /api/deployments` and on the dashboard. See the API note below for details **API** * **Per-Region Size and Pricing on `GET /api/volumes/regions`:** Each region entry now includes `minSizeGb`, `maxSizeGb`, and `hourlyRatePerGb`. If you are already listing regions, you no longer need a second call to `GET /api/volumes/pricing` to render a complete picker. Existing fields (`id`, `name`, `country_code`, `types`, `hasGpuOffers`) are unchanged * **Region-Aware Pricing on `GET /api/volumes/pricing`:** The pricing endpoint now accepts an optional `region` parameter. Spheron AI rates can vary by region, so pass the region you intend to use for an accurate rate. Calls without `region` keep returning the provider's default rate, so existing integrations continue to work * **New Spheron AI Region IDs Accepted:** `POST /api/volumes` and `POST /api/deployments` now accept `MON1` (Montreal 1) and `OSL1` (Oslo 1) as `region` values, alongside the existing `CANADA-1` and `NORWAY-1`. Use `GET /api/volumes/regions?provider=spheron-ai` to discover the full list at runtime * **Higher `sizeInGb` Ceiling:** `POST /api/volumes` accepts `sizeInGb` up to 51200 on Spheron AI's Montreal and Oslo regions (40960 on Canada and Norway). Read `maxSizeGb` from `GET /api/volumes/regions` for the per-region cap * **Cleaner `error` Bodies:** Error responses across deployment, volume, SSH key, and Kubernetes endpoints now return a short, human-readable message instead of a dense JSON envelope. Existing fields are unchanged; only the message text is tidier * **Cleaner `failureDetails` on Deployments:** `failureDetails` on `GET /api/deployments` and `GET /api/deployments/{deploymentId}` is now a single readable line on failed deployments. The classification in `failureReason` (e.g. out-of-stock, 409 conflict) is also more specific so retries and backoffs can branch on it * **Deployment `name` is Now Display-Only:** The `name` you pass to `POST /api/deployments` is treated as a display label only. It is stored verbatim and returned unchanged on `GET /api/deployments`, `GET /api/deployments/{deploymentId}`, and the dashboard. There is no longer any character or length restriction enforced at create time, so names with spaces, dots, slashes, emoji, or longer than 63 characters are accepted. Your existing integrations keep working: there are no request changes required, and existing names continue to be returned exactly as stored *** ### `v1.17.2` • 2026-05-04 #### Deployment Response: First-Class `gpuType` and `offerId` Fields > Deployment responses now return the canonical GPU type and the source offer ID as their own fields, so you no longer need to parse the legacy `gpuModelId` composite to render GPU details or correlate a deployment back to a GPU offer. **API** * **New `gpuType` field on deployments:** `POST /api/deployments`, `GET /api/deployments`, and `GET /api/deployments/{deploymentId}` responses now include a `gpuType` field with the canonical GPU type (for example `rtx-4090`, `h100`). Prefer this over splitting `gpuModelId` when rendering the GPU label. The existing `gpuModelId` field is unchanged so existing integrations continue to work. * **New `offerId` field on deployments:** The same three endpoints now also return the `offerId` used at create time, so you can correlate a deployment back to the entry from `GET /api/gpu-offers` directly. Existing fields are unchanged. * **No request changes required.** Both additions are response-only fields. Clients can opt in when ready and existing consumers keep working as-is. *** ### `v1.17.1` • 2026-04-28 #### API Reference & Referrals Page Refresh > The API reference and referrals pages have been rebuilt to match the v1.17.0 design refresh, the deployment, volume, and reserved GPU wizards have picked up another round of polish, and Spheron AI spot offers now stay fresher in the marketplace. **Design & UX Refresh** * **New API Reference Page:** Endpoints are now grouped by category, with short descriptions, cleaner endpoint cards, refreshed request and response examples, and a tighter quick-test panel for easier scanning and testing * **Refreshed Referrals Page:** Stats, the share link, share buttons, and the "how it works" section have been rebuilt with clearer hierarchy, step cards, and reward callouts, so it is easier to see your rewards and pass on your link * **More Wizard Polish:** The deployment, volume, and reserved GPU wizards have picked up another round of spacing and typography tweaks across cards, selections, and order summaries **Reliability** * **Fresher Spheron AI Spot Pricing:** Spheron AI spot offers now refresh on the same fast cadence as other spot providers, so spot availability and pricing stay current without a manual reload *** ### `v1.17.0` • 2026-04-27 #### Marketplace Design Refresh, Volume Discounts & NVLink GPU Flagging > A top-to-bottom visual refresh across billing, teams, volumes, API keys, SSH keys, deployment, and reserved GPU pages. Discounts now apply to volumes the same way they apply to deployments, the reserved GPU contact form captures more useful detail, and Spheron AI NVLink GPUs are clearly flagged in the marketplace. **Design & UX Refresh** * **Unified Visual Language:** Billing, teams, volumes, API keys, SSH keys, deployment wizard, and reserved GPU wizard have all been redesigned around a shared header, card, and table style for a calmer, more consistent look * **New Team Switcher:** The team menu has been consolidated into a single switcher in the top navigation. Create, switch, and manage teams from one place instead of several disconnected dialogs * **Refreshed Billing Page:** Balance, deposit history, usage analytics, discount overview, and the add-credits flow (custom amount, saved card, billing details) have all been rebuilt with clearer hierarchy and tighter spacing * **Smoother Wizards:** Deployment, volume, and reserved GPU wizards share a common header treatment and improved step layouts. The order summary sidebar now stays put when dropdowns or dialogs open, so it no longer disappears mid-configuration * **API Keys & SSH Keys:** Empty states, generation dialogs, the whitelist-required state, the quick reference, and the documentation card have all been updated to match the new style * **Volume Cards & Sidebar:** Volume cards, the volume details sidebar, the resize dialog, and the create-volume order summary have been refreshed to read more clearly at a glance **New Features** * **Volume Discounts:** Active team discounts now apply to volume hourly rates at creation and at resize time, the same way they already apply to deployments. The discounted rate is locked in when the volume is created. If a team's discount later expires or is revoked, the volume automatically reverts to its standard rate on the next billing cycle * **Spheron AI NVLink GPUs Flagged:** Spheron AI GPU offers that are NVLink-bridged variants (for example `H100 NVL`) are now clearly marked in the marketplace so you can pick the interconnect that matches your workload * **Richer Reserved GPU Contact Form:** The reserved GPU request form now captures phone country and country code separately (with a country picker), preferred GPU model, requested GPU quantity, and an optional marketing consent, so the team can route inquiries faster **Bug Fixes & Reliability** * **Discount Preview No Longer Fails Silently:** The discount-code preview used in billing, the deposit flow, and the deployment and volume wizards now handles non-JSON error responses gracefully instead of failing in the background. Users see a clear error state instead of a stuck preview * **Create Team Dialog Stays Open Until Done:** The create team dialog now stays open and shows its loading state until the team is actually created, matching the behavior of the invite member and add SSH key dialogs * **Data Crunch Cleanup Safety:** The background cleanup that removes orphaned Data Crunch volumes now has additional safeguards so marketplace-tracked, idle, and shared user-owned volumes are never eligible. Only true orphans can be removed * **Runtime Display:** Reserved runtime hours now display as `N/A` instead of `N.A` when no expiry is set **API** * **Volume Hourly Rate (all clients):** Volumes created or resized while a team has an active discount now bill at the discounted rate. The volume response from `GET /api/volumes` and `GET /api/volumes/:volumeId` reflects the locked-in discounted rate; the pre-discount rate is also returned for reference. If the team's discount later expires, the rate automatically reverts on the next billing cycle. No request changes are required for clients to benefit from this; pricing endpoints continue to return public list rates. * **Spheron AI GPU Offers:** GPU offers from Spheron AI now include an `nvlink: true` flag in their metadata when the GPU model is an NVLink-bridged variant (for example `H100 NVL`, `A100 NVL`). Non-NVLink offers do not include the flag. Existing fields are unchanged, so existing integrations continue to work and can opt in to the new flag when ready. *** ### `v1.16.0` • 2026-04-24 #### Spheron AI Persistent Volumes & Provider Rules Dialogs > Persistent storage, now on Spheron AI. Create a volume, attach it to a GPU instance at deploy time or while it's running, and move it between instances without losing data. Every volume provider now has a dedicated rules dialog so you know exactly how attachment and lifecycle work before you commit. **New Features** * **Spheron AI Volumes:** Spheron AI is now a supported volume provider. Create and manage persistent storage from the `/volumes` dashboard, backed by Cloud-SSD storage * **Attach at Deploy Time or Later:** Pick a Spheron AI volume in the deployment wizard, or attach one to an already-running instance from the volume or instance sidebar. No need to tear down and redeploy to add storage * **Hot-Detach Supported:** Detach a volume from a running instance and reattach it to a different instance without terminating either one. Your data moves with it * **Up to 10 Volumes per Instance:** A single Spheron AI instance can have up to 10 volumes attached at once. The UI and API enforce the limit automatically so attach requests fail fast instead of in the middle of a deploy * **Single-Attach Volumes:** Each Spheron AI volume can only be attached to one instance at a time. The dashboard hides incompatible volumes in the deploy wizard and shows a clear error if you try to double-attach * **Persistent After Termination:** Volumes survive instance termination by default. Delete them explicitly from the dashboard when you're done * **Large Storage Ceiling:** Create volumes from 1 GB up to 40 TB in a single volume * **Data Crunch Multi-Volume Support:** Data Crunch instances can now attach up to **10 shared volumes** at a time, up from a single volume in v1.14.1. Each Data Crunch volume can still be mounted on multiple instances concurrently, so you can fan out shared data and mix storage pools on the same instance **UX Improvements** * **Provider Rules Dialogs:** Every volume provider (Spheron AI, Data Crunch, Sesterce, Voltage Park) now has its own "Volume Rules" dialog accessible from the create-volume and attach flows. Each dialog spells out per-provider limits: attach timing, concurrent-attach rules, resize policy, and lifecycle behavior, so you know what you're getting before you create a volume * **Volume Created Success Modal:** After a Spheron AI volume is created, a confirmation modal summarizes the rules and offers a one-click "Deploy GPU" shortcut to go straight into the deployment wizard with the new volume pre-selected * **GPU Offer Availability Warning:** The create-volume wizard now checks whether the selected provider and region actually have live GPU offers. If there's nothing to attach the volume to, a warning surfaces in the order summary before you confirm * **Smarter Volume Matching in Deploy Wizard:** The attach step in the deployment wizard now respects per-provider constraints. Incompatible volumes are filtered, limit warnings appear when you hit the cap, and single-attach volumes already bound elsewhere are shown as blocked with an explanation * **Smarter Region Default on Create Volume:** The create volume wizard now auto-selects the first region that actually has live GPU offers instead of blindly picking the alphabetical first. Regions without GPU offers are clearly labeled "No GPU offer present" in the Sesterce, Data Crunch, and Spheron AI dropdowns so you can see which ones to avoid before selecting. The Data Crunch dropdown is also cleaner, with decorative flag graphics removed * **Consistent Region Name Formatting:** Massed Compute regions (for example `us-central-3`) now display as "Us Central 3" in the deployment wizard, order summary, and instance cards, matching the style used for Sesterce and Spheron AI **Bug Fixes** * **No In-Place Resize (Enforced):** Spheron AI volumes cannot be resized once created. The API now returns a clear error on resize attempts instead of silently succeeding. To grow storage, create a new larger volume and migrate your data * **Accurate Region Codes in UI:** The dashboard now shows clean region codes (for example `CANADA-1`) regardless of the provider's internal naming * **Stale Deployments No Longer Lock Volumes:** If a previous instance terminated without a clean detach, single-attach volumes are no longer permanently locked. Attach attempts skip terminated, failed, stopped, and deleted deployments when checking occupancy, so you can always reclaim the volume onto a new instance. Applies to both Spheron AI and Voltage Park volumes * **Cleaner Single-Attach Error Messages:** When a single attach volume is genuinely in use, the error message now lists only the live conflicting instances instead of every instance the volume has ever been attached to. Terminated and failed deployments no longer clutter the list * **Voltage Park Single-Attach Enforced Server-Side:** Voltage Park's one-volume-per-instance and one-instance-per-volume rules are now enforced by the API, not just the UI. Double-attach attempts are rejected even when the request bypasses the dashboard **API** Creating and using a Spheron AI volume involves three steps: 1. **Fetch available regions:** `GET /api/volumes/regions?provider=spheron-ai` returns a `regions` array. Each entry has an `id` (the region code to pass at creation time) and a `name`. Each region now also includes a `hasGpuOffers` boolean so you can check availability before creating a volume in a dead region. 2. **Create the volume:** `POST /api/volumes` with `provider: "spheron-ai"`, `region: ""`, `name` (max 50 characters), and `sizeInGb` (1–40960). The response includes the volume `id` you will use for all subsequent operations. 3. **Attach to an instance:** two options depending on your workflow: * At deploy time: include `volumeIds: [""]` in your `POST /api/deployments` request * After the instance is running: `POST /api/volumes/{volumeId}/attach` with `{ "deploymentId": "" }` **Detaching and re-attaching:** `POST /api/volumes/{volumeId}/detach` with `{ "deploymentId": "" }` frees the volume to be attached elsewhere. Data is preserved. Detach and re-attach are supported without instance downtime. **Limits:** Each Spheron AI instance supports up to 10 attached volumes. Each volume can be attached to only one instance at a time. Resize is not supported. Rename is not supported, so pick the name you want at creation. **Pricing:** `GET /api/volumes/pricing?provider=spheron-ai` returns the current hourly rate per GB so you can estimate cost before creating a volume. **Data Crunch limits (updated):** Each Data Crunch instance now supports up to **10 attached volumes** (was 1 in v1.14.1). Multi-instance attach is unchanged. A single Data Crunch volume can still be mounted on many instances at the same time. **API Docs correction:** The API reference now uses `CLUSTER` as the `instanceType` for multi-node deployments, matching the v1.10.0 rename. Any request examples that still showed `BARE_METAL` have been updated. *** ### `v1.15.0` • 2026-04-04 #### Sesterce Persistent Volume Support > Persistent storage is now available on Sesterce. Create volumes, pick your cloud provider and region, and attach them to instances at deploy time. Your data outlives any single session. **New Features** * **Sesterce Volumes:** Sesterce is now a supported volume provider. Create and manage persistent storage volumes from the `/volumes` dashboard * **Cloud Provider + Region Picker:** When creating a Sesterce volume, choose your cloud provider and region from a dynamic dropdown so volumes are always deployed where your compute is * **Deploy-time Attachment:** Select a compatible Sesterce volume in the deployment wizard. It attaches automatically when the instance starts, no extra steps needed * **Automatic Compatibility Filtering:** The deployment wizard only shows volumes that match the region and cloud provider of your selected GPU offer. No risk of picking an incompatible volume * **Volume Deletion:** Delete a Sesterce volume from the dashboard once the instance it was attached to has been terminated **API** Creating and using a Sesterce volume involves three steps: 1. **Fetch available cloud providers and regions:** `GET /api/volumes/regions?provider=sesterce` returns a `regions` array where each entry has an `id` (the region code), a `name`, a `cloudId`, and a `cloudName`. You need both `id` and `cloudId` when creating the volume. They must match the cloud provider and region of the instance you plan to deploy. 2. **Create the volume:** `POST /api/volumes` with `provider: "sesterce"`, `region: ""`, `cloudId: ""`, `name`, and `sizeInGb`. The response includes the volume `id` you will use when deploying. 3. **Attach at deploy time:** include `volumeIds: [""]` in your `POST /api/deployments` request. The volume attaches when the instance is created. Post-creation attach and detach are not supported for Sesterce. The volume is bound at launch. **Compatibility:** the `cloudId` and region of your volume must match the cloud provider and region of your GPU offer. Use `GET /api/gpu-offers` to find offers and cross-reference the region before creating a volume. **Pricing:** `GET /api/volumes/pricing?provider=sesterce` with optional `cloudId` and `region` query params returns the current hourly rate per GB for that specific location. *** ### `v1.14.6` • 2026-03-17 #### Spheron AI: Open All Inbound Ports by Default > All ports are open out of the box. Spheron AI provider VMs now have full inbound access (TCP/UDP/ICMP, ports 1–65535, IPv4 and IPv6) applied automatically at creation time, with no manual firewall configuration required. **Improvements** * **Security rules at creation:** Six inbound rules (TCP 1–65535, UDP 1–65535, and ICMP for both IPv4 and IPv6) are now passed directly in the VM creation payload via the `security_rules` field, replacing the previous post-creation polling approach * **Removed background firewall task:** Eliminated the `enableSSHFirewallWhenActive` polling loop (up to 10-minute wait) and the separate `enableSSHFirewall` method that made individual `POST /sg-rules` calls after the VM reached ACTIVE state * **No more `sshFirewallError` tracking:** Removed the `sshFirewallErrorMap`, the `sshFirewallError` field on `VMInstance`, and all related error-surface logic. Firewall setup is now atomic with VM creation *** ### `v1.14.5` • 2026-03-16 #### GPU Count Validation Hardening > Stricter GPU count validation. Deployment requests with a mismatched GPU count are now rejected reliably regardless of whether the value arrives as a string or a number, and validation errors are propagated correctly through the error-handling pipeline. **Bug Fixes** * **Type-safe GPU count comparison:** The GPU count check now coerces both the requested value and the offer config value to `Number` before comparing, preventing false validation failures caused by string/number type mismatches (e.g., `"2"` vs `2`) * **GpuValidationError class:** Introduced a dedicated `GpuValidationError` subclass so that GPU validation errors are identified with `instanceof` rather than fragile `error.message.startsWith(...)` string matching, eliminating the risk of silently swallowing errors or misclassifying HTTP status codes if the message text changes * **Route-level fix:** `deployment.routes.ts` now uses `instanceof GpuValidationError` to classify the error as an HTTP 400, replacing the previous `error.message.includes('Invalid GPU count:')` check *** ### `v1.14.4` • 2026-03-15 #### Feature Announcement Modal & Sidebar Changelog Link > Stay up to date without leaving the dashboard. A new in-app feature announcement modal greets users with what's new since their last visit, and the sidebar now links directly to the changelog. **New Features** * **Feature Announcement Modal:** Automatically shows authenticated users any features released since their last visit. Slides through announcements newest-first with story-style progress bars, smooth slide transitions, and a 25-second auto-advance timer * **Per-User Tracking:** Last-seen feature is persisted. The modal only re-appears when genuinely new features have shipped * **Learn More Links:** Each announcement card links directly to the relevant docs or changelog section * **Changelog Sidebar Link:** A compact "Changelog" entry with a "New" badge now lives in the sidebar bottom dock alongside the API Docs link, opening `docs.spheron.network/changelog` in a new tab *** ### `v1.14.3` • 2026-03-14 #### Sesterce Deployment Reliability Fix > Sesterce deployments no longer fail on name collisions. A `409 Conflict` error that occurred when instance names clashed is now handled automatically with a unique suffix and retry logic. **Bug Fixes** * **409 Name Collision:** Sesterce's `/gpu-cloud/instances` API rejects duplicate instance names with a 409. Deployment names are now suffixed with a random 6-character hex string (`crypto.randomBytes(3).toString('hex')`) to prevent collisions * **Retry Logic:** If a 409 still occurs (e.g. extremely unlikely suffix collision), the deployment automatically retries with a freshly generated name, up to 3 attempts before failing * **Status Code on Errors:** `makeAuthenticatedRequest` now attaches `statusCode` to thrown errors, enabling reliable detection of 409 vs other failure types * **SSH Key Cleanup:** If all retry attempts are exhausted, any provisioned temporary SSH key is deleted to prevent resource leaks *** ### `v1.14.2` • 2026-03-14 #### TensorDock Deployment Fix & Improved Error Reporting > TensorDock deployments now work reliably. A `400 Bad Request` error that blocked all TensorDock deployments has been fixed, and deployment failures now show human-readable error messages in the dashboard. **Bug Fixes** * **TensorDock 400 Error:** Removed an incorrect JSON:API wrapper (`data.attributes`) that was wrapping the request payload. TensorDock's API v2 expects a flat JSON body * **Field Name Casing:** Renamed `useDedicatedIp` (camelCase) → `use_dedicated_ip` (snake\_case) to match TensorDock's API contract * **Cloud-Init Format:** Converted `cloud_init` from a JSON object to a YAML string, consistent with how other providers (e.g. Spheron AI provider) handle startup scripts **Error Visibility** * **Human-Readable Failure Reasons:** TensorDock JSON error responses are now parsed and classified into user-friendly categories (e.g. "Insufficient resources", "Invalid configuration") stored as `failureReason` on the deployment * **Failure Details in Sidebar:** `InstanceDetailsSidebar` now surfaces `failureReason` and `failureDetails` so users can see exactly why a deployment failed without digging through logs *** ### `v1.14.1` • 2026-03-04 #### Data Crunch Shared Volume Support > Shared NFS volumes on Data Crunch. Create persistent NFS-backed volumes, attach them to multiple instances simultaneously, and keep your data safe after instance termination. **New Provider Support** * **Data Crunch Volumes:** Data Crunch is now a supported volume provider. Create and manage shared NFS volumes from the dashboard or via the API * **Multi-Instance Attachment:** A single Data Crunch volume can be attached to multiple GPU instances at the same time, unlike Voltage Park which restricts each volume to one instance * **Region Selection:** Deploy volumes into FIN-01 (Finland 1), FIN-02 (Finland 2), or FIN-03 (Finland 3). Each volume is pinned to the region you pick at creation time **Volume Lifecycle & Safety** * **Persistent Volumes:** Data Crunch volumes survive instance termination by default. Only deleted on explicit user action * **One Volume Per Instance:** Each Data Crunch instance supports at most one shared volume at a time, though that same volume can be attached to unlimited instances concurrently **API** Creating and using a Data Crunch volume involves three steps: 1. **Fetch available regions:** `GET /api/volumes/regions?provider=datacrunch` returns a `regions` array where each entry has an `id` (the region code to pass at creation time), a human-readable `name`, and a `country_code`. Use the `id` value as the `region` field when creating the volume. 2. **Create the volume:** `POST /api/volumes` with `provider: "datacrunch"`, `region: ""`, `name`, and `sizeInGb`. The response includes the volume `id` you will use for all subsequent operations. 3. **Attach to an instance:** two options depending on your workflow: * At deploy time: include `volumeIds: [""]` in your `POST /api/deployments` request * After the instance is running: `POST /api/volumes/{volumeId}/attach` with `{ "deploymentId": "" }` **After attachment**, `GET /api/volumes/{volumeId}` returns the NFS mount command and mount path in the response. Copy these directly into your instance to mount the volume. **Detaching and re-attaching:** `POST /api/volumes/{volumeId}/detach` with `{ "deploymentId": "" }` frees the volume to be attached elsewhere. Data is preserved. **Pricing:** `GET /api/volumes/pricing?provider=datacrunch` returns the current hourly rate per GB so you can estimate cost before creating a volume. *** ### `v1.14.0` • 2026-03-03 #### New GPU Provider: Europe & North America Regions > More GPUs, more regions. A new provider is now available on the Spheron AI marketplace, adding H200, H100, A100, L40S, A6000, and A4000 inventory across Canada, Norway, and the US. **New GPU Inventory** * **GPU Models:** H200 SXM, H100 SXM5 / NVL / PCIe, A100 SXM4 / NVL / PCIe, L40S, L40, A6000, RTX Pro 6000, A4000 * **Regions:** Canada (Montreal), Norway (Bergen), United States * **On-Demand & Spot:** Both instance types are available. Spot instances offer the same GPU configurations at a lower price with no uptime guarantee **Deployment Features** * **Startup Scripts:** Cloud-init startup scripts are supported. Packages, run commands, and file writes all work on this provider the same as others * **OS Options:** 11 OS images to choose from, including Ubuntu 22.04/24.04, AlmaLinux 9, Debian 12, and CUDA-enabled variants (R535, R550, R570). Defaults to Ubuntu Server 22.04 LTS with CUDA 12.8 and Docker * **SSH Access:** Port 22 is automatically opened on every new instance. No manual firewall configuration needed *** ### `v1.13.1` • 2026-02-27 #### Password Complexity Enforcement on Signup > Stronger account security. Signup now enforces password complexity rules before any Firebase call, giving users immediate, clear feedback. **Bug Fixes** * **Weak Password Allowed:** The signup form previously accepted any non-empty string as a password, including the user's own email address. This is now blocked * **No Complexity Checks:** Passwords with no uppercase, no lowercase, or no digits were accepted without warning. All three are now required **Password Rules (enforced client-side before Firebase)** * Minimum **8 characters** * Cannot be identical to your full email address (case-insensitive) * Cannot be identical to the local part of your email (the portion before `@`) * Must contain at least one **uppercase** letter * Must contain at least one **lowercase** letter * Must contain at least one **digit** **UX Improvements** * **Inline Error Messages:** Validation failures are shown immediately below the password field with a specific explanation. No generic Firebase errors * **Live Clearing:** The error clears on every keystroke in the password field, and also when the email field is changed (prevents a stuck form if a "password too similar to email" error was triggered and the user updates their email instead) * **Gated Submit:** The sign-up button stays disabled while a password validation error is active *** ### `v1.13.0` • 2026-02-27 #### Auto Top-Up Credits via Stripe > Never run out of credits. Configure a balance threshold and Spheron automatically charges your saved card to keep your deployments running. **Saved Card Management** * **Save a Card:** Add a payment card via Stripe's hosted setup flow (no card numbers stored; only a Stripe PaymentMethod ID) * **Card Details:** Saved card brand, last 4 digits, and expiry are shown in the billing page at all times * **Remove Card:** Detach your saved card from Stripe entirely. This automatically disables auto top-up if it was enabled * **Role-Gated Access:** Only team owners and admins can save or remove cards; members see card info in read-only mode **Auto Top-Up Configuration** * **Enable / Disable Toggle:** Turn auto top-up on or off from the billing page * **Threshold Setting:** Set the balance level (min $5, max $500) that triggers an automatic charge * **Top-Up Amount:** Choose how much to charge each time (min $15, max $5,000) * **Immediate Check:** Enabling auto top-up immediately checks your balance and triggers a charge if already below threshold * **Failure Banner:** A warning banner appears on the billing page if auto top-up was disabled due to a declined charge **Automatic Charging** * **Balance-Triggered Charge:** After each credit deduction cycle, if your team balance falls below the configured threshold, a Stripe off-session PaymentIntent is created and charged automatically * **5-Minute Cooldown:** A distributed lock prevents double-charging. Top-ups cannot fire more than once every 5 minutes per team * **Race Condition Safe:** Balance is re-fetched inside the lock before charging to prevent concurrent monitor cycles from triggering duplicate charges * **Instant Credit:** Team balance is credited immediately on successful charge without waiting for a webhook **Stripe Webhook Handlers** * **`payment_intent.succeeded`:** Idempotent safety net. Credits the team if the service layer missed it (e.g. network failure mid-request) * **`payment_intent.payment_failed`:** Automatically disables auto top-up and records `lastFailedAt` when a card is declined **Transaction History** * Auto top-up charges appear in Deposit History labeled **"Auto Top-Up"** with a distinct badge, clearly separated from manual credit purchases **Email Notifications** * **Success Email:** Confirms the charge amount and shows the new account balance * **Failure Email:** Notifies the configuring user that their card was declined and auto top-up has been disabled, with a direct link to re-enable *** ### `v1.12.2` • 2026-02-27 #### Mandatory Phone Number on Reserved GPU Form > Required contact info. Phone number is now enforced end-to-end so reserved GPU requests always include reachable contact details. **Bug Fixes** * **Mandatory Phone Field:** Phone number is now a required field on the Reserved GPU request form. The label, frontend validation, and server-side validation all enforce it * **Format Validation:** Phone input is validated against a format check (supports `+`, digits, spaces, dashes, parentheses, e.g. `+1 555-123-4567` or `(555) 123-4567`) with a minimum of 7 digits, on both client and server * **Review Step Gate:** If contact info (including phone) is incomplete when the user reaches the review step, the wizard redirects back to the contact form with a clear "Contact Info Required" toast notification * **Backwards Compatibility:** Existing reservations without a phone number are unaffected. The schema change is non-breaking for legacy documents *** ### `v1.12.1` • 2026-02-23 #### Zero-Downtime Deployment & Faster Container Restarts > Instant restarts, no build delays. App builds are now baked into the Docker image so containers spin up in seconds instead of minutes. **Deployment Scripts** * **Zero-Downtime Deploy:** New `script/deploy.sh` for all the apps. Builds the new image while the current container keeps serving traffic, then hot-swaps to the new container with no manual downtime * **Health-Gated Rollout:** The deploy script waits for Docker's health check to pass (up to 120s) before declaring success, ensuring the new container is fully ready before traffic is handed off **Docker Image Optimizations** * **Build at Image Time:** `npm run build` now runs during `docker build` (image layer) instead of at container startup. Containers start in seconds rather than waiting for a full compile * **Health Checks Added:** All app's Dockerfiles now include `HEALTHCHECK` directives with 10s intervals and 30s start periods so Docker and the deploy script can reliably detect readiness *** ### `v1.12.0` • 2026-02-23 #### Volume Management UI for Voltage Park > Full persistent storage experience. Create, browse, attach, detach, resize, and monitor volumes directly from the dashboard. **New Pages** * **Volumes Page** (`/volumes`): Dedicated page to view and manage all your persistent storage volumes in one place, with status badges, provider/region info, hourly rates, and quick actions * **Create Volume Page** (`/create-volume`): Step-by-step wizard to create a new volume. Select a provider, configure name, size, region, and lifecycle settings before reviewing the cost summary **Volume Management** * **Volume Cards:** Each volume displays its name, size, provider, region, status (available, attached, creating, deleting, error), and current cost, with one-click copy for Volume ID * **Volume Details Sidebar:** Click any volume to open a detailed side panel showing overview, configuration, storage usage metrics, and attached instances * **Attach to Deployment:** During the deployment wizard, an "Attach Volumes" step surfaces compatible volumes (same provider and region) and lets you select one to attach before launch * Voltage Park instances support **1 volume per instance**. The UI enforces this limit automatically * **Detach Volume:** Detach a volume from a running instance directly from the instance detail sidebar or the volumes page, without losing data * **Resize Volume:** Expand a volume's storage size on-demand from the volumes page (shrinking is not supported) * **Delete Volume:** Delete a volume (must be detached first) with a confirmation dialog **Instance Detail Sidebar** * New **Attached Volumes** card visible on each running instance showing all volumes currently mounted, their size, hourly cost, and a detach action **Navigation** * **Volumes** and **Create Volume** entries added to the sidebar for quick access **Smart Behaviors** * Volume selection resets automatically when you switch providers or networking type in the deployment wizard * Volume size input clamps to the provider's supported min/max range and rounds to a whole number * Region matching is normalized so minor formatting differences (e.g. `us-east-1` vs `US East 1`) don't prevent valid volumes from appearing * Provider pricing is validated before allowing volume creation. A clear error is shown if pricing is unavailable for the selected provider/region **Pricing & Cost Display** * Hourly and monthly cost estimates shown in real-time while configuring volume size * Order summary in the create wizard shows total hourly cost and projected 30-day cost before confirming **API Endpoints (unchanged from v1.11.0, now fully surfaced in UI)** * `GET /api/volumes`: list volumes (filterable by team, status, provider) * `POST /api/volumes`: create volume * `GET /api/volumes/:volumeId`: volume details with live usage data * `PATCH /api/volumes/:volumeId`: rename, resize, or update lifecycle settings * `DELETE /api/volumes/:volumeId`: delete volume * `POST /api/volumes/:volumeId/attach`: attach to a deployment * `POST /api/volumes/:volumeId/detach`: detach from a deployment * `GET /api/volumes/pricing`: storage pricing by provider ### `v1.11.1` • 2026-02-13 #### Kubernetes Add-on for Voltage Park > **Managed Kubernetes clusters** on bare-metal GPU instances with automatic provisioning, kubeconfig access, and health monitoring. **New Features** * **Kubernetes Cluster Deployment:** Deploy fully managed Kubernetes clusters on Voltage Park bare-metal GPU instances * **Version Selection:** Choose from multiple Kubernetes versions (1.35, 1.34, 1.33, 1.32) with automatic validation * **Automatic Provisioning:** Kubernetes clusters are automatically provisioned and configured during instance deployment * **Kubeconfig Access:** Download kubeconfig files directly from deployments for immediate kubectl access * **Cluster Health Monitoring:** Real-time health tracking for control plane nodes, worker nodes, and network components * **Grafana Integration:** Built-in Grafana monitoring links for cluster observability and metrics * **Custom Authentication:** Optional support for custom Kubernetes AuthenticationConfiguration YAML * **Persistent Cluster State:** Cluster configurations persist independently from instance lifecycle **Technical Implementation** * **Provider Validation:** Automatic validation ensures Kubernetes add-ons are only used with Voltage Park bare-metal instances * **Version Validation:** Server-side version checking against provider-supported Kubernetes releases * **Base64 Encoding:** Secure transmission of authentication configurations via base64 encoding * **Monitoring Service:** Background service updates cluster health and configuration data automatically **API Endpoints** * `GET /api/kubernetes/versions?provider=voltage-park`: List available Kubernetes versions * `GET /api/kubernetes/:clusterId/health`: Get cluster health status with node and network component metrics * `POST /api/deployments` with `kubernetesAddon` object: Create deployment with Kubernetes cluster **Deployment Requirements** * **Provider:** Voltage Park only (other providers not yet supported) * **Instance Type:** CLUSTER deployments only for H100 SXM5 * **Operating System:** Compatible with TensorML and other Voltage Park OS images ### `v1.11.0` • 2026-02-07 #### Persistent Storage Volumes > **Persistent storage for GPU instances** with flexible volume management and deployment attachment. **New Features** * **Volume Management:** Create, update, and delete persistent storage volumes independent of GPU instances * **Flexible Attachment:** Attach and detach volumes to/from running deployments without losing data * **Multi-Provider Support:** Volume storage available across supported providers (Voltage Park, etc.) * **Size Flexibility:** Configure volumes from 1GB to 10TB with dynamic expansion support * **Automatic Billing:** Hourly billing based on storage size with transparent pricing per GB * **Usage Tracking:** Real-time monitoring of used capacity and storage metrics * **Smart Lifecycle Management:** Choose whether volumes persist after instance termination or delete automatically * **Credit Validation:** Automatic validation ensures sufficient credits before volume creation (24-hour minimum) **Volume Features** * **Independent Lifecycle:** Volumes persist independently from GPU instances by default * **Cross-Instance Sharing:** Attach a single volume to multiple instances (provider-dependent) * **Capacity Expansion:** Expand volume size on-demand (shrinking not supported for data safety) * **Name Validation:** Alphanumeric naming with hyphens/underscores (max 60 characters) * **Status Tracking:** Real-time status monitoring (available, attached, deleting, deleted) * **Automatic Cleanup:** Orphaned volume references automatically cleaned from deployments **API Endpoints** * `GET /api/volumes`: List all volumes for a team with pagination and filtering * `POST /api/volumes`: Create new persistent storage volume * `GET /api/volumes/:volumeId`: Get volume details with fresh usage data * `PATCH /api/volumes/:volumeId`: Update volume name, size, or lifecycle settings * `DELETE /api/volumes/:volumeId`: Delete volume (must be detached first) * `POST /api/volumes/:volumeId/attach`: Attach volume to a deployment * `POST /api/volumes/:volumeId/detach`: Detach volume from deployment * `GET /api/volumes/pricing`: Get storage pricing by provider **Technical Improvements** * **Provider Consistency:** Volumes and deployments must be from the same provider for attachment * **Atomic Operations:** Provider updates happen before database updates to maintain consistency * **Graceful Cleanup:** Automatic cleanup of volume references when deployments are deleted * **Audit Logging:** Complete audit trail for all volume lifecycle events ### `v1.10.1` • 2026-01-14 #### Reserved Instance Management > **Dedicated GPU leasing** for users who have contacted the team and secured reserved GPU nodes. **New Features** * **Reserved Instance Display:** Users who have leased GPU nodes directly with Spheron AI can now view their reserved instances in the marketplace * **Direct Leasing Support:** Seamless integration for customers who have contacted the team for bulk GPU reservations * **Dedicated Node Access:** Reserved instances provide exclusive access to pre-allocated GPU nodes with guaranteed availability * **Custom Configurations:** Support for custom GPU configurations negotiated directly with the Spheron AI team **Improvements** * **Enhanced Visibility:** Reserved instances are clearly labeled and distinguished from on-demand offerings * **Better Management:** Improved interface for tracking and managing leased GPU resources * **Streamlined Experience:** Integrated workflow for users with both reserved and on-demand instances ### `v1.10.0` • 2026-01-08 #### Cluster Deployments & Baremetal GPU Offers > **Multi-node cluster support** with enhanced baremetal GPU offerings and clearer deployment terminology. **New Features** * **Cluster Deployment Support:** Multi-node GPU clusters are now clearly labeled and supported throughout the platform * **Baremetal GPU Offers:** New baremetal GPU configurations added to the marketplace for dedicated hardware performance * **Improved Nomenclature:** Voltage Park's H100 SXM5 offerings now accurately labeled as "H100 SXM5 Cluster" instead of "Baremetal" for better clarity * **Better GPU Classification:** Enhanced distinction between single-node baremetal instances and multi-node cluster deployments **Improvements** * **Clearer Labels:** Deployment types are now more accurately labeled to help users understand exactly what they're deploying * **Enhanced Discovery:** Cluster and baremetal options are now easier to find and understand in the GPU marketplace * **Consistent Terminology:** Standardized naming conventions across all providers for better user experience ### `v1.9.7` • 2026-01-06 #### Intercom Live Chat Support > **Get instant help** with integrated Intercom messenger for real-time customer support and assistance. **New Features** * **Live Chat Widget:** Intercom messenger widget integrated throughout the platform for instant support access * **Identity Verification:** Secure user authentication with HMAC-SHA256 hash-based identity verification to prevent user impersonation * **User Context:** Automatic user data synchronization (name, email, account creation date) for personalized support experience * **Anonymous Visitor Support:** Non-authenticated visitors can still access support through anonymous chat sessions * **Smart Session Management:** Automatic session handling when users log in, log out, or switch accounts * **Seamless Integration:** Support chat available on all pages without disrupting your workflow ### `v1.9.6` • 2025-12-30 #### Deployment Termination Controls > **Critical Fix:** Strict termination controls prevent premature instance termination and ensure proper billing accuracy. **Breaking Changes** * **Status-Based Termination:** Only instances with `running` status can now be terminated manually * `deploying` instances cannot be terminated (must wait until running or automatic failure) * `failed`, `terminated`, and `terminated-provider` instances are already in final states * **Minimum Runtime Enforcement:** Running instances must meet the 20-minute minimum runtime requirement before termination **Bug Fixes** * Fixed incorrect status semantics: Deployments that never started running are now marked as `failed` instead of `terminated` * Fixed API key users being able to bypass minimum runtime checks by terminating during `deploying` status * Fixed deployments showing "terminated" with N/A runtime and $0.00 cost (now correctly marked as `failed`) * Added proper error messages for termination attempts on non-running instances **New Features** * **Improved Error Messages:** Status-specific error messages guide users on correct actions * Clear explanations for why termination is blocked * Helpful guidance on what to do next * **Frontend Error Handling:** Enhanced UI feedback for termination failures * Status-specific toast messages * Better user experience during edge cases **Technical Changes** * Updated GET `/api/deployments/:id/can-terminate` endpoint with status validation * Updated DELETE `/api/deployments/:id` endpoint with strict pre-termination checks ### `v1.9.5` • 2025-12-30 #### Flexible Storage Options for Data Crunch > **Choose your storage size** when deploying Data Crunch dedicated instances with new 500GB and 1TB options. **New Features** * **Storage Size Selection:** Data Crunch dedicated instances now offer two storage options: * **500GB Standard:** Default option with $0.137/hr storage pricing * **1TB Extended:** Expanded storage option with $0.274/hr storage pricing * **Clear Pricing Display:** Storage costs are shown separately in the deployment wizard for transparent pricing * **Smart Defaults:** 500GB storage is automatically selected when configuring Data Crunch dedicated instances * **Flexible Configuration:** Easily switch between storage sizes to match your workload requirements **Technical Notes** * Storage property is now included in GPU offer configurations for Data Crunch dedicated instances * Pricing calculations properly account for storage costs in commission-adjusted totals ### `v1.9.4` • 2025-12-25 #### OTP Verification for Reserved GPU Requests > **Enhanced security** for bulk GPU reservations with email-based OTP verification. **New Features** * **OTP Verification Flow:** Reserved GPU requests now require email verification via one-time password (OTP) for added security * **Email OTP Delivery:** Receive a verification code via email when submitting a reserved GPU request * **OTP Resend Option:** Didn't receive the code? Request a new OTP to be sent to your email * **Session Management:** OTP verification sessions are securely managed with automatic expiration * **Rate Limiting:** OTP requests are rate-limited to prevent abuse and ensure system stability ### `v1.9.3` • 2025-12-25 #### API Access Control & Runtime Policies > **Controlled API access** with whitelist-based key generation and enforced minimum runtime for deployments. **New Features** * **API Key Whitelisting:** API key generation is now controlled through a whitelist system. Contact support to request API access * **Whitelist Status Visibility:** Users can now see their API access status clearly in the settings interface * **Minimum Runtime Enforcement:** Deployments now require a **20-minute minimum runtime** before termination to prevent accidental early shutdowns * **Runtime Protection:** Destroy action is automatically disabled during the minimum runtime period with a helpful countdown timer * **System Configuration API:** New endpoint (`GET /api/config/system`) exposes system configuration including minimum runtime requirements * **Termination Validation:** New endpoint (`GET /api/deployments/:id/can-terminate`) checks if an instance can be safely terminated **Improvements** * **Enhanced Rate Limiting:** Deployment creation now limited to **5 deployments per hour per user** for better platform stability and abuse prevention * **Better API Key Handling:** Improved handling of empty or undefined API keys in the UI * **Deployment Wizard Updates:** SSH key step now displays minimum runtime requirements upfront * **Clear User Feedback:** Disabled actions now include tooltips explaining why they're unavailable and when they'll be enabled **API Changes** * `GET /api/config/system`: Returns system configuration including minimum runtime settings * `GET /api/deployments/:id/can-terminate`: Validates if deployment can be terminated * `DELETE /api/deployments/:id`: Enforces minimum runtime checks before allowing termination * `POST /api/deployments`: Enhanced with rate limiting ### `v1.9.2` • 2025-12-22 #### Christmas Promo & Active Discount Display > **Time-limited promotional discounts** with automatic activation and clear discount visibility. **New Features** * **Christmas Promo:** Special time-limited discount offers appear automatically to eligible users with easy one-click activation * **Active Discount Display:** Your current discount percentage and expiration date are now prominently shown on the billing page * **Clear Savings:** See exactly how much you're saving with active discounts applied to your usage ### `v1.9.1` • 2025-12-20 #### Reserved GPU Offers > **Smarter GPU reservation options** with detailed specifications. **Reserved GPU Offers** * **Two Display Modes:** Reserved GPU offers now support two presentation styles: * **Tiers Mode:** Compare multiple pricing tiers (up to 3) with flexible commitment options, perfect for understanding pricing at different commitment levels * **Specs Mode:** View detailed technical specifications including vCPUs, RAM, storage, connectivity type, and deployment method (Bare Metal or VM), ideal for understanding exact hardware configurations * **Regional Availability:** GPU offers now display available regions, making it easier to choose deployments close to your users * **Better Descriptions:** Hover over offer descriptions to see full details without cluttering the interface * **Improved Reservation Flow:** When clicking "Reserve" on an offer, relevant details (specs, regions, pricing) are now pre-filled in the reservation form for faster booking ### `v1.9.0` • 2025-12-18 #### Major Frontend Refactor > **Complete codebase modernization** with modular components, centralized hooks, and improved UX. **Routing & Layout** * Introduce new routing and layout components * Split PublicLayout and Sidebar into components/shared **Billing & Payments** * Refactor AddCreditsTab into modular components * Powered by new usePayment hook and usePaymentCallback * Move deposit dialog to TopNavBar subcomponents **API Documentation** * Break ApiDocumentation into composable sections and utils/types **Instances & Deployments** * Modularize Card and Sidebar into subcomponents * Rebuild pages/instances.tsx using new grid/header/empty/error components with infinite loading **Shared Components & UI** * Extract Sidebar and TopNavBar for reusability * Normalize toast hook path (useToast) **UX Improvements** * All modals now wait for API completion before closing * Fixed React Hooks violations with proper hook ordering * Team switcher dropdown now works correctly * Better loading states and error handling throughout ### `v1.8.2` • 2025-12-17 #### Higher Deposit Limits & New Credit Packages > **Deposit up to $5,000** with new bulk credit packages for larger workloads. **New Features** * **Increased Deposit Limits:** Maximum deposit raised from $1,000 to **$5,000** for teams with larger GPU requirements * **New Credit Packages:** Added **$500**, **$1,000**, and **$5,000** quick purchase options for bulk credits * **Clear Limit Display:** Deposit limits are now prominently displayed in the UI for transparency * **Package Validation:** UI automatically prevents purchases outside allowed limits with helpful error messages * **Better Formatting:** Large numbers now display with proper comma formatting for easier reading **Improvements** * **Dynamic Configuration:** Deposit limits and referral rewards are now centrally managed for consistency * **Referral Page Updates:** Referral reward amounts and minimum deposit requirements are now displayed accurately throughout * **Enhanced UX:** Improved handling of edge cases when selecting credit packages ### `v1.8.1` • 2025-12-17 #### Search Improvements > **Enhanced GPU search** with better filtering and improved reliability. **Improvements** * **Reserved GPU Search:** Search now properly filters reserved GPU offers. When you search for "H100", only H100 models will appear in results * **More Accurate Results:** Improved search matching ensures you see only relevant GPU configurations * **Better Performance:** Enhanced search processing for faster and more reliable results * **Consistent Experience:** Search behavior is now unified across all GPU offer types ### `v1.8.0` • 2025-12-16 #### Referral Program Launch > **Earn rewards by referring friends!** Get **$5** credit when your referral deposits **$100**. **New Features** * **Referral Dashboard:** Access your unique referral link and track your referrals * **Shareable Links:** Easy sharing via Twitter, LinkedIn, and direct link copying * **Automatic Tracking:** Referrals are automatically tracked when someone signs up using your link * **Instant Rewards:** Credits are automatically added to your account when referrals make qualifying deposits * **Discount Codes:** New ability to validate and apply discount codes to your account * **Enhanced Transaction History:** Referral bonus deposits are now clearly labeled in your transaction history ### `v1.7.0` • 2025-11-20 #### Email Notifications & Credit Monitoring > **Stay informed with professional email notifications** and proactive balance alerts. **New Features** * **Enhanced Email Notifications:** Improved email design for welcome messages, deployment updates, and account alerts * **Smart Low Balance Alerts:** Receive notifications when your balance reaches **$50**, **$20**, **$10**, or **$5** to avoid service interruption * **Balance Exhaustion Alerts:** Get notified when your balance reaches **$0** and deployments are automatically stopped * **Rate-Limited Notifications:** Smart notification system prevents email spam with 6-hour intervals between similar alerts * **Priority Notification Delivery:** Account owners and admins receive critical balance alerts first ### `v1.6.0` • 2025-10-29 #### Transaction Receipts & Improved Navigation > **Download payment receipts** and enjoy **faster page loading** with improved pagination. **New Features** * **Receipt Downloads:** Download official receipts for all completed deposits (Stripe & CopperX payments) * **Deposit History:** Renamed transaction view to "Deposit History" for better clarity * **Paginated Views:** Faster loading with pagination across deployment history and usage analytics * **Load More Button:** Browse through your instances with easy "Load More" functionality * **Documentation Access:** Quick access to API documentation directly from the navigation menu **Improvements** * **Loading States:** Better visual feedback with loading skeletons while data loads * **Error Handling:** Improved error messages and handling throughout billing and instances pages * **Performance:** Faster page loads with optimized data fetching ### `v1.5.0` • 2025-10-18 #### Complete UI Redesign > **Modern dark theme** with sleek blue gradients and enhanced user experience throughout the platform. **Visual Overhaul** * **Modern Dark Theme:** New dark interface with blue gradient accents and improved contrast * **Redesigned Cards:** Sleek card designs with unique clipped borders for a futuristic look * **Enhanced Buttons:** Modern call-to-action buttons with hover effects and smooth transitions * **Improved Typography:** Updated fonts and text hierarchy for better readability **Page Improvements** * **Billing Dashboard:** Completely redesigned with clear balance overview, streamlined deposit flow, and organized transaction history * **Instance Management:** Improved instance cards with better status indicators and enhanced SSH key management * **Settings Interface:** Modern tabbed navigation with refreshed profile, SSH key, and API key management sections * **Deployment Wizard:** Enhanced GPU browsing experience with improved provider, region, and configuration selection * **Reserved GPU Portal:** New design for bulk GPU reservation requests with better quote workflow **User Experience** * **Faster Loading:** Optimized loading and redirect screens * **Better Navigation:** Improved top navigation and sidebar with clearer menu organization * **Enhanced Dialogs:** Modern confirmation dialogs with better visual feedback * **Consistent Design:** Unified design language across all pages and components ### `v1.4.0` • 2025-09-28 #### Reserved GPU Pricing & Compliance **New Features** * **Reserved GPU Pricing:** Special pricing model for long-term GPU reservations * **Provider Compliance Status:** View compliance and certification status for each provider during deployment * **Flexible SSH Key Options:** Enhanced SSH key support for programmatic deployments **Improvements** * **Better Pricing Display:** Improved GPU offer pricing calculations and display * **Enhanced Security:** Stronger SSH key validation and processing * **System Stability:** Improved reward processing reliability ### `v1.3.0` • 2025-09-02 #### Onboarding & Discounts **New Features** * **Welcome Onboarding:** New user onboarding flow to help you get started quickly * **Discount Codes:** Support for promotional and discount codes * **Reserved GPU Marketplace:** New page for requesting bulk GPU reservations from our provider network **Improvements** * **Accurate Billing:** Fixed credit deduction and monitoring for precise billing * **Better Calculations:** Improved accuracy in usage cost calculations ### `v1.2.0` • 2025-08-12 #### API Access & New Provider **New Features** * **API Key Management:** Create and manage deployments programmatically using API keys * **Massed Compute Provider:** New provider option for more GPU choices and competitive pricing * **Multi-Node Deployments:** Deploy multiple GPU nodes simultaneously with Voltage Park for larger workloads ### `v1.1.0` • 2025-07-25 #### Startup Scripts & Discounts **New Features** * **Startup Scripts:** Add custom initialization scripts that run automatically when your instance starts * **Usage Discounts:** Discount system for reduced pricing on GPU usage **Improvements** * **Real-Time Pricing:** Fixed spot pricing updates for accurate availability and costs * **Accurate GPU Selection:** Improved pricing calculations during GPU selection ### `v1.0.0` • 2025-07-04 #### Initial Release **Welcome to Spheron AI GPU Marketplace!** The easiest way to rent high-performance GPUs on-demand from multiple providers. **Core Features** * **Multiple GPU Providers:** Access GPUs from Voltage Park, Data Crunch, Sesterce, and TensorDock * **Simple Authentication:** Sign in with Google, GitHub, or email * **Team Management:** Create and manage teams for collaborative work * **Flexible Billing:** Pay with crypto or credit card * **Usage Analytics:** Track your GPU usage and spending in real-time * **Transaction History:** Complete history of all your deposits and usage charges ::: ## Cost optimization This page covers strategies for reducing compute costs on Spheron, including moving non-GPU work to CPU nodes, GPU tier selection, instance type trade-offs, reserved GPU savings, and spend monitoring. ### Move non-GPU work to CPU nodes The largest saving is not renting a GPU at all. Data preprocessing, ETL, build steps, schedulers, queue workers, and API front ends never touch CUDA, and running them on a GPU instance wastes the accelerator you are paying for. [CPU Node](/concepts/cpu-nodes) starts at **$0.09/hr** on Verda spot, against \~$0.25/hr for the cheapest GPU spot instance and several dollars per hour for an H100. Sizes start at 4 vCPU with 4 GB of memory. Check the [Deploy CPU page](https://app.spheron.ai/deploy-cpu) for the sizes on offer right now. **Split a pipeline across both:** 1. Preprocess and shard the dataset on a CPU node, writing to a [persistent volume](/connecting/volume-mounting). 2. Attach the same volume to a GPU instance and run training. 3. Terminate the GPU instance the moment training finishes; leave the CPU node running for postprocessing if needed. Deploy CPU nodes from **Deploy CPU** in the dashboard sidebar, or through the API with `computeType=cpu`. ### GPU tier selection matrix Choose the right GPU tier based on how much VRAM your workload needs: | VRAM needed | GPU | Type | Approx. $/hr | Best for | | --------------- | ---------------------- | -------------- | ------------ | ------------------------------------------ | | None | CPU Node (from 4 vCPU) | Dedicated/Spot | From $0.09 | Data prep, builds, schedulers, API workers | | Less than 16 GB | RTX 4090 (24 GB) | Dedicated/Spot | \~$0.25-0.55 | Dev, inference, fine-tuning | | 40 GB | A100 40 GB | Dedicated/Spot | Variable | Mid-scale training | | 80 GB | A100 80 GB / H100 | Dedicated | Variable | Large model training | | 640 GB+ | 8x H100 NVLink | Cluster | \~$15+/hr | Distributed training, K8s | Check current prices in the dashboard; prices vary by provider and availability. ### Instance type strategy #### Spot (lowest cost) Spot instances are 30-60% cheaper than Dedicated. The trade-off: the provider can reclaim them at any time. **Use Spot for:** * Experiments and hyperparameter search * Batch training jobs with checkpoint saving enabled * Any workload under 4 hours that can tolerate interruption **Handling interruption:** Save checkpoints to a persistent volume every N steps. If the instance is reclaimed, resume from the latest checkpoint on a new instance without losing progress. ```python # Save checkpoint every 100 steps if step % 100 == 0: torch.save(state, '/checkpoints/checkpoint_latest.pt') ``` #### Dedicated (guaranteed) Dedicated instances cannot be reclaimed. Use them when interruption would be costly: * Production inference servers * Multi-day training runs * Interactive workloads and demos #### Cluster (largest scale) Full physical servers with NVLink interconnects. Use for: * Multi-GPU distributed training (PyTorch DDP, DeepSpeed) * Workloads requiring maximum GPU-to-GPU bandwidth * Jobs sensitive to virtualization overhead ### Stop an instance instead of leaving it running An instance you are coming back to does not have to keep paying for its GPU. Stopping releases the GPU, keeps the disk and everything on it, and bills only for the retained disk plus the public IP where the provider charges for one. Starting it again returns the same disk, the same contents, and the same public IP. This is the cheapest option for work that pauses rather than ends: * An environment you spent hours building and will use again tomorrow * A dataset already downloaded to the boot disk that you do not want to fetch twice * An overnight or weekend gap in an otherwise active project Stopping is available on Spheron AI and Spheron ES, and on Spheron AI it depends on the machine type and region. Verda, Sesterce, Spheron MS, and Massed Compute keep billing at the full rate until an instance is destroyed. Check the note in the deploy summary before you commit. :::warning[Stopped is not free, and not permanent] A stopped instance still costs its disk rate, and a team that runs out of credit has every instance destroyed, stopped ones included. Terminate an instance you are genuinely finished with. See [Instance lifecycle](/concepts/instance-lifecycle). ::: ### Reserved GPUs for long-term work For multi-week or multi-month projects, Reserved GPUs offer significant savings: * Submit requests via dashboard > **Reserved GPU** * Multiple providers compete to offer the lowest price * Typical savings: 30-50% vs on-demand hourly rates for 3-12 month commitments * Select "Any Location" to maximize provider competition See [Reserved GPUs](/reserved-gpus) for the request form. ### Team discount program Teams with active discounts automatically see reduced prices on the dashboard. The discounted price is applied at deployment without any additional steps. * Discounts are either volume-based or admin-assigned; the higher of the two is applied automatically To inquire about discount eligibility for high-volume usage, use the chat widget on [app.spheron.ai](https://app.spheron.ai) or email [info@spheron.ai](mailto\:info@spheron.ai). ### Monitoring burn rate #### Check remaining balance View your current credit balance on the **Billing** page in the dashboard. The balance updates in real time as instances run. #### Track per-instance spend Open the instance details drawer from the **Instances** page to see the hourly rate and total cost accumulated for a running deployment. #### Stop or terminate when done Terminate instances from the dashboard as soon as your workload finishes to stop charges immediately. Navigate to **Instances**, select the instance, and click **Terminate**. When you will return to the same environment, click **Stop** instead where the provider offers it. The GPU stops billing, the disk is preserved, and you start it again without rebuilding. The dialog quotes both rates before you commit. Set up balance alerts in [User Settings](/user-settings) to receive a notification before credits run out. ### Practical tips **Use persistent volumes for datasets and model weights.** Avoid re-downloading multi-GB datasets on every deployment; mount a volume with data pre-loaded. This saves both time and egress costs. **Prefer Spot for short jobs.** Any job under 4 hours that can be checkpointed is a good Spot candidate. Switch to Dedicated for multi-day runs requiring uninterrupted time. **Batch GPU use.** Avoid leaving instances running idle. Terminate immediately when your job finishes, or stop the instance when you will return to the same environment, and re-deploy from a checkpoint when neither applies. **Use RTX 4090 for development.** The RTX 4090 is the most cost-effective GPU for code iteration, small model experiments, and inference serving at low traffic. Move to A100/H100 only when VRAM or compute requirements demand it. ### What's next * [Instance Types](/concepts/instance-types): Detailed Spot/Dedicated/Cluster comparison * [Regions & Providers](/concepts/regions-providers): Provider capabilities and GPU tiers * [Reserved GPUs](/reserved-gpus): Long-term GPU reservation form * [Instance Lifecycle](/concepts/instance-lifecycle): Stop and start an instance to pause GPU billing * [Billing](/billing): Credit management, auto top-up, and team discounts * [Volume mounting](/connecting/volume-mounting): Persistent storage for datasets and checkpoints ## General information This page lists official Spheron channels, support options, and answers to common questions. ### Official channels #### Social media * **X (Twitter)**: [https://x.com/spheronai](https://x.com/spheronai) * **LinkedIn**: [https://www.linkedin.com/company/spheron-ai/](https://www.linkedin.com/company/spheron-ai/) * **GitHub**: [https://github.com/spheron-core](https://github.com/spheron-core) * **Blog**: [https://blog.spheron.network](https://blog.spheron.network) #### Official sites * **Main website**: [https://spheron.ai](https://spheron.ai) * **Platform app**: [https://app.spheron.ai](https://app.spheron.ai) * **Documentation**: [https://docs.spheron.ai](https://docs.spheron.ai) :::warning Always verify URLs before entering credentials. Spheron will never ask for your passwords, API keys, or private SSH keys. ::: ### Support * **Chat support**: Use the chat widget on [spheron.ai](https://app.spheron.ai) for real-time assistance * **Documentation**: Browse guides and tutorials on this site * **Official contact**: Fill out the contact form on [spheron.ai](https://spheron.ai/contact) for specific inquiries ### Quick navigation * **Getting started**: [Getting Started Guide](/getting-started) | [Quick Start](/quick-start) * **Platform info**: [Overview](/overview) | [Concepts](/concepts) | [CPU Nodes](/concepts/cpu-nodes) * **Technical**: [API Reference](/api-reference) | [Connecting to instances](/connecting) * **Resources**: [Deploy Guides](/quick-guides) | [Reserved GPUs](/reserved-gpus) | [Billing](/billing) ### FAQs **Q:** How do I get started? **A:** See the [Getting Started](/getting-started) guide to deploy your first instance in 5 minutes. **Q:** Where can I get help? **A:** Use the chat support on [spheron.ai](https://app.spheron.ai) or check the documentation for guides and troubleshooting. **Q:** What is the pricing? **A:** Check [Billing](/billing) for detailed pricing. Spheron is 60-80% cheaper than traditional clouds. **Q:** Is there an API? **A:** Yes. See [API Reference](/api-reference) for full documentation. ### Important links * [Platform overview](/overview): Learn about Spheron * [Security best practices](/security): Keep your account secure * [User Settings](/user-settings): Manage your account * [Terms of Service](https://www.spheron.ai/SpheronAI_Website_Terms_of_Use.pdf): Available on [spheron.ai](https://spheron.ai) ### What's next * [Getting Started](/getting-started): Deploy your first GPU instance * [Overview](/overview): Platform features and use cases * [Security best practices](/security): Protect your account and instances * [Billing](/billing): Credits, pricing, and payment methods ## Getting started This guide takes you from account creation to a deployed and verified GPU instance in about 10 minutes. **Already have an account?** Jump to [Quick Start](/quick-start) for fast deployment. ### Prerequisites Before deploying, complete these setup steps: * A Spheron AI account (created in Step 1 below) * An SSH key pair (generated in Step 3 below) * Credits added to your account (added in Step 2 below) ### Step 1: Create your account #### Sign up 1. Visit [app.spheron.ai](https://app.spheron.ai) 2. Click **Sign Up** 3. Choose a sign-up method: * Google account * GitHub account (recommended for developers) * Email and password 4. Complete email verification if using email signup #### Navigate the dashboard Once logged in, the sidebar groups every page under three headings: **Compute** * **Deploy GPUs**: Browse the GPU catalog and launch a GPU instance * **Deploy CPU**: Launch a [CPU-only node](/concepts/cpu-nodes) for work that never touches a GPU * **Create Volume**: Provision persistent storage * **Reserved GPUs**: Request long-term reserved capacity **Manage** * **Instances**: Manage active deployments * **Volumes**: Manage persistent volumes **Account** * **Billing**: Add credits, view balance, and track usage * **Team**: Invite members and set roles * **Settings**: Profile, SSH keys, API keys, alerts, and notifications A theme switch at the bottom of the sidebar toggles between light and dark mode. Your choice is remembered across sessions. ### Step 2: Add billing #### Add credits 1. Open **Billing** from the sidebar under **Account** 2. Choose a payment method: * Credit/Debit Card * Stables (USDC/USDT) 3. Add initial credits (minimum $15, maximum $5,000 per transaction) **Pricing:** Pay-per-second billing with no hidden fees. See [Billing](/billing) for detailed pricing. :::tip Start with $15-$50 for testing. RTX 4090 costs \~$0.52/hour. Minimum deposit is $15. ::: ### Step 3: Set up SSH access SSH keys are required to access your GPU instances securely. #### Generate SSH key **On Linux/Mac:** ```bash # Generate new SSH key ssh-keygen -t ed25519 -C "your_email@example.com" # Press Enter to save to default location # Set a passphrase (optional but recommended) # Display your public key cat ~/.ssh/id_ed25519.pub ``` **On Windows (PowerShell):** ```bash # Generate new SSH key ssh-keygen -t ed25519 -C "your_email@example.com" # Display your public key type $env:USERPROFILE\.ssh\id_ed25519.pub ``` #### Upload SSH key to Spheron 1. Go to [User Settings](https://app.spheron.ai/settings) 2. Navigate to the **SSH Keys** section 3. Click **Add SSH Key** 4. Paste your public key (the one ending in `.pub`) 5. Give it a memorable name (e.g., "My Laptop") 6. Click **Save** :::warning Never share your private key. Only upload the public key (`.pub` file) to Spheron. ::: ### Step 4: Deploy your first instance #### Navigate to deploy 1. Click **Deploy GPUs** in the left sidebar under **Compute** 2. Browse the GPU catalog Your search, sort, provider, and region filters persist in the address bar. Refreshing keeps the view you were looking at, and copying the link opens the same filtered catalog for a teammate. :::tip[Not every job needs a GPU] If your workload never touches CUDA, deploy a [CPU node](/concepts/cpu-nodes) instead, from $0.09/hr. Click **Deploy CPU** in the sidebar. ::: #### Select your GPU For a first deployment, use: * **GPU:** RTX 4090 (24 GB VRAM) * **Cost:** \~$0.52/hour * **Good for:** Learning, testing, small models Click on the RTX 4090 to proceed. #### Configure instance 1. **Region:** Choose the region closest to you for lower latency 2. **Operating System:** Select **Ubuntu 22.04 LTS** for the most stable GPU driver support 3. **Storage:** Keep the default (usually sufficient) 4. **SSH Key:** Select the key you uploaded earlier 5. **Startup Script (optional):** Leave blank for now. See [Startup Scripts](/connecting) for advanced automation. #### Review and deploy 1. Check the **Order Summary** on the right: * Hourly cost * Current balance * Instance configuration 2. Click **Deploy Instance** 3. Wait 30-60 seconds for provisioning ### Step 5: Connect to your instance #### Get connection details Once deployed, the instance dashboard shows: * IP address * Username (usually `root`, `ubuntu`, or provider-specific) * SSH connection command #### Connect via SSH ```bash ssh root@ ``` If using a custom SSH key location: ```bash ssh -i ~/.ssh/id_ed25519 root@ ``` On first connection, type `yes` to accept the host fingerprint. Enter your SSH key passphrase if you set one. ### Step 6: Verify your setup Once connected, verify everything is working. #### Check GPU ```bash nvidia-smi ``` Expected output shows GPU model (RTX 4090), memory (24 GB), driver version, and GPU utilization. #### Check CUDA ```bash nvcc --version ``` The output shows the CUDA compiler version. #### Check system ```bash # Check CPU and memory htop # Check disk space df -h # Check OS version cat /etc/os-release ``` #### Test GPU access ```bash # Simple GPU test python3 -c "import torch; print(f'CUDA available: {torch.cuda.is_available()}')" ``` PyTorch does not need to be pre-installed. Install it when needed for your workload. ### Troubleshooting #### Issue: Cannot connect via SSH **Symptoms**: Connection refused or timeout when running `ssh` **Diagnosis**: Verify the SSH key is loaded: ```bash ssh-add -l ``` **Resolution**: If the key is not listed, add it: ```bash ssh-add ~/.ssh/id_ed25519 ``` Additional checks: * Verify you uploaded the correct public key * Check that firewall rules allow SSH (port 22) * Try with an explicit key path: `ssh -i ~/.ssh/id_ed25519 @` #### Issue: GPU not detected **Symptoms**: `nvidia-smi` returns an error **Diagnosis**: Drivers may still be loading after provisioning **Resolution**: Wait 30 seconds and run `nvidia-smi` again. If the error persists, reboot the instance with `sudo reboot`. #### Issue: Instance deployment failed **Symptoms**: Deployment status shows "failed" **Resolution**: * Check that your account balance has sufficient credits * Try a different region (some may be at capacity) * Contact support if the issue persists ### Stop or terminate your instance When you are finished for now but will come back to the same environment, stop the instance: 1. Go to the instance dashboard 2. Click **Stop** 3. Review the quoted stopped rate and confirm The GPU stops billing, the disk and everything on it is preserved, and starting it again returns the same public IP. Stopping is available on Spheron AI and Spheron ES. See [Instance lifecycle](/concepts/instance-lifecycle) for the full support matrix. When you are finished entirely, terminate the instance: 1. Go to the instance dashboard 2. Click **Terminate** or **Delete** 3. The instance stops and all data is permanently deleted :::warning Back up important data before terminating. Terminated instances and their data cannot be recovered. A stopped instance is also destroyed if your team runs out of credit, so terminate anything you are genuinely done with. ::: ### What's next * **[Quick Start](/quick-start)**: Condensed deployment flow for users already set up * **[CPU Nodes](/concepts/cpu-nodes)**: Deploy CPU-only compute for non-GPU workloads * **[Instance Lifecycle](/concepts/instance-lifecycle)**: Stop, start, and restart an instance * **[SSH Connection Guide](/connecting/ssh-connection)**: Advanced SSH setup and troubleshooting * **[Jupyter Notebook](/connecting/jupyter)**: Browser-based development via SSH tunnel * **[VS Code Remote](/connecting/vscode-remote)**: Remote development directly on the instance * **[Security Best Practices](/security)**: Keep your account secure ## Spheron overview Spheron is an aggregated GPU cloud that pools capacity from multiple providers and exposes it through a single API and dashboard, at 60-80% lower cost than traditional cloud providers. ### What is Spheron? Spheron is not a blockchain network. It is a GPU cloud platform that aggregates capacity from multiple providers across North America, Europe, and Asia Pacific and exposes it through a unified API and dashboard. You get a single interface across every provider without managing separate accounts, contracts, or billing relationships. Alongside GPUs, Spheron offers CPU-only nodes for workloads that need cores rather than accelerators. ### Key features #### VM access Get full root access to your instances from the moment they are deployed. You can install custom drivers, configure the operating system, and set up your software stack exactly the way you need it, with no container restrictions or sandboxed environments. #### Bare metal performance Bare metal instances give your workloads direct access to the physical hardware, with no hypervisor or virtualization layer in between. This means consistent, predictable performance and full utilization of GPU memory and compute resources for your training and inference jobs. #### Multi-GPU hosts with high-speed interconnects Deploy multi-GPU bare-metal instances with NVLink or NVSwitch between the GPUs on a host. SXM offers are purpose-built for large-scale distributed training workloads that require fast GPU-to-GPU communication and low-latency gradient synchronization. #### Aggregated provider network Access GPUs and CPU nodes from multiple providers including Verda, Sesterce, Spheron AI, Spheron ES, Spheron MS, and Massed Compute through a single dashboard and API. Switching between providers does not require separate accounts, contracts, or billing relationships. #### Hardware variety Choose from a wide range of GPU hardware to match your workload: * **High-end:** B300 SXM6, B200 SXM6, and H100 SXM5 machines with NVLink and InfiniBand for large-scale training * **Largest GPU memory:** AMD Instinct MI300X with 192 GB of HBM3e per GPU, running [ROCm](/connecting/rocm-amd) * **Mid-tier:** A100 GPUs for production workloads * **Cost-effective:** RTX 4090 and other PCIe GPUs for development and testing Offers and instance cards carry an AMD, NVIDIA, or Intel mark, so the vendor is visible before you deploy. #### Shared volumes and persistent storage Create persistent storage volumes that exist independently from your instances. Attach a volume to a running instance, detach it without losing data, and reattach it to a different instance later. Volumes support multi-instance attachment for shared datasets and model checkpoints across your team. #### CPU nodes for work that needs no GPU Not every job needs an accelerator. **CPU Node** is a CPU-only instance for build steps, data preparation, schedulers, API workers, and control planes, priced from $0.09 per hour. It has its own page in the dashboard sidebar and its own wizard, with sizes from 4 vCPU with 4 GB of memory across Verda, Sesterce, Spheron AI, and Massed Compute. Spot pricing is available on Verda. #### Reserved GPU nodes Reserve dedicated GPU nodes for long-term commitments to get better rates and guaranteed availability. Reserved instances are suited for teams with predictable, sustained compute needs who want to lock in access and reduce per-hour costs compared to on-demand pricing. #### Flexible billing and cost savings Pay only for what you use with per-second billing and no minimum commitments. Spot instances offer the same GPU hardware at lower prices when you can tolerate occasional interruptions. Combined with 60-80% savings over traditional cloud providers, Spheron significantly reduces your total infrastructure spend. #### Team coordination Manage GPU access for your entire team from a shared account. Teams share credits, SSH keys, and API keys across members. Role-based access controls let you assign owner, admin, or member permissions so each person has the right level of access for their responsibilities. ### Cost savings Spheron reduces GPU costs by 60-80% compared to traditional cloud providers: * **RTX 4090:** \~$0.52/hr (check current prices in the dashboard) * **Traditional clouds:** Typically charge 3-4x more for equivalent GPU resources * **No hidden fees:** Zero ingress/egress charges, transparent billing ### Performance notes * **Cluster (bare metal):** No hypervisor layer means direct NVLink access and no virtualization overhead for multi-GPU training * **Dedicated/Spot (VM):** High-performance VMs with guaranteed GPU access; suitable for single-node training and inference ### Platform advantages #### Reliability Five providers across dozens of regions mean you can redeploy to a different provider if one has availability issues. No single datacenter dependency. #### Scalability Deploy a single GPU instance or a multi-node H100 cluster. Scale up or down between deployments; no reserved capacity required. #### Security Choose providers with specific compliance certifications for your workload: Verda (ISO 27001, GDPR), Sesterce (SOC 2 Type II, ISO 27001), and Massed Compute (HIPAA, SOC 2 Type II). #### Stop instead of destroy Park an instance you will come back to. Stopping releases the GPU and drops billing to the disk rate while the disk and everything on it stays in place; starting returns the same environment on the same public IP. Available on Spheron AI and Spheron ES. See [Instance lifecycle](/concepts/instance-lifecycle). #### Deployment * Dashboard and REST API for deployment * Real-time metrics and monitoring * Pay-per-second billing with no hidden fees ### How Spheron compares | Feature | Spheron | Traditional Clouds | Other GPU Clouds | | -------------- | --------------------------------------------- | ------------------ | ------------------------ | | Root Access | ✅ Full by default | ⚠️ Limited | ⚠️ Container-only (some) | | Architecture | ✅ Bare metal (Cluster) / VM (Dedicated, Spot) | ❌ Virtualized | ⚠️ Mixed | | Provider Model | ✅ Aggregated | ❌ Single vendor | ❌ Single vendor | | High-end GPUs | ✅ SXM + NVLink | ⚠️ Limited | ⚠️ Limited | | Pricing | ✅ 60-80% cheaper | ❌ Premium | ⚠️ Moderate | ### Use cases * **LLM training and fine-tuning:** Single-GPU to 8x H100 NVLink runs with PyTorch DDP or DeepSpeed * **Production inference:** Dedicated instances that cannot be interrupted mid-request * **Distributed training:** Multi-GPU bare-metal instances with NVLink or NVSwitch interconnects * **Development and testing:** RTX 4090 Spot instances at \~$0.52/hr for prototyping and iteration * **Research:** EU data-resident instances (Verda, Sesterce) for GDPR-compliant workloads * **Support workloads:** CPU nodes from $0.09/hr for data prep, build steps, and schedulers that never touch a GPU ### Platform primitives Understand how the platform works before deploying at larger scales: * **[Instance Types](/concepts/instance-types)**: Spot, Dedicated, and Cluster trade-offs * **[CPU Nodes](/concepts/cpu-nodes)**: CPU-only instances, sizes, regions, and pricing * **[Instance Lifecycle](/concepts/instance-lifecycle)**: Stop, start, and restart a running instance * **[Regions & Providers](/concepts/regions-providers)**: GPU availability by provider and region * **[Networking](/concepts/networking)**: Port access, SSH tunneling, and public IPs * **[Teams](/concepts/teams)**: Shared credits, SSH keys, and role-based access ### What's next * **[Getting Started](/getting-started)**: Deploy your first instance in 5 minutes * **[Quick Start](/quick-start)**: Launch pre-configured models * **[Templates & Images](/templates)**: Copy-ready startup scripts for common stacks * **[Cost Optimization](/cost-optimization)**: GPU tier selection and spend strategies * **[Reserved GPUs](/reserved-gpus)**: Lock in long-term GPU access for better rates * **[Billing](/billing)**: Understand pricing and payment options ## Provider integration guide This guide describes the API contract a compute provider's orchestrator must expose for the Spheron AI Marketplace to list, provision, and manage GPU instances on the provider's infrastructure. It is written for the engineers who build and operate that orchestrator. By the end of integration, the marketplace can pull your offer catalog, deploy an instance on your platform, give the end user working SSH access, and stop, start, or terminate that instance, all by calling your API. The machine-readable companion is provider-orchestrator-openapi.yaml (OpenAPI 3.0.3). That file is the authoritative source for endpoint paths, payloads, and schemas. This page explains the intent and conventions behind it. :::tip Download the spec: provider-orchestrator-openapi.yaml (OpenAPI 3.0.3). Import it into Swagger UI, Postman, or your code generator to scaffold the server. ::: ### Integration model The marketplace is the client. The provider's orchestrator is the server. The integration is entirely poll-based. No webhooks or callbacks are required. After provisioning, the marketplace polls the instance-state endpoint every 10 to 30 seconds for each active instance and reacts to status transitions. Accurate, promptly updated status reporting is therefore the single most important property of the integration. All requests and responses are JSON. The marketplace sends `Content-Type: application/json` on every request body and expects the same in responses. ### Capability tiers Implement the Compute tier in full. Add the Storage tier only if your platform offers network volumes. | Tier | Scope | Required? | | ------- | ---------------------------------------------------------------------------------------------- | ----------------------------------------------------------------------------------------------------------- | | Compute | Offer catalog, real-time availability, instance create / get / list / start / stop / terminate | Required. A fully working compute tier is sufficient for a successful integration. | | Storage | Volume locations, volume create / get / attach / detach / delete | Optional. Implement only if your platform supports network volumes. Its absence does not block integration. | ### Authentication The preferred mechanism is a long-lived static API key sent on every request as `Authorization: Bearer `. ```bash # Every request carries the static API key curl -H "Authorization: Bearer " \ https://api.provider.example.com/v1/configurations ``` Keys must meet three requirements: * Scoped to the marketplace account. * Revocable. * Concurrently valid in multiples, so keys rotate with zero downtime. If your platform requires short-lived tokens instead, expose `POST /auth/token` and include `expires_in` in the response so the marketplace can refresh proactively. ### Offer catalog and availability Two endpoints serve different purposes, and both are required. #### Catalog: GET /configurations This endpoint is the catalog. It must return every offer the provider knows about, both deployable and out-of-stock, with an `available` boolean set per offer. Out-of-stock offers must be returned with `available: false`, never dropped from the array. The marketplace renders unavailable offers as out-of-stock cards with a notify-me flow. An offer that was never emitted simply vanishes from the marketplace UI. The example below shows one deployable offer and one out-of-stock offer in the same response: ```json { "configurations": [ { "id": "gpu-8x-h100-sxm", "name": "8x H100 SXM", "instance_type": "DEDICATED", "vcpus": 192, "memory_gb": 2048, "storage_gb": 8000, "gpu_count": 8, "gpu_type": "H100-SXM5-80GB", "gpu_memory_gb": 80, "price_per_hour": 21.52, "available": true, "regions": ["EU-North 1", "US-Central 1"], "os_options": ["ubuntu-22.04-cuda-12.4", "ubuntu-24.04"], "supports_cloud_init": true }, { "id": "gpu-1x-rtx4090", "name": "1x RTX 4090", "instance_type": "SPOT", "vcpus": 16, "memory_gb": 64, "storage_gb": 500, "gpu_count": 1, "gpu_type": "RTX-4090-24GB", "gpu_memory_gb": 24, "price_per_hour": 0.72, "spot_price_per_hour": 0.36, "available": false, "regions": ["EU-North 1"], "os_options": ["ubuntu-22.04-cuda-12.4"], "supports_cloud_init": true } ] } ``` #### Deploy-time gate: GET /availability This endpoint is the deploy-time gate. It returns only offers deployable right now (`available: true`), optionally filtered by region, and the marketplace calls it immediately before provisioning. It should reflect real-time inventory as closely as possible. ```bash # Check live inventory in a single region before deploying curl -H "Authorization: Bearer " \ "https://api.provider.example.com/v1/availability?region=EU-North%201" ``` #### Offer fields Each offer (`Configuration`) carries: * A stable `id` and `name`. * `instance_type`: one of `SPOT` or `DEDICATED`. * Hardware shape: `vcpus`, `memory_gb`, `storage_gb`, `gpu_count`, `gpu_type`, `gpu_memory_gb`. * Pricing: `price_per_hour` and optional `spot_price_per_hour`, both USD per hour. * `regions`, `os_options`, and `supports_cloud_init`. #### Region tokens Regions are identified by stable, human-readable tokens (for example `"EU-North 1"`), used consistently across every endpoint: offer `regions`, the availability filter, instance `region`, and volume locations. Translate internal datacenter codes to canonical tokens at the API boundary. Raw codes must never leak into responses. If the storage tier is implemented, each volume-location `id` must equal the matching offer region token. ### Instance lifecycle #### State machine Instances report one of eight canonical statuses. Map your internal platform states onto these: ```text ┌────────────► ERROR (terminal) │ PROVISIONING ────► ONLINE ◄──────────────┐ │ │ │ │ ▼ stop │ start │ STOPPING ─► STOPPED ┘ │ │ │ ▼ (reaped by platform) │ OFFLINE (terminal) ▼ terminate DESTROYING ─► DESTROYED (terminal) ``` The distinction between `STOPPED` and `OFFLINE` matters: * `STOPPED`: the resource still exists, is still owned by the deployment, and can be resumed via `/start`. * `OFFLINE`: the instance can no longer be resumed in place (for example, the platform reaped a shut-off VM) and the deployment is effectively over. `ERROR` is reserved for non-recoverable failures and should include a human-readable `error` field. #### Provisioning flow A single deployment follows this sequence. Steps 1 and 2 are marketplace calls; the rest is what your orchestrator does and reports: 1. The marketplace calls `GET /availability` to confirm live capacity. 2. The marketplace calls `POST /instances` with the offer, region, and SSH keys. 3. Your orchestrator returns a `PROVISIONING` instance record immediately, without waiting for boot. 4. The marketplace polls `GET /instances/{id}` every 10 to 30 seconds. 5. Your orchestrator transitions the instance to `ONLINE` once it has a reachable public IP (or port-forwarded SSH endpoint) and the injected SSH keys work. A create request looks like this: ```json { "configuration_id": "gpu-8x-h100-sxm", "region": "EU-North 1", "name": "spheron-d3f9a1", "ssh_keys": [ "ssh-ed25519 AAAAC3NzaC1lZDI1NTE5AAAA... user@host" ], "operating_system_image": "ubuntu-22.04-cuda-12.4", "cloud_init": { "package_update": true, "packages": ["tmux", "htop"], "runcmd": ["nvidia-smi"] } } ``` Return `201` with a `PROVISIONING` record as soon as the instance exists: ```json { "id": "inst-7f3a91c2", "configuration_id": "gpu-8x-h100-sxm", "region": "EU-North 1", "status": "PROVISIONING", "created_at": "2026-06-10T12:00:00Z", "updated_at": "2026-06-10T12:00:00Z" } ``` A later poll returns the live, reachable instance: ```json { "id": "inst-7f3a91c2", "configuration_id": "gpu-8x-h100-sxm", "region": "EU-North 1", "status": "ONLINE", "public_ip": "203.0.113.10", "ssh_port": 22, "ssh_username": "ubuntu", "gpu_count": 8, "gpu_type": "H100-SXM5-80GB", "image": "ubuntu-22.04-cuda-12.4", "price_per_hour": 21.52, "created_at": "2026-06-10T12:00:00Z", "updated_at": "2026-06-10T12:03:40Z" } ``` Expected provisioning times: * Virtual machines: reach `ONLINE` within 10 minutes, with a typical target under 5 minutes. * Bare metal: longer windows are acceptable. Agree on an SLA during onboarding, provided status is reported accurately throughout. #### SSH keys, images, and cloud-init The create request carries raw OpenSSH public key material in `ssh_keys`. The orchestrator injects these so the end user can connect. If your platform requires registered key objects, create temporary keys internally and clean them up at termination. `operating_system_image` selects one of the offer's `os_options`. When an offer reports `supports_cloud_init: true`, honor the structured `cloud_init` block (run commands, packages, file writes) on first boot. If instance names must be unique on your platform, de-duplicate (for example, by suffixing) rather than failing the request. #### Stop and start `POST /instances/{id}/stop` pauses a running instance while preserving its disk. Compute billing should pause while stopped. Document any storage charges during onboarding. `POST /instances/{id}/start` resumes the instance in place. If your platform cannot resume stopped instances, return `409` with a descriptive error rather than silently destroying state. #### Termination `DELETE /instances/{id}` destroys the instance and releases all associated resources, including temporary SSH keys or scripts created during provisioning. Once destroyed, `GET /instances/{id}` should return `404`. The marketplace interprets `404` on a previously known instance as `DESTROYED`. Deletion must be idempotent: deleting an already-destroyed instance is success, not an error. ### Volumes (optional tier) Implement these endpoints only if your platform supports network volumes: * `GET /volumes/locations`: lists regions where volumes can be created, with ids equal to region tokens. * `POST /volumes`: creates a volume, optionally attaching to instances at create time. * `POST /volumes/{id}/attach` and `/detach`: manage attachments. * `DELETE /volumes/{id}`: removes the volume. Several conventions make volume integrations robust: * Attach is idempotent. Attaching to an already-attached instance is success. * If attachment requires a stop, attach, then start cycle on your platform, handle it internally and report the intermediate instance states accurately. * If detachment is asynchronous, do not report the volume as detached until the attachment record is actually gone. * If attachment records can linger, force-detach internally before delete instead of failing. The create-instance request may carry `volume_ids` for inline attachment. Honor it if you support it; ignore it otherwise, and the marketplace falls back to post-create attach. ### Errors and operational conventions Errors use a consistent envelope with meaningful HTTP status codes: ```json { "error": { "code": "capacity_unavailable", "message": "No capacity for gpu-8x-h100-sxm in EU-North 1.", "details": {} } } ``` Map status codes as follows: | Status | Meaning | | ------ | ---------------------------------------------- | | `400` | Invalid request | | `401` | Bad credentials | | `404` | Not found (terminal for instances) | | `409` | Invalid state, or capacity loss at create time | Preserve real HTTP status codes. Do not return `200` with an embedded error. Operational expectations: * The state endpoint is polled continuously, so keep it fast and cheap. * Status transitions should be observable within seconds of occurring. * Rate limits, if any, should comfortably accommodate one poll per active instance per 10 seconds, plus catalog refreshes. * All prices are USD per hour. Memory and storage are in GB. * Timestamps are RFC 3339 UTC. ### Integration checklist A provider is ready for marketplace onboarding when: 1. All compute-tier endpoints in the OpenAPI spec are implemented and reachable over HTTPS. 2. `GET /configurations` returns the full catalog, including out-of-stock offers with `available: false`. 3. Region tokens are stable and consistent across all endpoints. 4. A test instance can be provisioned, reached over SSH with an injected key, stopped, started, and terminated, with every status transition visible via polling. 5. `GET /instances/{id}` returns `404` after termination. 6. VM provisioning reaches `ONLINE` within the agreed SLA. 7. API keys are issued, scoped to the marketplace account, and rotatable. 8. If applicable, volume endpoints pass the same lifecycle test, including idempotent attach and reliable detach. ### What we need from you to start To begin integration, share the following with the Spheron team: * Your orchestrator base URL for staging and production. * API credentials for a test account. * Your offer catalog with pricing and regions. * Expected provisioning times per instance type. * Any platform-specific constraints: naming rules, stop/start support, NAT or port-forwarding, and volume semantics. The Spheron team validates the contract with you against the checklist above. For questions, contact [info@spheron.ai](mailto\:info@spheron.ai). ### What's next * [API reference](/api-reference): the REST API the marketplace exposes to end users. * [Regions and providers](/concepts/regions-providers): how regions and providers map across the platform. * [Instance types](/concepts/instance-types): the commercial classes behind `instance_type`. * [Networking](/concepts/networking): public IPs, ports, and connectivity for deployed instances. ## Quick Start Fast GPU deployment for users with an account already configured. Deploy in under 3 minutes. :::info **First-time user?** This guide assumes you already have: * An active account with credits * An SSH key uploaded * Basic familiarity with the platform **New to Spheron?** Start with [Getting Started](/getting-started) for complete setup. ::: ### Recommended configurations Choose a configuration based on your use case: #### Development and testing **GPU:** RTX 4090 (24 GB VRAM) **Cost:** \~$0.52/hour **Best for:** Prototyping, small models, testing #### Production training **GPU:** H100 SXM5 (80 GB VRAM) **Cost:** Variable (check dashboard) **Best for:** Large language models, production training #### Research and fine-tuning **GPU:** A100 (40 GB/80 GB VRAM) **Cost:** Variable (check dashboard) **Best for:** Model fine-tuning, research workloads #### No GPU needed **Compute:** [CPU Node](/concepts/cpu-nodes) (from 4 vCPU) **Cost:** From $0.09/hour **Best for:** Data prep, build steps, schedulers, API workers ### Deploy in 3 steps ![Deploy a GPU instance in seconds](/quickdeploy.gif) :::steps #### 1. Select GPU Go to [app.spheron.ai](https://app.spheron.ai) and click **Deploy GPUs** in the sidebar. Choose from recommended configurations or browse the catalog: * **RTX 4090** for development and testing * **A100** for production training * **H100** for large-scale LLM work Filters persist in the URL, so a refresh keeps your view and the link opens the same catalog for a teammate. For a workload that never touches CUDA, click **Deploy CPU** instead. That page skips the catalog entirely and goes straight to configuration. #### 2. Configure * **Region:** Closest to your location * **OS:** Ubuntu 22.04 LTS * **SSH Key:** Select from your uploaded keys * Review pricing in the order summary #### 3. Launch Click **Deploy Instance** and wait about 30 seconds. Copy the SSH command from the instance details panel in the dashboard. The username and port vary by provider. ```bash # Spheron AI provider - username is ubuntu ssh ubuntu@ ``` ::: ### Verify and test #### Check GPU ```bash nvidia-smi # Shows GPU model, memory, driver ``` #### Quick tests ```bash # Test CUDA nvcc --version # Test PyTorch (if installed) python3 -c "import torch; print(torch.cuda.is_available())" # Monitor GPU nvidia-smi -l 1 ``` #### Install ML stack ```bash # Install common libraries pip install torch torchvision transformers accelerate bitsandbytes # Or use conda conda install pytorch torchvision torchaudio pytorch-cuda=12.1 -c pytorch -c nvidia ``` ### Advanced options #### Startup scripts Automate setup with cloud-init scripts. Add during deployment to: * Install dependencies on first boot * Configure environment variables * Clone repositories * Set up monitoring See [Startup Script examples](/connecting) for templates. #### Managing costs Stop the instance when you will return to it: * Go to the instance dashboard and click **Stop** * The GPU stops billing; the disk and its contents are preserved * Start it again on the same disk and the same public IP * Available on Spheron AI and Spheron ES Terminate the instance when you are done for good: * Go to the instance dashboard and click **Terminate** * Stops all charges immediately * All data is permanently deleted :::tip Use [Reserved GPUs](/reserved-gpus) for long-term work to save 30-50% on costs. ::: ### Troubleshooting **SSH connection issues:** * Verify the correct SSH key is uploaded: check [User Settings](https://app.spheron.ai/settings) * Try with an explicit key path: `ssh -i ~/.ssh/id_ed25519 @` * See [SSH Guide](/connecting/ssh-connection) for detailed help **GPU not showing:** * Wait 30 seconds after deployment (drivers may still be loading) * Run `nvidia-smi` to verify * Reboot if needed: `sudo reboot` **Deployment failed:** * Check that account balance has sufficient credits * Try a different region (some may be at capacity) * Contact support via the chat widget on [app.spheron.ai](https://app.spheron.ai) ### What's next #### Deploy AI models * [Deploy LLMs](/quick-guides): Run Qwen, Chandra OCR, and more * [AI Nodes](/quick-guides): Gonka AI, Pluralis #### Advanced setup * [Jupyter Notebook](/connecting/jupyter): Browser-based development * [VS Code Remote](/connecting/vscode-remote): Remote development environment * [Startup Scripts](/connecting): Automate configuration * [Templates & Images](/templates): Copy-ready startup scripts for common stacks #### Platform features * [CPU Nodes](/concepts/cpu-nodes): CPU-only instances from $0.09/hr * [Instance Lifecycle](/concepts/instance-lifecycle): Stop, start, and restart an instance * [API Reference](/api-reference): Automate deployments with the API * [Reserved GPUs](/reserved-gpus): Save 30-50% with reservations * [Security guide](/security): Best practices ## Reserved GPUs Request bulk GPU allocations, specific locations, or preferential pricing for long-term commitments. ### What are reserved GPUs Reserved GPUs are for requests requiring: * **Bulk quantities**: Multiple GPUs (8, 16, 32, 64+) * **Specific locations**: Regional compliance or data proximity requirements * **Long-term commitments**: Multi-month reservations with preferential pricing * **Custom configurations**: Specialized hardware or network requirements ### How it works 1. **Submit request**: Fill out the reservation form with your requirements 2. **Team review**: Spheron team reviews your request within 24 hours 3. **Receive quotes**: Multiple providers compete to offer the best pricing 4. **Choose option**: Select the quote that fits your needs 5. **[Book meeting](https://meetings-eu1.hubspot.com/prashant-maurya)** (optional): Schedule a consultation for complex requirements Competitive bidding across providers ensures optimal pricing. ### Benefits **Cost savings:** * 30-50% lower than on-demand hourly rates * Bulk discounts for multiple GPUs * Long-term commitment pricing advantages **Guaranteed availability:** * Reserved capacity ensures GPU access * No competition with the spot market * Predictable resource allocation **Provider competition:** * Multiple quotes from different providers * Compare pricing and terms * Choose the best value for your requirements ### Submitting a request Visit [app.spheron.ai](https://app.spheron.ai/) > **Reserved GPU** to access the request form. ![Reserved GPU Request Form](/reserved.png) :::steps #### Fill out request form ##### GPU model Select GPU type: H100, H200, A100, B200, RTX 4090, RTX 5090, L40S, A40, L4, V100 * **H100/H200:** Highest performance, large-scale training * **A100/B200:** Production-grade training and inference * **RTX 4090/5090:** Development and medium workloads * **L40S/A40:** Balanced price-performance * **L4/V100:** Cost-effective for inference Unsure? [Book a consultation](https://meetings-eu1.hubspot.com/prashant-maurya) with the team. ##### Quantity Enter the number of GPUs needed. Reserved requests start at **32 GPUs (4 nodes of 8)**. Reservations are for bulk capacity; for anything smaller, deploy from the on-demand [GPU catalog](https://app.spheron.ai) instead. ##### Duration Specify the reservation length: * Enter a value (e.g., 6) * Select a unit (Months or Years) * Choose a start time (ASAP or Within 12 Months) Longer commitments typically receive better pricing. ##### Location Select a region: North America, Europe, Asia Pacific, South America, Middle East, Africa, or Any Location * **Any Location:** Maximum provider competition, best pricing * **Specific region:** Required for data compliance or proximity ##### Start date Calendar selection for specific deployment timing (optional) ##### Additional requirements Specify custom needs (optional): * Network requirements (e.g., InfiniBand, NVLink) * Compliance needs (e.g., GDPR, HIPAA) * Storage requirements * Special configurations #### Contact information Provide your contact details so the team can deliver quotes: * **Name**: your full name * **Email**: where quotes and follow-ups are sent * **Phone** (required): include country code (e.g. `+1 555-123-4567`). Phone is validated and mandatory; the form will not advance to the review step without a valid number. #### Review and submit Review all details before submission. Edit any field if needed. Click **Submit Request** to send to the team. #### Receive quotes Within 24 hours: * Multiple provider quotes via email * Pricing, hardware specs, and availability * Terms and conditions No obligation to accept. Compare and choose the best option. ::: ### Support and consultation For complex requirements, [schedule a 30-minute consultation](https://meetings-eu1.hubspot.com/prashant-maurya) with the Spheron team to discuss GPU selection, quantity, and received quotes. For general questions, submit a request via the platform; responses are typically within 24 hours. ### Common use cases **LLM training**: Large language models requiring days or weeks of GPU time **Research projects**: Academic and lab projects needing predictable long-term costs **Production inference**: AI services requiring guaranteed GPU availability **Data processing**: Video processing, simulations, large-scale data analysis **Multi-GPU workloads**: Distributed training requiring 8+ GPUs with high-speed interconnects ### Best practices **Optimize costs:** * Request the exact quantity needed, at or above the 32 GPU minimum (submit additional requests later if needed) * Choose "Any Location" for competitive bidding unless a specific region is required * Longer commitments (6-12+ months) typically offer better per-month pricing * Select the appropriate GPU tier (L40S vs H100) based on actual workload needs **Improve quote quality:** * Provide detailed requirements in additional notes * Specify network, storage, and compliance needs upfront * Include realistic timelines * Book a consultation for complex configurations ### Frequently asked questions **Q:** Can I modify my request after submission? **A:** Contact the team with your updated requirements. The team sends a revised quote. **Q:** What if I need additional GPUs later? **A:** Submit a new request. Multiple concurrent reservations are supported. **Q:** Am I obligated to accept a quote? **A:** No. Quotes are non-binding offers. Choose only if the terms meet your needs. **Q:** What are the cancellation policies? **A:** Policies vary by provider. Review the specific terms included with each quote. **Q:** What if my preferred GPU is unavailable? **A:** Providers suggest equivalent alternatives. The large provider network ensures options are available. **Q:** How much cheaper are reserved vs on-demand? **A:** Typically 30-50% savings depending on duration, quantity, and GPU type. **Q:** Can I get a quote without committing? **A:** Yes. Request quotes with no commitment. Consultation is also free. ### What's next * [Getting Started](/getting-started): Deploy on-demand instances * [Quick Start](/quick-start): Fast deployment guide * [Cost Optimization](/cost-optimization): GPU tier selection and spend strategies * [Billing](/billing): Credit management and pricing * [General Info](/general-info): Support and official channels ## Security best practices This page covers essential security guidelines for protecting your Spheron account, API credentials, and GPU instances. Apply these practices before deploying in any production environment. :::warning Never share credentials, API keys, or SSH private keys with anyone. Spheron will never ask for this information. ::: ### Account security **Credentials protection:** * Use strong, unique passwords * Never share passwords, API keys, SSH keys, or payment info * Verify URLs before entering credentials (official: spheron.network) **Phishing protection:** * Watch for fake support messages and impersonation attempts * Use only official channels (see [General Info](/general-info)) * Verify domains before clicking links ### SSH keys SSH keys are required for instance access. Only upload public keys to Spheron. **Best practices:** * Generate keys using ED25519 or RSA 4096-bit * Use passphrases on private keys; never share them * Store private keys in a secure location, not in repositories * Rotate keys every 90 days * Use different keys for different services See [SSH Connection Guide](/connecting/ssh-connection) for setup. ### API keys API keys provide programmatic access to your account. See [API Reference](/api-reference) for endpoint details. **Best practices:** * Store API keys in environment variables; never hardcode them * Rotate every 90 days * Revoke immediately if compromised * Use separate keys per environment * Never commit API keys to version control ```bash export SPHERON_API_KEY="" # Store in environment, not in code ``` ### Monitoring and alerts Monitor regularly to detect unauthorized access: * Active instances and deployments * Billing and credit usage * API activity logs To set up alerts: * Enable billing notifications in [User Settings](/user-settings) * Set spending limits * Track unusual activity patterns See [Billing](/billing) for monitoring details. ### Instance security **Network:** * Close unnecessary ports * Configure firewall rules * Disable password authentication; use SSH keys only * Use VPN or SSH tunneling for sensitive services **System:** * Keep software updated * Apply security patches promptly * Monitor system logs regularly * Back up important data before terminating an instance **Startup scripts:** * Review scripts before deployment (they run with root privileges) * Never hardcode credentials in scripts * Use secrets management for sensitive data * Test scripts in a development environment first See [Connecting to instances](/connecting) for startup script examples. ### Official channels and support For a complete list of official Spheron channels and contact information, see [General Information](/general-info). Always verify you are on the correct official domain before: * Entering login credentials * Connecting your wallet to any website * Sharing sensitive information * Clicking links in messages or emails Bookmark official URLs and double-check domains to avoid phishing attempts. ### Reporting security issues If you suspect unauthorized access or find a vulnerability, take these steps immediately: 1. Change your account password 2. Revoke compromised API keys and SSH keys 3. Terminate any suspicious instances 4. Review billing for unauthorized usage Then report the issue: * Contact through official channels (see [General Info](/general-info)) * Provide timestamps, affected resources, and observed behavior * Report phishing attempts to help the community ### Security checklist **Account:** * [ ] Strong unique password set * [ ] Regular activity reviews scheduled **Keys:** * [ ] Only SSH public keys uploaded * [ ] Passphrases set on private keys * [ ] 90-day key rotation scheduled * [ ] API keys stored in environment variables **Instances:** * [ ] Firewall configured * [ ] Software kept up to date * [ ] Unnecessary ports closed * [ ] Instances terminated when not in use ### What's next * [Getting Started](/getting-started): Account setup * [SSH Connection Guide](/connecting/ssh-connection): SSH configuration * [API Reference](/api-reference): API key management * [User Settings](/user-settings): Account settings * [General Info](/general-info): Official channels ## Templates and images Copy-ready cloud-init startup scripts organized by use case. Paste the script into the **Startup Script** field when deploying an instance. For a full introduction to startup scripts, see the [Startup Script guide](/connecting). ### Available templates | Template | Minimum GPU | Stack | | -------------------------------------------------- | ----------- | -------------------------------- | | [PyTorch + CUDA 12.1](#pytorch--cuda-121) | RTX 4090 | Python 3.11, PyTorch 2.x | | [TensorFlow 2.x](#tensorflow-2x) | RTX 4090 | Python 3.11, TF 2.x, CUDA | | [JupyterLab ML Stack](#jupyterlab-ml-stack) | RTX 4090 | PyTorch + TF + JupyterLab | | [Docker + NVIDIA Runtime](#docker--nvidia-runtime) | Any | Docker, NVIDIA Container Toolkit | | [Prometheus + Grafana](#prometheus--grafana) | Any | Docker Compose monitoring | | [vLLM Inference Server](#vllm-inference-server) | H100 / A100 | vLLM, OpenAI-compatible API | | [Ollama + Open WebUI](#ollama--open-webui) | RTX 4090 | Docker, Ollama, Open WebUI | *** ### PyTorch + CUDA 12.1 Installs Python 3.11, PyTorch 2.x with CUDA 12.1, and common ML libraries. ```yaml #cloud-config runcmd: - apt-get update -y - apt-get install -y python3.11 python3.11-venv - python3.11 -m ensurepip --upgrade - python3.11 -m pip install --upgrade pip - python3.11 -m pip install torch torchvision torchaudio --index-url https://download.pytorch.org/whl/cu121 - python3.11 -m pip install transformers accelerate bitsandbytes datasets ``` **Verify after boot:** ```bash python3.11 -c "import torch; print(torch.cuda.is_available(), torch.version.cuda)" ``` *** ### TensorFlow 2.x Installs Python 3.11, TensorFlow 2.x with CUDA support, and common data science libraries. ```yaml #cloud-config runcmd: - apt-get update -y - apt-get install -y python3.11 - python3.11 -m ensurepip --upgrade - python3.11 -m pip install --upgrade pip - python3.11 -m pip install tensorflow[and-cuda] - python3.11 -m pip install numpy pandas scikit-learn matplotlib ``` **Verify after boot:** ```bash python3.11 -c "import tensorflow as tf; print(tf.config.list_physical_devices('GPU'))" ``` *** ### JupyterLab ML Stack Full ML environment with PyTorch, TensorFlow, and JupyterLab. JupyterLab starts on port 8888. ```yaml #cloud-config runcmd: - apt-get update -y - apt-get install -y python3.11 - python3.11 -m ensurepip --upgrade - python3.11 -m pip install --upgrade pip - python3.11 -m pip install torch torchvision --index-url https://download.pytorch.org/whl/cu121 - python3.11 -m pip install tensorflow[and-cuda] - python3.11 -m pip install jupyterlab transformers accelerate datasets matplotlib scikit-learn - | cat > /etc/systemd/system/jupyterlab.service << 'EOF' [Unit] Description=JupyterLab After=network.target [Service] Type=simple ExecStart=/usr/bin/python3.11 -m jupyterlab --ip=0.0.0.0 --port=8888 --no-browser --allow-root Restart=on-failure RestartSec=10 [Install] WantedBy=multi-user.target EOF - systemctl daemon-reload - systemctl enable jupyterlab - systemctl start jupyterlab ``` :::warning JupyterLab generates a random token on startup. Retrieve it from the service logs after boot: ```bash journalctl -u jupyterlab --no-pager | grep "token=" ``` Use SSH tunneling to access it securely: `ssh -L 8888:localhost:8888 @`, then open the URL with the token printed in the logs (e.g. `http://localhost:8888/lab?token=`). Do not open port 8888 publicly without token-based authentication. Replace `` and `` with the values from the SSH command in the instance details panel in the dashboard (e.g., `ubuntu` for Spheron AI instances). ::: *** ### Docker + NVIDIA Runtime Installs Docker CE and the NVIDIA Container Toolkit so you can run GPU-accelerated containers. ```yaml #cloud-config runcmd: - apt-get update -y - apt-get install -y ca-certificates curl gnupg - install -m 0755 -d /etc/apt/keyrings - curl -fsSL https://download.docker.com/linux/ubuntu/gpg | gpg --dearmor -o /etc/apt/keyrings/docker.gpg - chmod a+r /etc/apt/keyrings/docker.gpg - echo "deb [arch=$(dpkg --print-architecture) signed-by=/etc/apt/keyrings/docker.gpg] https://download.docker.com/linux/ubuntu $(. /etc/os-release && echo $VERSION_CODENAME) stable" > /etc/apt/sources.list.d/docker.list - apt-get update -y - apt-get install -y docker-ce docker-ce-cli containerd.io docker-compose-plugin - curl -fsSL https://nvidia.github.io/libnvidia-container/gpgkey | gpg --dearmor -o /usr/share/keyrings/nvidia-container-toolkit-keyring.gpg - curl -s -L https://nvidia.github.io/libnvidia-container/stable/deb/nvidia-container-toolkit.list | sed 's#deb https://#deb [signed-by=/usr/share/keyrings/nvidia-container-toolkit-keyring.gpg] https://#g' > /etc/apt/sources.list.d/nvidia-container-toolkit.list - apt-get update -y - apt-get install -y nvidia-container-toolkit - nvidia-ctk runtime configure --runtime=docker - systemctl restart docker ``` **Verify:** ```bash docker run --rm --gpus all nvidia/cuda:12.1.0-base-ubuntu22.04 nvidia-smi ``` *** ### Prometheus + Grafana Sets up a Docker Compose monitoring stack with Prometheus and Grafana on port 3000. ```yaml #cloud-config runcmd: - apt-get update -y - apt-get install -y ca-certificates curl gnupg - install -m 0755 -d /etc/apt/keyrings - curl -fsSL https://download.docker.com/linux/ubuntu/gpg | gpg --dearmor -o /etc/apt/keyrings/docker.gpg - chmod a+r /etc/apt/keyrings/docker.gpg - echo "deb [arch=$(dpkg --print-architecture) signed-by=/etc/apt/keyrings/docker.gpg] https://download.docker.com/linux/ubuntu $(. /etc/os-release && echo $VERSION_CODENAME) stable" > /etc/apt/sources.list.d/docker.list - apt-get update -y - apt-get install -y docker-ce docker-ce-cli containerd.io docker-compose-plugin - | ADMIN_PASS=$(openssl rand -hex 16) mkdir -p /opt/monitoring echo "Grafana admin password: $ADMIN_PASS" > /root/grafana-credentials.txt chmod 600 /root/grafana-credentials.txt echo "GF_SECURITY_ADMIN_PASSWORD=$ADMIN_PASS" > /opt/monitoring/grafana.env chmod 600 /opt/monitoring/grafana.env cat > /opt/monitoring/docker-compose.yml << 'EOF' services: prometheus: image: prom/prometheus:latest container_name: prometheus volumes: - ./prometheus.yml:/etc/prometheus/prometheus.yml restart: unless-stopped grafana: image: grafana/grafana:latest container_name: grafana ports: - "3000:3000" env_file: - ./grafana.env restart: unless-stopped node-exporter: image: prom/node-exporter:latest container_name: node-exporter volumes: - /proc:/host/proc:ro - /sys:/host/sys:ro - /:/rootfs:ro command: - '--path.procfs=/host/proc' - '--path.rootfs=/rootfs' - '--path.sysfs=/host/sys' restart: unless-stopped EOF chmod 644 /opt/monitoring/docker-compose.yml - | cat > /opt/monitoring/prometheus.yml << 'EOF' global: scrape_interval: 15s scrape_configs: - job_name: 'node' static_configs: - targets: ['node-exporter:9100'] EOF - docker compose -f /opt/monitoring/docker-compose.yml up -d ``` Access Grafana at `http://localhost:3000` via SSH tunnel. Log in as `admin` with the generated password stored in `/root/grafana-credentials.txt` on your instance: ```bash cat /root/grafana-credentials.txt ``` *** ### vLLM Inference Server Installs vLLM and starts an OpenAI-compatible inference server on port 8000. See the [full vLLM guide](/quick-guides/llms/frameworks/vllm-server) for configuration details. ```yaml #cloud-config runcmd: - apt-get update -y - apt-get install -y python3-pip - pip install vllm - | cat > /etc/systemd/system/vllm.service << 'EOF' [Unit] Description=vLLM Inference Server After=network.target [Service] Type=simple ExecStart=/usr/bin/python3 -m vllm.entrypoints.openai.api_server \ --model meta-llama/Llama-3-8B-Instruct \ --tensor-parallel-size 1 \ --port 8000 \ --gpu-memory-utilization 0.9 Restart=on-failure RestartSec=10 [Install] WantedBy=multi-user.target EOF - systemctl daemon-reload - systemctl enable vllm - systemctl start vllm ``` *** ### Ollama + Open WebUI Installs Docker and starts Ollama with the Open WebUI browser interface on port 3000. See the [full Ollama guide](/quick-guides/llms/frameworks/ollama) for model usage. ```yaml #cloud-config runcmd: - apt-get update -y - apt-get install -y ca-certificates curl gnupg - install -m 0755 -d /etc/apt/keyrings - curl -fsSL https://download.docker.com/linux/ubuntu/gpg | gpg --dearmor -o /etc/apt/keyrings/docker.gpg - chmod a+r /etc/apt/keyrings/docker.gpg - echo "deb [arch=$(dpkg --print-architecture) signed-by=/etc/apt/keyrings/docker.gpg] https://download.docker.com/linux/ubuntu $(. /etc/os-release && echo $VERSION_CODENAME) stable" > /etc/apt/sources.list.d/docker.list - apt-get update -y - apt-get install -y docker-ce docker-ce-cli containerd.io docker-compose-plugin - curl -fsSL https://nvidia.github.io/libnvidia-container/gpgkey | gpg --dearmor -o /usr/share/keyrings/nvidia-container-toolkit-keyring.gpg - curl -s -L https://nvidia.github.io/libnvidia-container/stable/deb/nvidia-container-toolkit.list | sed 's#deb https://#deb [signed-by=/usr/share/keyrings/nvidia-container-toolkit-keyring.gpg] https://#g' > /etc/apt/sources.list.d/nvidia-container-toolkit.list - apt-get update -y - apt-get install -y nvidia-container-toolkit - nvidia-ctk runtime configure --runtime=docker - systemctl restart docker - mkdir -p /opt/ollama - | cat > /opt/ollama/docker-compose.yml << 'EOF' services: ollama: image: ollama/ollama:latest container_name: ollama runtime: nvidia environment: - NVIDIA_VISIBLE_DEVICES=all volumes: - ollama_data:/root/.ollama ports: - "11434:11434" restart: unless-stopped open-webui: image: ghcr.io/open-webui/open-webui:main container_name: open-webui ports: - "3000:8080" environment: - OLLAMA_BASE_URL=http://ollama:11434 volumes: - webui_data:/app/backend/data depends_on: - ollama restart: unless-stopped volumes: ollama_data: webui_data: EOF - docker compose -f /opt/ollama/docker-compose.yml up -d ``` ### What's next * [Startup Script guide](/connecting): Cloud-init syntax and best practices * [vLLM guide](/quick-guides/llms/frameworks/vllm-server): Full vLLM configuration * [Ollama guide](/quick-guides/llms/frameworks/ollama): Model management and memory guidelines * [Networking](/concepts/networking): SSH tunneling and port exposure ## User settings Manage your account profile, SSH keys, API access credentials, GPU availability alerts, and email preferences. Access settings at [app.spheron.ai](https://app.spheron.ai/) > **Settings**. The page has five tabs: **Profile**, **SSH Keys**, **API Keys**, **Alerts**, and **Notifications**. ### Profile Update account information and preferences. ![Profile Settings](/usersetting.png) **Available fields:** * **Full Name**: Editable * **Email Address**: Must be changed through your OAuth provider (GitHub/Google) * **Company**: Optional organization name Click **Save Changes** to apply updates. ### SSH keys Manage SSH keys used to authenticate sessions on your GPU instances. Keys are scoped to the current team; switching teams shows a different key set. The header chip displays the total key count for the active team. ![SSH Keys Management](/usersetting2.png) **Each key entry shows:** * Key name * Public key (with copy button) * Date added * Delete action #### Adding SSH keys 1. Click **+ Add SSH Key** 2. Enter a key name 3. Paste public key content (from `~/.ssh/id_*.pub`) 4. Click **Save** **Generate SSH keys:** ```bash # Linux/Mac ssh-keygen -t ed25519 -C "your_email@example.com" cat ~/.ssh/id_ed25519.pub # Windows PowerShell ssh-keygen -t ed25519 -C "your_email@example.com" type $env:USERPROFILE\.ssh\id_ed25519.pub ``` See [SSH Connection Guide](/connecting/ssh-connection) for detailed setup. **Security:** Only upload public keys (`.pub` files). Never share private keys. ### API keys Generate and manage API keys for programmatic access. ![API Keys Management](/usersetting3.png) :::warning[Whitelist required before generating a key] API key generation is gated by the Spheron team. New accounts see an **API Key Generation Locked** state until your account is approved. To request access, email [info@spheron.ai](mailto\:info@spheron.ai) with the following details: * Whether you are an individual or a company * Your current location (country) * Your estimated monthly compute budget in USD * Your use case for the API key (training, inference, agents, automation, etc.) The team reviews requests to ensure secure and appropriate platform usage. Once approved, the **Generate New Key** button unlocks on this page. ::: #### Managing keys Once whitelisted and a key is issued, the **Active Key** card shows: * Masked key starting with `sai_` (with reveal-and-copy buttons) * **Expires** date plus a days-left indicator (for example, `320 DAYS LEFT`) * **Revoke** button to invalidate the key immediately To rotate a key, revoke the existing one and then click **+ Generate New Key** to issue a replacement. Only one API key can be active at a time. #### Quick reference The API keys page also displays the values needed to authenticate API requests: | Field | Value | | ------------ | ------------------------------------ | | Base URL | `https://app.spheron.ai` | | Auth header | `Authorization: Bearer YOUR_API_KEY` | | Content-Type | `application/json` | #### API capabilities With an API key, you can: * Deploy and manage GPU instances * Check GPU availability and pricing * Manage SSH keys programmatically * View account balance * Monitor usage and billing See the [API Reference](/api-reference) for complete endpoint documentation and usage examples. ### Alerts The **Alerts** tab lists your GPU availability alerts. Subscribe to one when the hardware you want is out of stock, and Spheron emails you as soon as it returns. #### Create an alert 1. Go to **Deploy GPUs** and find an offer card marked unavailable. 2. Click **Notify me** on that card. 3. Confirm the configuration: GPU type, GPU count, instance type (Spot, Dedicated, or any), and provider. CPU Node offers support alerts the same way. An out-of-stock CPU size shows the same **Notify me** action in place of the configure flow. #### Alert statuses | Status | Meaning | | --------- | --------------------------------------------------------- | | Pending | Waiting for the configuration to come back in stock | | Notified | The configuration became available and the email was sent | | Cancelled | You unsubscribed from the alert | Cancelled and notified alerts can be resubscribed from the same tab. Alerts are a dashboard feature and are not exposed on the API-key surface. ### Notifications The **Notifications** tab controls which marketing emails you receive. You are subscribed by default. Turn the toggle off and product and offer emails stop. Account and billing emails always reach you and are unaffected by this setting: * Deployment succeeded and deployment failed notices * Low-balance warnings and balance-exhaustion notices * Payment receipts and auto top-up failures Every marketing email carries a one-click unsubscribe link that opens this tab directly. ### Security best practices **API keys:** * Store in environment variables; never hardcode them * Revoke immediately if compromised * Rotate every 90 days * Generate separate keys per environment * Never commit to version control **SSH keys:** * Add keys only from controlled devices * Remove keys from lost or compromised devices * Use passphrases on private keys * Delete unused keys regularly **Monitoring:** * Review active keys periodically * Remove unrecognized keys immediately * Check key expiration dates See [Security best practices](/security) for comprehensive guidelines. ### Frequently asked questions **Q:** Why can't I change my email? **A:** Email is managed through your OAuth provider (GitHub/Google). Update it there first. **Q:** How many SSH keys can I add? **A:** There is no limit. Add keys for different devices or team members as needed. **Q:** What happens when my API key expires? **A:** Applications using that key fail. Generate a new key before expiration. **Q:** Can I have multiple active API keys? **A:** One active API key at a time. Generate a new key to replace the existing one. **Q:** Where do I find my SSH public key? **A:** * Linux/Mac: `cat ~/.ssh/id_ed25519.pub` * Windows: `type $env:USERPROFILE\.ssh\id_ed25519.pub` **Q:** Can I turn off deployment and billing emails? **A:** No. The Notifications toggle covers marketing email only. Deployment status, low-balance warnings, and payment receipts are always sent, because they affect running instances and your balance. **Q:** How do I rotate API keys safely? **A:** Generate a new key, update your applications, test them, then revoke the old key. ### What's next * [SSH Connection Guide](/connecting/ssh-connection): Detailed SSH setup * [API Reference](/api-reference): Complete API documentation * [Billing](/billing): Credits, auto top-up, and low-balance warnings * [Security best practices](/security): Comprehensive security guide * [Getting Started](/getting-started): Account setup and first deployment * [General Info](/general-info): Support and official channels ## Quick Guides ### Where to start * **Training a model?** → Start with [Distributed Training](/quick-guides/training/distributed-training) for multi-GPU, or pick any RTX 4090 Spot instance for single-GPU fine-tuning * **Running inference?** → [vLLM Server](/quick-guides/llms/frameworks/vllm-server) for an OpenAI-compatible API; [Ollama](/quick-guides/llms/frameworks/ollama) for interactive local usage * **Generating images?** → [FLUX.1](/quick-guides/image-generation/flux-1) for state-of-the-art text-to-image; [ComfyUI](/quick-guides/image-generation/comfyui) for visual workflows * **Running an AI node?** → See the [AI Nodes](#ai-nodes) section below ### Training Model training guides, from single-GPU fine-tuning to large-scale distributed runs. #### [Distributed Training (PyTorch DDP)](/quick-guides/training/distributed-training) Multi-GPU PyTorch DDP and DeepSpeed ZeRO-3 on a bare-metal SXM instance (up to 8 GPUs with NVLink). Covers `torchrun`, gradient checkpointing, BF16 precision, checkpoint persistence, and GPU monitoring. **Hardware:** Dedicated Bare Metal, SXM form factor (H100, H200, or B200; up to 8 GPUs) ### LLM inference Deploy and serve large language models on Spheron GPU instances. #### [Inference Frameworks](/quick-guides/llms/frameworks) Choose the right serving stack for your use case. #### [vLLM Inference Server](/quick-guides/llms/frameworks/vllm-server) OpenAI-compatible inference server using vLLM on H100 or A100. Includes a systemd service for persistence, SSH tunnel access, and performance tuning flags. **Hardware:** H100 80GB (7B–13B models) · 2× A100 80GB (30B+) #### [Ollama + Open WebUI](/quick-guides/llms/frameworks/ollama) Browser-based chat interface backed by Ollama on an RTX 4090. Docker Compose setup with GPU passthrough; pull any model with one command. **Hardware:** RTX 4090 (24GB VRAM) #### [DeepSeek R1 & V3](/quick-guides/llms/deepseek-r1) DeepSeek reasoning models from 7B distillations to the full 671B FP8 multi-GPU deployment. #### [Llama 4 Scout & Maverick](/quick-guides/llms/llama-4-scout) Meta's latest multimodal MoE models with long-context and image understanding. #### [Llama 3.1 / 3.2 / 3.3](/quick-guides/llms/llama-3) Meta Llama 3 family guides covering 8B through 405B with tensor parallelism. #### [Qwen3 Dense & MoE](/quick-guides/llms/qwen3) Qwen3 text models with thinking mode, 8B through 235B MoE variants. #### [Mistral & Mixtral](/quick-guides/llms/mistral-mixtral) Mistral 7B, Mixtral 8x7B MoE, and Mistral Small 3.1 with function calling. #### [Gemma 3](/quick-guides/llms/gemma-3) Google DeepMind Gemma 3, 4B through 27B, available under the Gemma Terms of Use (commercial use permitted). #### [Phi-4 & Phi-4 Multimodal](/quick-guides/llms/phi-4) Microsoft Phi-4 SLMs including the multimodal variant with image input. #### [Multimodal Models](/quick-guides/llms/multimodal) Vision-language models including Qwen3-Omni, InternVL3, LLaVA-Next, Pixtral, and Baidu ERNIE. #### [Chandra OCR](/quick-guides/llms/chandra-ocr) Specialized OCR model for document processing and text extraction. #### [Soulx Podcast-1.7B](/quick-guides/llms/soulx-podcast-1-7b) Compact 1.7B parameter model optimized for podcast and audio content generation. #### [Janus CoderV-8B](/quick-guides/llms/janus-coderv-8b) Code generation and understanding model with 8B parameters. ### Image generation Deploy GPU-accelerated image generation models on Spheron instances. #### [FLUX.1 & FLUX.2](/quick-guides/image-generation/flux-1) Black Forest Labs text-to-image models. FLUX.1-dev on RTX 4090 (24GB), FLUX.2 on H100 (80GB). **Hardware:** RTX 4090 24GB (FLUX.1-dev) · H100 80GB (FLUX.2) #### [Stable Diffusion 3.5 & SDXL](/quick-guides/image-generation/stable-diffusion-35) Stability AI diffusion models. SD 1.5 on 8GB, SDXL on 16GB, SD 3.5 on 24–40GB VRAM. **Hardware:** 8–40GB VRAM depending on model variant #### [ComfyUI](/quick-guides/image-generation/comfyui) Node-based visual workflow server for image generation. Docker-based, port 8188, SSH tunnel setup. **Hardware:** RTX 4090 24GB (recommended) ### AI nodes Deploy and run specialized AI network nodes. #### [Gonka AI Node](/quick-guides/nodes/gonka-ai) Deploy Gonka AI node infrastructure for AI compute network participation. #### [Pluralis Node 0](/quick-guides/nodes/pluralis-node-0) Set up and run Pluralis Node 0 for distributed AI network participation. ### What's next * [Instance Types](/concepts/instance-types): Choose the right GPU for your workload * [Cost Optimization](/cost-optimization): Reduce training and inference costs * [Templates & Images](/templates): Copy-ready startup scripts * [API Reference](/api-reference): Automate deployments programmatically ## Distributed Training (PyTorch DDP) Run large-scale distributed training with PyTorch DDP or DeepSpeed on a multi-GPU bare-metal instance. ### Recommended hardware #### Instance type overview Spheron GPU offerings are classified by two criteria: **interruptibility** and **hardware isolation**. All Spot instances are VM-based and can be reclaimed by the provider at any time. Use Spot only for fault-tolerant jobs with checkpointing. Dedicated instances carry a 99.95% SLA and are not reclaimed after deployment. Within Dedicated, two hardware isolation options are available: * **VM**: Runs in an isolated virtual machine on shared physical hardware. The default across most providers and GPU offers. * **Bare Metal**: Full physical server with no hypervisor, no shared tenants. GPU count varies by offer and provider, from single-GPU up to multi-GPU servers. On the dashboard, identified by the `BAREMETAL` suffix in the GPU type name. For multi-GPU distributed training, use a **Dedicated Bare Metal** offer with multiple GPUs on a single host. Bare metal removes the hypervisor layer and gives training processes direct access to every GPU and to the interconnect between them, which is what makes gradient synchronization efficient. **Offer:** Look for the `BAREMETAL` suffix in the GPU type name and a GPU count of 4 or 8 #### GPU form factor and interconnect Gradient synchronization speed depends on how the GPUs on the host talk to each other, which is determined by the GPU form factor in the offer you select: | Form factor | Intra-node interconnect | Notes | | ------------------------------------- | ----------------------- | ------------------------------------------------------------------------------ | | SXM (B200 SXM6, H200 SXM5, H100 SXM5) | NVLink / NVSwitch | Highest GPU-to-GPU bandwidth; optimal for all-reduce-heavy DDP and ZeRO-3 runs | | PCIe (H100 PCIE, A100 PCIE) | PCIe lanes | Lower cost; sufficient when gradient synchronization is not the bottleneck | Choose an SXM offer for large model training where gradient synchronization dominates step time. PCIe offers are adequate for smaller models or when cost is the priority. SXM multi-GPU offers are available on Spheron ES (B200 SXM6, H200 SXM5, H100 SXM5), Spheron AI (H200 SXM, H100 SXM5), and Verda (H100). See [Regions and Providers](/concepts/regions-providers) for current inventory per provider. :::warning[Do not use Spot for training runs] Spot instances are VM-based and can be reclaimed by the provider at any time. Do not use Spot for multi-day training runs or any job requiring uninterrupted access. Dedicated instances carry a 99.95% SLA and are not subject to provider interruption. However, **persistent volumes for checkpoints are still strongly recommended** to protect work against hardware failure or accidental termination. ::: ### Deploy the instance Deploy a multi-GPU bare-metal instance from the dashboard. On the **Deploy GPUs** page, select a Dedicated offer with the `BAREMETAL` suffix and the GPU count your run needs. Choose Ubuntu 22.04 as the operating system and attach your SSH key. ### Running distributed training with `torchrun` Once SSH'd into the instance, launch your training script with `torchrun`: ```bash torchrun \ --nproc_per_node=8 \ --nnodes=1 \ train.py \ --batch_size 32 \ --gradient_checkpointing ``` `--nproc_per_node=8` uses all 8 H100 GPUs. For a 4-GPU offer, use `--nproc_per_node=4`. ### PyTorch DDP training script Minimal example of a DDP-compatible training loop: ```python import argparse import os import torch import torch.distributed as dist from torch.nn.parallel import DistributedDataParallel as DDP from torch.utils.data import DataLoader from torch.utils.data.distributed import DistributedSampler def setup(): dist.init_process_group(backend="nccl") torch.cuda.set_device(int(os.environ["LOCAL_RANK"])) def cleanup(): dist.destroy_process_group() def train(): parser = argparse.ArgumentParser() parser.add_argument("--batch_size", type=int, default=8) parser.add_argument("--gradient_checkpointing", action="store_true") args = parser.parse_args() setup() rank = dist.get_rank() local_rank = int(os.environ["LOCAL_RANK"]) model = YourModel().to(local_rank) model = DDP(model, device_ids=[local_rank]) # Enable gradient checkpointing to reduce VRAM usage if args.gradient_checkpointing: model.module.gradient_checkpointing_enable() optimizer = torch.optim.AdamW(model.parameters(), lr=1e-4) # DistributedSampler ensures each worker sees a disjoint shard of the data dataset = YourDataset() # replace with your dataset sampler = DistributedSampler(dataset) dataloader = DataLoader(dataset, batch_size=args.batch_size, sampler=sampler) num_epochs = 3 for epoch in range(num_epochs): # Reshuffle the dataset differently for each epoch across all workers sampler.set_epoch(epoch) for step, batch in enumerate(dataloader): with torch.autocast(device_type="cuda", dtype=torch.bfloat16): loss = model(**batch).loss loss.backward() optimizer.step() optimizer.zero_grad() # Save checkpoint every 100 steps if step % 100 == 0 and rank == 0: torch.save({ 'step': step, 'epoch': epoch, 'model_state_dict': model.module.state_dict(), 'optimizer_state_dict': optimizer.state_dict(), }, f'/checkpoints/checkpoint_epoch{epoch}_step{step}.pt') cleanup() if __name__ == '__main__': train() ``` ### DeepSpeed ZeRO-3 for models >30B For models too large to fit in a single GPU's memory, use DeepSpeed ZeRO-3 to shard parameters, gradients, and optimizer states across all GPUs. `ds_config.json`: ```json { "zero_optimization": { "stage": 3, "offload_optimizer": { "device": "cpu", "pin_memory": true }, "offload_param": { "device": "cpu", "pin_memory": true }, "overlap_comm": true, "contiguous_gradients": true, "reduce_bucket_size": 5e8, "stage3_prefetch_bucket_size": 5e7, "stage3_param_persistence_threshold": 1e6 }, "bf16": { "enabled": true }, "activation_checkpointing": { "partition_activations": true, "cpu_checkpointing": true }, "train_micro_batch_size_per_gpu": 1, "gradient_accumulation_steps": 8 } ``` Launch with DeepSpeed: ```bash deepspeed --num_gpus=8 train.py \ --deepspeed ds_config.json \ --model_name_or_path meta-llama/Meta-Llama-3.1-70B ``` ### Mixed precision (BF16) H100, H200, and B200 GPUs have native BF16 support. Always use BF16 for training on these GPUs; it is faster and more numerically stable than FP16: ```python with torch.autocast(device_type="cuda", dtype=torch.bfloat16): outputs = model(**batch) ``` ### Checkpoint persistence Mount a persistent volume at `/checkpoints` before your training run to protect checkpoints across deployments: 1. Create a volume: see [Volume Mounting](/connecting/volume-mounting) 2. Mount it at `/checkpoints` in your cloud-init script 3. Save checkpoints to `/checkpoints/` in your training loop (example above) ### Dataset storage For large datasets, stage the data on the instance's local NVMe disk rather than reading it from a network volume during training. Local disks deliver much higher I/O bandwidth than NFS or virtiofs volumes. Keep the authoritative copy on a persistent volume and copy the working set to local disk at the start of the run. ### GPU monitoring Watch per-GPU utilization during training: ```bash nvidia-smi dmon -s u ``` Check NVLink health and bandwidth (SXM offers only): ```bash nvidia-smi nvlink --status nvidia-smi nvlink --capabilities ``` Monitor GPU memory: ```bash nvidia-smi --query-gpu=memory.used,memory.free --format=csv -l 1 ``` ### What's next * [Volume Mounting](/connecting/volume-mounting): Persistent checkpoint storage * [Instance Types](/concepts/instance-types): Spot vs Dedicated, and hardware isolation categories (VM, Bare Metal) * [Regions and Providers](/concepts/regions-providers): Multi-GPU inventory by provider * [Cost Optimization](/cost-optimization): Reserved GPU pricing for long-term training ## Training Guides Guides for running model training workloads on Spheron GPU instances, from single-GPU fine-tuning to large-scale distributed training on bare-metal H100 clusters. ### Choosing the right instance for training | Workload | Recommended Type | Why | | ------------------------------- | ------------------------------------ | ------------------------------------------------- | | Experiments, prototyping | Spot | 30–60% cheaper; interrupt-safe with checkpointing | | Single-GPU fine-tuning | Dedicated (RTX 4090 / A100) | No interruption risk for multi-hour runs | | Multi-GPU distributed training | Dedicated Bare Metal (multi-GPU SXM) | NVLink interconnect, full physical server access | | Production training runs (days) | Dedicated | Guaranteed availability | Use [Spot instances](/concepts/instance-types#spot) for experiments; they save significant cost. Enable checkpoint saving to a [persistent volume](/connecting/volume-mounting) so work survives if the instance is reclaimed. ### Available guides #### [Distributed Training (PyTorch DDP)](/quick-guides/training/distributed-training) Multi-GPU PyTorch DDP and DeepSpeed ZeRO-3 training on a bare-metal SXM instance (up to 8 GPUs with NVLink). Covers `torchrun` invocation, gradient checkpointing, BF16 mixed precision, checkpoint persistence, and GPU monitoring. **Best for:** Large language model pre-training and fine-tuning; multi-day training runs on multi-GPU NVLink hosts. ### What's next * [Instance Types](/concepts/instance-types): Spot vs Dedicated, and hardware isolation categories * [Volume Mounting](/connecting/volume-mounting): Persistent checkpoint storage * [Cost Optimization](/cost-optimization): Reducing training costs with Spot and Reserved GPUs import { YouTube } from '../../../components/YouTube' ## Gonka AI Node Deploy a Gonka AI node on a Spheron GPU instance. Gonka is a decentralized AI compute network that uses Proof of Work 2.0, directing GPU compute toward real AI training and inference workloads. Operators earn rewards for providing verifiable compute. ### Overview Gonka transforms GPU compute into useful AI work through Proof of Work 2.0, where computational power advances real AI models instead of solving arbitrary puzzles. Operators earn rewards for delivering verifiable compute. **Key features:** * Real AI workloads (not wasteful mining) * Honest-majority validation * Reputation-based trust system * Open, censorship-free LLM inference and training ### Hardware requirements **Minimum per MLNode:** * VRAM: 40GB+ usable * GPUs: 2-5 Network Nodes recommended **Large models** (DeepSeek R1, Qwen3-235B): * 2+ MLNodes, each with 8x H200 GPUs * 640GB+ VRAM per MLNode **Medium models** (Qwen3-32B, Gemma-3-27B): * 2+ MLNodes, each with 4x A100 or 2x H100 * 80GB+ VRAM per MLNode **Network Node server:** * CPU: 16-core * RAM: 64GB+ * Storage: 1TB NVMe SSD * Network: Stable high-speed connection **MLNode server:** * RAM: 1.5x GPU VRAM * CPU: 16-core * NVIDIA Container Toolkit with CUDA 12.6-12.9 ### Key management overview Gonka uses a three-key system: * **Account Key (Cold):** Created locally, high-privilege, store offline * **Consensus Key (TMKMS):** Managed by secure service for block validation * **ML Operational Key (Warm):** Created on server for automated transactions Read the [Gonka Key Management Guide](https://github.com/gonka-ai/gonka) before production deployment. ### Prerequisites * Spheron AI account ([sign up](https://app.spheron.ai)) * Payment method configured * SSH key (see [SSH connection guide](/connecting/ssh-connection)) * Local secure machine for Account Key generation * HuggingFace account and token ### Part A: Local machine setup #### Step 1: Install CLI tool Download the `inferenced` binary from [Gonka releases](https://github.com/gonka-ai/gonka/releases): ```bash chmod +x inferenced ./inferenced --help ``` On macOS, allow execution in System Settings → Privacy & Security if prompted. #### Step 2: Create Account Key :::warning[Run on local machine only] Run this step on your secure local machine, not on the server. ::: ```bash ./inferenced keys add gonka-account-key --keyring-backend file ``` Save the mnemonic phrase securely offline. This is your only recovery method. ### Part B: Deploy GPU on Spheron #### Step 3: Sign up and add credits 1. Go to [app.spheron.ai](https://app.spheron.ai) and sign up. 2. Click **Credits** → Add funds (card or stables). #### Step 4: Deploy instance 1. Click **Deploy** in the sidebar. 2. Select GPU: **A100 (80GB) or H100** (40GB+ VRAM required). 3. Region: Closest to you. 4. OS: **Ubuntu 22.04 LTS + CUDA 12.8**. 5. Select your SSH key. 6. Click **Deploy Instance**. ### Part C: Server setup #### Step 5: Connect to instance ```bash ssh root@ ``` #### Step 6: Install dependencies ```bash sudo apt update && apt upgrade -y sudo apt install git docker.io docker-compose -y ``` #### Step 7: Install NVIDIA container toolkit ```bash sudo apt install nvidia-container-toolkit -y sudo nvidia-ctk runtime configure --runtime=docker systemctl restart docker ``` Verify GPU access: ```bash docker run --rm --gpus all nvidia/cuda:12.2.0-base-ubuntu22.04 nvidia-smi ``` #### Step 8: Clone Gonka repository ```bash git clone https://github.com/gonka-ai/gonka.git -b main cp /root/gonka/deploy/join/config.env.template /root/gonka/deploy/join/config.env cd /root/gonka/deploy/join ``` #### Step 9: Configure environment ```bash # Create HuggingFace cache directory mkdir -p /mnt/shared ``` Edit `config.env`: ```bash nano config.env ``` Required fields: * Key name * Public URL of your node * Account public key * SSH ports Load the configuration: ```bash source config.env ``` Configure `node-config.json`: * Define MLNodes and inference ports * Specify models to load * Set concurrent request limits #### Step 10: Download model weights ```bash # Setup HuggingFace cache mkdir -p $HF_HOME sudo apt update && apt install -y python3-pip pipx pipx install huggingface_hub[cli] pipx ensurepath export PATH="$HOME/.local/bin:$PATH" # Download model hf download Qwen/Qwen2.5-7B-Instruct ``` #### Step 11: Pull containers ```bash # Pull all images docker compose -f docker-compose.yml -f docker-compose.mlnode.yml pull # Start chain components source config.env && docker compose up tmkms node -d --no-deps # Check logs docker compose logs tmkms node -f ``` #### Step 12: Create ML operational key Enter the API container: ```bash docker compose run --rm --no-deps -it api /bin/sh ``` Create the warm key: ```bash printf '%s\n%s\n' "$KEYRING_PASSWORD" "$KEYRING_PASSWORD" | inferenced keys add "$KEY_NAME" --keyring-backend file ``` Save the mnemonic, then exit the container: ```bash exit ``` #### Step 13: Register host Re-enter the API container: ```bash docker compose run --rm --no-deps -it api /bin/sh ``` Register the participant: ```bash inferenced register-new-participant \ $DAPI_API__PUBLIC_URL \ $ACCOUNT_PUBKEY \ --node-address $DAPI_CHAIN_NODE__SEED_API_URL ``` Exit: ```bash exit ``` #### Step 14: Grant permissions (switch to local machine) :::warning[Run on local machine only] Run this step on your local machine where you created the Account Key. ::: ```bash ./inferenced tx inference grant-ml-ops-permissions \ gonka-account-key \ \ --from gonka-account-key \ --keyring-backend file \ --gas 2000000 \ --node /chain-rpc/ ``` This grants the ML Operational Key permission to submit inference proofs. #### Step 15: Launch node (switch back to server) ```bash source config.env && \ docker compose -f docker-compose.yml -f docker-compose.mlnode.yml up -d ``` All services start: chain node, API node, MLNodes. ### Verification #### Check participant registration ``` http://node2.gonka.ai:8000/v1/participants/ ``` The response displays your public key in JSON. #### Check current epoch After Proof of Compute completes (every 24 hours): ``` http://node2.gonka.ai:8000/v1/epochs/current/participants ``` #### Monitor dashboard ``` http://node2.gonka.ai:8000/dashboard/gonka/validator ``` Track the next Proof of Compute session timing. #### Check node status Using public IP: ```bash curl http://:/status ``` Using private (on server): ```bash curl http://0.0.0.0:26657/status ``` Using genesis node: ```bash curl http://node2.gonka.ai:26657/status ``` ### Proof of Compute **Simulation:** Test PoC on MLNode before the actual PoC phase begins. **Timing:** * Runs every 24 hours * Check the dashboard for the next session * Stop the server between sessions and restart before PoC ### Troubleshooting #### Issue: Container won't start **Symptoms:** Container exits immediately or fails to start. **Diagnosis:** ```bash docker ps -a docker compose logs ``` **Resolution:** Verify configuration and reload: ```bash source config.env env | grep DAPI ``` #### Issue: GPU not accessible **Symptoms:** NVIDIA toolkit not found or GPU not visible in container. **Resolution:** ```bash nvidia-ctk --version sudo nvidia-ctk runtime configure --runtime=docker systemctl restart docker ``` #### Issue: Permission grant failed **Symptoms:** Transaction rejected or timeout. **Resolution:** * Verify the Account Key is correct. * Check network connectivity to the seed node. * Ensure sufficient gas. * Verify the ML Operational Key address. #### Issue: PoC failures **Symptoms:** Proof of Compute does not complete. **Resolution:** * Verify all MLNodes have sufficient VRAM. * Confirm model weights downloaded correctly. * Review MLNode logs: `docker compose logs mlnode` ### Managing your node **Update profile:** Update host name, website, and avatar on the dashboard to help the network identify your node. **Monitor performance:** * Check PoC completion status. * View earned rewards. * Monitor GPU usage: `nvidia-smi -l 1` **Stop node:** ```bash docker compose down ``` **Restart node:** ```bash source config.env && \ docker compose -f docker-compose.yml -f docker-compose.mlnode.yml up -d ``` ### What's next * [Gonka GitHub](https://github.com/gonka-ai/gonka) * [Gonka Dashboard](http://node2.gonka.ai:8000/dashboard) * [Getting Started](/getting-started): Spheron deployment basics * [SSH Connection](/connecting/ssh-connection): SSH setup guide ## AI Node Guides Guides for deploying and running AI network nodes on Spheron GPU instances. Participate in decentralized AI compute networks and distributed model training protocols. ### Choosing the right instance for AI nodes | Node Type | Recommended Type | Why | | -------------- | --------------------------- | ---------------------------------------------- | | Gonka AI Node | Dedicated (A100 / H100) | Sustained uptime for Proof of Work 2.0 tasks | | Pluralis Node0 | Dedicated (RTX 4090 / A100) | 16GB+ VRAM required for collaborative training | Use Dedicated instances for node operations to ensure consistent availability. Spot instances may be interrupted, which can affect node participation and rewards. ### Available guides #### [Gonka AI Node](/quick-guides/nodes/gonka-ai) Decentralized AI network using Proof of Work 2.0 for meaningful compute contribution to AI training and inference. Docker-based deployment on A100 or H100 instances. **Best for:** Contributing GPU compute to the Gonka decentralized AI network. #### [Pluralis Node 0](/quick-guides/nodes/pluralis-node-0) Collaborative multi-participant model training via Protocol Learning. Node0-7.5B enables permissionless participation in distributed AI model pretraining with 16GB+ VRAM. **Best for:** Participating in collaborative distributed AI model training. ### What's next * [Instance Types](/concepts/instance-types): Spot vs Dedicated vs Cluster * [Networking](/concepts/networking): SSH tunneling and port access * [Getting Started](/getting-started): Deploy your first Spheron instance import { YouTube } from '../../../components/YouTube' ## Pluralis Node0-7.5B Deploy a Pluralis Node0-7.5B on a Spheron GPU instance. Pluralis Protocol Learning allows multiple participants to collaboratively train large-scale foundation models without central ownership. Node0-7.5B enables permissionless participation in distributed AI model pretraining with 16GB+ VRAM. ### Overview Models remain unextractable and become collectively owned protocol assets under the Pluralis Protocol Learning framework. **Node0-7.5B:** Permissionless, model-parallel pretraining framework for GPUs with 16GB+ VRAM. ### Requirements **Hardware:** * GPU: 16GB+ VRAM * RAM: 16GB+ recommended * Storage: 50GB free * Network: Stable connection **Recommended GPUs:** * RTX 4090, A100, H100 **Software:** * Ubuntu 22.04 or 24.04 * Python 3.11 * Miniconda * Git ### Prerequisites * Spheron account ([sign up](https://app.spheron.ai)) * Payment method configured * SSH key (see [SSH connection guide](/connecting/ssh-connection)) * HuggingFace account and token ([get token](https://huggingface.co/settings/tokens)) ### Step 1: Deploy GPU on Spheron 1. **Sign up** at [app.spheron.ai](https://app.spheron.ai). 2. **Add credits:** Click Credits → Add funds (card/stables). 3. **Deploy:** * Click **Deploy** in the sidebar. * Select GPU: **RTX 4090, A100, or H100** (16GB+ VRAM). * Region: Closest to you. * OS: **Ubuntu 22.04 or 24.04 LTS**. * Select your SSH key. * Click **Deploy Instance**. ### Step 2: Connect to instance ```bash ssh root@ ``` ### Step 3: Install dependencies ```bash # Install PyTorch (CPU version for setup) pip3 install torch torchvision torchaudio --index-url https://download.pytorch.org/whl/cpu # Install Git sudo apt install -y git ``` ### Step 4: Clone repository ```bash git clone https://github.com/PluralisResearch/node0 cd node0 ``` ### Step 5: Install Miniconda ```bash # Download installer wget https://repo.anaconda.com/miniconda/Miniconda3-latest-Linux-x86_64.sh -O ~/miniconda.sh # Install bash ~/miniconda.sh -b -p ~/miniconda3 # Initialize ~/miniconda3/bin/conda init bash # Clean up rm ~/miniconda.sh # Verify source ~/miniconda3/etc/profile.d/conda.sh && conda --version ``` ### Step 6: Create Conda environment ```bash # Create environment conda create -n node0 python=3.11 -y # Activate conda activate node0 # Install Node0 pip install . ``` ### Step 7: Configure Node0 ```bash # Generate configuration python3 generate_script.py --host_port 49200 --announce_port 22 ``` When prompted, enter your HuggingFace token: 1. Visit [huggingface.co/settings/tokens](https://huggingface.co/settings/tokens). 2. Create a new token with "Read" permissions. 3. Copy and paste when prompted. ### Step 8: Start Node0 server ```bash ./start_server.sh ``` The server starts and begins listening on the configured ports. ### Verification Check server status: ```bash # Monitor logs tail -f logs/node0.log # Verify process running ps aux | grep node0 ``` Confirm participation: * Check the Pluralis dashboard for your node. * Verify network connectivity. * Monitor contribution metrics. ### Troubleshooting #### Issue: Installation fails **Symptoms:** pip or conda errors during setup. **Resolution:** ```bash # Verify Python version python --version # Check conda environment conda env list ``` #### Issue: HuggingFace token error **Symptoms:** Authentication failure when generating configuration. **Resolution:** * Verify the token has "Read" permissions. * Regenerate the token if expired. * Check that the token was copied without extra spaces. #### Issue: Server won't start **Symptoms:** `start_server.sh` exits with an error. **Resolution:** ```bash # Check ports available lsof -i :49200 lsof -i :22 # View error logs cat logs/node0.log ``` #### Issue: Connection issues **Symptoms:** Node cannot reach the Pluralis network. **Resolution:** * Verify the firewall allows ports 49200 and 22. * Check GPU is accessible: `nvidia-smi` * Ensure sufficient VRAM is available. ### What's next * [Pluralis Research GitHub](https://github.com/PluralisResearch/node0) * [Getting Started](/getting-started): Spheron deployment basics * [SSH Connection](/connecting/ssh-connection): SSH setup guide * [General Info](/general-info): Support channels import { YouTube } from '../../../components/YouTube' ## Chandra OCR Deploy [Chandra OCR](https://huggingface.co/datalab-to/chandra) on a Spheron GPU instance. Chandra OCR converts images and PDFs into structured Markdown, HTML, or JSON while preserving document layout, hierarchy, and visual elements. It achieves 83.1% accuracy on the olmOCR benchmark, outperforming GPT-4o, Mistral OCR, and DeepSeek OCR. ### Key capabilities * Multi-format output (Markdown, HTML, JSON) * Handwriting recognition * Form reconstruction (including checkboxes) * Complex layouts (tables, math equations) * Visual element extraction (images, diagrams, captions) * 40+ languages Chandra OCR supports two inference modes: * **Local:** HuggingFace transformers for privacy-sensitive and edge deployments * **Remote:** vLLM server for scalable production and high-throughput pipelines Benchmark accuracy on olmOCR (83.1% overall): | Category | Accuracy | | --------------- | -------- | | Headers/Footers | 90.8% | | Long Tiny Text | 92.3% | | Tables | 88.0% | | ArXiv | 82.2% | Accuracy vs. competitors: +13.2 pp vs. GPT-4o, +19.3 pp vs. Gemini Flash 2, +4 pp vs. dots.ocr ### Deployment tiers | Tier | GPU | Performance | Use Case | | -------------------- | ------------------------------- | ------------- | -------------------------- | | **Dev/Test** | CPU | 0.1-0.3 img/s | PoC, batch processing | | **Cost-Optimized** | RTX 3060/4060 Ti (4-bit) | 0.4-0.8 img/s | Moderate volumes | | **High-Performance** | RTX 3090/4090, L40S (BF16/FP16) | 1.5-3.0 img/s | High daily volumes | | **Enterprise** | A100/H100 (FlashAttention2) | 3.0-5.0 img/s | Mission-critical pipelines | | **Distributed** | 2x A100/H100 (tensor-parallel) | 5.0-8.0 img/s | Real-time OCR services | The model weights are available on [HuggingFace](https://huggingface.co/datalab-to/chandra). ### Manual setup Use these steps to set up the server manually after SSH-ing into your instance. This works on any provider regardless of cloud-init support. #### Step 1: Provision a Spheron instance 1. Sign up at [app.spheron.ai](https://app.spheron.ai) 2. Add credits (card/stables) 3. Click **Deploy** → Select GPU (see Deployment Tiers above) → Region → **Ubuntu 22.04** → add your SSH key → **Deploy** See [Getting Started](/getting-started) or [SSH Connection](/connecting/ssh-connection) for details. #### Step 2: Connect to your instance ```bash ssh @ ``` Replace `` with the username shown in the instance details panel (e.g., `root` or `ubuntu`) and `` with your instance's public IP. #### Step 3: Update system packages ```bash sudo apt update && sudo apt install -y software-properties-common curl ca-certificates ``` #### Step 4: Add Python PPA repository ```bash sudo add-apt-repository -y ppa:deadsnakes/ppa sudo apt update ``` #### Step 5: Install Python 3.11 ```bash sudo apt-get -o Acquire::Retries=3 install -y python3.11 python3.11-venv python3.11-dev ``` #### Step 6: Set up pip ```bash python3.11 -m ensurepip --upgrade python3.11 -m pip install --upgrade pip setuptools wheel ``` #### Step 7: Create virtual environment ```bash python3.11 -m venv ~/.venvs/py311 source ~/.venvs/py311/bin/activate ``` #### Step 8: Install PyTorch (CUDA 12.1) ```bash pip install --index-url https://download.pytorch.org/whl/cu121 torch torchvision torchaudio ``` #### Step 9: Install Chandra OCR dependencies ```bash pip install chandra-ocr vllm transformers accelerate pillow bitsandbytes ``` ### Usage #### Launch web interface ```bash chandra_app ``` Access at: **[http://localhost:8501](http://localhost:8501)** **Features:** * Upload PDFs or images * Visualize OCR results * Export as Markdown, HTML, or JSON ### Programmatic usage ```python from chandra_ocr import ChandraOCR # Initialize the model ocr = ChandraOCR() # Process a document result = ocr.process("path/to/document.pdf", output_format="markdown") # Print the result print(result) ``` #### Batch processing ```python import os from chandra_ocr import ChandraOCR ocr = ChandraOCR() input_dir = "path/to/documents" output_dir = "path/to/output" for filename in os.listdir(input_dir): if filename.endswith((".pdf", ".png", ".jpg")): input_path = os.path.join(input_dir, filename) result = ocr.process(input_path, output_format="markdown") output_path = os.path.join(output_dir, f"{filename}.md") with open(output_path, "w") as f: f.write(result) ``` ### Advanced configuration #### vLLM server (high throughput) ```bash # Install vLLM if not already installed pip install vllm # Start the vLLM server python -m vllm.entrypoints.openai.api_server \ --model datalab-to/chandra \ --dtype bfloat16 \ --max-model-len 4096 ``` #### Custom parameters ```python from chandra_ocr import ChandraOCR ocr = ChandraOCR( max_tokens=2048, temperature=0.7, batch_size=4, use_flash_attention=True ) ``` ### Performance optimization #### Memory * Use 4-bit or 8-bit quantization to reduce VRAM requirements. * Reduce batch size when you encounter out-of-memory errors. * Enable gradient checkpointing for large documents. #### Speed * Enable FlashAttention2 on A100 and H100 GPUs. * Use vLLM for concurrent multi-request processing. * Use distributed inference for high-volume workloads. #### Accuracy * Use BF16 or FP16 precision for full-precision output. * Process images at 2560 px or higher resolution. * Apply multi-pass processing for critical documents. ### Troubleshooting #### OOM errors ```bash # Solution 1: Reduce batch size ocr = ChandraOCR(batch_size=1) # Solution 2: Use quantization pip install bitsandbytes ocr = ChandraOCR(quantization="4bit") # Solution 3: Lower resolution ocr.process("document.pdf", max_resolution=1920) ``` #### Slow processing ```bash # Ensure CUDA is properly configured python -c "import torch; print(torch.cuda.is_available())" # Check GPU utilization nvidia-smi # Enable vLLM for better throughput # See Advanced Configuration section above ``` #### Installation issues ```bash # If pip install fails, try: pip install --no-cache-dir chandra-ocr # Or install dependencies separately: pip install torch torchvision --index-url https://download.pytorch.org/whl/cu121 pip install transformers accelerate pip install chandra-ocr ``` ### Supported formats **Input formats:** PNG, JPEG, JPG, TIFF, BMP, WebP, PDF, scanned documents, screenshots **Specialized document types:** Academic papers, forms, tables, equations, diagrams, handwritten notes **Output formats:** * **Markdown:** Preserves structure, hierarchy, and formatting * **HTML:** Browser-ready output with semantic markup * **JSON:** Includes text, layout, bounding boxes, confidence scores, and metadata ### Best practices #### Document quality * Use good lighting and scan at 300 DPI or higher. * Avoid skewed or rotated pages and remove background noise before processing. #### Deployment * Start with the Balanced tier and scale up as volume increases. * Monitor GPU usage and adjust batch sizes to stay within VRAM limits. * Add error handling and retry logic to your pipeline. #### Production * Use async processing for web applications. * Use a queue system for high-volume workloads. * Cache results for frequently processed documents. * Add logging and monitoring to track throughput and errors. ### Use cases * **Enterprise:** Legacy archives, invoice automation, contract analysis, compliance reporting * **Academic:** Research papers, databases, publications, historical documents * **Legal and financial:** Contracts, statements, filings, due diligence review * **Healthcare:** Medical records, prescriptions, forms, clinical trial documents ### Cloud-init startup script (optional) If your provider supports cloud-init, you can paste this into the **Startup Script** field when deploying to automate the environment setup. After the instance is ready, SSH in and run `. /opt/chandra-ocr/bin/activate && chandra_app` to launch the web interface. ```yaml #cloud-config runcmd: - apt update && apt install -y software-properties-common curl ca-certificates - add-apt-repository -y ppa:deadsnakes/ppa - apt update - apt-get -o Acquire::Retries=3 install -y python3.11 python3.11-venv python3.11-dev - python3.11 -m ensurepip --upgrade - python3.11 -m pip install --upgrade pip setuptools wheel - python3.11 -m venv /opt/chandra-ocr - /opt/chandra-ocr/bin/pip install --index-url https://download.pytorch.org/whl/cu121 torch torchvision torchaudio - /opt/chandra-ocr/bin/pip install chandra-ocr vllm transformers accelerate pillow bitsandbytes ``` After cloud-init completes, activate the environment and start the web interface: ```bash . /opt/chandra-ocr/bin/activate chandra_app ``` ### What's next * [Specialized Models](/quick-guides/llms/specialized-models): Compare Chandra OCR with SoulX Podcast and Janus CoderV * [vLLM Inference Server](/quick-guides/llms/frameworks/vllm-server): Configure vLLM for high-throughput OCR pipelines * [Instance Types](/concepts/instance-types): Select the right GPU tier for your document volume * [Getting Started](/getting-started): Create a Spheron account and deploy your first instance ## DeepSeek R1 & V3 Deploy [DeepSeek R1](https://huggingface.co/deepseek-ai/DeepSeek-R1) and [DeepSeek V3](https://huggingface.co/deepseek-ai/DeepSeek-V3) reasoning models on Spheron GPU instances using vLLM. DeepSeek R1 features chain-of-thought reasoning exposed via `` blocks; distilled variants (7B–32B) run on single GPUs. ### Recommended hardware | Model | Recommended GPU | Instance Type | Notes | | ---------------- | ------------------ | ----------------- | -------------------------- | | R1-Distill-7B | RTX 4090 (24GB) | Dedicated or Spot | Single-GPU, fast iteration | | R1-Distill-14B | A100 40GB | Dedicated | Full precision | | R1-Distill-32B | A100 80GB (INT4) | Dedicated | AWQ quantization | | DeepSeek-V3 671B | 8× H100 80GB (FP8) | Cluster | `--tensor-parallel-size 8` | | DeepSeek-R1 671B | 8× H100 80GB (FP8) | Cluster | `--tensor-parallel-size 8` | ### Manual setup Use these steps to set up the server manually after SSH-ing into your instance. This works on any provider regardless of cloud-init support. #### Step 1: Connect to your instance ```bash ssh @ ``` Replace `` with the username shown in the instance details panel (e.g., `ubuntu` for Spheron AI instances) and `` with your instance's public IP. #### Step 2: Install vLLM ```bash sudo apt-get update -y sudo apt-get install -y python3-pip pip install vllm ``` #### Step 3: Start the server Run the server in the foreground to verify it works: ```bash python3 -m vllm.entrypoints.openai.api_server \ --model deepseek-ai/DeepSeek-R1-Distill-Qwen-7B \ --port 8000 \ --dtype bfloat16 ``` Press `Ctrl+C` to stop. #### Step 4: Run as a background service To keep the server running after you close your SSH session, create a systemd service: ```bash sudo tee /etc/systemd/system/vllm-deepseek.service > /dev/null << 'EOF' [Unit] Description=DeepSeek R1 vLLM Inference Server After=network.target [Service] Type=simple ExecStart=/usr/bin/python3 -m vllm.entrypoints.openai.api_server \ --model deepseek-ai/DeepSeek-R1-Distill-Qwen-7B \ --port 8000 \ --dtype bfloat16 Restart=on-failure RestartSec=10 [Install] WantedBy=multi-user.target EOF sudo systemctl daemon-reload sudo systemctl enable vllm-deepseek sudo systemctl start vllm-deepseek ``` For the full DeepSeek-R1 671B model on 8× H100, replace the `ExecStart` command with: ```bash /usr/bin/python3 -m vllm.entrypoints.openai.api_server \ --model deepseek-ai/DeepSeek-R1 \ --port 8000 \ --dtype fp8 \ --tensor-parallel-size 8 \ --gpu-memory-utilization 0.95 ``` ### Accessing the server :::warning[Port 8000 is publicly accessible by default] Use SSH tunneling during development or add `--api-key ` to the vLLM startup command. ::: #### SSH tunnel ```bash ssh -L 8000:localhost:8000 @ ``` ### Usage example: reasoning block parsing DeepSeek R1 outputs reasoning inside `...` tags before the final answer. ```python from openai import OpenAI import re client = OpenAI(base_url="http://localhost:8000/v1", api_key="not-needed") response = client.chat.completions.create( model="deepseek-ai/DeepSeek-R1-Distill-Qwen-7B", messages=[{"role": "user", "content": "What is 17 × 23? Show your reasoning."}], ) content = response.choices[0].message.content # Extract reasoning and final answer think_match = re.search(r"(.*?)", content, re.DOTALL) if think_match: reasoning = think_match.group(1).strip() answer = content[think_match.end():].strip() print("Reasoning:", reasoning) print("Answer:", answer) else: print(content) ``` ### Cloud-init startup script (optional) If your provider supports cloud-init, you can paste this into the **Startup Script** field when deploying to automate the setup above. #### R1-Distill-7B (RTX 4090) ```yaml #cloud-config write_files: - path: /etc/systemd/system/vllm-deepseek.service content: | [Unit] Description=DeepSeek R1 vLLM Inference Server After=network.target [Service] Type=simple ExecStart=/usr/bin/python3 -m vllm.entrypoints.openai.api_server \ --model deepseek-ai/DeepSeek-R1-Distill-Qwen-7B \ --port 8000 \ --dtype bfloat16 Restart=on-failure RestartSec=10 [Install] WantedBy=multi-user.target runcmd: - apt-get update -y - apt-get install -y python3-pip - pip install vllm - systemctl daemon-reload - systemctl enable vllm-deepseek - systemctl start vllm-deepseek ``` #### DeepSeek-R1 671B (8× H100, FP8) Replace the ExecStart line with: ```bash /usr/bin/python3 -m vllm.entrypoints.openai.api_server \ --model deepseek-ai/DeepSeek-R1 \ --port 8000 \ --dtype fp8 \ --tensor-parallel-size 8 \ --gpu-memory-utilization 0.95 ``` ### What's next * [vLLM Inference Server](/quick-guides/llms/frameworks/vllm-server): vLLM configuration details * [Llama 3.1 / 3.2 / 3.3](/quick-guides/llms/llama-3): Meta Llama model guides * [Instance Types](/concepts/instance-types): H100 NVLink cluster for full 671B * [Cost Optimization](/cost-optimization): GPU tier selection for inference workloads ## Gemma 3 Deploy [Gemma 3](https://huggingface.co/google/gemma-3-27b-it) from Google DeepMind on Spheron GPU instances using vLLM. Gemma 3 is released under the [Gemma Terms of Use](https://ai.google.dev/gemma/terms), which permits commercial use and modification after accepting Google's license agreement. :::warning[HuggingFace Token Required] Gemma 3 models require accepting Google's terms on HuggingFace. Visit [google/gemma-3-27b-it](https://huggingface.co/google/gemma-3-27b-it) to request access, then set `HF_TOKEN` in your environment before running the server. ::: ### Recommended hardware | Model | Recommended GPU | Instance Type | Notes | | --------------------- | --------------- | ----------------- | -------------- | | Gemma-3-4B-IT | Any 8GB GPU | Spot | Lightweight | | Gemma-3-12B-IT | RTX 4090 (24GB) | Dedicated or Spot | Full precision | | Gemma-3-27B-IT | A100 80GB | Dedicated | Full precision | | Gemma-3-27B-IT (INT4) | RTX 4090 (24GB) | Dedicated or Spot | AWQ 4-bit | ### Manual setup Use these steps to set up the server manually after SSH-ing into your instance. This works on any provider regardless of cloud-init support. #### Step 1: Connect to your instance ```bash ssh @ ``` Replace `` with the username shown in the instance details panel (e.g., `ubuntu` for Spheron AI instances) and `` with your instance's public IP. #### Step 2: Install vLLM ```bash sudo apt-get update -y sudo apt-get install -y python3-pip pip install vllm ``` #### Step 3: Start the server Run the server in the foreground to verify it works: ```bash HF_TOKEN= python3 -m vllm.entrypoints.openai.api_server \ --model google/gemma-3-12b-it \ --port 8000 \ --dtype bfloat16 ``` Press `Ctrl+C` to stop. Replace `` with your HuggingFace token. For Gemma-3-27B on A100 80GB, replace the model with `google/gemma-3-27b-it`. #### Step 4: Run as a background service To keep the server running after you close your SSH session, create a restricted token file and a systemd service: ```bash # Store the token in a file readable only by root sudo mkdir -p /etc/vllm sudo install -m 600 /dev/null /etc/vllm/hf-token echo "HF_TOKEN=" | sudo tee -a /etc/vllm/hf-token > /dev/null sudo tee /etc/systemd/system/vllm-gemma3.service > /dev/null << 'EOF' [Unit] Description=Gemma 3 vLLM Inference Server After=network.target [Service] Type=simple EnvironmentFile=/etc/vllm/hf-token ExecStart=/usr/bin/python3 -m vllm.entrypoints.openai.api_server \ --model google/gemma-3-12b-it \ --port 8000 \ --dtype bfloat16 Restart=on-failure RestartSec=10 [Install] WantedBy=multi-user.target EOF sudo systemctl daemon-reload sudo systemctl enable vllm-gemma3 sudo systemctl start vllm-gemma3 ``` Replace `` with your HuggingFace token. Using `EnvironmentFile=` with `chmod 600` prevents other local users from reading the token via `systemctl show`. ### Accessing the server :::warning[Port 8000 is publicly accessible by default] Use SSH tunneling during development or add `--api-key ` to the vLLM startup command. ::: #### SSH tunnel ```bash ssh -L 8000:localhost:8000 @ ``` ### Usage example ```python from openai import OpenAI client = OpenAI(base_url="http://localhost:8000/v1", api_key="not-needed") response = client.chat.completions.create( model="google/gemma-3-12b-it", messages=[{"role": "user", "content": "Explain the Apache 2.0 license in one paragraph."}], ) print(response.choices[0].message.content) ``` :::info[Gemma Terms of Use] Gemma 3 is released under the [Gemma Terms of Use](https://ai.google.dev/gemma/terms). You must accept Google's license agreement on HuggingFace before downloading the model weights. Commercial use and modification are permitted under these terms. ::: ### Cloud-init startup script (optional) If your provider supports cloud-init, you can paste this into the **Startup Script** field when deploying to automate the setup above. #### Gemma-3-12B (RTX 4090) ```yaml #cloud-config write_files: - path: /etc/systemd/system/vllm-gemma3.service content: | [Unit] Description=Gemma 3 vLLM Inference Server After=network.target [Service] Type=simple EnvironmentFile=/etc/vllm/hf-token ExecStart=/usr/bin/python3 -m vllm.entrypoints.openai.api_server \ --model google/gemma-3-12b-it \ --port 8000 \ --dtype bfloat16 Restart=on-failure RestartSec=10 [Install] WantedBy=multi-user.target runcmd: - apt-get update -y - apt-get install -y python3-pip - pip install vllm - mkdir -p /etc/vllm - install -m 600 /dev/null /etc/vllm/hf-token - echo "HF_TOKEN=" >> /etc/vllm/hf-token - systemctl daemon-reload - systemctl enable vllm-gemma3 - systemctl start vllm-gemma3 ``` Replace `` with your HuggingFace token. #### Gemma-3-27B (A100 80GB) Replace the model in ExecStart with `google/gemma-3-27b-it`. ### What's next * [vLLM Inference Server](/quick-guides/llms/frameworks/vllm-server): vLLM configuration details * [Phi-4 & Phi-4 Multimodal](/quick-guides/llms/phi-4): Another efficient small model option * [Instance Types](/concepts/instance-types): GPU selection for small models * [Cost Optimization](/cost-optimization): Spot instances for Gemma 3 ## LLM & AI Guides Guides for running language model and AI inference workloads on Spheron GPU instances, from interactive chat interfaces to high-throughput OpenAI-compatible API servers. ### Choosing the right instance for inference | Workload | Recommended Type | Why | | ------------------------- | ------------------------ | ----------------------------------------- | | Interactive chat, testing | Spot (RTX 4090) | Cost-effective for low-traffic usage | | Production API (7B–13B) | Dedicated (H100 80GB) | Consistent latency, single-GPU throughput | | Large models (30B+) | Dedicated (2× A100 80GB) | Multi-GPU tensor parallelism | | 70B+ models | Cluster (H100 NVLink) | NVLink bandwidth for maximum throughput | Use [Spot instances](/concepts/instance-types#spot) for experiments and development; switch to Dedicated for production traffic. ### Inference frameworks Choose the right serving stack for your use case. See the [Inference Frameworks](/quick-guides/llms/frameworks) index for a comparison. #### [vLLM Inference Server](/quick-guides/llms/frameworks/vllm-server) OpenAI-compatible inference server using vLLM on H100 or A100. Includes a systemd service for persistence across reboots, SSH tunnel access, and performance tuning flags (`--tensor-parallel-size`, `--dtype`, `--max-model-len`). **Best for:** Production API workloads; drop-in replacement for the OpenAI API. #### [Ollama + Open WebUI](/quick-guides/llms/frameworks/ollama) Browser-based chat interface backed by Ollama on an RTX 4090. Docker Compose setup with NVIDIA GPU passthrough; pull any model with a single command. **Best for:** Interactive local model usage; exploring models without writing code. #### [SGLang](/quick-guides/llms/frameworks/sglang) Agentic LLM serving with RadixAttention for KV cache reuse, constrained decoding, and OpenAI-compatible API. **Best for:** Agentic pipelines, multi-turn workloads, and structured output generation. #### [TensorRT-LLM + Triton](/quick-guides/llms/frameworks/tensorrt-llm) NVIDIA-optimized engine compilation via TensorRT-LLM with Triton Inference Server for production-grade serving. **Best for:** Maximum throughput on NVIDIA GPUs; production deployments requiring low latency. #### [llama.cpp Server](/quick-guides/llms/frameworks/llama-cpp) GGUF model serving with CPU+GPU offload, lightweight and portable. **Best for:** Running quantized models on consumer GPUs; mixed CPU/GPU inference. #### [LMDeploy](/quick-guides/llms/frameworks/lmdeploy) LMDeploy TurboMind inference toolkit with AWQ quantization support. **Best for:** Memory-efficient deployment with AWQ-quantized models on A100/H100. #### [LocalAI](/quick-guides/llms/frameworks/localai) OpenAI-compatible drop-in replacement via Docker with support for LLMs, Whisper, and Stable Diffusion. **Best for:** Multi-modal local inference with a single OpenAI-compatible endpoint. ### Text models #### [DeepSeek R1 & V3](/quick-guides/llms/deepseek-r1) DeepSeek reasoning models, from 7B distillations to the full 671B FP8 multi-GPU deployment. Includes `` reasoning block parsing. **Best for:** Complex reasoning tasks, math, and code generation. #### [Llama 4 Scout & Maverick](/quick-guides/llms/llama-4-scout) Meta's latest multimodal MoE models (Scout 109B and Maverick 400B) with long-context and image understanding. **Best for:** State-of-the-art multimodal reasoning with large context windows. #### [Llama 3.1 / 3.2 / 3.3](/quick-guides/llms/llama-3) Meta Llama 3 family: 8B on RTX 4090, 70B on 2× A100, 405B on 8× H100 with tensor parallelism and function calling. **Best for:** General-purpose chat, instruction following, and function calling. #### [Qwen3 Dense & MoE](/quick-guides/llms/qwen3) Qwen3 text models with thinking mode toggle, 7B dense through 235B-A22B MoE on multi-GPU. **Best for:** Reasoning tasks with controllable chain-of-thought via `/think` and `/no_think` tokens. #### [Mistral & Mixtral](/quick-guides/llms/mistral-mixtral) Mistral 7B, Mixtral 8x7B MoE, and Mistral Small 3.1 24B with function calling support. **Best for:** Efficient inference with strong instruction following and function calling. #### [Gemma 3](/quick-guides/llms/gemma-3) Google DeepMind Gemma 3 in 4B, 12B, and 27B (INT4). Available under the Gemma Terms of Use; commercial use is permitted after accepting Google's license agreement on HuggingFace. **Best for:** Low-latency inference on smaller GPUs; research and commercial projects. #### [Phi-4 & Phi-4 Multimodal](/quick-guides/llms/phi-4) Microsoft Phi-4 14B SLM and Phi-4-multimodal with image input support. MIT license. **Best for:** Efficient SLM inference; multimodal tasks on a single RTX 4090. ### Multimodal models #### [Qwen3-Omni-30B-A3B](/quick-guides/llms/multimodal/qwen3-omni-30b-a3b) Multimodal language model with 30B parameters supporting text, audio, images, and video inputs. 32K context window (single GPU) on A100/H100. **Best for:** Multimodal tasks requiring audio, vision, and text processing in a single model. #### [Qwen3-VL 4B & 8B](/quick-guides/llms/multimodal/qwen3-vl-4b-8b) Vision-language models available in 4B and 8B parameter variants. 256K context, multimodal reasoning, and GUI automation capabilities on RTX 4090 or A100. **Best for:** Image understanding, visual reasoning, and GUI automation tasks. #### [InternVL3](/quick-guides/llms/multimodal/internvl3) InternVL3 vision-language model series, 8B through 78B, deployed via vLLM. **Best for:** High-accuracy visual question answering and multimodal reasoning. #### [LLaVA-Next](/quick-guides/llms/multimodal/llava-next) LLaVA-NeXT vision-language model (7B/13B) with improved visual reasoning, deployed via vLLM. **Best for:** Image-to-text tasks; accessible VLM on RTX 4090 or A100. #### [Pixtral-12B](/quick-guides/llms/multimodal/pixtral-12b) Mistral's Pixtral-12B multimodal model, deployed via vLLM on RTX 4090 (24GB). **Best for:** Compact multimodal inference with Mistral-quality text generation. #### [Baidu ERNIE-4.5-VL-28B-A3B](/quick-guides/llms/multimodal/baidu-ernie-4-5-vl-28b-a3b) Advanced vision-language model from Baidu with 28B active parameters (MoE architecture). Strong visual reasoning and STEM task performance on RTX 4090 or A6000. **Best for:** Visual reasoning, multimodal understanding, and STEM-domain tasks. ### Specialized models #### [Chandra OCR](/quick-guides/llms/chandra-ocr) Specialized OCR model for document processing with 83.1% accuracy, outperforming GPT-4o on document tasks. Supports vLLM deployment for high-throughput document pipelines. **Best for:** Document digitization, text extraction, and OCR pipelines. #### [Soulx Podcast-1.7B](/quick-guides/llms/soulx-podcast-1-7b) Multi-speaker podcast generation model (1.7B parameters). Generates 60+ minute dialogues with speaker switching, zero-shot voice cloning, and paralinguistics. **Best for:** Audio content generation, podcast production, and voice synthesis. #### [Janus CoderV-8B](/quick-guides/llms/janus-coderv-8b) 8B multimodal code intelligence model. Generates HTML/CSS/React from screenshots, charts, and mockups. Trained on JANUSCODE-800K, the largest multimodal code dataset. **Best for:** Visual-to-code translation, layout bug fixing, and UI mockup generation. ### What's next * [Instance Types](/concepts/instance-types): Spot vs Dedicated vs Cluster * [Networking](/concepts/networking): SSH tunneling and port access * [Cost Optimization](/cost-optimization): Reducing inference costs with Spot instances * [Templates & Images](/templates): Copy-ready startup scripts import { YouTube } from '../../../components/YouTube' ## Janus CoderV-8B Deploy [JanusCoderV-8B](https://huggingface.co/internlm/JanusCoderV-8B) on a Spheron GPU instance. JanusCoderV-8B is an 8B multimodal model that generates code from visual inputs including charts, screenshots, and UI mockups. It converts images into HTML, CSS, React components, and data visualization code. ### Key capabilities * Visual-to-code translation: converts charts and screenshots to HTML and code * Layout bug fixing from screenshot inputs * Animation reconstruction using Manim * 32K token context support * Multimodal understanding across text, images, and code **Benchmarks:** * ChartMimic: 74.20 (beats Qwen2.5VL-7B, InternVL3.5-8B) * WebCode2,M: 18.28 (best open-weight structural correctness) * InteractScience: 33.32 (visual metrics leader) ### Requirements **Hardware:** * GPU: RTX 4090, A100, or H100 (16 GB VRAM minimum, 24 GB recommended) * RAM: 16 GB (32 GB for large context workloads) * Storage: 20 GB (SSD recommended) **Software:** * Ubuntu 22.04 LTS * CUDA 12.1 or later * Python 3.11 ### Manual setup Use these steps to set up the server manually after SSH-ing into your instance. This works on any provider regardless of cloud-init support. #### Step 1: Provision a Spheron instance 1. Sign up at [app.spheron.ai](https://app.spheron.ai) 2. Add credits (card/stables) 3. Click **Deploy** → **RTX 4090** → Region → **Ubuntu 22.04** → add your SSH key → **Deploy** See [Getting Started](/getting-started) or [SSH Connection](/connecting/ssh-connection) for details. #### Step 2: Connect to your instance ```bash ssh @ ``` Replace `` with the username shown in the instance details panel (e.g., `root` or `ubuntu`) and `` with your instance's public IP. #### Step 3: Set up the environment ```bash sudo apt update && apt install -y software-properties-common curl ca-certificates sudo add-apt-repository -y ppa:deadsnakes/ppa sudo apt update ``` #### Step 4: Install Python 3.11 ```bash sudo apt install -y python3.11 python3.11-venv python3.11-dev python3.11 -m ensurepip --upgrade python3.11 -m pip install --upgrade pip setuptools wheel ``` #### Step 5: Create virtual environment ```bash python3.11 -m venv ~/.venvs/py311 source ~/.venvs/py311/bin/activate ``` #### Step 6: Install PyTorch (CUDA) ```bash pip install --index-url https://download.pytorch.org/whl/cu121 torch torchvision torchaudio ``` #### Step 7: Install dependencies ```bash pip install -U "transformers>=4.57.0" accelerate huggingface-hub safetensors pillow requests pip install -U bitsandbytes ``` ### Create the runner script Create `run_januscoder.py` using nano, vim, or an SSH-capable editor: ```python #!/usr/bin/env python3 # JanusCoderV-8B runner (InternVL head) # Uses AutoModelForImageTextToText + AutoProcessor and supports URL/local images. import argparse import io import sys import requests import torch from PIL import Image from transformers import AutoProcessor, AutoModelForImageTextToText # <-- key class MODEL_NAME = "internlm/JanusCoderV-8B" def load_image_from_url(url: str) -> Image.Image: response = requests.get(url, timeout=30) response.raise_for_status() return Image.open(io.BytesIO(response.content)).convert("RGB") def load_image_local(path: str) -> Image.Image: return Image.open(path).convert("RGB") def main(): parser = argparse.ArgumentParser() source_group = parser.add_mutually_exclusive_group(required=True) source_group.add_argument("--image-url", type=str, help="URL of the image to process") source_group.add_argument("--image-path", type=str, help="Local path to the image file") parser.add_argument("--task", type=str, default="Please describe the image explicitly.", help="Task description for the model") parser.add_argument("--max-new-tokens", type=int, default=1024, help="Maximum number of new tokens to generate") parser.add_argument("--bits8", action="store_true", help="Load model in 8-bit mode (requires bitsandbytes)") parser.add_argument("--no-bf16", action="store_true", help="Force FP16 inputs instead of BF16") args = parser.parse_args() use_bf16 = (not args.no_bf16) and torch.cuda.is_available() and torch.cuda.is_bf16_supported() input_dtype = torch.bfloat16 if use_bf16 else torch.float16 print(f"torch={torch.__version__} | cuda={torch.cuda.is_available()} | bf16_ok={use_bf16} | dtype={input_dtype}") print("Loading processor …") processor = AutoProcessor.from_pretrained(MODEL_NAME, trust_remote_code=True) print("Loading model …") load_kwargs = dict(device_map="auto", trust_remote_code=True) if args.bits8: load_kwargs["load_in_8bit"] = True else: load_kwargs["torch_dtype"] = input_dtype # Use torch_dtype for consistency model = AutoModelForImageTextToText.from_pretrained(MODEL_NAME, **load_kwargs).eval() # Build messages with either URL or PIL image content = [] if args.image_url: content.append({"type": "image", "url": args.image_url}) else: pil_image = load_image_local(args.image_path) content.append({"type": "image", "image": pil_image}) content.append({"type": "text", "text": args.task}) messages = [{"role": "user", "content": content}] print("Tokenizing …") inputs = processor.apply_chat_template( messages, add_generation_prompt=True, tokenize=True, return_dict=True, return_tensors="pt", ) # Move input tensors to model device/dtype device = next(iter(model.parameters())).device for key, value in list(inputs.items()): if torch.is_floating_point(value): inputs[key] = value.to(device, dtype=input_dtype) else: inputs[key] = value.to(device) print("Generating …") with torch.inference_mode(): output_ids = model.generate(**inputs, max_new_tokens=args.max_new_tokens, do_sample=False, use_cache=True) prompt_length = inputs["input_ids"].shape[1] generated_text = processor.decode(output_ids[0, prompt_length:], skip_special_tokens=True) print("\n" + "=" * 80 + "\nOUTPUT:\n" + "=" * 80) print(generated_text) if __name__ == "__main__": main() ``` ### Usage examples #### Basic image description ```bash python run_januscoder.py \ --image-url https://c7.alamy.com/comp/BHKEPY/woman-running-with-two-rottweilers-canis-lupus-familiaris-in-garden-BHKEPY.jpg ``` #### Generate HTML/CSS from a mockup ```bash python run_januscoder.py \ --image-url https://example.com/mockup.jpg \ --task "Generate responsive HTML+CSS from this mockup." ``` #### Process a local image ```bash python run_januscoder.py \ --image-path /path/to/image.jpg \ --task "Convert this UI mockup into React components." ``` #### Convert a chart to code ```bash python run_januscoder.py \ --image-url https://example.com/chart.png \ --task "Generate matplotlib code to recreate this chart." ``` #### Fix layout bugs ```bash python run_januscoder.py \ --image-path screenshot.png \ --task "Identify layout issues and provide corrected CSS." ``` ### Configuration **Arguments:** * `--image-url` or `--image-path`: Input source (URL or local file path) * `--task`: Task description (default: "describe image") * `--max-new-tokens`: Maximum output length (default: 1024) * `--bits8`: Enable 8-bit quantization to reduce VRAM usage * `--no-bf16`: Force FP16 for GPU compatibility 8-bit quantization for low VRAM: ```bash python run_januscoder.py --image-url --bits8 ``` Long output for complex tasks: ```bash python run_januscoder.py --image-url --max-new-tokens 4096 ``` FP16 mode for GPU compatibility: ```bash python run_januscoder.py --image-url --no-bf16 ``` ### Performance optimization * **Memory:** Use `--bits8`, lower `--max-new-tokens`, and batch smaller workloads. * **Speed:** Use BF16 on A100 and H100 GPUs; ensure CUDA is properly configured and caching is enabled. * **Quality:** Use high-resolution images, write detailed task prompts, and increase `--max-new-tokens` for complex outputs. ### Use cases * **Web development:** Convert mockups to HTML/CSS, generate responsive layouts, fix layout bugs, create React and Vue components. * **Data visualization:** Convert charts to matplotlib or plotly code and generate interactive dashboards. * **Animation:** Rebuild animations using Manim, generate SVG, or create CSS animations. * **Documentation:** Generate code explanations, visual docs, and GUI documentation from screenshots. ### Troubleshooting #### Issue: Out-of-memory (OOM) error Use 8-bit quantization, reduce output length, or switch to FP16: ```bash # Use 8-bit quantization python run_januscoder.py --image-url --bits8 # Reduce output length python run_januscoder.py --image-url --max-new-tokens 512 # Use FP16 python run_januscoder.py --image-url --no-bf16 ``` #### Issue: Model download failures Set a custom cache directory with sufficient storage: ```bash export HF_HOME=/path/to/large/storage export TRANSFORMERS_CACHE=/path/to/large/storage python run_januscoder.py --image-url ``` #### Issue: CUDA errors Verify CUDA availability and reinstall PyTorch if needed: ```bash python -c "import torch; print(torch.cuda.is_available())" nvidia-smi pip install --index-url https://download.pytorch.org/whl/cu121 torch torchvision torchaudio ``` #### Issue: Image loading errors Download the image locally or fix file permissions: ```bash wget https://example.com/image.jpg python run_januscoder.py --image-path image.jpg --task "Your task" chmod 644 /path/to/image.jpg ``` ### Best practices * **Prompts:** Be specific. Include the target format (HTML/CSS, Python) and framework (React, Vue). * **Images:** Use high-resolution, well-lit, and cropped images in standard formats (JPEG or PNG). * **Output:** Save generated code to files, review before use, iterate on prompts, and track what works. * **Resources:** Monitor GPU usage with `nvidia-smi`, close unused processes, use quantization, and batch tasks where possible. ### Integration example Python subprocess wrapper: ```python import subprocess def generate_code_from_image(image_path, task): cmd = ["python", "run_januscoder.py", "--image-path", image_path, "--task", task, "--max-new-tokens", "2048"] result = subprocess.run(cmd, capture_output=True, text=True) return result.stdout code = generate_code_from_image("mockup.png", "Generate React components") ``` Flask API wrapper: ```python from flask import Flask, request, jsonify import subprocess app = Flask(__name__) @app.route('/generate', methods=['POST']) def generate(): data = request.json cmd = ["python", "run_januscoder.py", "--image-url", data['image_url'], "--task", data.get('task', 'Describe')] result = subprocess.run(cmd, capture_output=True, text=True) return jsonify({"code": result.stdout}) app.run(port=5000) ``` ### Performance on Spheron | Task | RTX 4090 time | A100 time | VRAM usage | | -------------------------- | ------------- | --------- | ---------- | | Simple description | 5 s | 3 s | 12 GB | | HTML generation | 10 s | 6 s | 14 GB | | Complex output (2K tokens) | 20 s | 12 s | 16 GB | | Full output (4K tokens) | 40 s | 24 s | 18 GB | ### Supported output formats * **Web:** HTML/CSS, JavaScript, React, Vue, Tailwind, Bootstrap * **Data visualization:** Python (matplotlib, plotly), JavaScript (D3, Chart.js), R (ggplot2) * **Animation:** Manim, CSS, JavaScript, SVG * **Other:** SVG, LaTeX, Processing, Three.js ### Cloud-init startup script (optional) If your provider supports cloud-init, you can paste this into the **Startup Script** field when deploying to automate the environment setup. After the instance is ready, SSH in, activate the virtual environment, and create the `run_januscoder.py` script following the [Create Runner Script](#create-runner-script) section above. ```yaml #cloud-config runcmd: - apt update && apt install -y software-properties-common curl ca-certificates - add-apt-repository -y ppa:deadsnakes/ppa - apt update - apt install -y python3.11 python3.11-venv python3.11-dev - python3.11 -m ensurepip --upgrade - python3.11 -m pip install --upgrade pip setuptools wheel - python3.11 -m venv /opt/januscoder - /opt/januscoder/bin/pip install --index-url https://download.pytorch.org/whl/cu121 torch torchvision torchaudio - /opt/januscoder/bin/pip install -U "transformers>=4.57.0" accelerate huggingface-hub safetensors pillow requests bitsandbytes ``` After cloud-init completes, SSH in, activate the environment, and create the runner script: ```bash source /opt/januscoder/bin/activate # Create run_januscoder.py as shown in the "Create the runner script" section above python run_januscoder.py --image-url https://example.com/image.jpg ``` ### What's next * [Specialized Models](/quick-guides/llms/specialized-models): Compare Janus CoderV with Chandra OCR and SoulX Podcast * [Instance Types](/concepts/instance-types): Select the right GPU for multimodal code generation * [Getting Started](/getting-started): Create a Spheron account and deploy your first instance * [SSH Connection](/connecting/ssh-connection): Connect to your instance after deployment ## Llama 3.1 / 3.2 / 3.3 Deploy Meta's Llama 3 family on Spheron GPU instances using vLLM. The Llama 3 series covers 8B through 405B parameters with strong instruction following and function calling capabilities. :::warning[HuggingFace Token Required] Llama 3 models are gated on HuggingFace. Request access at [meta-llama/Meta-Llama-3.1-8B-Instruct](https://huggingface.co/meta-llama/Meta-Llama-3.1-8B-Instruct), then set `HF_TOKEN` in your environment before running the server. ::: ### Recommended hardware | Model | Recommended GPU | Instance Type | Notes | | -------------------- | --------------- | ----------------- | -------------------------------------- | | Llama 3.1/3.2/3.3 8B | RTX 4090 (24GB) | Dedicated or Spot | Single-GPU | | Llama 3.1 70B | 2× A100 80GB | Dedicated | `--tensor-parallel-size 2` | | Llama 3.1 405B | 8× H100 80GB | Cluster | `--tensor-parallel-size 8 --dtype fp8` | ### Manual setup Use these steps to set up the server manually after SSH-ing into your instance. This works on any provider regardless of cloud-init support. #### Step 1: Connect to your instance ```bash ssh @ ``` Replace `` with the username shown in the instance details panel (e.g., `ubuntu` for Spheron AI instances) and `` with your instance's public IP. #### Step 2: Install vLLM ```bash sudo apt-get update -y sudo apt-get install -y python3-pip pip install vllm ``` #### Step 3: Start the server Run the server in the foreground to verify it works: ```bash HF_TOKEN= python3 -m vllm.entrypoints.openai.api_server \ --model meta-llama/Meta-Llama-3.1-8B-Instruct \ --port 8000 \ --dtype bfloat16 ``` Press `Ctrl+C` to stop. Replace `` with your HuggingFace token. #### Step 4: Run as a background service To keep the server running after you close your SSH session, create a restricted token file and a systemd service: ```bash # Store the token in a file readable only by root sudo mkdir -p /etc/vllm sudo install -m 600 /dev/null /etc/vllm/hf-token echo "HF_TOKEN=" | sudo tee -a /etc/vllm/hf-token > /dev/null sudo tee /etc/systemd/system/vllm-llama3.service > /dev/null << 'EOF' [Unit] Description=Llama 3 vLLM Inference Server After=network.target [Service] Type=simple EnvironmentFile=/etc/vllm/hf-token ExecStart=/usr/bin/python3 -m vllm.entrypoints.openai.api_server \ --model meta-llama/Meta-Llama-3.1-8B-Instruct \ --port 8000 \ --dtype bfloat16 Restart=on-failure RestartSec=10 [Install] WantedBy=multi-user.target EOF sudo systemctl daemon-reload sudo systemctl enable vllm-llama3 sudo systemctl start vllm-llama3 ``` Replace `` with your HuggingFace token. Using `EnvironmentFile=` with `chmod 600` prevents other local users from reading the token via `systemctl show`. #### Llama 3.1 70B (2× A100 80GB) For the 70B model, replace the `ExecStart` command with: ```bash /usr/bin/python3 -m vllm.entrypoints.openai.api_server \ --model meta-llama/Meta-Llama-3.1-70B-Instruct \ --port 8000 \ --dtype bfloat16 \ --tensor-parallel-size 2 ``` #### Llama 3.1 405B (8× H100) The 405B model in BF16 requires more than 640 GB VRAM and cannot run on a single 8× H100 node. Use the official FP8 quantized variant, which fits within the 640 GB total VRAM available across 8× H100 80GB. ```bash /usr/bin/python3 -m vllm.entrypoints.openai.api_server \ --model meta-llama/Meta-Llama-3.1-405B-Instruct-FP8 \ --port 8000 \ --dtype fp8 \ --tensor-parallel-size 8 \ --gpu-memory-utilization 0.95 ``` ### Accessing the server :::warning[Port 8000 is publicly accessible by default] Use SSH tunneling during development or add `--api-key ` to the vLLM startup command. ::: #### SSH tunnel ```bash ssh -L 8000:localhost:8000 @ ``` ### Usage example: function calling (Llama 3.1/3.3) ```python from openai import OpenAI import json client = OpenAI(base_url="http://localhost:8000/v1", api_key="not-needed") tools = [ { "type": "function", "function": { "name": "get_weather", "description": "Get current weather for a city", "parameters": { "type": "object", "properties": {"city": {"type": "string"}}, "required": ["city"], }, }, } ] response = client.chat.completions.create( model="meta-llama/Meta-Llama-3.1-8B-Instruct", messages=[{"role": "user", "content": "What is the weather in Paris?"}], tools=tools, tool_choice="auto", ) if response.choices[0].message.tool_calls: tool_call = response.choices[0].message.tool_calls[0] print(f"Function: {tool_call.function.name}") print(f"Arguments: {tool_call.function.arguments}") ``` ### Cloud-init startup script (optional) If your provider supports cloud-init, you can paste this into the **Startup Script** field when deploying to automate the setup above. #### Llama 3.1 8B (RTX 4090) ```yaml #cloud-config runcmd: - apt-get update -y - apt-get install -y python3-pip - pip install vllm - mkdir -p /etc/vllm - install -m 600 /dev/null /etc/vllm/hf-token - echo "HF_TOKEN=" >> /etc/vllm/hf-token - | cat > /etc/systemd/system/vllm-llama3.service << 'EOF' [Unit] Description=Llama 3 vLLM Inference Server After=network.target [Service] Type=simple EnvironmentFile=/etc/vllm/hf-token ExecStart=/usr/bin/python3 -m vllm.entrypoints.openai.api_server \ --model meta-llama/Meta-Llama-3.1-8B-Instruct \ --port 8000 \ --dtype bfloat16 Restart=on-failure RestartSec=10 [Install] WantedBy=multi-user.target EOF - systemctl daemon-reload - systemctl enable vllm-llama3 - systemctl start vllm-llama3 ``` #### Llama 3.1 70B (2× A100 80GB) Replace the ExecStart line with: ```bash /usr/bin/python3 -m vllm.entrypoints.openai.api_server \ --model meta-llama/Meta-Llama-3.1-70B-Instruct \ --port 8000 \ --dtype bfloat16 \ --tensor-parallel-size 2 ``` #### Llama 3.1 405B (8× H100) ```bash /usr/bin/python3 -m vllm.entrypoints.openai.api_server \ --model meta-llama/Meta-Llama-3.1-405B-Instruct-FP8 \ --port 8000 \ --dtype fp8 \ --tensor-parallel-size 8 \ --gpu-memory-utilization 0.95 ``` ### What's next * [Llama 4 Scout & Maverick](/quick-guides/llms/llama-4-scout): Latest Llama generation * [vLLM Inference Server](/quick-guides/llms/frameworks/vllm-server): vLLM configuration details * [Instance Types](/concepts/instance-types): Multi-GPU setup for 70B+ models * [Cost Optimization](/cost-optimization): Spot vs Dedicated for inference workloads ## Llama 4 Scout & Maverick Deploy [Meta Llama 4](https://huggingface.co/meta-llama) Scout and Maverick on Spheron GPU instances using vLLM. Llama 4 introduces a Mixture-of-Experts (MoE) architecture with native multimodal support for text and images. :::warning[HuggingFace Token Required] Llama 4 models are gated on HuggingFace. Request access at [meta-llama/Llama-4-Scout-17B-16E-Instruct](https://huggingface.co/meta-llama/Llama-4-Scout-17B-16E-Instruct), then set `HF_TOKEN` in your environment before running the server. ::: ### Recommended hardware | Model | Parameters | Recommended GPU | Instance Type | Notes | | ---------------- | ----------------- | --------------- | ------------- | ------------------ | | Llama 4 Scout | 109B (17B active) | H100 80GB (FP8) | Dedicated | MoE, 16 experts | | Llama 4 Maverick | 400B (17B active) | 8× H200 141 GB | Cluster | Requires multi-GPU | ### Manual setup Use these steps to set up the server manually after SSH-ing into your instance. This works on any provider regardless of cloud-init support. #### Step 1: Connect to your instance ```bash ssh @ ``` Replace `` with the username shown in the instance details panel (e.g., `ubuntu` for Spheron AI instances) and `` with your instance's public IP. #### Step 2: Install vLLM ```bash sudo apt-get update -y sudo apt-get install -y python3-pip pip install vllm ``` #### Step 3: Start the server Run the server in the foreground to verify it works: ```bash HF_TOKEN= python3 -m vllm.entrypoints.openai.api_server \ --model meta-llama/Llama-4-Scout-17B-16E-Instruct \ --port 8000 \ --dtype fp8 \ --gpu-memory-utilization 0.95 ``` Press `Ctrl+C` to stop. Replace `` with your HuggingFace token. #### Step 4: Run as a background service To keep the server running after you close your SSH session, create a restricted token file and a systemd service: ```bash # Store the token in a file readable only by root sudo mkdir -p /etc/vllm sudo install -m 600 /dev/null /etc/vllm/hf-token echo "HF_TOKEN=" | sudo tee -a /etc/vllm/hf-token > /dev/null sudo tee /etc/systemd/system/vllm-llama4.service > /dev/null << 'EOF' [Unit] Description=Llama 4 Scout vLLM Inference Server After=network.target [Service] Type=simple EnvironmentFile=/etc/vllm/hf-token ExecStart=/usr/bin/python3 -m vllm.entrypoints.openai.api_server \ --model meta-llama/Llama-4-Scout-17B-16E-Instruct \ --port 8000 \ --dtype fp8 \ --gpu-memory-utilization 0.95 Restart=on-failure RestartSec=10 [Install] WantedBy=multi-user.target EOF sudo systemctl daemon-reload sudo systemctl enable vllm-llama4 sudo systemctl start vllm-llama4 ``` Replace `` with your HuggingFace token. Using `EnvironmentFile=` with `chmod 600` prevents other local users from reading the token via `systemctl show`. ### Accessing the server :::warning[Port 8000 is publicly accessible by default] Use SSH tunneling during development or add `--api-key ` to the vLLM startup command. ::: #### SSH tunnel ```bash ssh -L 8000:localhost:8000 @ ``` ### Usage example: multimodal image input ```python import base64 from openai import OpenAI client = OpenAI(base_url="http://localhost:8000/v1", api_key="not-needed") with open("image.jpg", "rb") as f: image_b64 = base64.b64encode(f.read()).decode() response = client.chat.completions.create( model="meta-llama/Llama-4-Scout-17B-16E-Instruct", messages=[ { "role": "user", "content": [ {"type": "image_url", "image_url": {"url": f"data:image/jpeg;base64,{image_b64}"}}, {"type": "text", "text": "What is in this image?"}, ], } ], ) print(response.choices[0].message.content) ``` ### Cloud-init startup script (optional) If your provider supports cloud-init, you can paste this into the **Startup Script** field when deploying to automate the setup above. #### Llama 4 Scout (H100, FP8) ```yaml #cloud-config write_files: - path: /etc/systemd/system/vllm-llama4.service content: | [Unit] Description=Llama 4 Scout vLLM Inference Server After=network.target [Service] Type=simple EnvironmentFile=/etc/vllm/hf-token ExecStart=/usr/bin/python3 -m vllm.entrypoints.openai.api_server \ --model meta-llama/Llama-4-Scout-17B-16E-Instruct \ --port 8000 \ --dtype fp8 \ --gpu-memory-utilization 0.95 Restart=on-failure RestartSec=10 [Install] WantedBy=multi-user.target runcmd: - apt-get update -y - apt-get install -y python3-pip - pip install vllm - mkdir -p /etc/vllm - install -m 600 /dev/null /etc/vllm/hf-token - echo "HF_TOKEN=" >> /etc/vllm/hf-token - systemctl daemon-reload - systemctl enable vllm-llama4 - systemctl start vllm-llama4 ``` Replace `` with your HuggingFace token. ### What's next * [Llama 3.1 / 3.2 / 3.3](/quick-guides/llms/llama-3): Previous Llama generation guides * [vLLM Inference Server](/quick-guides/llms/frameworks/vllm-server): vLLM configuration details * [Instance Types](/concepts/instance-types): H100/H200 cluster requirements * [Multimodal Models](/quick-guides/llms/multimodal): Other vision-language model guides ## Mistral & Mixtral Deploy [Mistral AI](https://huggingface.co/mistralai) models on Spheron GPU instances using vLLM. Includes Mistral 7B for single-GPU deployment, Mixtral 8x7B MoE (requires \~90 GB VRAM in bfloat16, needs 2× A100 80GB), and Mistral Small 3.1 24B. ### Recommended hardware | Model | Recommended GPU | Instance Type | Notes | | -------------------------- | --------------- | ----------------- | ----------------------------- | | Mistral-7B-Instruct-v0.3 | RTX 4090 (24GB) | Dedicated or Spot | Fits in 16GB VRAM | | Mixtral-8x7B-Instruct-v0.1 | 2× A100 80GB | Dedicated | MoE, \~90 GB VRAM in bfloat16 | | Mistral-Small-3.1-24B | A100 80GB | Dedicated | Full precision (\~55GB VRAM) | ### Manual setup Use these steps to set up the server manually after SSH-ing into your instance. This works on any provider regardless of cloud-init support. #### Step 1: Connect to your instance ```bash ssh @ ``` Replace `` with the username shown in the instance details panel (e.g., `ubuntu` for Spheron AI instances) and `` with your instance's public IP. #### Step 2: Install vLLM ```bash sudo apt-get update -y sudo apt-get install -y python3-pip pip install vllm ``` #### Step 3: Start the server Run the server in the foreground to verify it works: ```bash python3 -m vllm.entrypoints.openai.api_server \ --model mistralai/Mistral-7B-Instruct-v0.3 \ --port 8000 \ --dtype bfloat16 ``` Press `Ctrl+C` to stop. #### Step 4: Run as a background service To keep the server running after you close your SSH session, create a systemd service: ```bash sudo tee /etc/systemd/system/vllm-mistral.service > /dev/null << 'EOF' [Unit] Description=Mistral vLLM Inference Server After=network.target [Service] Type=simple ExecStart=/usr/bin/python3 -m vllm.entrypoints.openai.api_server \ --model mistralai/Mistral-7B-Instruct-v0.3 \ --port 8000 \ --dtype bfloat16 Restart=on-failure RestartSec=10 [Install] WantedBy=multi-user.target EOF sudo systemctl daemon-reload sudo systemctl enable vllm-mistral sudo systemctl start vllm-mistral ``` #### Mixtral 8x7B (2× A100 80GB) For the Mixtral MoE model, replace the `ExecStart` command with: ```bash /usr/bin/python3 -m vllm.entrypoints.openai.api_server \ --model mistralai/Mixtral-8x7B-Instruct-v0.1 \ --port 8000 \ --dtype bfloat16 \ --tensor-parallel-size 2 ``` ### Accessing the server :::warning[Port 8000 is publicly accessible by default] Use SSH tunneling during development or add `--api-key ` to the vLLM startup command. ::: #### SSH tunnel ```bash ssh -L 8000:localhost:8000 @ ``` ### Usage example: function calling ```python from openai import OpenAI import json client = OpenAI(base_url="http://localhost:8000/v1", api_key="not-needed") tools = [ { "type": "function", "function": { "name": "search_web", "description": "Search the web for information", "parameters": { "type": "object", "properties": {"query": {"type": "string"}}, "required": ["query"], }, }, } ] response = client.chat.completions.create( model="mistralai/Mistral-7B-Instruct-v0.3", messages=[{"role": "user", "content": "Search for the latest GPU benchmarks."}], tools=tools, tool_choice="auto", ) if response.choices[0].message.tool_calls: tool_call = response.choices[0].message.tool_calls[0] print(f"Function: {tool_call.function.name}") print(f"Arguments: {tool_call.function.arguments}") ``` ### Cloud-init startup script (optional) If your provider supports cloud-init, you can paste this into the **Startup Script** field when deploying to automate the setup above. #### Mistral 7B (RTX 4090) ```yaml #cloud-config runcmd: - apt-get update -y - apt-get install -y python3-pip - pip install vllm - | cat > /etc/systemd/system/vllm-mistral.service << 'EOF' [Unit] Description=Mistral vLLM Inference Server After=network.target [Service] Type=simple ExecStart=/usr/bin/python3 -m vllm.entrypoints.openai.api_server \ --model mistralai/Mistral-7B-Instruct-v0.3 \ --port 8000 \ --dtype bfloat16 Restart=on-failure RestartSec=10 [Install] WantedBy=multi-user.target EOF - systemctl daemon-reload - systemctl enable vllm-mistral - systemctl start vllm-mistral ``` #### Mixtral 8x7B (2× A100 80GB) Replace the ExecStart line with: ```bash /usr/bin/python3 -m vllm.entrypoints.openai.api_server \ --model mistralai/Mixtral-8x7B-Instruct-v0.1 \ --port 8000 \ --dtype bfloat16 \ --tensor-parallel-size 2 ``` ### What's next * [vLLM Inference Server](/quick-guides/llms/frameworks/vllm-server): vLLM configuration details * [Llama 3.1 / 3.2 / 3.3](/quick-guides/llms/llama-3): Meta Llama model guides * [Instance Types](/concepts/instance-types): GPU selection for MoE models * [Cost Optimization](/cost-optimization): Spot instances for Mistral 7B ## Phi-4 & Phi-4 Multimodal Deploy [Microsoft Phi-4](https://huggingface.co/microsoft/phi-4) and [Phi-4-multimodal](https://huggingface.co/microsoft/Phi-4-multimodal-instruct) on Spheron GPU instances using vLLM. Phi-4 is a 14B parameter small language model (SLM) with strong reasoning capabilities released under the MIT license. ### Recommended hardware | Model | Recommended GPU | Instance Type | Notes | | ---------------- | ----------------------- | ------------- | ------------------ | | Phi-4 (14B) | A100 40GB | Dedicated | Full precision | | Phi-4-multimodal | RTX 4090 (24GB) or A100 | Dedicated | Image + text input | ### Manual setup Use these steps to set up the server manually after SSH-ing into your instance. This works on any provider regardless of cloud-init support. #### Step 1: Connect to your instance ```bash ssh @ ``` Replace `` with the username shown in the instance details panel (e.g., `ubuntu` for Spheron AI instances) and `` with your instance's public IP. #### Step 2: Install vLLM ```bash sudo apt-get update -y sudo apt-get install -y python3-pip pip install vllm ``` #### Step 3: Start the server Run the server in the foreground to verify it works: ```bash python3 -m vllm.entrypoints.openai.api_server \ --model microsoft/phi-4 \ --port 8000 \ --dtype bfloat16 \ --trust-remote-code ``` Press `Ctrl+C` to stop. For Phi-4-multimodal, replace `microsoft/phi-4` with `microsoft/Phi-4-multimodal-instruct`. #### Step 4: Run as a background service To keep the server running after you close your SSH session, create a systemd service: ```bash sudo tee /etc/systemd/system/vllm-phi4.service > /dev/null << 'EOF' [Unit] Description=Phi-4 vLLM Inference Server After=network.target [Service] Type=simple ExecStart=/usr/bin/python3 -m vllm.entrypoints.openai.api_server \ --model microsoft/phi-4 \ --port 8000 \ --dtype bfloat16 \ --trust-remote-code Restart=on-failure RestartSec=10 [Install] WantedBy=multi-user.target EOF sudo systemctl daemon-reload sudo systemctl enable vllm-phi4 sudo systemctl start vllm-phi4 ``` ### Accessing the server :::warning[Port 8000 is publicly accessible by default] Use SSH tunneling during development or add `--api-key ` to the vLLM startup command. ::: #### SSH tunnel ```bash ssh -L 8000:localhost:8000 @ ``` ### Usage example: text ```python from openai import OpenAI client = OpenAI(base_url="http://localhost:8000/v1", api_key="not-needed") response = client.chat.completions.create( model="microsoft/phi-4", messages=[{"role": "user", "content": "Write a Python function that checks if a number is prime."}], ) print(response.choices[0].message.content) ``` ### Usage example: image input (Phi-4-multimodal) ```python import base64 from openai import OpenAI client = OpenAI(base_url="http://localhost:8000/v1", api_key="not-needed") with open("image.jpg", "rb") as f: image_b64 = base64.b64encode(f.read()).decode() response = client.chat.completions.create( model="microsoft/Phi-4-multimodal-instruct", messages=[ { "role": "user", "content": [ {"type": "image_url", "image_url": {"url": f"data:image/jpeg;base64,{image_b64}"}}, {"type": "text", "text": "What is shown in this image?"}, ], } ], ) print(response.choices[0].message.content) ``` :::info[MIT License] Phi-4 is released under the [MIT license](https://opensource.org/licenses/MIT), allowing commercial use and modification without restrictions. ::: ### Cloud-init startup script (optional) If your provider supports cloud-init, you can paste this into the **Startup Script** field when deploying to automate the setup above. #### Phi-4 (A100 40GB) ```yaml #cloud-config runcmd: - apt-get update -y - apt-get install -y python3-pip - pip install vllm - | cat > /etc/systemd/system/vllm-phi4.service << 'EOF' [Unit] Description=Phi-4 vLLM Inference Server After=network.target [Service] Type=simple ExecStart=/usr/bin/python3 -m vllm.entrypoints.openai.api_server \ --model microsoft/phi-4 \ --port 8000 \ --dtype bfloat16 \ --trust-remote-code Restart=on-failure RestartSec=10 [Install] WantedBy=multi-user.target EOF - systemctl daemon-reload - systemctl enable vllm-phi4 - systemctl start vllm-phi4 ``` #### Phi-4-multimodal Replace the model in ExecStart with `microsoft/Phi-4-multimodal-instruct`. ### What's next * [Gemma 3](/quick-guides/llms/gemma-3): Another efficient small model option (Gemma Terms of Use) * [Multimodal Models](/quick-guides/llms/multimodal): Other vision-language model guides * [vLLM Inference Server](/quick-guides/llms/frameworks/vllm-server): vLLM configuration details * [Instance Types](/concepts/instance-types): GPU selection for SLMs ## Qwen3 Dense & MoE Deploy [Qwen3](https://huggingface.co/Qwen) dense and Mixture-of-Experts (MoE) models on Spheron GPU instances using vLLM. Qwen3 introduces a thinking mode that can be toggled at inference time using system prompt tokens. ### Recommended hardware | Model | Recommended GPU | Instance Type | Notes | | --------------- | --------------- | ----------------- | ------------------------------- | | Qwen3-8B | RTX 4090 (24GB) | Dedicated or Spot | Dense, single-GPU | | Qwen3-14B | A100 40GB | Dedicated | Dense | | Qwen3-32B | A100 80GB | Dedicated | Dense | | Qwen3-30B-A3B | A100 80GB | Dedicated | MoE, 3B active params | | Qwen3-235B-A22B | 8× H100 80GB | Cluster | MoE, `--tensor-parallel-size 8` | ### Manual setup Use these steps to set up the server manually after SSH-ing into your instance. This works on any provider regardless of cloud-init support. #### Step 1: Connect to your instance ```bash ssh @ ``` Replace `` with the username shown in the instance details panel (e.g., `ubuntu` for Spheron AI instances) and `` with your instance's public IP. #### Step 2: Install vLLM ```bash sudo apt-get update -y sudo apt-get install -y python3-pip pip install vllm ``` #### Step 3: Start the server Run the server in the foreground to verify it works: ```bash python3 -m vllm.entrypoints.openai.api_server \ --model Qwen/Qwen3-32B \ --port 8000 \ --dtype bfloat16 ``` Press `Ctrl+C` to stop. #### Step 4: Run as a background service To keep the server running after you close your SSH session, create a systemd service: ```bash sudo tee /etc/systemd/system/vllm-qwen3.service > /dev/null << 'EOF' [Unit] Description=Qwen3 vLLM Inference Server After=network.target [Service] Type=simple ExecStart=/usr/bin/python3 -m vllm.entrypoints.openai.api_server \ --model Qwen/Qwen3-32B \ --port 8000 \ --dtype bfloat16 Restart=on-failure RestartSec=10 [Install] WantedBy=multi-user.target EOF sudo systemctl daemon-reload sudo systemctl enable vllm-qwen3 sudo systemctl start vllm-qwen3 ``` #### Qwen3-235B-A22B MoE (8× H100) For the large MoE model, replace the `ExecStart` command with: ```bash /usr/bin/python3 -m vllm.entrypoints.openai.api_server \ --model Qwen/Qwen3-235B-A22B \ --port 8000 \ --dtype bfloat16 \ --tensor-parallel-size 8 \ --gpu-memory-utilization 0.95 ``` ### Accessing the server :::warning[Port 8000 is publicly accessible by default] Use SSH tunneling during development or add `--api-key ` to the vLLM startup command. ::: #### SSH tunnel ```bash ssh -L 8000:localhost:8000 @ ``` ### Usage example: thinking mode Qwen3 supports toggleable chain-of-thought reasoning via system prompt tokens. ```python from openai import OpenAI client = OpenAI(base_url="http://localhost:8000/v1", api_key="not-needed") # Enable thinking mode (default for instruction models) response_think = client.chat.completions.create( model="Qwen/Qwen3-32B", messages=[ {"role": "system", "content": "/think"}, {"role": "user", "content": "Solve: if x² + 3x - 10 = 0, what is x?"}, ], ) # Disable thinking mode for faster responses response_no_think = client.chat.completions.create( model="Qwen/Qwen3-32B", messages=[ {"role": "system", "content": "/no_think"}, {"role": "user", "content": "What is the capital of France?"}, ], ) print("With thinking:", response_think.choices[0].message.content[:200]) print("Without thinking:", response_no_think.choices[0].message.content) ``` ### Cloud-init startup script (optional) If your provider supports cloud-init, you can paste this into the **Startup Script** field when deploying to automate the setup above. #### Qwen3-32B (A100 80GB) ```yaml #cloud-config runcmd: - apt-get update -y - apt-get install -y python3-pip - pip install vllm - | cat > /etc/systemd/system/vllm-qwen3.service << 'EOF' [Unit] Description=Qwen3 vLLM Inference Server After=network.target [Service] Type=simple ExecStart=/usr/bin/python3 -m vllm.entrypoints.openai.api_server \ --model Qwen/Qwen3-32B \ --port 8000 \ --dtype bfloat16 Restart=on-failure RestartSec=10 [Install] WantedBy=multi-user.target EOF - systemctl daemon-reload - systemctl enable vllm-qwen3 - systemctl start vllm-qwen3 ``` #### Qwen3-235B-A22B MoE (8× H100) Replace the ExecStart line with: ```bash /usr/bin/python3 -m vllm.entrypoints.openai.api_server \ --model Qwen/Qwen3-235B-A22B \ --port 8000 \ --dtype bfloat16 \ --tensor-parallel-size 8 \ --gpu-memory-utilization 0.95 ``` ### What's next * [vLLM Inference Server](/quick-guides/llms/frameworks/vllm-server): vLLM configuration details * [DeepSeek R1 & V3](/quick-guides/llms/deepseek-r1): Another reasoning model option * [Instance Types](/concepts/instance-types): Multi-GPU setup for MoE models * [Cost Optimization](/cost-optimization): Spot instances for development import { YouTube } from '../../../components/YouTube' ## SoulX Podcast-1.7B Deploy [SoulX Podcast-1.7B](https://huggingface.co/Soul-AILab/SoulX-Podcast-1.7B) on a Spheron GPU instance. SoulX Podcast-1.7B is a 1.7B parameter speech generation model that produces multi-speaker podcast dialogues with speaker switching, zero-shot voice cloning, and paralinguistic elements such as laughter and sighs. It supports English, Mandarin, and several Chinese dialects. ### Key capabilities * **Multi-speaker dialogue:** Maintains consistency across turns and handles interruptions * **Zero-shot voice cloning:** Replicates voices from 10 to 30 second reference samples * **Paralinguistics:** Generates laughter, sighs, throat clearing, and intonation shifts * **Multi-language:** Supports English, Mandarin, Sichuanese, Henanese, and Cantonese * **Efficient deployment:** Runs on GPUs ranging from RTX 4060 to H100 ![GPU Tiers](/soulx.png) **Resources:** * [HuggingFace Model](https://huggingface.co/Soul-AILab/SoulX-Podcast-1.7B) * [GitHub Repository](https://github.com/Soul-AILab/SoulX-Podcast) ### Manual setup Use these steps to set up the server manually after SSH-ing into your instance. This works on any provider regardless of cloud-init support. #### Step 1: Provision a Spheron instance 1. Sign up at [app.spheron.ai](https://app.spheron.ai) 2. Add credits (card/stables) 3. Click **Deploy** → **RTX 4090** (or RTX 4060+ for testing) → Region → **Ubuntu 22.04** → add your SSH key → **Deploy** See [Getting Started](/getting-started) or [SSH Connection](/connecting/ssh-connection) for details. #### Step 2: Connect to your instance ```bash ssh @ ``` Replace `` with the username shown in the instance details panel (e.g., `root` or `ubuntu`) and `` with your instance's public IP. #### Step 3: Set up the environment ```bash sudo apt update && apt install -y software-properties-common curl ca-certificates sudo add-apt-repository -y ppa:deadsnakes/ppa sudo apt update ``` #### Step 4: Install Python 3.11 ```bash sudo apt install -y python3.11 python3.11-venv python3.11-dev python3.11 -m ensurepip --upgrade python3.11 -m pip install --upgrade pip setuptools wheel ``` #### Step 5: Install Miniconda ```bash curl -O https://repo.anaconda.com/miniconda/Miniconda3-latest-Linux-x86_64.sh bash Miniconda3-latest-Linux-x86_64.sh -b -p $HOME/miniconda3 $HOME/miniconda3/bin/conda init bash source ~/.bashrc ``` #### Step 6: Create conda environment ```bash conda create -n soulxpodcast -y python=3.11 ``` Accept ToS if prompted: ```bash conda tos accept --override-channels --channel https://repo.anaconda.com/pkgs/main conda tos accept --override-channels --channel https://repo.anaconda.com/pkgs/r ``` #### Step 7: Activate environment ```bash conda activate soulxpodcast ``` #### Step 8: Clone the repository ```bash git clone https://github.com/Soul-AILab/SoulX-Podcast.git cd SoulX-Podcast ``` #### Step 9: Install dependencies ```bash pip install -r requirements.txt pip install --index-url https://download.pytorch.org/whl/cu121 torch torchvision torchaudio pip install "transformers==4.57.1" "huggingface_hub<1.0,>=0.34.0" ``` ### Download models #### Base model (English/Mandarin) ```bash huggingface-cli download --resume-download Soul-AILab/SoulX-Podcast-1.7B \ --local-dir pretrained_models/SoulX-Podcast-1.7B ``` #### Dialect model (Sichuanese/Henanese/Cantonese) ```bash huggingface-cli download --resume-download Soul-AILab/SoulX-Podcast-1.7B-dialect \ --local-dir pretrained_models/SoulX-Podcast-1.7B-dialect ``` ### Test the model ```bash bash example/infer_dialogue.sh ``` Check `outputs/` directory for generated `.wav` files. ### Launch the WebUI #### Modify webui.py Change `share=False` to `share=True`: ```python # In webui.py: share=True ``` #### Start the WebUI Base model: ```bash python3 webui.py --model_path pretrained_models/SoulX-Podcast-1.7B ``` Dialect model: ```bash python3 webui.py --model_path pretrained_models/SoulX-Podcast-1.7B-dialect ``` Open the Gradio link printed in the terminal (e.g., `https://baccd06ba693323c35.gradio.live`) to access the interface. ### Troubleshooting #### Issue: Low audio quality Set a higher sample rate: ```bash python3 webui.py --model_path pretrained_models/SoulX-Podcast-1.7B --sample_rate 48000 ``` #### Issue: Out-of-memory (OOM) error Increase the CUDA memory split size: ```bash export PYTORCH_CUDA_ALLOC_CONF=max_split_size_mb:512 ``` #### Issue: Model download failures Set a custom cache directory and retry the download: ```bash export HF_HOME=/path/to/cache huggingface-cli download --resume-download Soul-AILab/SoulX-Podcast-1.7B ``` #### Issue: CUDA errors Verify CUDA availability, check GPU status, and reinstall PyTorch if needed: ```bash python -c "import torch; print(torch.cuda.is_available())" nvidia-smi pip install --index-url https://download.pytorch.org/whl/cu121 torch torchvision torchaudio ``` #### Issue: Gradio interface not accessible Ensure `share=True` is set in `webui.py`, then allow the port through the firewall or specify an alternate port: ```bash sudo ufw allow 7860/tcp python3 webui.py --model_path pretrained_models/SoulX-Podcast-1.7B --server_port 8080 ``` ### Cloud-init startup script (optional) If your provider supports cloud-init, you can paste this into the **Startup Script** field when deploying to automate the environment setup. After the instance is ready, SSH in, activate the conda environment, and follow the [Download Models](#download-models) and [Launch WebUI](#launch-webui) steps. ```yaml #cloud-config runcmd: - apt update && apt install -y software-properties-common curl ca-certificates git - add-apt-repository -y ppa:deadsnakes/ppa - apt update - apt install -y python3.11 python3.11-venv python3.11-dev - curl -fsSL -o /tmp/miniconda.sh https://repo.anaconda.com/miniconda/Miniconda3-latest-Linux-x86_64.sh - bash /tmp/miniconda.sh -b -p /opt/miniconda3 - /opt/miniconda3/bin/conda create -n soulxpodcast -y python=3.11 - /opt/miniconda3/bin/conda run -n soulxpodcast pip install --index-url https://download.pytorch.org/whl/cu121 torch torchvision torchaudio - git clone https://github.com/Soul-AILab/SoulX-Podcast.git /opt/SoulX-Podcast - /opt/miniconda3/bin/conda run -n soulxpodcast pip install -r /opt/SoulX-Podcast/requirements.txt - /opt/miniconda3/bin/conda run -n soulxpodcast pip install "transformers==4.57.1" "huggingface_hub<1.0,>=0.34.0" ``` After cloud-init completes, SSH in and download the model: ```bash source /opt/miniconda3/bin/activate soulxpodcast cd /opt/SoulX-Podcast huggingface-cli download --resume-download Soul-AILab/SoulX-Podcast-1.7B \ --local-dir pretrained_models/SoulX-Podcast-1.7B python3 webui.py --model_path pretrained_models/SoulX-Podcast-1.7B ``` ### What's next * [Specialized Models](/quick-guides/llms/specialized-models): Compare SoulX Podcast with Chandra OCR and Janus CoderV * [Instance Types](/concepts/instance-types): Select the right GPU tier for audio generation workloads * [Getting Started](/getting-started): Create a Spheron account and deploy your first instance * [SSH Connection](/connecting/ssh-connection): Connect to your instance after deployment ## Specialized Models Guides for deploying task-specific AI models on Spheron GPU instances. These models are purpose-built for document processing, audio generation, and visual code intelligence rather than general-purpose chat. ### Available guides #### [Chandra OCR](/quick-guides/llms/chandra-ocr) State-of-the-art document processing model with 83.1% accuracy on the olmOCR benchmark, outperforming GPT-4o, Gemini Flash 2, and Mistral OCR. Converts images and PDFs to structured Markdown, HTML, or JSON while preserving layout, tables, and formulas. **Best for:** Document digitization, text extraction from PDFs and scanned documents, OCR pipelines with 40+ language support. **Deployment:** CPU (dev/test) through distributed H100 (enterprise). Supports local inference via HuggingFace transformers and high-throughput via vLLM server. #### [SoulX Podcast-1.7B](/quick-guides/llms/soulx-podcast-1-7b) Multi-speaker podcast generation model (1.7B parameters). Generates 60+ minute dialogues with natural speaker switching, zero-shot voice cloning from 10–30 second samples, and paralinguistic expressions (laughter, sighs, intonation). **Best for:** Audio content generation, podcast production, multi-speaker voice synthesis, and zero-shot voice cloning. **Deployment:** RTX 4060 (testing) to H100 (production). Runs via a Gradio web interface. #### [Janus CoderV-8B](/quick-guides/llms/janus-coderv-8b) 8B multimodal code intelligence model trained on JANUSCODE-800K, the largest multimodal code dataset. Generates HTML, CSS, and React components from screenshots, mockups, charts, and animations. Supports 32K token context. **Best for:** Visual-to-code translation, UI mockup generation, layout bug fixing from screenshots, and chart-to-code conversion. **Deployment:** RTX 4090 (standard) through H100 (high throughput). Supports 8-bit quantization for reduced VRAM. ### Hardware overview | Model | Min VRAM | Recommended GPU | Notes | | ------------------- | -------- | ---------------- | -------------------- | | Chandra OCR (4-bit) | 6GB | RTX 3060/4060 Ti | Quantized | | Chandra OCR (BF16) | 16GB | RTX 4090 / L40S | Full precision | | SoulX Podcast-1.7B | 4GB | RTX 4060+ | RTX 4090 recommended | | Janus CoderV-8B | 16GB | RTX 4090 (24GB) | 8-bit: \~12GB | ### What's next * [Text Models](/quick-guides/llms/text-models): General-purpose LLM guides * [Multimodal Models](/quick-guides/llms/multimodal): Vision-language model guides * [Instance Types](/concepts/instance-types): GPU selection * [Getting Started](/getting-started): Spheron account and instance setup ## Text Models Guides for deploying large language models (LLMs) on Spheron GPU instances. All models are served via vLLM's OpenAI-compatible API unless otherwise noted. ### VRAM requirements | Model | Parameters | Min VRAM | Recommended GPU | | ------------------------------ | ---------- | -------- | --------------- | | DeepSeek-R1-Distill-7B | 7B | 16GB | RTX 4090 (24GB) | | Llama 3.1/3.2/3.3 8B | 8B | 16GB | RTX 4090 (24GB) | | Mistral 7B | 7B | 14GB | RTX 4090 (24GB) | | Gemma 3 12B | 12B | 24GB | RTX 4090 (24GB) | | Phi-4 14B | 14B | 24GB | RTX 4090 (24GB) | | Qwen3-32B | 32B | 64GB | A100 80GB | | DeepSeek-R1-Distill-32B (INT4) | 32B | 20GB | A100 40GB | | Llama 3.1 70B | 70B | 140GB | 2× A100 80GB | | Mixtral 8x7B | \~47B | 90GB | 2× A100 80GB | | Llama 4 Scout 109B (INT4) | 17B active | 40GB | H100 80GB | | DeepSeek-R1 671B (FP8) | 671B | 8× H100 | 8× H100 80GB | ### Available guides #### [DeepSeek R1 & V3](/quick-guides/llms/deepseek-r1) DeepSeek's reasoning models, from 7B distillations on RTX 4090 to the full 671B FP8 deployment on 8× H100. Features chain-of-thought reasoning exposed via `` blocks. **Best for:** Complex reasoning, math, and code generation tasks. #### [Llama 4 Scout & Maverick](/quick-guides/llms/llama-4-scout) Meta's latest multimodal MoE models (Scout at 109B total/17B active, Maverick at 400B total/17B active) with long-context and native image understanding. **Best for:** State-of-the-art multimodal reasoning and large context windows. #### [Llama 3.1 / 3.2 / 3.3](/quick-guides/llms/llama-3) Meta Llama 3 family: 8B on a single RTX 4090, 70B on 2× A100, 405B on 8× H100. Strong instruction following and function calling. **Best for:** General-purpose chat, instruction following, and function calling. #### [Qwen3 Dense & MoE](/quick-guides/llms/qwen3) Alibaba Qwen3 text models with toggleable chain-of-thought reasoning. Dense models from 7B to 32B; MoE models up to 235B-A22B. **Best for:** Reasoning tasks with controllable chain-of-thought via `/think` and `/no_think` tokens. #### [Mistral & Mixtral](/quick-guides/llms/mistral-mixtral) Mistral 7B, Mixtral 8x7B MoE, and Mistral Small 3.1 24B with efficient inference and function calling support. **Best for:** Efficient inference with strong instruction following and function calling. #### [Gemma 3](/quick-guides/llms/gemma-3) Google DeepMind Gemma 3 in 4B, 12B, and 27B (INT4 option). Available under the Gemma Terms of Use; commercial use is permitted after accepting Google's license agreement. **Best for:** Low-latency inference on smaller GPUs; research and commercial projects. #### [Phi-4 & Phi-4 Multimodal](/quick-guides/llms/phi-4) Microsoft Phi-4 14B small language model and Phi-4-multimodal with image input support. MIT license. **Best for:** Efficient SLM inference; multimodal tasks on a single RTX 4090. ### What's next * [Inference Frameworks](/quick-guides/llms/frameworks): Choose the right serving stack (vLLM, SGLang, llama.cpp, etc.) * [Multimodal Models](/quick-guides/llms/multimodal): Vision-language model guides * [Specialized Models](/quick-guides/llms/specialized-models): OCR, audio generation, and code intelligence * [Instance Types](/concepts/instance-types): GPU selection for text models * [Cost Optimization](/cost-optimization): Reducing inference costs with Spot instances import { YouTube } from '../../../../components/YouTube' ## Baidu ERNIE-4.5-VL-28B-A3B-Thinking Deploy [Baidu ERNIE-4.5-VL-28B-A3B-Thinking](https://huggingface.co/baidu/ERNIE-4.5-VL-28B-A3B-Thinking) on a Spheron GPU instance. This multimodal reasoning model uses a Mixture-of-Experts architecture with 28B total parameters and 3B active per token. It supports visual reasoning, STEM problem solving, chart analysis, and video understanding under the Apache 2.0 license. ### Overview ERNIE-4.5-VL-28B-A3B-Thinking includes a "Thinking" mode for multi-step chain-of-thought reasoning over visual inputs. 28B parameters with MoE design (3B active per token). Performance is competitive with GPT-4o and Gemini 2.5 Pro on visual reasoning, STEM, charts, and video understanding tasks. **Released:** November 11, 2025 by Baidu **Architecture:** ERNIE-4.5-VL-28B-A3B + reasoning fine-tuning (GSPO, IcePop) **Training:** Visual-language reasoning datasets with multimodal RL ### Key capabilities * **Visual reasoning:** Multi-step reasoning, chart analysis, causal relationships * **STEM reasoning:** Math, science, engineering from images * **Visual grounding:** Object localization, industrial QC/automation * **Dynamic detail focus:** Zooms into regions, chain-of-thought over visuals * **Tool calling:** Image search, cropping, web lookup integration * **Video understanding:** Temporal awareness, event localization, frame tracking **Use cases:** Multimodal agents, document automation, visual search, education, video analysis ### Requirements **Hardware:** * GPU: A100 80GB (recommended), RTX A6000 48GB (minimum for single-card), or 2× RTX 4090 for tensor parallelism * RAM: 32GB+ * Storage: 60GB free * VRAM: 48GB+ per card for bfloat16 (80GB recommended); 20GB+ with 4-bit quantization **Software:** * Ubuntu 22.04 LTS * CUDA 12.1+ * Python 3.11 * Conda/Miniconda ### Deploy on Spheron 1. Sign up at [app.spheron.ai](https://app.spheron.ai) 2. Add credits (card/stables) 3. **Deploy** → Select **A100 80GB** (or 2× RTX 4090 for multi-GPU) → Region → **Ubuntu 22.04** → SSH key → Deploy **Connect:** ```bash ssh -i root@ ``` New to Spheron? See [Getting Started](/getting-started) and [SSH Setup](/connecting/ssh-connection). ### Installation #### Install Miniconda ```bash curl -O https://repo.anaconda.com/miniconda/Miniconda3-latest-Linux-x86_64.sh bash Miniconda3-latest-Linux-x86_64.sh -b -p $HOME/miniconda3 $HOME/miniconda3/bin/conda init bash source ~/.bashrc ``` #### Create Python environment ```bash conda create -n ernie python=3.11 -y && conda activate ernie ``` #### Install dependencies ```bash pip install torch torchvision torchaudio einops timm pillow pip install git+https://github.com/huggingface/transformers pip install git+https://github.com/huggingface/accelerate pip install git+https://github.com/huggingface/diffusers pip install huggingface_hub pip install sentencepiece bitsandbytes protobuf decord numpy ``` #### Install Jupyter ```bash conda install -c conda-forge --override-channels notebook -y conda install -c conda-forge --override-channels ipywidgets -y jupyter notebook --allow-root ``` #### Access Jupyter from your local machine SSH port forwarding from your local machine: ```bash ssh -L 8888:localhost:8888 -p -i root@ ``` Copy the Jupyter URL from the server terminal to your browser. ### Run model #### Load model Open a notebook and run: ```python import torch from transformers import AutoProcessor, AutoTokenizer, AutoModelForCausalLM model_path = 'baidu/ERNIE-4.5-VL-28B-A3B-Thinking' model = AutoModelForCausalLM.from_pretrained( model_path, device_map="auto", dtype=torch.bfloat16, trust_remote_code=True ) processor = AutoProcessor.from_pretrained(model_path, trust_remote_code=True) model.add_image_preprocess(processor) ``` #### Run inference ```python messages = [ { "role": "user", "content": [ { "type": "text", "text": "What is in the image and what is the color of the dog" }, { "type": "image_url", "image_url": { "url": "https://images.pexels.com/photos/58997/pexels-photo-58997.jpeg" } }, ] }, ] text = processor.tokenizer.apply_chat_template( messages, tokenize=False, add_generation_prompt=True, ) image_inputs, video_inputs = processor.process_vision_info(messages) inputs = processor( text=[text], images=image_inputs, videos=video_inputs, padding=True, return_tensors="pt", ) device = next(model.parameters()).device inputs = inputs.to(device) generated_ids = model.generate( inputs=inputs['input_ids'].to(device), **inputs, max_new_tokens=1024, use_cache=False ) output_text = processor.decode(generated_ids[0][len(inputs['input_ids'][0]):]) print(output_text) ``` ### What's next * [Model on HuggingFace](https://huggingface.co/baidu/ERNIE-4.5-VL-28B-A3B-Thinking) * [Multimodal Models](/quick-guides/llms/multimodal): Other vision-language model guides * [Getting Started](/getting-started): Spheron deployment basics * [vLLM Inference Server](/quick-guides/llms/frameworks/vllm-server): Serve multimodal models via an OpenAI-compatible API ## Multimodal Models Guides for deploying vision-language models (VLMs) on Spheron GPU instances. All models accept both text and image inputs and are served via vLLM's OpenAI-compatible multimodal API. ### VRAM requirements | Model | Parameters | Min VRAM | Recommended GPU | | -------------------------- | ---------- | -------- | --------------- | | Qwen3-VL 4B | 4B | 10GB | RTX 4090 (24GB) | | Qwen3-VL 8B | 8B | 18GB | RTX 4090 (24GB) | | LLaVA-NeXT 7B | 7B | 14GB | RTX 4090 (24GB) | | InternVL3-8B | 8B | 18GB | RTX 4090 (24GB) | | Pixtral-12B | 12B | 24GB | RTX 4090 (24GB) | | LLaVA-NeXT 13B | 13B | 28GB | A100 40GB | | Baidu ERNIE-4.5-VL-28B-A3B | 28B active | 48GB | A100 80GB | | Qwen3-Omni-30B-A3B | 30B active | 40GB | A100 80GB | | InternVL3-78B | 78B | 80GB × 2 | 2× A100 80GB | ### Available guides #### [Qwen3-Omni-30B-A3B](/quick-guides/llms/multimodal/qwen3-omni-30b-a3b) Multimodal language model with 30B parameters supporting text, audio, images, and video inputs. 32K context window (single GPU). **Best for:** Multimodal tasks requiring audio, vision, and text processing in a single model. #### [Qwen3-VL 4B & 8B](/quick-guides/llms/multimodal/qwen3-vl-4b-8b) Vision-language models in 4B and 8B variants. 256K context, multimodal reasoning, and GUI automation. **Best for:** Image understanding, visual reasoning, and GUI automation tasks. #### [InternVL3](/quick-guides/llms/multimodal/internvl3) InternVL3 series (1B–78B) deployed via vLLM. Strong visual question answering and multimodal reasoning. **Best for:** High-accuracy visual QA and multimodal reasoning across model scales. #### [LLaVA-Next](/quick-guides/llms/multimodal/llava-next) LLaVA-NeXT 7B and 13B with improved visual reasoning, served via vLLM. **Best for:** Accessible image-to-text inference on RTX 4090 or A100. #### [Pixtral-12B](/quick-guides/llms/multimodal/pixtral-12b) Mistral's Pixtral-12B multimodal model on RTX 4090 (24GB) via vLLM. **Best for:** Compact multimodal inference with Mistral-quality text generation. #### [Baidu ERNIE-4.5-VL-28B-A3B](/quick-guides/llms/multimodal/baidu-ernie-4-5-vl-28b-a3b) 28B active parameter MoE vision-language model from Baidu. Strong STEM and visual reasoning performance. **Best for:** Visual reasoning, multimodal understanding, and STEM-domain tasks. ### What's next * [LLM Inference Overview](/quick-guides/llms): Text model and framework guides * [vLLM Inference Server](/quick-guides/llms/frameworks/vllm-server): Serving stack used by most guides here * [Instance Types](/concepts/instance-types): GPU selection for VLMs * [Cost Optimization](/cost-optimization): Reducing inference costs with Spot instances ## InternVL3 Deploy [InternVL3](https://huggingface.co/OpenGVLab/InternVL3-8B) on Spheron GPU instances using vLLM. InternVL3 is a vision-language model series from 1B to 78B parameters with strong performance on visual question answering and multimodal reasoning benchmarks. ### Recommended hardware | Model | Recommended GPU | Instance Type | Notes | | ------------- | --------------- | ------------------- | -------------------------- | | InternVL3-8B | RTX 4090 (24GB) | Dedicated or Spot | Single-GPU | | InternVL3-14B | A100 40GB | Dedicated | Full precision | | InternVL3-38B | A100 80GB | Dedicated | Single-GPU | | InternVL3-78B | 2× A100 80GB | Dedicated / Cluster | `--tensor-parallel-size 2` | ### Manual setup Use these steps to set up the server manually after SSH-ing into your instance. This works on any provider regardless of cloud-init support. #### Step 1: Connect to your instance ```bash ssh @ ``` Replace `` with the username shown in the instance details panel (e.g., `ubuntu` for Spheron AI instances) and `` with your instance's public IP. #### Step 2: Install vLLM ```bash sudo apt-get update -y sudo apt-get install -y python3-pip pip install vllm ``` #### Step 3: Start the server Run the server in the foreground to verify it works: ```bash python3 -m vllm.entrypoints.openai.api_server \ --model OpenGVLab/InternVL3-8B \ --port 8000 \ --dtype auto \ --trust-remote-code ``` Press `Ctrl+C` to stop. For InternVL3-78B on 2× A100, add `--tensor-parallel-size 2`. #### Step 4: Run as a background service To keep the server running after you close your SSH session, create a systemd service: ```bash sudo tee /etc/systemd/system/vllm-internvl.service > /dev/null << 'EOF' [Unit] Description=InternVL3 vLLM Inference Server After=network.target [Service] Type=simple ExecStart=/usr/bin/python3 -m vllm.entrypoints.openai.api_server \ --model OpenGVLab/InternVL3-8B \ --port 8000 \ --dtype auto \ --trust-remote-code Restart=on-failure RestartSec=10 [Install] WantedBy=multi-user.target EOF sudo systemctl daemon-reload sudo systemctl enable vllm-internvl sudo systemctl start vllm-internvl ``` ### Accessing the server :::warning[Port 8000 is publicly accessible by default] Use SSH tunneling during development or add `--api-key ` to the vLLM startup command. ::: #### SSH tunnel ```bash ssh -L 8000:localhost:8000 @ ``` ### Usage example: image input ```python import base64 from openai import OpenAI client = OpenAI(base_url="http://localhost:8000/v1", api_key="not-needed") with open("image.jpg", "rb") as f: image_b64 = base64.b64encode(f.read()).decode() response = client.chat.completions.create( model="OpenGVLab/InternVL3-8B", messages=[ { "role": "user", "content": [ {"type": "image_url", "image_url": {"url": f"data:image/jpeg;base64,{image_b64}"}}, {"type": "text", "text": "Describe what you see in this image."}, ], } ], ) print(response.choices[0].message.content) ``` ### Check server logs ```bash journalctl -u vllm-internvl -f ``` ### Cloud-init startup script (optional) If your provider supports cloud-init, you can paste this into the **Startup Script** field when deploying to automate the setup above. ```yaml #cloud-config runcmd: - apt-get update -y - apt-get install -y python3-pip - pip install vllm - | cat > /etc/systemd/system/vllm-internvl.service << 'EOF' [Unit] Description=InternVL3 vLLM Inference Server After=network.target [Service] Type=simple ExecStart=/usr/bin/python3 -m vllm.entrypoints.openai.api_server \ --model OpenGVLab/InternVL3-8B \ --port 8000 \ --dtype auto \ --trust-remote-code Restart=on-failure RestartSec=10 [Install] WantedBy=multi-user.target EOF - systemctl daemon-reload - systemctl enable vllm-internvl - systemctl start vllm-internvl ``` For InternVL3-78B on 2× A100, add `--tensor-parallel-size 2` to the ExecStart command. ### What's next * [Multimodal Models](/quick-guides/llms/multimodal): Other vision-language model guides * [vLLM Inference Server](/quick-guides/llms/frameworks/vllm-server): vLLM configuration details * [Networking](/concepts/networking): SSH tunneling and port access * [Instance Types](/concepts/instance-types): Multi-GPU setup for large VLMs ## LLaVA-Next Deploy [LLaVA-NeXT](https://huggingface.co/llava-hf/llava-v1.6-mistral-7b-hf) on Spheron GPU instances using vLLM. LLaVA-NeXT (Large Language and Vision Assistant Next) improves on LLaVA with better visual reasoning, higher image resolution support, and improved OCR capabilities. ### Recommended hardware | Model | Recommended GPU | Instance Type | Notes | | -------------- | --------------- | ----------------- | -------------------------- | | LLaVA-NeXT 7B | RTX 4090 (24GB) | Dedicated or Spot | `llava-v1.6-mistral-7b-hf` | | LLaVA-NeXT 13B | A100 40GB | Dedicated | `llava-v1.6-vicuna-13b-hf` | ### Manual setup Use these steps to set up the server manually after SSH-ing into your instance. This works on any provider regardless of cloud-init support. #### Step 1: Connect to your instance ```bash ssh @ ``` Replace `` with the username shown in the instance details panel (e.g., `ubuntu` for Spheron AI instances) and `` with your instance's public IP. #### Step 2: Install vLLM ```bash sudo apt-get update -y sudo apt-get install -y python3-pip pip install vllm ``` #### Step 3: Start the server Run the server in the foreground to verify it works: ```bash python3 -m vllm.entrypoints.openai.api_server \ --model llava-hf/llava-v1.6-mistral-7b-hf \ --port 8000 \ --dtype auto ``` Press `Ctrl+C` to stop. #### Step 4: Run as a background service To keep the server running after you close your SSH session, create a systemd service: ```bash sudo tee /etc/systemd/system/vllm-llava.service > /dev/null << 'EOF' [Unit] Description=LLaVA-Next vLLM Inference Server After=network.target [Service] Type=simple ExecStart=/usr/bin/python3 -m vllm.entrypoints.openai.api_server \ --model llava-hf/llava-v1.6-mistral-7b-hf \ --port 8000 \ --dtype auto Restart=on-failure RestartSec=10 [Install] WantedBy=multi-user.target EOF sudo systemctl daemon-reload sudo systemctl enable vllm-llava sudo systemctl start vllm-llava ``` ### Accessing the server :::warning[Port 8000 is publicly accessible by default] Use SSH tunneling during development or add `--api-key ` to the vLLM startup command. ::: #### SSH tunnel ```bash ssh -L 8000:localhost:8000 @ ``` ### Usage example: image input ```python import base64 from openai import OpenAI client = OpenAI(base_url="http://localhost:8000/v1", api_key="not-needed") with open("image.jpg", "rb") as f: image_b64 = base64.b64encode(f.read()).decode() response = client.chat.completions.create( model="llava-hf/llava-v1.6-mistral-7b-hf", messages=[ { "role": "user", "content": [ {"type": "image_url", "image_url": {"url": f"data:image/jpeg;base64,{image_b64}"}}, {"type": "text", "text": "What is shown in this image?"}, ], } ], ) print(response.choices[0].message.content) ``` ### Check server logs ```bash journalctl -u vllm-llava -f ``` ### Cloud-init startup script (optional) If your provider supports cloud-init, you can paste this into the **Startup Script** field when deploying to automate the setup above. ```yaml #cloud-config runcmd: - apt-get update -y - apt-get install -y python3-pip - pip install vllm - | cat > /etc/systemd/system/vllm-llava.service << 'EOF' [Unit] Description=LLaVA-Next vLLM Inference Server After=network.target [Service] Type=simple ExecStart=/usr/bin/python3 -m vllm.entrypoints.openai.api_server \ --model llava-hf/llava-v1.6-mistral-7b-hf \ --port 8000 \ --dtype auto Restart=on-failure RestartSec=10 [Install] WantedBy=multi-user.target EOF - systemctl daemon-reload - systemctl enable vllm-llava - systemctl start vllm-llava ``` ### What's next * [Multimodal Models](/quick-guides/llms/multimodal): Other vision-language model guides * [InternVL3](/quick-guides/llms/multimodal/internvl3): Higher-accuracy VLM alternative * [vLLM Inference Server](/quick-guides/llms/frameworks/vllm-server): vLLM configuration details * [Networking](/concepts/networking): SSH tunneling and port access ## Pixtral-12B Deploy [Pixtral-12B](https://huggingface.co/mistralai/Pixtral-12B-2409) on a Spheron RTX 4090 (24GB) instance using vLLM. Pixtral-12B is Mistral AI's multimodal model built on Mistral-NeMo 12B, with a dedicated 400M visual encoder supporting variable-resolution image inputs. ### Recommended hardware | Model | Recommended GPU | Instance Type | Notes | | ----------- | --------------- | ----------------- | ----------------- | | Pixtral-12B | RTX 4090 (24GB) | Dedicated or Spot | Fits in 24GB VRAM | ### Manual setup Use these steps to set up the server manually after SSH-ing into your instance. This works on any provider regardless of cloud-init support. #### Step 1: Connect to your instance ```bash ssh @ ``` Replace `` with the username shown in the instance details panel (e.g., `ubuntu` for Spheron AI instances) and `` with your instance's public IP. #### Step 2: Install vLLM ```bash sudo apt-get update -y sudo apt-get install -y python3-pip pip install vllm ``` #### Step 3: Start the server Run the server in the foreground to verify it works: ```bash python3 -m vllm.entrypoints.openai.api_server \ --model mistralai/Pixtral-12B-2409 \ --port 8000 \ --dtype bfloat16 \ --tokenizer-mode mistral \ --config-format mistral \ --load-format mistral ``` Press `Ctrl+C` to stop. #### Step 4: Run as a background service To keep the server running after you close your SSH session, create a systemd service: ```bash sudo tee /etc/systemd/system/vllm-pixtral.service > /dev/null << 'EOF' [Unit] Description=Pixtral-12B vLLM Inference Server After=network.target [Service] Type=simple ExecStart=/usr/bin/python3 -m vllm.entrypoints.openai.api_server \ --model mistralai/Pixtral-12B-2409 \ --port 8000 \ --dtype bfloat16 \ --tokenizer-mode mistral \ --config-format mistral \ --load-format mistral Restart=on-failure RestartSec=10 [Install] WantedBy=multi-user.target EOF sudo systemctl daemon-reload sudo systemctl enable vllm-pixtral sudo systemctl start vllm-pixtral ``` ### Accessing the server :::warning[Port 8000 is publicly accessible by default] Use SSH tunneling during development or add `--api-key ` to the vLLM startup command. ::: #### SSH tunnel ```bash ssh -L 8000:localhost:8000 @ ``` ### Usage example: image input ```python import base64 from openai import OpenAI client = OpenAI(base_url="http://localhost:8000/v1", api_key="not-needed") with open("image.jpg", "rb") as f: image_b64 = base64.b64encode(f.read()).decode() response = client.chat.completions.create( model="mistralai/Pixtral-12B-2409", messages=[ { "role": "user", "content": [ {"type": "image_url", "image_url": {"url": f"data:image/jpeg;base64,{image_b64}"}}, {"type": "text", "text": "Describe the image in detail."}, ], } ], ) print(response.choices[0].message.content) ``` ### Check server logs ```bash journalctl -u vllm-pixtral -f ``` ### Cloud-init startup script (optional) If your provider supports cloud-init, you can paste this into the **Startup Script** field when deploying to automate the setup above. ```yaml #cloud-config runcmd: - apt-get update -y - apt-get install -y python3-pip - pip install vllm - | cat > /etc/systemd/system/vllm-pixtral.service << 'EOF' [Unit] Description=Pixtral-12B vLLM Inference Server After=network.target [Service] Type=simple ExecStart=/usr/bin/python3 -m vllm.entrypoints.openai.api_server \ --model mistralai/Pixtral-12B-2409 \ --port 8000 \ --dtype bfloat16 \ --tokenizer-mode mistral \ --config-format mistral \ --load-format mistral Restart=on-failure RestartSec=10 [Install] WantedBy=multi-user.target EOF - systemctl daemon-reload - systemctl enable vllm-pixtral - systemctl start vllm-pixtral ``` ### What's next * [Multimodal Models](/quick-guides/llms/multimodal): Other vision-language model guides * [Mistral & Mixtral](/quick-guides/llms/mistral-mixtral): Mistral text-only model guides * [vLLM Inference Server](/quick-guides/llms/frameworks/vllm-server): vLLM configuration details * [Networking](/concepts/networking): SSH tunneling and port access import { YouTube } from '../../../../components/YouTube' ## Qwen3-Omni-30B-A3B Deploy [Qwen3-Omni-30B-A3B](https://huggingface.co/Qwen/Qwen3-Omni-30B-A3B-Instruct) on a Spheron A100 or H100 instance. This multimodal language model processes text, audio, images, and video with a 32K context window (single GPU). It differs from Qwen3-VL, which handles vision and language only. ### Key capabilities * **Multimodal inputs:** Text, audio, images, video * **Audio understanding:** Speech recognition, audio analysis * **Vision-language:** Image understanding and generation * **Context window:** 32K tokens (single GPU), up to 65K (multi-GPU) * **Multilingual:** 119+ languages and dialects **Use cases:** Audio transcription, multimodal chat, content analysis, accessibility tools ### Requirements **Hardware:** * GPU: A100 or H100 (30B model needs significant VRAM) * VRAM: 24GB+ minimum, 40GB+ recommended * RAM: 32GB+ * Storage: 60GB (SSD recommended) **Software:** * Ubuntu 22.04 LTS * CUDA 12.1+ * Python 3.11 * Conda/Miniconda ### Deploy on Spheron 1. Sign up at [app.spheron.ai](https://app.spheron.ai) 2. Add credits (card/stables) 3. **Deploy** → **A100** or **H100** → Region → **Ubuntu 22.04** → SSH key → Deploy **Connect:** ```bash ssh -i root@ ``` New to Spheron? See [Getting Started](/getting-started) and [SSH Setup](/connecting/ssh-connection). ### Installation #### Install Miniconda ```bash curl -O https://repo.anaconda.com/miniconda/Miniconda3-latest-Linux-x86_64.sh bash Miniconda3-latest-Linux-x86_64.sh -b -p $HOME/miniconda3 $HOME/miniconda3/bin/conda init bash source ~/.bashrc ``` #### Create environment ```bash conda create -n qwen python=3.11 -y && conda activate qwen ``` Accept ToS if prompted: ```bash conda tos accept --override-channels --channel https://repo.anaconda.com/pkgs/main conda tos accept --override-channels --channel https://repo.anaconda.com/pkgs/r ``` #### Install PyTorch (CUDA 12.1) ```bash pip install torch torchvision torchaudio --index-url https://download.pytorch.org/whl/cu121 ``` #### Install dependencies ```bash pip install git+https://github.com/huggingface/transformers pip install git+https://github.com/huggingface/accelerate pip install huggingface_hub pip install einops timm pillow sentencepiece protobuf decord numpy requests pip install bitsandbytes pip install qwen-omni-utils -U ``` ### Create test.py Create the inference script: ```python from transformers import Qwen3OmniMoeForConditionalGeneration, Qwen3OmniMoeProcessor # Load the model on available devices model = Qwen3OmniMoeForConditionalGeneration.from_pretrained( "Qwen/Qwen3-Omni-30B-A3B-Instruct", dtype="auto", device_map="auto" ) # Optional: Enable flash_attention_2 for better performance and memory efficiency, # especially in multi-image, video, or audio tasks. # model = Qwen3OmniMoeForConditionalGeneration.from_pretrained( # "Qwen/Qwen3-Omni-30B-A3B-Instruct", # dtype=torch.bfloat16, # attn_implementation="flash_attention_2", # device_map="auto", # ) # Load the processor processor = Qwen3OmniMoeProcessor.from_pretrained("Qwen/Qwen3-Omni-30B-A3B-Instruct") # Define input messages (image + text prompt) messages = [ { "role": "user", "content": [ { "type": "image", "image": "https://qianwen-res.oss-cn-beijing.aliyuncs.com/Qwen-VL/assets/demo.jpeg", }, {"type": "text", "text": "Describe this image."}, ], } ] # Prepare inputs for inference inputs = processor.apply_chat_template( messages, tokenize=True, add_generation_prompt=True, return_dict=True, return_tensors="pt" ).to(model.device) # Generate model output generated_ids = model.generate(**inputs, max_new_tokens=128) # Extract generated tokens (excluding prompt tokens) generated_ids_trimmed = [ output[len(input_ids):] for input_ids, output in zip(inputs.input_ids, generated_ids) ] # Decode output text output_text = processor.batch_decode( generated_ids_trimmed, skip_special_tokens=True, clean_up_tokenization_spaces=False ) print(output_text) ``` ### Run script ```bash conda activate qwen python3 test.py ``` ### Configuration **Model variants:** * For a smaller omni model from the previous generation, use `Qwen/Qwen2.5-Omni-7B`. **Precision:** * `dtype=torch.float16` or `torch.bfloat16` (A100/H100) **Flash Attention:** * Add `attn_implementation="flash_attention_2"` if supported. **Device:** * `device_map="auto"` (default, recommended) * `device_map={"":0}` (single GPU) **Local images:** * Use `load_image_from_path()` instead of a URL. ### Troubleshooting #### Issue: Out of memory (OOM) **Symptoms:** CUDA OOM error during model load or inference. **Resolution:** Reduce `max_new_tokens`, switch to `dtype=torch.float16`, or enable bitsandbytes quantization. #### Issue: Slow model loading **Symptoms:** Model takes several minutes to load. **Resolution:** Cache models locally, use NVMe storage, and enable `use_safetensors=True`. #### Issue: CUDA errors **Symptoms:** CUDA version mismatch errors. **Resolution:** Verify that your PyTorch and CUDA versions match. Run `nvidia-smi` to check the installed CUDA version. ### What's next * [Qwen3 Models on HuggingFace](https://huggingface.co/Qwen) * [Multimodal Models](/quick-guides/llms/multimodal): Other vision-language model guides * [Getting Started](/getting-started): Spheron deployment basics * [Instance Types](/concepts/instance-types): GPU selection for large multimodal models import { YouTube } from '../../../../components/YouTube' ## Qwen3-VL 4B & 8B Deploy [Qwen3-VL](https://huggingface.co/Qwen/Qwen3-VL-4B-Thinking) on a Spheron GPU instance. These vision-language models process text, images, and video with a 256K native context window (scalable to 1M tokens). Two size variants are available: 4B and 8B, plus an 8B-Thinking variant with enhanced reasoning. **Training:** 36 trillion tokens, 119 languages/dialects ### Key features **Architecture:** * Interleaved-MRoPE: Multi-resolution position embeddings for long video reasoning * DeepStack: Multi-level ViT feature fusion for fine-grained detail * Text-Timestamp Alignment: Precise event localization in videos **Capabilities:** * Visual agents (GUI automation, OS World, Android Control) * Visual coding (mockups to HTML/CSS/JS, Draw\.io diagrams) * Spatial understanding (2D/3D grounding, position/viewpoint) * OCR (32 languages, robust to low-light/blur/tilt) **Benchmarks:** * 8B-Thinking: MathVision 36.8, MMMU 61.7, MathVista 71.3 * 235B: Top scores on agent, document, and spatial reasoning benchmarks ### Requirements **Hardware:** * GPU: RTX 4090, A6000, A100, H100 * VRAM: 8GB minimum, 16GB+ recommended * RAM: 16GB+ * Storage: 10GB+ (SSD recommended) **Software:** * Ubuntu 22.04 LTS * CUDA 12.1+ * Python 3.11 * Conda/Miniconda FP8-quantized versions reduce VRAM requirements (block size 128). ### Deploy on Spheron 1. Sign up at [app.spheron.ai](https://app.spheron.ai) 2. Add credits (card/stables) 3. **Deploy** → **RTX 4090/A100** → Region → **Ubuntu 22.04** → SSH key → Deploy **Connect:** ```bash ssh -i root@ ``` New to Spheron? See [Getting Started](/getting-started) and [SSH Setup](/connecting/ssh-connection). ### Installation #### Install Miniconda ```bash curl -O https://repo.anaconda.com/miniconda/Miniconda3-latest-Linux-x86_64.sh bash Miniconda3-latest-Linux-x86_64.sh -b -p $HOME/miniconda3 $HOME/miniconda3/bin/conda init bash source ~/.bashrc ``` #### Create environment ```bash conda create -n qwen python=3.11 -y && conda activate qwen ``` Accept ToS if prompted: ```bash conda tos accept --override-channels --channel https://repo.anaconda.com/pkgs/main conda tos accept --override-channels --channel https://repo.anaconda.com/pkgs/r ``` #### Install PyTorch (CUDA 12.1) ```bash pip install torch torchvision torchaudio --index-url https://download.pytorch.org/whl/cu121 ``` #### Install dependencies ```bash pip install git+https://github.com/huggingface/transformers pip install git+https://github.com/huggingface/accelerate pip install huggingface_hub pip install einops timm pillow sentencepiece protobuf decord numpy requests pip install bitsandbytes ``` ### Create test.py Create the inference script: ```python from transformers import Qwen3VLForConditionalGeneration, AutoProcessor # Load the model on available devices model = Qwen3VLForConditionalGeneration.from_pretrained( "Qwen/Qwen3-VL-4B-Thinking", dtype="auto", device_map="auto" ) # Optional: Enable flash_attention_2 for better performance and memory efficiency, # especially in multi-image or video tasks. # model = Qwen3VLForConditionalGeneration.from_pretrained( # "Qwen/Qwen3-VL-4B-Thinking", # dtype=torch.bfloat16, # attn_implementation="flash_attention_2", # device_map="auto", # ) # Load the processor processor = AutoProcessor.from_pretrained("Qwen/Qwen3-VL-4B-Thinking") # Define input messages (image + text prompt) messages = [ { "role": "user", "content": [ { "type": "image", "image": "https://qianwen-res.oss-cn-beijing.aliyuncs.com/Qwen-VL/assets/demo.jpeg", }, {"type": "text", "text": "Describe this image."}, ], } ] # Prepare inputs for inference inputs = processor.apply_chat_template( messages, tokenize=True, add_generation_prompt=True, return_dict=True, return_tensors="pt" ).to(model.device) # Generate model output generated_ids = model.generate(**inputs, max_new_tokens=128) # Extract generated tokens (excluding prompt tokens) generated_ids_trimmed = [ output[len(input_ids):] for input_ids, output in zip(inputs.input_ids, generated_ids) ] # Decode output text output_text = processor.batch_decode( generated_ids_trimmed, skip_special_tokens=True, clean_up_tokenization_spaces=False ) print(output_text) ``` ### Run script ```bash conda activate qwen python3 test.py ``` ### Configuration **Model variants:** * 4B: `Qwen/Qwen3-VL-4B-Thinking` * 8B: `Qwen/Qwen3-VL-8B-Thinking` (requires more VRAM) **Precision:** * `dtype=torch.float16` or `torch.bfloat16` (A100/H100) **Flash Attention:** * Add `attn_implementation="flash_attention_2"` if supported. **Device:** * `device_map="auto"` (recommended) * `device_map={"":0}` (single GPU) ### Troubleshooting #### Issue: Out of memory (OOM) **Symptoms:** CUDA OOM error during model load or inference. **Resolution:** Reduce `max_new_tokens`, switch to `dtype=torch.float16`, or enable bitsandbytes quantization. #### Issue: Slow model loading **Symptoms:** Model takes several minutes to load. **Resolution:** Cache models locally, use NVMe storage, and enable `use_safetensors=True`. #### Issue: CUDA errors **Symptoms:** CUDA version mismatch errors. **Resolution:** Verify that your PyTorch and CUDA versions match. Run `nvidia-smi` to check the installed CUDA version. ### What's next * [Qwen3-VL on HuggingFace](https://huggingface.co/Qwen/Qwen3-VL-4B-Thinking) * [Multimodal Models](/quick-guides/llms/multimodal): Other vision-language model guides * [Getting Started](/getting-started): Spheron deployment basics * [Instance Types](/concepts/instance-types): GPU selection for vision-language models ## Inference Frameworks Choose the right LLM serving stack for your workload. All frameworks listed here expose an OpenAI-compatible `/v1` API unless otherwise noted. ### Framework comparison | Framework | Interface | Best For | Key Differentiator | | --------------------- | ---------------- | ------------------------------------ | ------------------------------------- | | vLLM | OpenAI REST | Production API, high throughput | PagedAttention; most widely used | | SGLang | OpenAI REST | Agentic pipelines, structured output | RadixAttention; constrained decoding | | TensorRT-LLM + Triton | Triton HTTP/gRPC | Maximum NVIDIA throughput | Engine compilation; NVIDIA-optimized | | llama.cpp | OpenAI REST | Quantized models, CPU+GPU offload | GGUF format; runs on 8GB cards | | LMDeploy | OpenAI REST | AWQ-quantized models | TurboMind engine; memory-efficient | | LocalAI | OpenAI REST | Multi-modal drop-in replacement | Docker; LLMs + Whisper + SD | | Ollama | OpenAI REST | Interactive local usage | Browser WebUI; one-command model pull | ### Available guides #### [vLLM Inference Server](/quick-guides/llms/frameworks/vllm-server) OpenAI-compatible inference server using vLLM on H100 or A100. Includes systemd service, SSH tunnel access, and performance tuning flags (`--tensor-parallel-size`, `--dtype`, `--max-model-len`). **Best for:** Production API workloads; drop-in replacement for the OpenAI API. #### [Ollama + Open WebUI](/quick-guides/llms/frameworks/ollama) Browser-based chat interface backed by Ollama on an RTX 4090. Docker Compose setup with NVIDIA GPU passthrough; pull any model with a single command. **Best for:** Interactive local model usage; exploring models without writing code. #### [SGLang](/quick-guides/llms/frameworks/sglang) Agentic LLM serving with RadixAttention for KV cache reuse across requests, constrained decoding for JSON output, and torch.compile support. **Best for:** Agentic pipelines, multi-turn workloads, and structured output generation. #### [TensorRT-LLM + Triton](/quick-guides/llms/frameworks/tensorrt-llm) NVIDIA-optimized engine compilation via TensorRT-LLM with Triton Inference Server for production-grade serving. Requires an engine-build step before inference. **Best for:** Maximum throughput on NVIDIA GPUs; latency-critical production deployments. #### [llama.cpp Server](/quick-guides/llms/frameworks/llama-cpp) GGUF model serving with CPU+GPU offload. Supports Q4, Q8, and F16 quantizations. Runs on GPUs as small as 8GB VRAM. **Best for:** Running quantized models on consumer GPUs; mixed CPU/GPU inference; minimal dependencies. #### [LMDeploy](/quick-guides/llms/frameworks/lmdeploy) LMDeploy TurboMind inference toolkit with AWQ quantization support and OpenAI-compatible API. **Best for:** Memory-efficient deployment of AWQ-quantized models on A100/H100. #### [LocalAI](/quick-guides/llms/frameworks/localai) OpenAI-compatible drop-in replacement via Docker with support for LLMs, Whisper speech-to-text, and Stable Diffusion image generation. **Best for:** Multi-modal local inference with a single OpenAI-compatible endpoint; replacing OpenAI calls without code changes. ### What's next * [LLM Inference Overview](/quick-guides/llms): Model guides and hardware recommendations * [Instance Types](/concepts/instance-types): Spot vs Dedicated vs Cluster * [Networking](/concepts/networking): SSH tunneling and port access * [Cost Optimization](/cost-optimization): Reducing inference costs with Spot instances ## llama.cpp Server Deploy [llama.cpp](https://github.com/ggerganov/llama.cpp) as an OpenAI-compatible HTTP server on Spheron GPU instances. llama.cpp supports GGUF-quantized models and can offload layers between CPU and GPU, making it ideal for consumer-grade GPUs and quantized inference. ### Recommended hardware | Model Size | Quantization | VRAM Required | Recommended GPU | | ---------- | ------------ | ------------- | ----------------------- | | 7B | Q4\_K\_M | \~4GB | RTX 4090 or any 8GB GPU | | 7B | Q8\_0 | \~8GB | RTX 4090 | | 7B | F16 | \~14GB | RTX 4090 (24GB) | | 13B | Q4\_K\_M | \~8GB | RTX 4090 | | 30B | Q4\_K\_M | \~20GB | RTX 4090 (24GB, tight) | | 70B | Q4\_K\_M | \~40GB | A100 80GB | ### Manual setup Use these steps to set up the server manually after SSH-ing into your instance. This works on any provider regardless of cloud-init support. #### Step 1: Connect to your instance ```bash ssh @ ``` Replace `` with your instance username (e.g., `root` or `ubuntu`) and `` with your instance's public IP. #### Step 2: Install dependencies ```bash sudo apt-get update -y sudo apt-get install -y python3-pip cmake build-essential pip install "llama-cpp-python[server]" --extra-index-url https://abetlen.github.io/llama-cpp-python/whl/cu121 ``` #### Step 3: Download a GGUF model ```bash mkdir -p /opt/llama-models # Example: download a GGUF model using huggingface-cli pip install huggingface_hub huggingface-cli download TheBloke/Llama-2-7B-Chat-GGUF llama-2-7b-chat.Q4_K_M.gguf \ --local-dir /opt/llama-models ``` Or copy your own GGUF file to `/opt/llama-models/model.gguf`. #### Step 4: Start the server Run the server in the foreground to verify it works: ```bash python3 -m llama_cpp.server \ --model /opt/llama-models/model.gguf \ --n_gpu_layers -1 \ --port 8080 ``` Press `Ctrl+C` to stop. #### Step 5: Run as a background service To keep the server running after you close your SSH session, create a systemd service: ```bash sudo tee /etc/systemd/system/llama-cpp.service > /dev/null << 'EOF' [Unit] Description=llama.cpp Inference Server After=network.target [Service] Type=simple ExecStart=/usr/bin/python3 -m llama_cpp.server \ --model /opt/llama-models/model.gguf \ --n_gpu_layers -1 \ --port 8080 Restart=on-failure RestartSec=10 [Install] WantedBy=multi-user.target EOF sudo systemctl daemon-reload sudo systemctl enable llama-cpp sudo systemctl start llama-cpp ``` Replace `/opt/llama-models/model.gguf` with your downloaded GGUF file path. Set `--n_gpu_layers -1` to offload all layers to GPU; reduce this number for CPU+GPU mixed inference. ### Accessing the server :::warning[Port 8080 is publicly accessible by default] Use SSH tunneling during development to keep the endpoint private. ::: #### SSH tunnel ```bash ssh -L 8080:localhost:8080 @ ``` #### Test completion ```bash curl http://localhost:8080/v1/completions \ -H "Content-Type: application/json" \ -d '{ "prompt": "Explain GGUF quantization briefly.", "max_tokens": 100 }' ``` ### Usage example ```python from openai import OpenAI client = OpenAI( base_url="http://localhost:8080/v1", api_key="not-needed", ) response = client.chat.completions.create( model="model", messages=[{"role": "user", "content": "What is GGUF quantization?"}], ) print(response.choices[0].message.content) ``` ### GPU layer offload | `--n_gpu_layers` | Behavior | | ---------------- | ----------------------------------- | | `-1` | All layers on GPU (fastest) | | `0` | CPU only (no GPU) | | `20` | First 20 layers on GPU, rest on CPU | Use partial offload when VRAM is insufficient for the full model. ### Check server logs ```bash journalctl -u llama-cpp -f ``` ### Cloud-init startup script (optional) If your provider supports cloud-init, you can paste this into the **Startup Script** field when deploying to automate the setup above. ```yaml #cloud-config runcmd: - apt-get update -y - apt-get install -y python3-pip cmake build-essential - pip install "llama-cpp-python[server]" --extra-index-url https://abetlen.github.io/llama-cpp-python/whl/cu121 - pip install huggingface_hub - mkdir -p /opt/llama-models - huggingface-cli download TheBloke/Llama-2-7B-Chat-GGUF llama-2-7b-chat.Q4_K_M.gguf --local-dir /opt/llama-models - mv /opt/llama-models/llama-2-7b-chat.Q4_K_M.gguf /opt/llama-models/model.gguf - | cat > /etc/systemd/system/llama-cpp.service << 'EOF' [Unit] Description=llama.cpp Inference Server After=network.target [Service] Type=simple ExecStart=/usr/bin/python3 -m llama_cpp.server \ --model /opt/llama-models/model.gguf \ --n_gpu_layers -1 \ --port 8080 Restart=on-failure RestartSec=10 [Install] WantedBy=multi-user.target EOF - systemctl daemon-reload - systemctl enable llama-cpp - systemctl start llama-cpp ``` The script downloads `llama-2-7b-chat.Q4_K_M.gguf` (\~4GB) as `model.gguf` before starting the service. To use a different model, replace the `huggingface-cli download` and `mv` lines with your preferred model download, ensuring the final file is saved to `/opt/llama-models/model.gguf`. ### What's next * [vLLM Inference Server](/quick-guides/llms/frameworks/vllm-server): Higher throughput for production workloads * [Inference Frameworks](/quick-guides/llms/frameworks): Compare all serving stacks * [Networking](/concepts/networking): SSH tunneling and port access * [Instance Types](/concepts/instance-types): Choosing the right GPU for your model ## LMDeploy Deploy [LMDeploy](https://github.com/InternLM/lmdeploy) with the TurboMind inference engine on Spheron A100 or H100 instances. LMDeploy supports AWQ quantization for memory-efficient inference and exposes an OpenAI-compatible API. ### Recommended hardware | Model Size | Recommended GPU | Instance Type | Notes | | ---------- | ---------------------- | ----------------- | ----------------------------------- | | 7B (AWQ) | RTX 4090 (24GB) | Dedicated or Spot | \~8GB VRAM with W4A16 AWQ | | 7B (FP16) | A100 40GB | Dedicated | Full precision | | 30B+ | A100 80GB (1–2×) | Dedicated | Use `--tp 2` for tensor parallelism | | 70B+ | H100 80GB (2× or more) | Cluster | TurboMind multi-GPU | ### Manual setup Use these steps to set up the server manually after SSH-ing into your instance. This works on any provider regardless of cloud-init support. #### Step 1: Connect to your instance ```bash ssh @ ``` Replace `` with the username shown in the instance details panel in the dashboard (e.g., `ubuntu` for Spheron AI instances) and `` with your instance's public IP. #### Step 2: Install LMDeploy ```bash sudo apt-get update -y sudo apt-get install -y python3-pip pip install lmdeploy ``` #### Step 3: Start the server Run the server in the foreground to verify it works: ```bash python3 -m lmdeploy serve api_server \ Qwen/Qwen2.5-7B-Instruct \ --server-port 23333 \ --backend turbomind ``` Press `Ctrl+C` to stop. Replace `Qwen/Qwen2.5-7B-Instruct` with your target model. #### Step 4: Run as a background service To keep the server running after you close your SSH session, create a systemd service: ```bash sudo tee /etc/systemd/system/lmdeploy.service > /dev/null << 'EOF' [Unit] Description=LMDeploy Inference Server After=network.target [Service] Type=simple ExecStart=/usr/bin/python3 -m lmdeploy serve api_server \ Qwen/Qwen2.5-7B-Instruct \ --server-port 23333 \ --backend turbomind Restart=on-failure RestartSec=10 [Install] WantedBy=multi-user.target EOF sudo systemctl daemon-reload sudo systemctl enable lmdeploy sudo systemctl start lmdeploy ``` ### AWQ quantization To convert a model to AWQ 4-bit before serving (reduces VRAM by \~50%): ```bash lmdeploy lite auto_awq \ Qwen/Qwen2.5-7B-Instruct \ --calib-dataset ptb \ --calib-samples 128 \ --work-dir ./qwen-7b-awq ``` Then serve the quantized model: ```bash lmdeploy serve api_server ./qwen-7b-awq \ --server-port 23333 \ --backend turbomind ``` ### Accessing the server :::warning[Port 23333 is publicly accessible by default] Use SSH tunneling during development to keep the endpoint private. ::: #### SSH tunnel ```bash ssh -L 23333:localhost:23333 @ ``` ### Usage example ```python from openai import OpenAI client = OpenAI( base_url="http://localhost:23333/v1", api_key="not-needed", ) response = client.chat.completions.create( model="Qwen/Qwen2.5-7B-Instruct", messages=[{"role": "user", "content": "What is AWQ quantization?"}], ) print(response.choices[0].message.content) ``` ### Performance flags | Flag | Description | | ------------------------- | --------------------------------------- | | `--backend turbomind` | Use TurboMind engine (default, fastest) | | `--tp` | Tensor parallel degree | | `--cache-max-entry-count` | KV cache size fraction | ### Check server logs ```bash journalctl -u lmdeploy -f ``` ### Cloud-init startup script (optional) If your provider supports cloud-init, you can paste this into the **Startup Script** field when deploying to automate the setup above. ```yaml #cloud-config runcmd: - apt-get update -y - apt-get install -y python3-pip - pip install lmdeploy - | cat > /etc/systemd/system/lmdeploy.service << 'EOF' [Unit] Description=LMDeploy Inference Server After=network.target [Service] Type=simple ExecStart=/usr/bin/python3 -m lmdeploy serve api_server \ Qwen/Qwen2.5-7B-Instruct \ --server-port 23333 \ --backend turbomind Restart=on-failure RestartSec=10 [Install] WantedBy=multi-user.target EOF - systemctl daemon-reload - systemctl enable lmdeploy - systemctl start lmdeploy ``` Replace `Qwen/Qwen2.5-7B-Instruct` with your target model. ### What's next * [vLLM Inference Server](/quick-guides/llms/frameworks/vllm-server): Wider model compatibility * [Inference Frameworks](/quick-guides/llms/frameworks): Compare all serving stacks * [Networking](/concepts/networking): SSH tunneling and port access * [Instance Types](/concepts/instance-types): A100 vs H100 for inference workloads ## LocalAI Deploy [LocalAI](https://github.com/mudler/LocalAI) on a Spheron GPU instance. LocalAI is an OpenAI-compatible drop-in replacement that supports LLMs, Whisper speech-to-text, and Stable Diffusion image generation through a single Docker container with NVIDIA GPU passthrough. ### Recommended hardware | Workload | Recommended GPU | Instance Type | Notes | | ---------------------- | --------------- | ----------------- | ---------------------------- | | LLM inference (7B Q4) | RTX 4090 (24GB) | Dedicated or Spot | \~4GB VRAM | | LLM + image generation | A100 40GB | Dedicated | Separate VRAM budgets | | Whisper only | Any GPU | Spot | CPU-capable, GPU accelerated | ### Supported model types | Type | Example Models | Notes | | ---------------- | -------------------------- | -------------------------------- | | LLMs (GGUF) | Llama, Mistral, Qwen | Download GGUF files to `/models` | | Speech-to-text | Whisper base/small/large | Auto-downloaded | | Image generation | Stable Diffusion 1.5, SDXL | Requires 8–16GB VRAM | ### Manual setup Use these steps to set up the server manually after SSH-ing into your instance. This works on any provider regardless of cloud-init support. #### Step 1: Connect to your instance ```bash ssh @ ``` Replace `` with the username shown in the instance details panel in the dashboard (e.g., `ubuntu` for Spheron AI instances) and `` with your instance's public IP. #### Step 2: Install Docker and NVIDIA container toolkit ```bash sudo apt-get update -y sudo apt-get install -y docker.io nvidia-container-toolkit sudo nvidia-ctk runtime configure --runtime=docker sudo systemctl restart docker ``` #### Step 3: Create the models directory ```bash sudo mkdir -p /opt/localai/models ``` Place GGUF model files in `/opt/localai/models/` before or after startup. LocalAI auto-discovers any `.gguf` file placed in the models directory. #### Step 4: Start the LocalAI container ```bash docker run -d \ --gpus all \ --name localai \ -p 8080:8080 \ -v /opt/localai/models:/models \ -e DEBUG=true \ quay.io/go-skynet/local-ai:latest-gpu-nvidia-cuda-12 ``` Verify it is running: ```bash docker ps docker logs -f localai ``` ### Accessing the server :::warning[Port 8080 is publicly accessible by default] Use SSH tunneling during development or add an authentication proxy. ::: #### SSH tunnel ```bash ssh -L 8080:localhost:8080 @ ``` #### List available models ```bash curl http://localhost:8080/v1/models ``` ### Usage example ```python from openai import OpenAI client = OpenAI( base_url="http://localhost:8080/v1", api_key="not-needed", ) response = client.chat.completions.create( model="my-model.gguf", # filename of the GGUF file in /models messages=[{"role": "user", "content": "Hello from LocalAI!"}], ) print(response.choices[0].message.content) ``` ### Check container logs ```bash docker logs -f localai ``` ### Cloud-init startup script (optional) If your provider supports cloud-init, you can paste this into the **Startup Script** field when deploying to automate the setup above. ```yaml #cloud-config runcmd: - apt-get update -y - apt-get install -y docker.io nvidia-container-toolkit - nvidia-ctk runtime configure --runtime=docker - systemctl restart docker - mkdir -p /opt/localai/models - | docker run -d \ --gpus all \ --name localai \ -p 8080:8080 \ -v /opt/localai/models:/models \ -e DEBUG=true \ quay.io/go-skynet/local-ai:latest-gpu-nvidia-cuda-12 ``` Place GGUF model files in `/opt/localai/models/` before or after startup. ### What's next * [vLLM Inference Server](/quick-guides/llms/frameworks/vllm-server): Higher throughput for production API workloads * [Inference Frameworks](/quick-guides/llms/frameworks): Compare all serving stacks * [Networking](/concepts/networking): SSH tunneling and port access * [Templates & Images](/templates): Additional startup script templates ## Ollama + Open WebUI Run [Ollama](https://ollama.com) with [Open WebUI](https://github.com/open-webui/open-webui) on an RTX 4090 Spheron instance. Open WebUI provides a browser-based chat interface backed by any model Ollama can load into VRAM. ### Recommended hardware **GPU:** RTX 4090 (24GB VRAM) **Instance Type:** Dedicated or Spot **OS:** Ubuntu 22.04 LTS The RTX 4090 supports: * Models up to \~13B parameters at Q4 quantization * Models up to \~7B parameters in full precision (FP16) For larger models (30B+), use an A100 or H100 instead. ### Manual setup Use these steps to set up the server manually after SSH-ing into your instance. This works on any provider regardless of cloud-init support. #### Step 1: Connect to your instance ```bash ssh @ ``` Replace `` with the username shown in the instance details panel in the dashboard (e.g., `ubuntu` for Spheron AI instances) and `` with your instance's public IP. #### Step 2: Install Docker ```bash sudo apt-get update -y sudo apt-get install -y ca-certificates curl gnupg sudo install -m 0755 -d /etc/apt/keyrings curl -fsSL https://download.docker.com/linux/ubuntu/gpg | sudo gpg --dearmor -o /etc/apt/keyrings/docker.gpg sudo chmod a+r /etc/apt/keyrings/docker.gpg echo "deb [arch=$(dpkg --print-architecture) signed-by=/etc/apt/keyrings/docker.gpg] https://download.docker.com/linux/ubuntu $(. /etc/os-release && echo $VERSION_CODENAME) stable" | sudo tee /etc/apt/sources.list.d/docker.list > /dev/null sudo apt-get update -y sudo apt-get install -y docker-ce docker-ce-cli containerd.io docker-compose-plugin ``` #### Step 3: Install NVIDIA container toolkit ```bash curl -fsSL https://nvidia.github.io/libnvidia-container/gpgkey | sudo gpg --dearmor -o /usr/share/keyrings/nvidia-container-toolkit-keyring.gpg curl -s -L https://nvidia.github.io/libnvidia-container/stable/deb/nvidia-container-toolkit.list | sed 's#deb https://#deb [signed-by=/usr/share/keyrings/nvidia-container-toolkit-keyring.gpg] https://#g' | sudo tee /etc/apt/sources.list.d/nvidia-container-toolkit.list sudo apt-get update -y sudo apt-get install -y nvidia-container-toolkit sudo nvidia-ctk runtime configure --runtime=docker sudo systemctl restart docker ``` #### Step 4: Create Docker Compose file ```bash mkdir -p /opt/ollama cat > /opt/ollama/docker-compose.yml << 'EOF' services: ollama: image: ollama/ollama:latest container_name: ollama runtime: nvidia environment: - NVIDIA_VISIBLE_DEVICES=all volumes: - ollama_data:/root/.ollama ports: - "11434:11434" restart: unless-stopped open-webui: image: ghcr.io/open-webui/open-webui:main container_name: open-webui ports: - "3000:8080" environment: - OLLAMA_BASE_URL=http://ollama:11434 volumes: - webui_data:/app/backend/data depends_on: - ollama restart: unless-stopped volumes: ollama_data: webui_data: EOF ``` #### Step 5: Start the services ```bash docker compose -f /opt/ollama/docker-compose.yml up -d ``` Verify both containers are running: ```bash docker compose -f /opt/ollama/docker-compose.yml ps ``` ### Access the web UI :::warning[Port 3000 is publicly accessible by default; enable authentication] All ports on your instance are open by default via its dedicated public IP. Open WebUI on port 3000 is reachable from the public internet. Enable authentication in Open WebUI settings before sharing the URL with others, or use SSH tunneling for development to keep it private. ::: #### SSH tunnel (recommended) ```bash ssh -L 3000:localhost:3000 @ ``` Replace `` with the username shown in the instance details panel in the dashboard (e.g., `ubuntu` for Spheron AI instances). Then open [http://localhost:3000](http://localhost:3000) in your browser. On first launch, create an admin account. ### Pull and use models #### Pull a model ```bash docker exec -it ollama ollama pull llama3.2 ``` Popular models for RTX 4090: ```bash docker exec -it ollama ollama pull llama3.2 # 3B, fast docker exec -it ollama ollama pull llama3.1:8b # 8B, good balance docker exec -it ollama ollama pull mistral:7b # 7B, good quality docker exec -it ollama ollama pull codellama:13b # 13B coding model ``` #### CLI usage ```bash docker exec -it ollama ollama run llama3.2 ``` #### API usage Ollama exposes an OpenAI-compatible API on port 11434. It is published to the host, so you can tunnel it the same way: ```bash ssh -L 11434:localhost:11434 @ ``` Then query it: ```bash curl http://localhost:11434/api/generate \ -d '{ "model": "llama3.2", "prompt": "Why is the sky blue?", "stream": false }' ``` ### Memory guidelines for RTX 4090 (24GB VRAM) | Model | Quantization | VRAM | Fits on 4090? | | ----- | ------------ | ------ | ----------------- | | 7B | FP16 | \~14GB | Yes | | 7B | Q4 | \~4GB | Yes | | 13B | Q4 | \~8GB | Yes | | 30B | Q4 | \~20GB | Yes (tight) | | 70B | Q4 | \~40GB | No; use A100/H100 | ### Cloud-init startup script (optional) If your provider supports cloud-init, you can paste this into the **Startup Script** field when deploying. It installs Docker with the NVIDIA Container Toolkit, writes a `docker-compose.yml`, and starts both services. ```yaml #cloud-config runcmd: - apt-get update -y - apt-get install -y ca-certificates curl gnupg - install -m 0755 -d /etc/apt/keyrings - curl -fsSL https://download.docker.com/linux/ubuntu/gpg | gpg --dearmor -o /etc/apt/keyrings/docker.gpg - chmod a+r /etc/apt/keyrings/docker.gpg - echo "deb [arch=$(dpkg --print-architecture) signed-by=/etc/apt/keyrings/docker.gpg] https://download.docker.com/linux/ubuntu $(. /etc/os-release && echo $VERSION_CODENAME) stable" > /etc/apt/sources.list.d/docker.list - apt-get update -y - apt-get install -y docker-ce docker-ce-cli containerd.io docker-compose-plugin - curl -fsSL https://nvidia.github.io/libnvidia-container/gpgkey | gpg --dearmor -o /usr/share/keyrings/nvidia-container-toolkit-keyring.gpg - curl -s -L https://nvidia.github.io/libnvidia-container/stable/deb/nvidia-container-toolkit.list | sed 's#deb https://#deb [signed-by=/usr/share/keyrings/nvidia-container-toolkit-keyring.gpg] https://#g' > /etc/apt/sources.list.d/nvidia-container-toolkit.list - apt-get update -y - apt-get install -y nvidia-container-toolkit - nvidia-ctk runtime configure --runtime=docker - systemctl restart docker - mkdir -p /opt/ollama - | cat > /opt/ollama/docker-compose.yml << 'EOF' services: ollama: image: ollama/ollama:latest container_name: ollama runtime: nvidia environment: - NVIDIA_VISIBLE_DEVICES=all volumes: - ollama_data:/root/.ollama ports: - "11434:11434" restart: unless-stopped open-webui: image: ghcr.io/open-webui/open-webui:main container_name: open-webui ports: - "3000:8080" environment: - OLLAMA_BASE_URL=http://ollama:11434 volumes: - webui_data:/app/backend/data depends_on: - ollama restart: unless-stopped volumes: ollama_data: webui_data: EOF - chmod 644 /opt/ollama/docker-compose.yml - docker compose -f /opt/ollama/docker-compose.yml up -d ``` ### What's next * [vLLM Inference Server](/quick-guides/llms/frameworks/vllm-server): OpenAI-compatible API for production workloads * [Templates & Images](/templates): Additional startup script templates * [Networking](/concepts/networking): SSH tunneling and port access * [Instance Types](/concepts/instance-types): Choosing the right GPU for your model ## SGLang Inference Server Deploy an [SGLang](https://github.com/sgl-project/sglang) OpenAI-compatible inference server on Spheron GPU instances. SGLang features RadixAttention for KV cache reuse across requests and native support for constrained decoding and structured output. ### Recommended hardware | Model Size | Recommended GPU | Instance Type | Notes | | ---------- | ---------------------- | ------------------- | --------------------------------- | | 7B–13B | RTX 4090 (24GB) | Dedicated or Spot | Single-GPU, fast iteration | | 30B–70B | A100 80GB (1×) | Dedicated | Full-precision or AWQ | | 70B+ | H100 80GB (2× or more) | Dedicated / Cluster | Use `--tp` for tensor parallelism | ### Manual setup Use these steps to set up the server manually after SSH-ing into your instance. This works on any provider regardless of cloud-init support. #### Step 1: Connect to your instance ```bash ssh @ ``` Replace `` with the username shown in the instance details panel in the dashboard (e.g., `ubuntu` for Spheron AI instances) and `` with your instance's public IP. #### Step 2: Install SGLang ```bash sudo apt-get update -y sudo apt-get install -y python3-pip pip install "sglang[all]" ``` #### Step 3: Start the server Run the server in the foreground to verify it works: ```bash python3 -m sglang.launch_server \ --model-path meta-llama/Llama-3.1-8B-Instruct \ --port 30000 \ --tp 1 ``` Press `Ctrl+C` to stop. Replace `meta-llama/Llama-3.1-8B-Instruct` with your target model and adjust `--tp` to match the number of GPUs. #### Step 4: Run as a background service To keep the server running after you close your SSH session, create a systemd service: ```bash sudo tee /etc/systemd/system/sglang.service > /dev/null << 'EOF' [Unit] Description=SGLang Inference Server After=network.target [Service] Type=simple ExecStart=/usr/bin/python3 -m sglang.launch_server \ --model-path meta-llama/Llama-3.1-8B-Instruct \ --port 30000 \ --tp 1 Restart=on-failure RestartSec=10 [Install] WantedBy=multi-user.target EOF sudo systemctl daemon-reload sudo systemctl enable sglang sudo systemctl start sglang ``` ### Accessing the server :::warning[Port 30000 is publicly accessible by default; add authentication] All ports on your instance are open by default. Use SSH tunneling during development to keep the endpoint private, or add `--api-key ` to the launch command. ::: #### SSH tunnel (recommended) ```bash ssh -L 30000:localhost:30000 @ ``` #### List available models ```bash curl http://localhost:30000/v1/models ``` ### Usage example ```python from openai import OpenAI client = OpenAI( base_url="http://localhost:30000/v1", api_key="not-needed", ) response = client.chat.completions.create( model="meta-llama/Llama-3.1-8B-Instruct", messages=[{"role": "user", "content": "Explain RadixAttention briefly."}], ) print(response.choices[0].message.content) ``` ### Performance flags | Flag | Description | Recommended Value | | ------------------------ | ----------------------------------- | -------------------------------- | | `--tp` | Tensor parallel degree | Match GPU count | | `--chunked-prefill-size` | Chunked prefill token budget | `512` or `1024` | | `--enable-torch-compile` | torch.compile for kernel fusion | Slower startup, faster inference | | `--mem-fraction-static` | Fraction of GPU memory for KV cache | `0.85` | ### Check server logs ```bash journalctl -u sglang -f ``` ### Cloud-init startup script (optional) If your provider supports cloud-init, you can paste this into the **Startup Script** field when deploying to automate the setup above. ```yaml #cloud-config runcmd: - apt-get update -y - apt-get install -y python3-pip - pip install "sglang[all]" - | cat > /etc/systemd/system/sglang.service << 'EOF' [Unit] Description=SGLang Inference Server After=network.target [Service] Type=simple ExecStart=/usr/bin/python3 -m sglang.launch_server \ --model-path meta-llama/Llama-3.1-8B-Instruct \ --port 30000 \ --tp 1 Restart=on-failure RestartSec=10 [Install] WantedBy=multi-user.target EOF - systemctl daemon-reload - systemctl enable sglang - systemctl start sglang ``` Replace `meta-llama/Llama-3.1-8B-Instruct` with your target model and adjust `--tp` to match the number of GPUs. ### What's next * [vLLM Inference Server](/quick-guides/llms/frameworks/vllm-server): Alternative for production API workloads * [Inference Frameworks](/quick-guides/llms/frameworks): Compare all serving stacks * [Networking](/concepts/networking): SSH tunneling and port access * [Cost Optimization](/cost-optimization): GPU tier selection for inference workloads ## TensorRT-LLM + Triton Inference Server Deploy [TensorRT-LLM](https://github.com/NVIDIA/TensorRT-LLM) with [Triton Inference Server](https://github.com/triton-inference-server/server) on Spheron H100 instances for maximum NVIDIA GPU throughput. TensorRT-LLM compiles model weights into an optimized engine before inference, yielding best-in-class token generation rates. ### Recommended hardware | Model Size | Recommended GPU | Instance Type | Notes | | ---------- | -------------------- | ------------- | -------------------------------------- | | 7B–13B | H100 80GB (1×) | Dedicated | FP8 precision, highest throughput | | 30B–70B | H100 80GB (2× or 4×) | Cluster | Multi-GPU engine with `--tp_size` | | 70B+ | H100 NVLink (8×) | Cluster | Requires NVLink for tensor parallelism | ### Manual setup Use these steps to set up the server manually after SSH-ing into your instance. This works on any provider regardless of cloud-init support. #### Step 1: Connect to your instance ```bash ssh @ ``` Replace `` with the username shown in the instance details panel in the dashboard (e.g., `ubuntu` for Spheron AI instances) and `` with your instance's public IP. #### Step 2: Install dependencies ```bash sudo apt-get update -y sudo apt-get install -y docker.io nvidia-container-toolkit git python3-pip sudo nvidia-ctk runtime configure --runtime=docker sudo systemctl restart docker ``` #### Step 3: Pull the TensorRT-LLM Docker image ```bash docker pull nvcr.io/nvidia/tritonserver:25.08-trtllm-python-py3 ``` #### Step 4: Prepare directories and download model ```bash sudo mkdir -p /opt/trtllm/engines /opt/trtllm/model_repo /opt/trtllm/hf_model pip install huggingface_hub # Store the token in a file readable only by root sudo mkdir -p /etc/trtllm sudo install -m 600 /dev/null /etc/trtllm/hf-token echo "HF_TOKEN=" | sudo tee /etc/trtllm/hf-token > /dev/null # Load and use the token without exposing it in the process list or shell history . /etc/trtllm/hf-token huggingface-cli download meta-llama/Meta-Llama-3.1-8B-Instruct \ --local-dir /opt/trtllm/hf_model ``` Replace `` with your HuggingFace token. The token is stored in `/etc/trtllm/hf-token` (mode 600) and loaded via `. /etc/trtllm/hf-token` so it never appears inline on the command line. #### Step 5: Build the TensorRT engine :::info[Engine Build Time] Engine compilation can take 15–60 minutes depending on model size. The compiled engine is cached on disk and reused on restart. ::: ```bash docker run --rm --gpus all \ -v /opt/trtllm:/workspace \ nvcr.io/nvidia/tritonserver:25.08-trtllm-python-py3 \ bash -c " pip install tensorrt_llm -U && \ python3 -m tensorrt_llm.commands.build \ --model_dir /workspace/hf_model \ --output_dir /workspace/engines/llama-8b \ --dtype float16 \ --tp_size 1 " ``` #### Step 6: Configure Triton model repository ```bash git clone --depth 1 https://github.com/triton-inference-server/tensorrtllm_backend.git /opt/trtllm/tensorrtllm_backend cp -r /opt/trtllm/tensorrtllm_backend/all_models/inflight_batcher_llm/* /opt/trtllm/model_repo/ docker run --rm \ -v /opt/trtllm:/workspace \ nvcr.io/nvidia/tritonserver:25.08-trtllm-python-py3 \ bash -c " python3 /workspace/tensorrtllm_backend/tools/fill_template.py \ --in_place \ /workspace/model_repo/tensorrt_llm/config.pbtxt \ 'decoupled_mode:false,engine_dir:/engines/llama-8b,max_tokens_in_paged_kv_cache:2560,max_attention_window_size:2560,kv_cache_free_gpu_mem_fraction:0.5,exclude_input_in_output:true,enable_kv_cache_reuse:false,batching_strategy:inflight_fused_batching,max_beam_width:1' && \ python3 /workspace/tensorrtllm_backend/tools/fill_template.py \ --in_place \ /workspace/model_repo/preprocessing/config.pbtxt \ 'tokenizer_dir:/hf_model,tokenizer_type:auto,triton_max_batch_size:64,preprocessing_instance_count:1' && \ python3 /workspace/tensorrtllm_backend/tools/fill_template.py \ --in_place \ /workspace/model_repo/postprocessing/config.pbtxt \ 'tokenizer_dir:/hf_model,tokenizer_type:auto,triton_max_batch_size:64,postprocessing_instance_count:1' && \ python3 /workspace/tensorrtllm_backend/tools/fill_template.py \ --in_place \ /workspace/model_repo/ensemble/config.pbtxt \ 'triton_max_batch_size:64' && \ python3 /workspace/tensorrtllm_backend/tools/fill_template.py \ --in_place \ /workspace/model_repo/tensorrt_llm_bls/config.pbtxt \ 'triton_max_batch_size:64,decoupled_mode:false,bls_instance_count:1,accumulate_tokens:false' " ``` #### Step 7: Start Triton server ```bash docker run -d --gpus all \ -p 8000:8000 -p 8001:8001 -p 8002:8002 \ -v /opt/trtllm/model_repo:/opt/tritonserver/model_repo \ -v /opt/trtllm/engines:/engines \ -v /opt/trtllm/hf_model:/hf_model \ --name triton \ nvcr.io/nvidia/tritonserver:25.08-trtllm-python-py3 \ tritonserver --model-repository=/opt/tritonserver/model_repo ``` Monitor startup: ```bash docker logs -f triton ``` ### Accessing the server :::warning[Port 8000 is publicly accessible by default] Use SSH tunneling during development or add an authentication proxy in front of Triton. ::: #### SSH tunnel ```bash ssh -L 8000:localhost:8000 @ ``` #### Health check ```bash curl http://localhost:8000/v2/health/ready ``` ### Usage example ```python import requests response = requests.post( "http://localhost:8000/v2/models/ensemble/generate", json={ "text_input": "Explain GPU tensor parallelism.", "max_tokens": 200, "bad_words": "", "stop_words": "", }, ) response.raise_for_status() print(response.json()["text_output"]) ``` ### Engine build flags | Flag | Description | | ------------------ | ------------------------------------------------- | | `--dtype` | Weight precision: `float16`, `bfloat16`, `float8` | | `--tp_size` | Tensor parallel degree (match GPU count) | | `--max_batch_size` | Maximum concurrent requests | | `--max_input_len` | Maximum input sequence length | ### Check container logs ```bash docker logs -f triton ``` ### Cloud-init startup script (optional) If your provider supports cloud-init, you can paste this into the **Startup Script** field when deploying. This script pulls the NVIDIA Triton + TensorRT-LLM Docker image, builds an engine for Llama-3-8B in FP16, configures the Triton model repository from the official `tensorrtllm_backend` templates, and starts the Triton HTTP server on port 8000. ```yaml #cloud-config runcmd: - apt-get update -y - apt-get install -y docker.io nvidia-container-toolkit git python3-pip - nvidia-ctk runtime configure --runtime=docker - systemctl restart docker - docker pull nvcr.io/nvidia/tritonserver:25.08-trtllm-python-py3 - mkdir -p /opt/trtllm/engines /opt/trtllm/model_repo /opt/trtllm/hf_model /etc/trtllm - pip install huggingface_hub - install -m 600 /dev/null /etc/trtllm/hf-token - echo "HF_TOKEN=" > /etc/trtllm/hf-token - sh -c '. /etc/trtllm/hf-token && huggingface-cli download meta-llama/Meta-Llama-3.1-8B-Instruct --local-dir /opt/trtllm/hf_model' - | docker run --rm --gpus all \ -v /opt/trtllm:/workspace \ nvcr.io/nvidia/tritonserver:25.08-trtllm-python-py3 \ bash -c " pip install tensorrt_llm -U && \ python3 -m tensorrt_llm.commands.build \ --model_dir /workspace/hf_model \ --output_dir /workspace/engines/llama-8b \ --dtype float16 \ --tp_size 1 " - git clone --depth 1 https://github.com/triton-inference-server/tensorrtllm_backend.git /opt/trtllm/tensorrtllm_backend - cp -r /opt/trtllm/tensorrtllm_backend/all_models/inflight_batcher_llm/* /opt/trtllm/model_repo/ - | docker run --rm \ -v /opt/trtllm:/workspace \ nvcr.io/nvidia/tritonserver:25.08-trtllm-python-py3 \ bash -c " python3 /workspace/tensorrtllm_backend/tools/fill_template.py \ --in_place \ /workspace/model_repo/tensorrt_llm/config.pbtxt \ 'decoupled_mode:false,engine_dir:/engines/llama-8b,max_tokens_in_paged_kv_cache:2560,max_attention_window_size:2560,kv_cache_free_gpu_mem_fraction:0.5,exclude_input_in_output:true,enable_kv_cache_reuse:false,batching_strategy:inflight_fused_batching,max_beam_width:1' && \ python3 /workspace/tensorrtllm_backend/tools/fill_template.py \ --in_place \ /workspace/model_repo/preprocessing/config.pbtxt \ 'tokenizer_dir:/hf_model,tokenizer_type:auto,triton_max_batch_size:64,preprocessing_instance_count:1' && \ python3 /workspace/tensorrtllm_backend/tools/fill_template.py \ --in_place \ /workspace/model_repo/postprocessing/config.pbtxt \ 'tokenizer_dir:/hf_model,tokenizer_type:auto,triton_max_batch_size:64,postprocessing_instance_count:1' && \ python3 /workspace/tensorrtllm_backend/tools/fill_template.py \ --in_place \ /workspace/model_repo/ensemble/config.pbtxt \ 'triton_max_batch_size:64' && \ python3 /workspace/tensorrtllm_backend/tools/fill_template.py \ --in_place \ /workspace/model_repo/tensorrt_llm_bls/config.pbtxt \ 'triton_max_batch_size:64,decoupled_mode:false,bls_instance_count:1,accumulate_tokens:false' " - | docker run -d --gpus all \ -p 8000:8000 -p 8001:8001 -p 8002:8002 \ -v /opt/trtllm/model_repo:/opt/tritonserver/model_repo \ -v /opt/trtllm/engines:/engines \ -v /opt/trtllm/hf_model:/hf_model \ --name triton \ nvcr.io/nvidia/tritonserver:25.08-trtllm-python-py3 \ tritonserver --model-repository=/opt/tritonserver/model_repo ``` ### What's next * [vLLM Inference Server](/quick-guides/llms/frameworks/vllm-server): Easier setup for most use cases * [Inference Frameworks](/quick-guides/llms/frameworks): Compare all serving stacks * [Instance Types](/concepts/instance-types): H100 NVLink cluster requirements * [Networking](/concepts/networking): SSH tunneling and port access ## vLLM Inference Server Deploy an OpenAI-compatible inference server using [vLLM](https://github.com/vllm-project/vllm) on Spheron H100 or A100 instances. ### Recommended hardware | Model Size | Recommended GPU | Instance Type | Notes | | ---------- | ---------------------- | ------------- | ------------------------------------ | | 7B–13B | H100 80GB (1×) | Dedicated | Single-GPU, fastest throughput | | 30B+ | A100 80GB (2×) | Dedicated | Use `tensor_parallel_size=2` | | 70B+ | H100 NVLink (4× or 8×) | Cluster | Use NVLink offers for best bandwidth | For multi-GPU offers, select an offer with `interconnectType: "NVLink"` for maximum tensor-parallel performance. ### Manual setup Use these steps to set up the server manually after SSH-ing into your instance. This works on any provider regardless of cloud-init support. #### Step 1: Connect to your instance ```bash ssh @ ``` Replace `` with the username shown in the instance details panel in the dashboard (e.g., `ubuntu` for Spheron AI instances) and `` with your instance's public IP. #### Step 2: Install vLLM ```bash sudo apt-get update -y sudo apt-get install -y python3-pip pip install vllm ``` #### Step 3: Start the server Run the server in the foreground to verify it works: ```bash python3 -m vllm.entrypoints.openai.api_server \ --model meta-llama/Meta-Llama-3.1-8B-Instruct \ --tensor-parallel-size 1 \ --port 8000 \ --gpu-memory-utilization 0.9 ``` Press `Ctrl+C` to stop. Replace `meta-llama/Meta-Llama-3.1-8B-Instruct` with your target model and adjust `--tensor-parallel-size` to match the number of GPUs on your instance. #### Step 4: Run as a background service To keep the server running after you close your SSH session, create a systemd service: ```bash sudo tee /etc/systemd/system/vllm.service > /dev/null << 'EOF' [Unit] Description=vLLM Inference Server After=network.target [Service] Type=simple ExecStart=/usr/bin/python3 -m vllm.entrypoints.openai.api_server \ --model meta-llama/Meta-Llama-3.1-8B-Instruct \ --tensor-parallel-size 1 \ --port 8000 \ --gpu-memory-utilization 0.9 Restart=on-failure RestartSec=10 [Install] WantedBy=multi-user.target EOF sudo systemctl daemon-reload sudo systemctl enable vllm sudo systemctl start vllm ``` ### Accessing the server :::warning[Port 8000 is publicly accessible by default; add authentication] All ports on your instance are open by default via its dedicated public IP. Anyone who can reach your IP can send requests to the vLLM server. Add token-based authentication (`--api-key `) to the vLLM startup command before exposing the server publicly, or use SSH tunneling for development to keep the endpoint private. ::: #### SSH tunnel (recommended) ```bash ssh -L 8000:localhost:8000 @ ``` Replace `` with the username shown in the instance details panel in the dashboard (e.g., `ubuntu` for Spheron AI instances). Keep this terminal open, then test from another terminal on your machine: ```bash curl http://localhost:8000/v1/completions \ -H "Content-Type: application/json" \ -d '{ "model": "meta-llama/Meta-Llama-3.1-8B-Instruct", "prompt": "Hello, world!", "max_tokens": 50 }' ``` #### List available models ```bash curl http://localhost:8000/v1/models ``` #### OpenAI SDK compatibility ```python from openai import OpenAI client = OpenAI( base_url="http://localhost:8000/v1", api_key="not-needed", # vLLM does not require a key by default ) response = client.chat.completions.create( model="meta-llama/Meta-Llama-3.1-8B-Instruct", messages=[{"role": "user", "content": "Explain GPU parallelism briefly."}], ) print(response.choices[0].message.content) ``` ### Performance tuning | Flag | Description | Recommended Value | | -------------------------- | ---------------------------------------- | ------------------------------------ | | `--tensor-parallel-size` | Number of GPUs for tensor parallelism | Match GPU count | | `--gpu-memory-utilization` | Fraction of GPU VRAM to use for KV cache | `0.9` | | `--max-model-len` | Maximum sequence length | Reduce if OOM | | `--dtype` | Model weight precision | `fp8` for H100, `bfloat16` otherwise | Example for 2× A100 with BF16 and large context: ```bash python3 -m vllm.entrypoints.openai.api_server \ --model meta-llama/Meta-Llama-3.1-70B-Instruct \ --tensor-parallel-size 2 \ --port 8000 \ --gpu-memory-utilization 0.9 \ --dtype bfloat16 \ --max-model-len 32768 ``` ### Monitoring Check server logs: ```bash journalctl -u vllm -f ``` Watch GPU utilization: ```bash nvidia-smi dmon -s u ``` ### Cloud-init startup script (optional) If your provider supports cloud-init, you can paste this into the **Startup Script** field when deploying. It installs vLLM, starts the server on port 8000, and creates a systemd service for persistence across reboots. ```yaml #cloud-config runcmd: - apt-get update -y - apt-get install -y python3-pip - pip install vllm - | cat > /etc/systemd/system/vllm.service << 'EOF' [Unit] Description=vLLM Inference Server After=network.target [Service] Type=simple ExecStart=/usr/bin/python3 -m vllm.entrypoints.openai.api_server \ --model meta-llama/Meta-Llama-3.1-8B-Instruct \ --tensor-parallel-size 1 \ --port 8000 \ --gpu-memory-utilization 0.9 Restart=on-failure RestartSec=10 [Install] WantedBy=multi-user.target EOF - systemctl daemon-reload - systemctl enable vllm - systemctl start vllm ``` Replace `meta-llama/Meta-Llama-3.1-8B-Instruct` with your target model and adjust `--tensor-parallel-size` to match the number of GPUs on your instance. ### What's next * [Templates & Images](/templates): Copy-ready startup scripts * [Ollama + Open WebUI](/quick-guides/llms/frameworks/ollama): Alternative for interactive local usage * [Networking](/concepts/networking): Dedicated IP, port access, and SSH tunneling * [Cost Optimization](/cost-optimization): GPU tier selection for inference workloads ## ComfyUI Deploy [ComfyUI](https://github.com/Comfy-Org/ComfyUI) on a Spheron GPU instance using Docker. ComfyUI provides a browser-based node editor for building image generation workflows, plus a JSON API for programmatic access. ### Recommended hardware | Workload | Min VRAM | Recommended GPU | Instance Type | | ---------------------- | -------- | ---------------- | ----------------- | | SD 1.5 workflows | 6 GB | Any 6 GB+ GPU | Spot | | SDXL workflows | 10 GB | RTX 4090 (24 GB) | Spot or Dedicated | | FLUX.1 workflows | 16 GB | RTX 4090 (24 GB) | Dedicated | | Large batch generation | 40 GB | A100 40/80 GB | Dedicated | ### Prerequisites * A running Spheron GPU instance (see [Instance Types](/concepts/instance-types)) * SSH access to the instance * A model checkpoint file (`.safetensors` or `.ckpt`) for the workflow you want to run ### Manual setup Use these steps to set up the server manually after SSH-ing into your instance. This works on any provider regardless of cloud-init support. #### Step 1: Connect to your instance ```bash ssh @ ``` Replace `` with the username shown in the instance details panel (e.g., `ubuntu` for Spheron AI instances) and `` with your instance's public IP. #### Step 2: Install Docker and NVIDIA container toolkit ```bash sudo apt-get update -y sudo apt-get install -y docker.io nvidia-container-toolkit sudo nvidia-ctk runtime configure --runtime=docker sudo systemctl restart docker ``` #### Step 3: Create model and output directories ```bash sudo mkdir -p /opt/comfyui/models /opt/comfyui/output /opt/comfyui/custom_nodes ``` Place model checkpoints (`.safetensors`, `.ckpt`) in `/opt/comfyui/models/checkpoints/` before or after startup. ComfyUI auto-detects them. #### Step 4: Start ComfyUI ```bash docker run -d \ --gpus all \ --name comfyui \ -p 8188:8188 \ -v /opt/comfyui/models:/root/ComfyUI/models \ -v /opt/comfyui/output:/root/ComfyUI/output \ -v /opt/comfyui/custom_nodes:/root/ComfyUI/custom_nodes \ yanwk/comfyui-boot:cu128-slim ``` Verify it is running: ```bash docker ps docker logs -f comfyui ``` ### Accessing the server :::warning[Port 8188 is publicly accessible by default] Use SSH tunneling during development to keep the ComfyUI interface private. ::: #### SSH tunnel (recommended) ```bash ssh -L 8188:localhost:8188 @ ``` Then open [http://localhost:8188](http://localhost:8188) in your browser. ### Programmatic workflow API ComfyUI exposes a `POST /prompt` endpoint for running workflows programmatically. Use the browser UI to build and export your workflow as API JSON, then submit it via HTTP. ```python import requests import uuid # Export your workflow from ComfyUI browser UI as API format JSON with open("workflow_api.json") as f: import json workflow = json.load(f) response = requests.post( "http://localhost:8188/prompt", json={ "client_id": str(uuid.uuid4()), "prompt": workflow, }, ) response.raise_for_status() prompt_id = response.json()["prompt_id"] print("Prompt ID:", prompt_id) ``` #### Poll for completion ```python import requests, time prompt_id = "your-prompt-id" # Terminal states per ComfyUI execution.py: "success" or "error" TERMINAL_ERROR_STATES = {"error"} max_retries = 300 # 5 minutes at 1-second intervals for _ in range(max_retries): response = requests.get(f"http://localhost:8188/history/{prompt_id}") response.raise_for_status() history = response.json() if prompt_id in history: job = history[prompt_id] status = job.get("status") if isinstance(status, dict): status_str = status.get("status_str") elif status is not None: print(f"Warning: unexpected status format (type={type(status).__name__!r}), continuing to poll...") status_str = None else: status_str = None if status_str == "success": outputs = job.get("outputs", {}) print("Generation complete:", outputs) break elif status_str in TERMINAL_ERROR_STATES: # Extract the exception message from the execution_error entry in messages messages = status.get("messages", []) if isinstance(status, dict) else [] error_detail = next( (msg[1] for msg in messages if isinstance(msg, (list, tuple)) and msg[0] == "execution_error"), None, ) detail_str = ( f": {error_detail.get('exception_message', '')}" if isinstance(error_detail, dict) else "" ) raise RuntimeError(f"Generation failed with status '{status_str}'{detail_str}") elif status_str is not None: # Unknown status: log a warning and keep polling print(f"Warning: unknown status '{status_str}', continuing to poll...") time.sleep(1) else: raise TimeoutError(f"Generation did not complete within {max_retries} seconds") ``` ### Check container logs ```bash docker logs -f comfyui ``` ### Cloud-init startup script (optional) If your provider supports cloud-init, you can paste this into the **Startup Script** field when deploying to automate the setup above. It starts ComfyUI via the `yanwk/comfyui-boot:cu128-slim` Docker image (CUDA 12.8), a minimal install that includes ComfyUI and ComfyUI-Manager. Install additional custom nodes through the ComfyUI-Manager interface after startup. ```yaml #cloud-config runcmd: - apt-get update -y - apt-get install -y docker.io nvidia-container-toolkit - nvidia-ctk runtime configure --runtime=docker - systemctl restart docker - mkdir -p /opt/comfyui/models /opt/comfyui/output /opt/comfyui/custom_nodes - | docker run -d \ --gpus all \ --name comfyui \ -p 8188:8188 \ -v /opt/comfyui/models:/root/ComfyUI/models \ -v /opt/comfyui/output:/root/ComfyUI/output \ -v /opt/comfyui/custom_nodes:/root/ComfyUI/custom_nodes \ yanwk/comfyui-boot:cu128-slim ``` Place model checkpoints (`.safetensors`, `.ckpt`) in `/opt/comfyui/models/checkpoints/` before or after startup. ### What's next * [FLUX.1 & FLUX.2](/quick-guides/image-generation/flux-1): FLUX models compatible with ComfyUI * [Stable Diffusion 3.5 & SDXL](/quick-guides/image-generation/stable-diffusion-35): SD models for ComfyUI workflows * [Image Generation Overview](/quick-guides/image-generation): VRAM requirements and model comparison * [Networking](/concepts/networking): SSH tunneling and port access ## FLUX.1 & FLUX.2 Deploy [FLUX.1](https://huggingface.co/black-forest-labs/FLUX.1-dev) and FLUX.2 from [Black Forest Labs](https://blackforestlabs.ai) on Spheron GPU instances. FLUX models deliver state-of-the-art photorealistic text-to-image generation. ### Recommended hardware | Model | Min VRAM | Recommended GPU | Instance Type | | -------------- | -------- | ------------------------------- | ----------------- | | FLUX.1-dev | 16 GB | RTX 4090 (24 GB) | Dedicated or Spot | | FLUX.1-schnell | 16 GB | RTX 4090 (24 GB) | Dedicated or Spot | | FLUX.2-dev | 80 GB | H100 80 GB (FP8) or H200 141 GB | Dedicated | ### Prerequisites * A running Spheron GPU instance (see [Instance Types](/concepts/instance-types)) * SSH access to the instance * A [HuggingFace account](https://huggingface.co) with access granted to the FLUX model you intend to use: both [FLUX.1-dev](https://huggingface.co/black-forest-labs/FLUX.1-dev) (non-commercial license) and [FLUX.1-schnell](https://huggingface.co/black-forest-labs/FLUX.1-schnell) (Apache 2.0 license) are gated models that require accepting their respective licenses before downloading. :::warning[HuggingFace access required for FLUX.1 models] Both FLUX.1-dev and FLUX.1-schnell are gated models. Accept the license on each model's HuggingFace page ([FLUX.1-dev](https://huggingface.co/black-forest-labs/FLUX.1-dev), [FLUX.1-schnell](https://huggingface.co/black-forest-labs/FLUX.1-schnell)) and set `HF_TOKEN` before running the server. FLUX.1-dev uses a non-commercial license; FLUX.1-schnell uses the Apache 2.0 license. ::: ### Manual setup Use these steps to set up the server manually after SSH-ing into your instance. This works on any provider regardless of cloud-init support. #### Step 1: Connect to your instance ```bash ssh @ ``` Replace `` with the username shown in the instance details panel (e.g., `ubuntu` for Spheron AI instances) and `` with your instance's public IP. #### Step 2: Install dependencies ```bash sudo apt-get update -y sudo apt-get install -y python3-pip pip install diffusers transformers accelerate torch fastapi uvicorn pillow sentencepiece huggingface_hub ``` #### Step 2a: Authenticate with HuggingFace Both FLUX.1-dev and FLUX.1-schnell are gated models and require a HuggingFace token. ```bash huggingface-cli login --token ``` Replace `` with a token from [huggingface.co/settings/tokens](https://huggingface.co/settings/tokens). #### Step 3: Create the server script ```bash cat > /opt/flux_server.py << 'EOF' import io, base64 from fastapi import FastAPI from pydantic import BaseModel import torch from diffusers import FluxPipeline app = FastAPI() pipe = FluxPipeline.from_pretrained( "black-forest-labs/FLUX.1-dev", torch_dtype=torch.bfloat16, ).to("cuda") class GenerateRequest(BaseModel): prompt: str width: int = 1024 height: int = 1024 num_inference_steps: int = 28 guidance_scale: float = 3.5 @app.post("/generate") def generate(req: GenerateRequest): image = pipe( req.prompt, width=req.width, height=req.height, num_inference_steps=req.num_inference_steps, guidance_scale=req.guidance_scale, ).images[0] buf = io.BytesIO() image.save(buf, format="PNG") return {"image_b64": base64.b64encode(buf.getvalue()).decode()} if __name__ == "__main__": import uvicorn uvicorn.run(app, host="0.0.0.0", port=8000) EOF ``` :::info[Model Download Time] First startup downloads FLUX.1-dev (\~23 GB). Allow 10–20 minutes for initial model loading on a fresh instance. ::: #### Step 4: Start the server Run the server in the foreground to verify it works: ```bash python3 /opt/flux_server.py ``` Press `Ctrl+C` to stop. #### Step 5: Run as a background service To keep the server running after you close your SSH session, create a systemd service: ```bash sudo tee /etc/systemd/system/flux.service > /dev/null << 'EOF' [Unit] Description=FLUX.1 Image Generation Server After=network.target [Service] Type=simple Environment=HF_TOKEN= ExecStart=/usr/bin/python3 /opt/flux_server.py Restart=on-failure RestartSec=10 [Install] WantedBy=multi-user.target EOF sudo systemctl daemon-reload sudo systemctl enable flux sudo systemctl start flux ``` ### Accessing the server :::warning[Port 8000 is publicly accessible by default] Use SSH tunneling during development to keep the endpoint private. ::: #### SSH tunnel ```bash ssh -L 8000:localhost:8000 @ ``` ### Usage example ```python import requests import base64 from PIL import Image import io response = requests.post( "http://localhost:8000/generate", json={ "prompt": "A photorealistic mountain landscape at sunset, golden hour lighting", "width": 1024, "height": 1024, "num_inference_steps": 28, "guidance_scale": 3.5, }, ) response.raise_for_status() image_bytes = base64.b64decode(response.json()["image_b64"]) image = Image.open(io.BytesIO(image_bytes)) image.save("output.png") print("Image saved to output.png") ``` ### Check server logs ```bash journalctl -u flux -f ``` ### Cloud-init startup script (optional) If your provider supports cloud-init, you can paste this into the **Startup Script** field when deploying to automate the setup above. It installs the required Python packages and starts a FastAPI server exposing a `/generate` endpoint on port 8000. :::warning[Set your HuggingFace token] Replace `` in the service file below with a token from [huggingface.co/settings/tokens](https://huggingface.co/settings/tokens) before deploying. FLUX.1-dev is a gated model and the service will fail on startup without a valid token. ::: ```yaml #cloud-config write_files: - path: /opt/flux_server.py content: | import io, base64 from fastapi import FastAPI from pydantic import BaseModel import torch from diffusers import FluxPipeline app = FastAPI() pipe = FluxPipeline.from_pretrained( "black-forest-labs/FLUX.1-dev", torch_dtype=torch.bfloat16, ).to("cuda") class GenerateRequest(BaseModel): prompt: str width: int = 1024 height: int = 1024 num_inference_steps: int = 28 guidance_scale: float = 3.5 @app.post("/generate") def generate(req: GenerateRequest): image = pipe( req.prompt, width=req.width, height=req.height, num_inference_steps=req.num_inference_steps, guidance_scale=req.guidance_scale, ).images[0] buf = io.BytesIO() image.save(buf, format="PNG") return {"image_b64": base64.b64encode(buf.getvalue()).decode()} if __name__ == "__main__": import uvicorn uvicorn.run(app, host="0.0.0.0", port=8000) - path: /etc/systemd/system/flux.service content: | [Unit] Description=FLUX.1 Image Generation Server After=network.target [Service] Type=simple Environment=HF_TOKEN= ExecStart=/usr/bin/python3 /opt/flux_server.py Restart=on-failure RestartSec=10 [Install] WantedBy=multi-user.target runcmd: - apt-get update -y - apt-get install -y python3-pip - pip install diffusers transformers accelerate torch fastapi uvicorn pillow sentencepiece huggingface_hub - systemctl daemon-reload - systemctl enable flux - systemctl start flux ``` ### What's next * [Stable Diffusion 3.5 & SDXL](/quick-guides/image-generation/stable-diffusion-35): Alternative image generation models * [ComfyUI](/quick-guides/image-generation/comfyui): Node-based workflow interface * [Image Generation Overview](/quick-guides/image-generation): VRAM requirements and model comparison * [Networking](/concepts/networking): SSH tunneling and port access ## Image Generation Guides Deploy GPU-accelerated text-to-image generation models on Spheron GPU instances. ### VRAM requirements | Model | Min VRAM | Recommended GPU | | --------------------------- | -------- | ------------------------------- | | Stable Diffusion 1.5 | 6 GB | Any 6 GB+ GPU | | SDXL | 10 GB | RTX 4090 (24 GB) | | FLUX.1-dev | 16 GB | RTX 4090 (24 GB) | | Stable Diffusion 3.5 Medium | 12 GB | RTX 4090 (24 GB) | | Stable Diffusion 3.5 Large | 24 GB | RTX 4090 (24 GB) or A100 40 GB | | FLUX.2-dev | 80 GB | H100 80 GB (FP8) or H200 141 GB | ### Available guides #### [FLUX.1 & FLUX.2](/quick-guides/image-generation/flux-1) Black Forest Labs text-to-image models. FLUX.1-dev delivers state-of-the-art photorealism on an RTX 4090; FLUX.2 on H100 for highest fidelity. **Hardware:** RTX 4090 24GB (FLUX.1-dev) · H100 80GB (FLUX.2) #### [Stable Diffusion 3.5 & SDXL](/quick-guides/image-generation/stable-diffusion-35) Stability AI diffusion models from SD 1.5 (6GB) through SDXL (10GB) and SD 3.5 Large (24GB). FastAPI `/generate` endpoint for programmatic use. **Hardware:** 6–24GB VRAM depending on model variant #### [ComfyUI](/quick-guides/image-generation/comfyui) Node-based visual workflow server for image generation. Docker container on port 8188 with SSH tunnel setup. Supports custom workflows via JSON API. **Hardware:** RTX 4090 24GB (recommended) ### What's next * [Instance Types](/concepts/instance-types): Choose the right GPU for image generation * [Cost Optimization](/cost-optimization): Spot instances for batch image generation * [Networking](/concepts/networking): SSH tunneling and port access * [Templates & Images](/templates): Copy-ready startup scripts ## Stable Diffusion 3.5 & SDXL Deploy [Stable Diffusion 3.5](https://huggingface.co/stabilityai/stable-diffusion-3.5-large) and [SDXL](https://huggingface.co/stabilityai/stable-diffusion-xl-base-1.0) from Stability AI on Spheron GPU instances. A FastAPI wrapper exposes a `/generate` endpoint for programmatic image generation. ### Recommended hardware | Model | Min VRAM | Recommended GPU | Instance Type | | ------------- | -------- | ------------------------------ | ----------------- | | SD 1.5 | 6 GB | Any 6 GB+ GPU | Spot | | SDXL Base | 10 GB | RTX 4090 (24 GB) | Spot or Dedicated | | SD 3.5 Medium | 10 GB | RTX 4090 (24 GB) | Dedicated | | SD 3.5 Large | 24 GB | RTX 4090 (24 GB) or A100 40 GB | Dedicated | ### Prerequisites * A running Spheron GPU instance (see [Instance Types](/concepts/instance-types)) * SSH access to the instance * A [HuggingFace account](https://huggingface.co) with access granted to `stabilityai/stable-diffusion-3.5-medium` and `stabilityai/stable-diffusion-3.5-large`: the SD 3.5 models are gated and require accepting the Stability Community License on the model pages before downloading. :::warning[HuggingFace access required for SD 3.5] SD 3.5 Medium and Large are gated models. Accept the license at [stabilityai/stable-diffusion-3.5-medium](https://huggingface.co/stabilityai/stable-diffusion-3.5-medium) and set `HF_TOKEN` before running the server. SD 1.5 and SDXL do not require authentication. ::: ### Manual setup Use these steps to set up the server manually after SSH-ing into your instance. This works on any provider regardless of cloud-init support. #### Step 1: Connect to your instance ```bash ssh @ ``` Replace `` with the username shown in the instance details panel (e.g., `ubuntu` for Spheron AI instances) and `` with your instance's public IP. #### Step 2: Install dependencies ```bash sudo apt-get update -y sudo apt-get install -y python3-pip pip install diffusers transformers accelerate torch fastapi uvicorn pillow sentencepiece huggingface_hub ``` #### Step 2a: Authenticate with HuggingFace (SD 3.5 only) SD 3.5 models require a HuggingFace token. Skip this step if you are using SD 1.5 or SDXL only. ```bash huggingface-cli login --token ``` Replace `` with a token from [huggingface.co/settings/tokens](https://huggingface.co/settings/tokens). #### Step 3: Create the server script ```bash cat > /opt/sd_server.py << 'EOF' import io, base64 from fastapi import FastAPI from pydantic import BaseModel import torch from diffusers import StableDiffusion3Pipeline app = FastAPI() pipe = StableDiffusion3Pipeline.from_pretrained( "stabilityai/stable-diffusion-3.5-medium", torch_dtype=torch.bfloat16, ).to("cuda") class GenerateRequest(BaseModel): prompt: str negative_prompt: str = "" width: int = 1024 height: int = 1024 num_inference_steps: int = 40 guidance_scale: float = 4.5 @app.post("/generate") def generate(req: GenerateRequest): image = pipe( req.prompt, negative_prompt=req.negative_prompt, width=req.width, height=req.height, num_inference_steps=req.num_inference_steps, guidance_scale=req.guidance_scale, ).images[0] buf = io.BytesIO() image.save(buf, format="PNG") return {"image_b64": base64.b64encode(buf.getvalue()).decode()} if __name__ == "__main__": import uvicorn uvicorn.run(app, host="0.0.0.0", port=8000) EOF ``` For SDXL, replace the pipeline class with `StableDiffusionXLPipeline` and the model ID with `stabilityai/stable-diffusion-xl-base-1.0`. #### Step 4: Start the server Run the server in the foreground to verify it works: ```bash python3 /opt/sd_server.py ``` Press `Ctrl+C` to stop. #### Step 5: Run as a background service To keep the server running after you close your SSH session, create a systemd service: ```bash sudo tee /etc/systemd/system/sd-server.service > /dev/null << 'EOF' [Unit] Description=Stable Diffusion Image Generation Server After=network.target [Service] Type=simple ExecStart=/usr/bin/python3 /opt/sd_server.py Restart=on-failure RestartSec=10 [Install] WantedBy=multi-user.target EOF sudo systemctl daemon-reload sudo systemctl enable sd-server sudo systemctl start sd-server ``` ### Accessing the server :::warning[Port 8000 is publicly accessible by default] Use SSH tunneling during development to keep the endpoint private. ::: #### SSH tunnel ```bash ssh -L 8000:localhost:8000 @ ``` ### Usage example ```python import requests import base64 from PIL import Image import io response = requests.post( "http://localhost:8000/generate", json={ "prompt": "A serene Japanese garden with cherry blossoms, soft morning light", "negative_prompt": "blurry, low quality, distorted", "width": 1024, "height": 1024, "num_inference_steps": 40, }, ) response.raise_for_status() image_bytes = base64.b64decode(response.json()["image_b64"]) image = Image.open(io.BytesIO(image_bytes)) image.save("garden.png") print("Image saved to garden.png") ``` ### Check server logs ```bash journalctl -u sd-server -f ``` ### Cloud-init startup script (optional) If your provider supports cloud-init, you can paste this into the **Startup Script** field when deploying to automate the setup above. #### SD 3.5 Medium (RTX 4090) :::warning[Set your HuggingFace token] Replace `` in the service file below with a token from [huggingface.co/settings/tokens](https://huggingface.co/settings/tokens) before deploying. The service will fail on startup without a valid token. ::: ```yaml #cloud-config write_files: - path: /opt/sd_server.py content: | import io, base64 from fastapi import FastAPI from pydantic import BaseModel import torch from diffusers import StableDiffusion3Pipeline app = FastAPI() pipe = StableDiffusion3Pipeline.from_pretrained( "stabilityai/stable-diffusion-3.5-medium", torch_dtype=torch.bfloat16, ).to("cuda") class GenerateRequest(BaseModel): prompt: str negative_prompt: str = "" width: int = 1024 height: int = 1024 num_inference_steps: int = 40 guidance_scale: float = 4.5 @app.post("/generate") def generate(req: GenerateRequest): image = pipe( req.prompt, negative_prompt=req.negative_prompt, width=req.width, height=req.height, num_inference_steps=req.num_inference_steps, guidance_scale=req.guidance_scale, ).images[0] buf = io.BytesIO() image.save(buf, format="PNG") return {"image_b64": base64.b64encode(buf.getvalue()).decode()} if __name__ == "__main__": import uvicorn uvicorn.run(app, host="0.0.0.0", port=8000) - path: /etc/systemd/system/sd-server.service content: | [Unit] Description=Stable Diffusion Image Generation Server After=network.target [Service] Type=simple Environment=HF_TOKEN= ExecStart=/usr/bin/python3 /opt/sd_server.py Restart=on-failure RestartSec=10 [Install] WantedBy=multi-user.target runcmd: - apt-get update -y - apt-get install -y python3-pip - pip install diffusers transformers accelerate torch fastapi uvicorn pillow sentencepiece huggingface_hub - systemctl daemon-reload - systemctl enable sd-server - systemctl start sd-server ``` For SDXL, replace the pipeline class with `StableDiffusionXLPipeline` and the model ID with `stabilityai/stable-diffusion-xl-base-1.0`. ### What's next * [FLUX.1 & FLUX.2](/quick-guides/image-generation/flux-1): Higher quality text-to-image models * [ComfyUI](/quick-guides/image-generation/comfyui): Node-based workflow interface * [Image Generation Overview](/quick-guides/image-generation): VRAM requirements and model comparison * [Networking](/concepts/networking): SSH tunneling and port access ## CUDA and NVIDIA drivers This page explains NVIDIA drivers and CUDA on Spheron GPU instances, how they interact with AI/ML frameworks, and how to choose the right version for your workload. :::info[Not every GPU on the platform is NVIDIA] Spheron AM supplies AMD Instinct MI300X, which runs ROCm rather than CUDA. Nothing on this page applies to those machines. See [ROCm and AMD Instinct](/connecting/rocm-amd). ::: ### What are NVIDIA drivers? NVIDIA drivers are software components that let the operating system communicate with the GPU hardware. Without a compatible driver, the GPU cannot be used for any compute workload. On Spheron instances, NVIDIA drivers come **pre-installed** on all GPU images. You do not need to install them manually. **Key points:** * Drivers are specific to the GPU architecture (e.g., Hopper for H100, Ampere for A100) * Each driver version exposes a maximum supported CUDA version * Driver version and CUDA version are separate but must be compatible Check the installed driver after connecting: ```bash nvidia-smi ``` Example output: ``` +-----------------------------------------------------------------------------------------+ | NVIDIA-SMI 550.127.08 Driver Version: 550.127.08 CUDA Version: 12.4 | +-----------------------------------------------------------------------------------------+ | GPU Name Persistence-M | Bus-Id Disp.A | Volatile Uncorr. ECC | | Fan Temp Perf Pwr:Usage/Cap | Memory-Usage | GPU-Util Compute M. | |=========================================================================================| | 0 NVIDIA H100 80GB HBM3 Off | 00000000:00:00.0 Off | 0 | | N/A 34C P0 72W / 700W | 0MiB / 81920MiB | 0% Default | +-----------------------------------------------------------------------------------------+ ``` The `Driver Version` and `CUDA Version` fields confirm what is installed. ### What is CUDA? CUDA (Compute Unified Device Architecture) is NVIDIA's parallel computing platform that lets software run computations on the GPU. Nearly all AI/ML frameworks depend on it. **CUDA has two components:** | Component | What it is | How to check | | ---------------- | ---------------------------------- | ------------------------------------- | | **CUDA Runtime** | Libraries used by your application | `nvidia-smi` shows max supported CUDA | | **CUDA Toolkit** | Compiler (`nvcc`) and dev tools | `nvcc --version` | ```bash # Compiler version (CUDA toolkit) nvcc --version # List all CUDA installations ls /usr/local/ | grep cuda ``` ### How CUDA and drivers affect development The relationship between drivers, CUDA, and your frameworks determines what works: ``` GPU Hardware └── NVIDIA Driver (minimum requirement) └── CUDA Runtime (must be ≤ driver's max CUDA) └── Framework (PyTorch, TensorFlow, JAX...) └── Your Code ``` **What this means in practice:** * A newer driver supports a higher maximum CUDA version but is backward-compatible with older CUDA runtimes * If your framework requires CUDA 12.4 but the instance only has CUDA 12.0, builds or training runs will fail * Mismatched versions are the most common source of `CUDA not available` errors **Framework to CUDA compatibility quick reference:** | Framework | Minimum CUDA | Recommended CUDA | | ---------------- | ------------ | ---------------- | | PyTorch 2.3+ | 11.8 | 12.1 to 12.4 | | TensorFlow 2.16+ | 12.3 | 12.3 to 12.4 | | JAX (latest) | 12.0 | 12.4+ | | vLLM 0.4+ | 12.1 | 12.4 | Always check the framework's official docs for the exact compatibility matrix before selecting a CUDA version. ### Available CUDA versions on Spheron | CUDA version | NVIDIA driver | Notes | | ------------- | ------------------ | ------------------------------------------------ | | **12.0** | 525+ | Maximum compatibility with older frameworks | | **12.4** | 550+ | Stable, broadly compatible; good default | | **12.6** | 560+ | Optimized for RTX 5090, H100, newer GPUs | | **12.8 Open** | 570+ (open-source) | Open-source kernel module, community use | | **13.0 Open** | 575+ (open-source) | Latest features; early adoption and research use | **Open-source drivers** (`12.8 Open`, `13.0 Open`) use NVIDIA's open-source kernel module instead of the proprietary driver. They are functionally equivalent for most AI/ML workloads but preferred in community and research environments. ### Choose a driver version at deployment When deploying an instance on Spheron, select the CUDA version and driver via the **OS image** dropdown. They are bundled together. 1. Go to [app.spheron.ai](https://app.spheron.ai) → **Deploy** 2. Select your GPU 3. Open the **OS / Environment** dropdown 4. Choose an image that includes your desired CUDA version: | Goal | Recommended image | | ----------------------------------- | ------------------------------------------------------- | | Stable AI/ML work | `Ubuntu 22.04 + CUDA 12.4` or `Ubuntu 24.04 ML PyTorch` | | Latest GPU support (H100, RTX 5090) | `Ubuntu 24.04 + CUDA 12.6` | | Open-source driver preference | `Ubuntu 22.04 + CUDA 12.8 Open` | | Research and early adoption | `Ubuntu 24.04 + CUDA 13.0 Open` | | Legacy framework compatibility | `Ubuntu 20.04 + CUDA 12.0` | 5. Deploy. The instance is ready in 30 to 60 seconds with the driver already loaded. :::warning You cannot change the CUDA version after deployment. If you need a different version, deploy a new instance with the correct image. ::: ### Verify after deployment Once connected via SSH, confirm the environment is set up correctly: ```bash # Driver version and max supported CUDA nvidia-smi # CUDA toolkit version (compiler) nvcc --version # Installed CUDA directories ls /usr/local/ | grep cuda # Quick Python check (PyTorch) python3 -c "import torch; print('CUDA available:', torch.cuda.is_available()); print('CUDA version:', torch.version.cuda)" ``` ### Troubleshooting **`nvidia-smi: command not found`** The instance may have launched on a CPU-only node, or the driver failed to load. Redeploy with a GPU image. **`CUDA not available` in PyTorch/TensorFlow** The framework's CUDA build does not match the installed runtime. Reinstall the framework with the correct CUDA wheel: ```bash # PyTorch example: match cu124 to your CUDA version pip install torch --index-url https://download.pytorch.org/whl/cu124 ``` **`nvcc: command not found` but `nvidia-smi` works** The CUDA toolkit (compiler) is not installed, only the runtime. Install it: ```bash apt-get install -y cuda-toolkit-12-4 ``` **Version mismatch between `nvidia-smi` and `nvcc`** This is expected behavior. `nvidia-smi` shows the driver's maximum supported CUDA, while `nvcc` shows the toolkit version. Both are valid as long as the toolkit version is less than or equal to the driver's max CUDA. ### What's next * [Ubuntu Environments](/connecting/ubuntu): Full list of OS images and configurations * [PyTorch Environment](/connecting/pytorch): PyTorch and CUDA setup * [TensorFlow Environment](/connecting/tensorflow): TensorFlow and CUDA setup * [Templates and Images](/templates): Pre-built startup scripts * [ROCm and AMD Instinct](/connecting/rocm-amd): The AMD equivalent of this page ## Startup scripts Run scripts automatically when your instance first boots to automate environment setup and ensure consistent configuration across deployments. ### Overview Startup scripts run once during the first boot of a new instance. The platform supports two formats: * **Cloud-init (YAML):** Recommended for complex, multi-step setups * **Bash scripts:** Traditional shell scripts for simpler configurations Both formats save 15 to 30 minutes of manual setup per deployment and ensure every instance starts with an identical environment. ### Adding startup scripts During deployment, paste your script in the **Startup Script** section or upload a script file. The platform auto-detects the format (cloud-init or bash) and executes it appropriately. ### Example scripts #### Basic setup Install essential packages and update the system: ```yaml #cloud-config # Update package database and install essential packages packages: - curl - git - build-essential - python3-pip # Run commands on first boot runcmd: - echo "Instance setup started" >> /var/log/startup.log - apt-get update - systemctl enable docker - echo "Setup complete" >> /var/log/startup.log ``` #### Docker setup Install Docker and Docker Compose with required dependencies: ```yaml #cloud-config # Install Docker and Docker Compose packages: - apt-transport-https - ca-certificates - curl - gnupg - lsb-release runcmd: - curl -fsSL https://get.docker.com -o get-docker.sh - sh get-docker.sh - usermod -aG docker ubuntu - curl -L "https://github.com/docker/compose/releases/latest/download/docker-compose-$(uname -s)-$(uname -m)" -o /usr/local/bin/docker-compose - chmod +x /usr/local/bin/docker-compose - systemctl enable docker - systemctl start docker ``` #### NVIDIA GPU setup Install NVIDIA drivers, CUDA toolkit, and nvidia-docker: ```yaml #cloud-config # Setup NVIDIA drivers and CUDA packages: - build-essential - linux-headers-$(uname -r) runcmd: # Add NVIDIA package repositories - wget https://developer.download.nvidia.com/compute/cuda/repos/ubuntu2004/x86_64/cuda-keyring_1.0-1_all.deb - dpkg -i cuda-keyring_1.0-1_all.deb - apt-get update # Install CUDA and drivers - apt-get install -y cuda-toolkit-12-2 - apt-get install -y nvidia-driver-535 # Install nvidia-docker - distribution=$(. /etc/os-release;echo $ID$VERSION_ID) - curl -s -L https://nvidia.github.io/nvidia-docker/gpgkey | apt-key add - - curl -s -L https://nvidia.github.io/nvidia-docker/$distribution/nvidia-docker.list | tee /etc/apt/sources.list.d/nvidia-docker.list - apt-get update && apt-get install -y nvidia-docker2 - systemctl restart docker # Verify installation - nvidia-smi >> /var/log/gpu-setup.log ``` #### ML/AI environment Complete Python ML stack with PyTorch, TensorFlow, and Jupyter: ```yaml #cloud-config # Machine Learning environment setup packages: - python3-pip - python3-dev - python3-venv - git - wget - tmux runcmd: # Create virtual environment - python3 -m venv /opt/ml-env - source /opt/ml-env/bin/activate # Install ML frameworks - pip install --upgrade pip - pip install torch torchvision torchaudio --index-url https://download.pytorch.org/whl/cu118 - pip install transformers datasets accelerate - pip install jupyter notebook # Setup Jupyter - jupyter notebook --generate-config - echo "c.NotebookApp.ip = '0.0.0.0'" >> ~/.jupyter/jupyter_notebook_config.py - echo "c.NotebookApp.allow_remote_access = True" >> ~/.jupyter/jupyter_notebook_config.py # Create workspace - mkdir -p /workspace/models /workspace/datasets /workspace/notebooks - echo "ML environment ready" >> /var/log/ml-setup.log ``` #### Monitoring stack Deploy Prometheus and Grafana with Docker Compose: ```yaml #cloud-config # Setup monitoring with Prometheus and Grafana write_files: - path: /etc/docker/compose/monitoring/docker-compose.yml content: | version: '3' services: prometheus: image: prom/prometheus:latest ports: - "9090:9090" volumes: - ./prometheus.yml:/etc/prometheus/prometheus.yml - prometheus_data:/prometheus command: - '--config.file=/etc/prometheus/prometheus.yml' - '--storage.tsdb.path=/prometheus' grafana: image: grafana/grafana:latest ports: - "3000:3000" volumes: - grafana_data:/var/lib/grafana environment: - GF_SECURITY_ADMIN_PASSWORD=admin node-exporter: image: prom/node-exporter:latest ports: - "9100:9100" volumes: prometheus_data: grafana_data: ``` #### Shell script format Traditional bash scripts (auto-converted to cloud-init): ```bash #!/bin/bash # Traditional shell script format (will be converted to cloud-init) # Update system apt-get update && apt-get upgrade -y # Install essential packages apt-get install -y \ build-essential \ curl \ wget \ git \ vim \ htop # Create directories mkdir -p /opt/app /var/log/app # Set up environment variables echo "export APP_HOME=/opt/app" >> /etc/environment echo "export NODE_ENV=production" >> /etc/environment # Clone repository (example) cd /opt/app git clone https://github.com/example/app.git . # Install dependencies and start service npm install npm run build npm start # Log completion echo "Setup completed at $(date)" >> /var/log/setup.log ``` ### Best practices **Script design:** * Start simple and add complexity as needed * Test commands manually before scripting * Add logging to track execution * Use comments to document each step **Error handling:** ```bash #!/bin/bash set -e # Exit on error echo "Setup started" >> /var/log/startup.log apt-get update || { echo "Failed"; exit 1; } echo "Setup completed" >> /var/log/startup.log ``` **Security:** * Never hardcode credentials in scripts * Use secure secret management * Review scripts before deployment :::warning Scripts run with root privileges. Review all scripts carefully before deploying. ::: See [Security Best Practices](/security) for detailed guidelines. ### Troubleshooting **Script didn't run:** ```bash # Check cloud-init logs cat /var/log/cloud-init.log cat /var/log/cloud-init-output.log ``` **Commands failed:** * Verify package names and syntax for Ubuntu * Test commands manually first * Check logs for specific errors **Script takes too long:** * Keep scripts under 10 minutes * Use background processes for long tasks * Check for hanging commands **YAML syntax errors:** * Validate YAML format before deploying * Use an online YAML validator * Check indentation (spaces, not tabs) ### What's next * [Getting Started](/getting-started): Deploy your first instance * [Quick Start](/quick-start): Fast deployment walkthrough * [Security Best Practices](/security): Startup script security guidelines ## Jupyter Notebook Deploy GPU instances with Jupyter Notebook pre-configured for interactive AI/ML development. ### What's included **Jupyter environment:** * Jupyter Notebook and JupyterLab * IPython kernel * GPU support enabled **Pre-installed libraries:** * PyTorch or TensorFlow (depending on environment) * NumPy, Pandas, Matplotlib, Seaborn * scikit-learn, SciPy * CUDA toolkit and GPU drivers **System:** * Ubuntu 22.04 or 24.04 LTS * Python 3.9 to 3.11 * pip and conda ### Deploy a Jupyter environment #### Select an environment 1. Go to [app.spheron.ai](https://app.spheron.ai) → **Deploy** 2. Choose your GPU 3. Select an OS image: * **Ubuntu 24.04 LTS ML Everything:** includes PyTorch and TensorFlow * **Ubuntu 24.04 LTS ML PyTorch:** PyTorch-focused environment * **Ubuntu 24.04 LTS ML TensorFlow:** TensorFlow-focused environment 4. Click **Deploy** #### Connect via SSH ```bash ssh root@ ``` ### Start Jupyter Notebook #### Basic setup ```bash # Start Jupyter on all interfaces jupyter notebook --ip=0.0.0.0 --port=8888 --no-browser --allow-root # Start with a custom password jupyter notebook --ip=0.0.0.0 --port=8888 --no-browser --allow-root --NotebookApp.token='your-password' ``` #### Access Jupyter Open your browser and navigate to: ``` http://:8888 ``` Retrieve the token if you did not set a custom password: ```bash jupyter notebook list ``` #### Run in background ```bash # Using nohup nohup jupyter notebook --ip=0.0.0.0 --port=8888 --no-browser --allow-root & # Using screen screen -S jupyter jupyter notebook --ip=0.0.0.0 --port=8888 --no-browser --allow-root # Press Ctrl+A then D to detach ``` ### Configuration #### Set a password ```bash # Generate a hashed password interactively jupyter notebook password # Or generate the config file first jupyter notebook --generate-config ``` Edit `~/.jupyter/jupyter_notebook_config.py`: ```python c.NotebookApp.password = 'your-hashed-password' c.NotebookApp.ip = '0.0.0.0' c.NotebookApp.port = 8888 c.NotebookApp.open_browser = False c.NotebookApp.allow_root = True ``` #### Enable GPU in notebooks **For PyTorch:** ```python import torch print(f"CUDA available: {torch.cuda.is_available()}") print(f"GPU count: {torch.cuda.device_count()}") print(f"GPU name: {torch.cuda.get_device_name(0)}") ``` **For TensorFlow:** ```python import tensorflow as tf print(f"GPU devices: {tf.config.list_physical_devices('GPU')}") ``` ### Quick examples #### Create a new notebook 1. Open Jupyter in your browser 2. Click **New** → **Python 3** 3. Start coding #### Install additional packages ```python # In a notebook cell !pip install transformers accelerate bitsandbytes # Or from the terminal pip install package-name ``` #### Monitor GPU usage ```python # In a notebook !nvidia-smi # Or use gpustat !pip install gpustat !gpustat -i 1 ``` ### Troubleshooting **Cannot access Jupyter in browser:** * Verify Jupyter is running: `ps aux | grep jupyter` * Check that port 8888 is open * Use the instance public IP, not localhost * Verify the token or password **GPU not detected in notebook:** ```python # Check CUDA installation !nvcc --version !nvidia-smi # Reinstall PyTorch with CUDA !pip install torch torchvision torchaudio --index-url https://download.pytorch.org/whl/cu118 ``` **Notebook server crashed:** ```bash # Check logs tail -f ~/.jupyter/*.log # Restart Jupyter pkill jupyter jupyter notebook --ip=0.0.0.0 --port=8888 --no-browser --allow-root ``` **Port already in use:** ```bash # Use a different port jupyter notebook --ip=0.0.0.0 --port=8889 --no-browser --allow-root ``` ### What's next * [Jupyter Documentation](https://jupyter.org/documentation) * [Getting Started](/getting-started): Deploy your first instance * [Quick Start](/quick-start): Fast deployment options * [SSH Connection](/connecting/ssh-connection): SSH setup guide ## PyTorch environment Deploy GPU instances with PyTorch pre-configured for AI/ML development. ### What's included **Core frameworks:** * PyTorch 2.x with CUDA support * torchvision and torchaudio * Hugging Face Transformers and Accelerate **Development tools:** * Jupyter Notebook for interactive development * TensorBoard for training visualization * NumPy, Pandas, Matplotlib * datasets and scikit-learn **System:** * Ubuntu 22.04 or 24.04 LTS * NVIDIA drivers (550 or 570) pre-installed * CUDA toolkit (12.x) * Python 3.10 to 3.11 ### CUDA and NVIDIA drivers PyTorch requires a compatible CUDA version and NVIDIA driver. Spheron GPU images come with NVIDIA drivers and CUDA pre-installed. Verify your driver and CUDA versions after connecting: ```bash # Check NVIDIA driver version nvidia-smi # Check CUDA compiler version nvcc --version # Check which CUDA versions are installed ls /usr/local/ | grep cuda ``` **PyTorch to CUDA compatibility:** | PyTorch version | CUDA 11.8 | CUDA 12.1 | CUDA 12.4 | | --------------- | --------- | --------- | --------- | | 2.0.x | Yes | Yes | N/A | | 2.1.x | Yes | Yes | N/A | | 2.2.x | Yes | Yes | Yes | | 2.3.x+ | Yes | Yes | Yes | Always match the `--index-url` in your pip install command to your CUDA version (see [PyTorch install page](https://pytorch.org/get-started/locally/)). ### Deploy a PyTorch environment #### Using a pre-configured OS image 1. Go to [app.spheron.ai](https://app.spheron.ai) → **Deploy** 2. Choose your GPU 3. Select OS: **Ubuntu 24.04 LTS ML PyTorch** or **Ubuntu 24.04 LTS ML Everything** 4. Deploy. The instance is ready in 30 to 60 seconds. #### Using a startup script Use the [PyTorch + CUDA 12.1 startup template](/templates#pytorch--cuda-121) to install PyTorch on a base Ubuntu image: ```yaml #cloud-config runcmd: - apt-get update -y - apt-get install -y python3.11 python3.11-venv - python3.11 -m ensurepip --upgrade - python3.11 -m pip install --upgrade pip - python3.11 -m pip install torch torchvision torchaudio --index-url https://download.pytorch.org/whl/cu121 - python3.11 -m pip install transformers accelerate bitsandbytes datasets ``` ### Verify installation After connecting via SSH: ```bash # Check PyTorch version and CUDA availability python3 -c "import torch; print('PyTorch:', torch.__version__); print('CUDA available:', torch.cuda.is_available()); print('CUDA version:', torch.version.cuda)" # Check GPU count and names python3 -c "import torch; print('GPU count:', torch.cuda.device_count()); [print(f' GPU {i}:', torch.cuda.get_device_name(i)) for i in range(torch.cuda.device_count())]" # Run nvidia-smi to see GPU utilization nvidia-smi ``` Expected output on an H100 instance: ``` PyTorch: 2.3.0+cu121 CUDA available: True CUDA version: 12.1 GPU count: 8 GPU 0: NVIDIA H100 80GB HBM3 ... ``` ### Quick start #### Basic GPU computation ```python import torch device = torch.device("cuda" if torch.cuda.is_available() else "cpu") print(f"Using device: {device}") # Move tensor to GPU x = torch.randn(1000, 1000).to(device) y = torch.matmul(x, x.T) print("Matrix multiply done, result shape:", y.shape) ``` #### Load a Hugging Face model on GPU ```python from transformers import AutoTokenizer, AutoModelForCausalLM import torch model_id = "meta-llama/Llama-3-8B-Instruct" # replace with your model tokenizer = AutoTokenizer.from_pretrained(model_id) model = AutoModelForCausalLM.from_pretrained( model_id, torch_dtype=torch.bfloat16, device_map="auto", # spreads across all available GPUs ) inputs = tokenizer("Hello, how are you?", return_tensors="pt").to("cuda") outputs = model.generate(**inputs, max_new_tokens=50) print(tokenizer.decode(outputs[0], skip_special_tokens=True)) ``` ### Common packages ```bash # Large language models pip install transformers accelerate bitsandbytes peft trl # Computer vision pip install torchvision timm opencv-python pillow # Distributed training pip install deepspeed # Experiment tracking pip install wandb tensorboard # Data pip install datasets huggingface-hub ``` ### Troubleshooting **CUDA not available:** ```bash # Confirm NVIDIA driver is loaded nvidia-smi # Reinstall PyTorch matching your CUDA version pip uninstall torch torchvision torchaudio pip install torch torchvision torchaudio --index-url https://download.pytorch.org/whl/cu121 ``` **Out of GPU memory:** * Reduce batch size * Enable gradient checkpointing: `model.gradient_checkpointing_enable()` * Use BF16: `model = model.to(torch.bfloat16)` * Monitor memory: `nvidia-smi -l 1` or `torch.cuda.memory_summary()` **Slow training: check NVLink/NVMe utilization:** ```bash # Per-GPU utilization nvidia-smi dmon -s u # NVLink status (on NVLink clusters) nvidia-smi nvlink --status ``` ### What's next * [Distributed Training guide](/quick-guides/training/distributed-training): PyTorch DDP on H100 bare-metal clusters * [Templates and Images](/templates#pytorch--cuda-121): PyTorch startup script * [Ubuntu Environments](/connecting/ubuntu): OS images with CUDA and NVIDIA drivers * [TensorFlow](/connecting/tensorflow): TensorFlow GPU environment ## ROCm and AMD Instinct Spheron AM offers AMD Instinct MI300X GPUs, the first non-NVIDIA silicon in the catalog. They run ROCm, AMD's compute stack, rather than CUDA. This page covers what changes for your workflow and what does not. If you are deploying an NVIDIA GPU, see [CUDA and NVIDIA drivers](/connecting/cuda-nvidia-drivers) instead. ### What ROCm is ROCm (Radeon Open Compute) is AMD's equivalent of the CUDA stack: the kernel driver, runtime, compiler, and math libraries that let a framework run compute work on an AMD GPU. It ships pre-installed on every Spheron AM machine, so there is nothing to install before you start. The parts map closely onto their NVIDIA counterparts: | NVIDIA | AMD | Purpose | | ------------ | ----------------- | ------------------------ | | CUDA | ROCm | Compute platform | | `nvidia-smi` | `rocm-smi` | Query GPU state | | cuDNN | MIOpen | Deep learning primitives | | cuBLAS | rocBLAS / hipBLAS | Linear algebra | | NCCL | RCCL | Multi-GPU collectives | | `nvcc` | `hipcc` | Compiler | ### MI300X hardware | Specification | Value | | -------------- | ------------------------- | | Memory | 192 GB HBM3e per GPU | | Configurations | 1x, 2x, and 4x GPU | | Region | Michigan 1, United States | | Instance type | Dedicated only, no spot | The 192 GB of memory per GPU is the practical headline: a model that needs several 80 GB NVIDIA GPUs to hold its weights can fit on fewer MI300X cards, which changes how you shard it. ### Verify the GPU after connecting SSH into the instance, then query the GPU: ```bash # Equivalent of nvidia-smi rocm-smi ``` Check what the installed stack reports: ```bash # ROCm version cat /opt/rocm/.info/version # HIP compiler and runtime configuration hipconfig --version ``` `nvidia-smi` does not exist on these machines. A `command not found` for it is expected, not a fault. ### PyTorch on ROCm PyTorch supports ROCm through HIP. Install the ROCm build rather than the default CUDA wheels, matching the ROCm version reported above: ```bash # Check the installed ROCm version first, then match the wheel index to it pip install torch torchvision torchaudio \ --index-url https://download.pytorch.org/whl/rocm6.2 ``` :::warning[`torch.cuda` still works, and that is intentional] On a ROCm build of PyTorch, `torch.cuda.is_available()` returns `True` and `torch.device("cuda")` maps to the AMD GPU. HIP deliberately reuses the `cuda` namespace so existing code runs unmodified. Do not treat this as a sign that CUDA is installed. To confirm you are actually on ROCm, check `torch.version.hip`. It is a version string on ROCm and `None` on a CUDA build. ::: ```python import torch print(torch.cuda.is_available()) # True print(torch.version.hip) # e.g. '6.2.41133-dd7f95766' print(torch.version.cuda) # None on a ROCm build print(torch.cuda.get_device_name(0)) ``` ### Porting CUDA code Most PyTorch and TensorFlow code runs on ROCm without changes, because the frameworks absorb the difference. Attention is needed where code reaches below the framework: * **Framework-level code** (PyTorch, TensorFlow, JAX): usually runs unchanged. Keep using `.to("cuda")`. * **Custom CUDA kernels**: port with `hipify-perl` or `hipify-clang`, which translate CUDA source to HIP. * **Prebuilt CUDA-only wheels**: packages shipping compiled CUDA kernels (some quantization and attention libraries) need a ROCm build. Check for one before you deploy. * **Docker images**: use a ROCm base image. A `nvidia/cuda` image does not run here. ```bash # Translate a CUDA source tree to HIP hipify-perl my_kernel.cu > my_kernel.hip.cpp hipcc my_kernel.hip.cpp -o my_kernel ``` ### What differs on Spheron AM Beyond the silicon, a few platform behaviors differ from other providers: * **One OS image.** Machines boot Ubuntu with ROCm, plus Docker or Podman. There is no image picker, because the machine type determines what it boots. * **The boot disk comes with the machine type.** Its size is shown on the offer rather than being something you set. * **No volumes.** Persistent volumes are not available on Spheron AM. A deployment that asks for one is refused rather than created without it. Keep data you need to survive termination somewhere off the instance. * **Restart, but no stop.** A Spheron AM instance bills at the full hourly rate until it is destroyed. Terminate an instance you have finished with. See [Instance lifecycle](/concepts/instance-lifecycle). * **A minimum reservation, charged in full.** Each machine type carries its own minimum runtime, which can be longer than the 20 minute default. Terminating early does not reduce the charge. The wizard shows the figure before you deploy. * **Startup scripts work normally.** Cloud-init is supported, so the [startup script](/connecting) flow is unchanged. ### Troubleshooting #### Issue: `nvidia-smi: command not found` **Symptoms**: The command is missing after connecting to a Spheron AM instance. **Diagnosis**: This is expected. The machine has an AMD GPU and no NVIDIA driver. **Resolution**: Use `rocm-smi` instead. #### Issue: PyTorch reports no GPU **Symptoms**: `torch.cuda.is_available()` returns `False`. **Diagnosis**: The installed PyTorch is a CUDA build, which cannot see an AMD GPU. **Resolution**: Reinstall from the ROCm wheel index. Confirm the fix with `torch.version.hip`, which must be a version string rather than `None`. ```bash pip uninstall -y torch torchvision torchaudio pip install torch torchvision torchaudio \ --index-url https://download.pytorch.org/whl/rocm6.2 ``` #### Issue: A pip package fails to build or import **Symptoms**: A library that compiles CUDA kernels fails to install, or imports and then errors on first use. **Diagnosis**: The package ships CUDA-only compiled kernels with no ROCm build. **Resolution**: Check the project for a ROCm or HIP build. Where none exists, either drop the dependency or run that part of the workload on an NVIDIA instance. #### Issue: A Docker container sees no GPU **Symptoms**: The GPU is invisible inside a container that works on NVIDIA hosts. **Diagnosis**: The image is CUDA-based, or the container was started without the AMD device nodes. **Resolution**: Use a ROCm base image and pass the devices through: ```bash docker run --device=/dev/kfd --device=/dev/dri \ --group-add video --ipc=host \ rocm/pytorch:latest ``` ### What's next * [Instance lifecycle](/concepts/instance-lifecycle): Restart support and why stopping is unavailable here * [Regions and providers](/concepts/regions-providers): Spheron AM inventory and region * [CUDA and NVIDIA drivers](/connecting/cuda-nvidia-drivers): The NVIDIA equivalent of this page * [Startup scripts](/connecting): Automate setup on first boot * [SSH connection](/connecting/ssh-connection): Connect to your instance ## SSH connection setup Generate and configure SSH keys for secure GPU instance access. ### What are SSH keys? SSH keys are cryptographic key pairs used for secure authentication: * **Public key:** Uploaded to Spheron AI * **Private key:** Kept secure on your machine and never shared SSH keys provide stronger security than passwords and enable automatic authentication. ### Prerequisites * Terminal access (Linux, macOS, or Windows) * Spheron AI account * Basic terminal familiarity ### Generate SSH key :::steps #### Run ssh-keygen **Linux/Mac:** ```bash ssh-keygen -t ed25519 -C "your_email@example.com" ``` **Windows PowerShell:** ```bash ssh-keygen -t ed25519 -C "your_email@example.com" ``` ![SSH Key Generation](/ssh1.png) #### Configure key * **Save location:** Press Enter for the default (`~/.ssh/id_ed25519`) * **Passphrase:** Press Enter twice for no passphrase, or set a passphrase for extra security ![SSH Passphrase](/ssh2.png) #### Verify creation The output confirms where both keys were saved: ``` Your identification has been saved in /Users/yourname/.ssh/id_ed25519 Your public key has been saved in /Users/yourname/.ssh/id_ed25519.pub ``` * **Private key:** `id_ed25519`: never share this file * **Public key:** `id_ed25519.pub`: upload this to Spheron ::: ### Upload to Spheron AI #### Method 1: Account settings (recommended) Use this method to reuse keys across multiple deployments. :::steps #### Navigate to settings [app.spheron.ai](https://app.spheron.ai) → **Settings** → **SSH Keys** ![SSH Keys Settings](/ssh3.png) #### Add key 1. Click **+ Add SSH Key** 2. Enter a key name 3. Paste your public key content: ```bash # Display your public key cat ~/.ssh/id_ed25519.pub ``` 4. Click **Add Key** ::: #### Method 2: During deployment Upload a key when deploying an instance: 1. Select **Upload New SSH Key** 2. Choose a file or paste the public key content 3. Enter a key name 4. Continue deployment ### Connect to instance ```bash ssh root@ # Specify key explicitly ssh -i ~/.ssh/id_ed25519 root@ ``` ### Best practices * Only upload public keys (`.pub` files) * Never share private keys * Use passphrases for additional security * Rotate keys every 90 days * Use different keys for different services * Back up private keys securely * Delete unused keys See [Security Best Practices](/security) for comprehensive guidance. ### Troubleshooting **Permission denied:** ```bash # Check key is loaded ssh-add -l # Add key to agent ssh-add ~/.ssh/id_ed25519 # Verify permissions chmod 600 ~/.ssh/id_ed25519 chmod 644 ~/.ssh/id_ed25519.pub ``` **Wrong key:** * Verify the correct public key was uploaded * Check the key fingerprint matches * Try with an explicit key: `ssh -i ~/.ssh/id_ed25519 user@` **Connection timeout:** * Verify the instance is running * Check the IP address is correct * Ensure the firewall allows SSH (port 22) ### What's next * [Getting Started](/getting-started): Complete setup guide * [User Settings](/user-settings): Manage SSH keys * [Security Best Practices](/security): Security guidelines * [Quick Start](/quick-start): Fast deployment walkthrough ## TensorFlow environment Deploy GPU instances with TensorFlow pre-configured for immediate AI/ML development. ### What's included **Core frameworks:** * TensorFlow 2.x with GPU support * Keras (high-level neural networks API) * CUDA and cuDNN pre-configured **Development tools:** * Jupyter Notebook for interactive development * TensorBoard for visualization * NumPy, Pandas, Matplotlib * scikit-learn for traditional ML **System:** * Ubuntu 22.04 or 24.04 LTS * NVIDIA drivers and CUDA toolkit * Python 3.9 to 3.11 * pip and conda package managers ### Deploy a TensorFlow environment #### Select an environment 1. Go to [app.spheron.ai](https://app.spheron.ai) → **Deploy** 2. Choose your GPU 3. Select OS: **Ubuntu 24.04 LTS ML TensorFlow** or **Ubuntu 22.04 LTS + TensorFlow** 4. Click **Deploy**. The instance is ready in 30 to 60 seconds. #### Connect via SSH ```bash ssh root@ ``` #### Verify installation ```bash # Check TensorFlow python3 -c "import tensorflow as tf; print(f'TensorFlow version: {tf.__version__}')" python3 -c "import tensorflow as tf; print(f'GPU available: {tf.config.list_physical_devices(\"GPU\")}')" # Check CUDA nvcc --version # Check GPU nvidia-smi ``` ### Quick start examples #### Run a TensorFlow test ```python import tensorflow as tf # Verify GPU print("Num GPUs Available:", len(tf.config.list_physical_devices('GPU'))) # Simple computation test with tf.device('/GPU:0'): a = tf.constant([[1.0, 2.0], [3.0, 4.0]]) b = tf.constant([[1.0, 1.0], [0.0, 1.0]]) c = tf.matmul(a, b) print(c) ``` #### Train a simple model ```python import tensorflow as tf from tensorflow import keras # Load dataset mnist = keras.datasets.mnist (x_train, y_train), (x_test, y_test) = mnist.load_data() x_train, x_test = x_train / 255.0, x_test / 255.0 # Build model model = keras.Sequential([ keras.layers.Flatten(input_shape=(28, 28)), keras.layers.Dense(128, activation='relu'), keras.layers.Dropout(0.2), keras.layers.Dense(10) ]) # Compile and train model.compile(optimizer='adam', loss=tf.keras.losses.SparseCategoricalCrossentropy(from_logits=True), metrics=['accuracy']) model.fit(x_train, y_train, epochs=5) ``` #### Start Jupyter Notebook ```bash # Install Jupyter if not included pip install jupyter # Start Jupyter (accessible from browser) jupyter notebook --ip=0.0.0.0 --port=8888 --no-browser --allow-root ``` Access at: `http://:8888` ### Common packages Install additional packages as needed: ```bash # Computer vision pip install opencv-python pillow # Data processing pip install pandas numpy scipy # Model optimization pip install tensorflow-model-optimization # TensorFlow Datasets pip install tensorflow-datasets # Visualization pip install tensorboard seaborn ``` ### Use cases * **Production deployment:** enterprise-grade model serving * **Computer vision:** image classification, object detection * **NLP:** text analysis, sentiment analysis * **Time series:** forecasting and prediction * **Mobile AI:** TensorFlow Lite model development ### Troubleshooting **GPU not detected by TensorFlow:** ```bash # Check GPU visibility python3 -c "import tensorflow as tf; print(tf.config.list_physical_devices('GPU'))" # Reinstall TensorFlow with GPU support pip uninstall tensorflow pip install tensorflow[and-cuda] ``` **CUDA version mismatch:** * Check TensorFlow compatibility: [TensorFlow GPU support](https://www.tensorflow.org/install/source#gpu) * Use a compatible CUDA version for your TensorFlow release **Out of memory errors:** * Reduce batch size * Enable memory growth: `tf.config.experimental.set_memory_growth(gpu, True)` * Monitor with: `nvidia-smi -l 1` ### What's next * [TensorFlow Official Docs](https://www.tensorflow.org/guide) * [Keras Documentation](https://keras.io/guides/) * [Getting Started](/getting-started): Deploy your first instance * [Quick Start](/quick-start): Fast deployment guide * [API Reference](/api-reference): Automate deployments ## Ubuntu environments Available Ubuntu configurations for Spheron GPU instances. ### Available versions | Version | Support until | Best for | | -------------------- | ------------- | --------------------------------------- | | **Ubuntu 20.04 LTS** | 2025 | Legacy applications, older dependencies | | **Ubuntu 22.04 LTS** | 2027 | Production workloads (most stable) | | **Ubuntu 24.04 LTS** | 2029 | Latest features, experimental projects | ### Configuration options #### Base images * **Base / LTS Base:** minimal Ubuntu installation * **+ NVIDIA 550/570:** NVIDIA drivers pre-installed * **+ CUDA X.X:** CUDA toolkit included * **+ Docker:** Docker pre-installed for containerized workflows * **Shade OS:** optimized lightweight version for maximum GPU performance #### Pre-configured ML environments (Ubuntu 24.04) | Environment | Includes | Best for | | ----------------- | ------------------------ | ------------------------------- | | **ML Everything** | PyTorch, TensorFlow, JAX | Multi-framework experimentation | | **ML PyTorch** | PyTorch optimized | LLM training, computer vision | | **ML TensorFlow** | TensorFlow optimized | Production ML, enterprise | ### Selection guide | Use case | Recommended environment | Why | | ------------------- | --------------------------------- | ---------------------------------- | | **Getting started** | Ubuntu 24.04 ML Everything | All frameworks pre-installed | | **LLM training** | Ubuntu 24.04 ML PyTorch | PyTorch with CUDA pre-installed | | **TensorFlow** | Ubuntu 24.04 ML TensorFlow | TensorFlow with CUDA pre-installed | | **Production** | Ubuntu 22.04 + CUDA 12.8 + Docker | Stable, containerized | | **Research** | Ubuntu 24.04 + CUDA 13.0 Open | Latest features | | **Legacy apps** | Ubuntu 20.04 LTS | Older dependency support | | **Max performance** | Ubuntu 22.04 (Shade OS) | Optimized, minimal overhead | ### Docker vs non-Docker **Without Docker:** * Direct GPU access * Simpler setup * Single-purpose instances * Good for learning and simple projects **With Docker:** * Containerized workflows * Dependency isolation * Multi-project instances * Good for production and complex setups ### Deploy 1. Go to [app.spheron.ai](https://app.spheron.ai) → **Deploy** 2. Select a GPU 3. Choose an Ubuntu environment from the OS dropdown 4. Click **Deploy** (ready in 30 to 60 seconds) ### Verify installation After deployment, connect and verify: ```bash # Connect ssh root@ # Check OS version cat /etc/os-release # Check CUDA (if applicable) nvcc --version # Check GPU nvidia-smi # Check Docker (if applicable) docker --version ``` ### Frequently asked questions **Q:** What does LTS mean? **A:** Long Term Support: 5 years of security updates and bug fixes. **Q:** Can I change environments after deployment? **A:** No. Deploy a new instance with the desired environment. **Q:** Do I need Docker? **A:** Not for simple projects. Use Docker for complex dependencies or multi-project instances. **Q:** Which CUDA version should I use? **A:** See [CUDA and NVIDIA Drivers](/connecting/cuda-nvidia-drivers) for a full guide including framework compatibility tables and version recommendations. **Q:** Can I install multiple CUDA versions? **A:** Not recommended. Select the correct version during deployment. **Q:** Ubuntu 22.04 or 24.04? **A:** 22.04 for production stability. 24.04 for latest features. **Q:** What is Shade OS? **A:** An optimized Ubuntu variant with minimal overhead for maximum GPU performance. ### What's next * [CUDA and NVIDIA Drivers](/connecting/cuda-nvidia-drivers): CUDA versions, driver details, and how to choose * [Getting Started](/getting-started): Deploy your first instance * [SSH Connection](/connecting/ssh-connection): SSH setup guide * [TensorFlow](/connecting/tensorflow): TensorFlow environment setup * [Jupyter](/connecting/jupyter): Jupyter Notebook setup ## VS Code Remote SSH Connect VS Code directly to a Spheron GPU instance. IntelliSense, debugging, extensions, and the Ports panel run against the remote environment. ### Prerequisites * VS Code installed locally * [Remote - SSH](https://marketplace.visualstudio.com/items?itemName=ms-vscode-remote.remote-ssh) extension (`ms-vscode-remote.remote-ssh`) * A running Spheron instance with SSH access configured Install the extension from the VS Code Extensions panel or run: ```bash code --install-extension ms-vscode-remote.remote-ssh ``` ### Configure SSH host Add your instance to `~/.ssh/config` on your local machine: ``` Host spheron-gpu HostName User Port IdentityFile ~/.ssh/id_ed25519 ``` Replace ``, ``, and `` with the values from the SSH command in the instance details panel in the dashboard. Connection details vary by provider: * **Spheron AI:** `User ubuntu`, `Port 22` * **Sesterce / Verda / Massed Compute:** `Port 22` (username varies by provider; check the dashboard) Replace `~/.ssh/id_ed25519` with the path to your private key. ### Connect 1. Open the Command Palette: `Ctrl+Shift+P` (macOS: `Cmd+Shift+P`) 2. Type **Remote-SSH: Connect to Host** 3. Select `spheron-gpu` VS Code opens a new window connected to the remote instance. The status bar shows `SSH: spheron-gpu` when connected. ### Install remote extensions Once connected, install extensions inside the remote session so they run on the GPU instance rather than your local machine: * **Python** (`ms-python.python`): remote IntelliSense, debugging, test runner * **Jupyter** (`ms-toolsai.jupyter`): run notebooks directly in VS Code * **PyTorch Snippets:** code completion for PyTorch APIs Search for these in the Extensions panel while connected to the remote host. VS Code automatically installs them on the instance. ### Port forwarding VS Code handles port forwarding automatically via the **Ports** tab, replacing manual `ssh -L` tunnel commands: 1. While connected, open the **Terminal** panel and select the **Ports** tab 2. Click **Forward a Port** 3. Enter the port number (e.g., `8888` for Jupyter, `6006` for TensorBoard) 4. VS Code creates the tunnel and opens a local URL; click to open in browser ### Dev containers (optional) Add a `.devcontainer/devcontainer.json` file to your project to define a container-based development environment with CUDA pre-installed: ```json { "name": "GPU Dev Container", "image": "nvcr.io/nvidia/pytorch:24.01-py3", "runArgs": ["--gpus", "all"], "customizations": { "vscode": { "extensions": [ "ms-python.python", "ms-toolsai.jupyter" ] } }, "postCreateCommand": "pip install -r requirements.txt" } ``` VS Code builds and attaches to the container automatically when you open the project folder. GPU passthrough is enabled via `--gpus all`. ### Tips * **IntelliSense indexes the remote environment:** after installing Python/Jupyter extensions, run the **Python: Select Interpreter** command and choose the environment where your packages are installed. * **TensorBoard:** forward port 6006 via the Ports tab, then run `tensorboard --logdir ./logs` in the remote terminal. * **Large file transfers:** use `scp` or `rsync` for bulk transfers. VS Code drag-and-drop file upload works better for small files. ### What's next * [SSH Connection](/connecting/ssh-connection): Key setup and basic SSH access * [Jupyter Notebook](/connecting/jupyter): Browser-based Jupyter setup * [Networking](/concepts/networking): Dedicated IP, port access, and SSH tunneling * [Security Best Practices](/security): Secure your development environment ## Verda: mounting shared storage Mount persistent shared filesystems on Verda instances using Network File System (NFS) protocol. ### Overview Verda shared filesystems (SFS) use NFS protocol for high-performance network-attached storage. Each filesystem is accessible via a datacenter-specific NFS endpoint and identified by a unique pseudopath. **Protocol:** NFS **Connection:** Datacenter-region NFS endpoint **Performance:** Parallel connections via `nconnect` option :::info[Only shared filesystems can be mounted] Only filesystems shared with the instance can be mounted. Ensure the filesystem's share settings include your instance before proceeding. ::: :::info[Same-location requirement] Shared filesystems can only be mounted from instances in the same datacenter location. ::: ### Prerequisites Before starting, ensure you have: 1. Created a volume with provider: `datacrunch` via the Spheron dashboard (Create Volume page) 2. Attached the shared filesystem to your Verda instance 3. Retrieved the following from the Spheron AI dashboard: * **Pseudopath:** starts with `/` (e.g., `/grgwrgwrg-20f77f6a`) * **Datacenter location slug** (e.g., `fin-01`) 4. SSH access to your Verda instance ### Mounting process :::steps #### Connect to your instance SSH into your Verda GPU instance using the connection details from the instance's Details drawer: ```bash ssh ubuntu@ ``` See [SSH Connection Setup](/connecting/ssh-connection) for detailed connection instructions. #### Install NFS client tools Ensure the NFS client is installed on your instance: ```bash sudo apt-get update sudo apt-get install -y nfs-common ``` #### Create mount directory Create a directory where you'll mount the shared filesystem. Replace `` with your preferred directory name: ```bash sudo mkdir -p /mnt/ ``` Common choices include: * `/mnt/storage`: standard mount location * `/mnt/datasets`: for ML/AI datasets * `/mnt/models`: for model checkpoints #### Mount the filesystem Mount the shared filesystem. Replace the placeholders with your values: * ``: datacenter location slug (e.g., `fin-01`) * ``: filesystem pseudopath (e.g., `/grgwrgwrg-20f77f6a`) * ``: your mount directory name ```bash sudo mount -t nfs -o nconnect=16 nfs..datacrunch.io: /mnt/ ``` **Example:** ```bash sudo mount -t nfs -o nconnect=16 nfs.fin-01.datacrunch.io:/grgwrgwrg-20f77f6a /mnt/storage ``` #### Persist the mount in `/etc/fstab` (recommended) Add the filesystem to `/etc/fstab` so it remounts automatically on reboot: ```bash grep -qxF 'nfs..datacrunch.io: /mnt/ nfs defaults,nconnect=16 0 0' /etc/fstab || echo 'nfs..datacrunch.io: /mnt/ nfs defaults,nconnect=16 0 0' | sudo tee -a /etc/fstab ``` **Example:** ```bash grep -qxF 'nfs.fin-01.datacrunch.io:/grgwrgwrg-20f77f6a /mnt/storage nfs defaults,nconnect=16 0 0' /etc/fstab || echo 'nfs.fin-01.datacrunch.io:/grgwrgwrg-20f77f6a /mnt/storage nfs defaults,nconnect=16 0 0' | sudo tee -a /etc/fstab ``` #### Verify mount Confirm the filesystem mounted successfully: ```bash df -h ``` Look for your shared filesystem in the output: ``` Filesystem Size Used Avail Use% Mounted on ... nfs.fin-01.datacrunch.io:/grgwrgwrg-20f77f6a 100G 1.0G 99G 1% /mnt/storage ``` #### Set permissions (optional) Make the mounted storage writable by your user: ```bash sudo chown ubuntu:ubuntu /mnt/ ``` Replace `ubuntu:ubuntu` with your username if different. ::: ### Find the pseudopath After attaching the volume to an instance, open the **Volumes** page in the Spheron AI dashboard. Select your volume from the sidebar. The **Pseudopath** is displayed in the volume details; it starts with `/` and looks like `/grgwrgwrg-20f77f6a`. The datacenter location slug is also visible there in the NFS mount command (e.g., `nfs.fin-01.datacrunch.io`). ### Mount to every node in a cluster To mount the shared filesystem across all nodes in a cluster at once, use `pdsh`. Replace the placeholders as above: ```bash pdsh -a "sudo mkdir -vp /mnt/ && grep -qxF 'nfs..datacrunch.io: /mnt/ nfs defaults,nconnect=16 0 0' /etc/fstab || echo 'nfs..datacrunch.io: /mnt/ nfs defaults,nconnect=16 0 0' | sudo tee -a /etc/fstab && sudo mount /mnt/" ``` ### Use your mounted volume #### Access the storage Once mounted, use the shared filesystem like any local directory: ```bash # Navigate to the storage cd /mnt/storage # Create files and directories mkdir my-project echo "Hello, storage!" > my-project/readme.txt # List contents ls -lh /mnt/storage/ ``` #### Check storage usage ```bash # Check space on the mounted filesystem df -h /mnt/storage # Check detailed disk usage du -sh /mnt/storage/* ``` #### Work with large datasets Download datasets and checkpoints to the mounted volume. Data persists across instance restarts and is accessible to other instances in the same datacenter region. ```bash # Example: Download dataset to storage cd /mnt/storage wget https://example.com/large-dataset.tar.gz tar -xzf large-dataset.tar.gz ``` ### Unmount shared storage Unmount when swapping volumes, detaching the filesystem, or terminating the instance. #### Unmount the filesystem ```bash sudo umount /mnt/ ``` If you get a "target is busy" error, check for active processes: ```bash # Check what's using the storage lsof /mnt/ # Or use fuser fuser -m /mnt/ ``` #### Remove from file system table Remove the entry from `/etc/fstab` to prevent auto-mount on next boot: ```bash # Edit fstab manually sudo nano /etc/fstab # Or remove automatically with sed sudo sed -i '/datacrunch\.io.*nfs/d' /etc/fstab ``` ### Troubleshooting #### Mount fails with "Connection refused" **Cause:** Wrong datacenter slug, pseudopath, or filesystem not shared with this instance. **Solution:** 1. Verify the volume is attached to your instance in the Spheron AI dashboard 2. Double-check the datacenter slug and pseudopath 3. Confirm the instance and filesystem are in the same datacenter location #### Mount fails with "No such file or directory" **Cause:** Mount point directory doesn't exist. **Solution:** ```bash sudo mkdir -p /mnt/ sudo mount -t nfs -o nconnect=16 nfs..datacrunch.io: /mnt/ ``` #### Filesystem not mounting on boot **Cause:** Network not ready when fstab mounts are processed. **Solution:** Add the `_netdev` option to the fstab entry: ``` nfs..datacrunch.io: /mnt/ nfs defaults,nconnect=16,_netdev 0 0 ``` The `_netdev` option tells the system to wait for the network before mounting. #### Performance issues **Cause:** Suboptimal `nconnect` value or high network latency. **Solutions:** * Increase `nconnect` for more parallel connections (try 32) * Ensure the instance and filesystem are in the same datacenter ``` nfs..datacrunch.io: /mnt/ nfs defaults,nconnect=32 0 0 ``` #### Check mount status ```bash # List all NFS mounts mount | grep nfs # Check NFS statistics nfsstat # Verify fstab syntax sudo mount -fav ``` ### Best practices **Organization:** * Use descriptive mount points: `/mnt/data`, `/mnt/models`, `/mnt/datasets` * Create subdirectories for different projects * Document what data is stored where **Performance:** * Use `nconnect=16` or higher for better throughput * Keep instances and shared filesystems in the same datacenter location **Data safety:** * Maintain backups of critical data * Filesystems persist independently of instances, but data can still be lost due to accidental deletion * Test backup and restore procedures **Security:** * Restrict access using filesystem permissions * Only mount filesystems shared explicitly with your instance * Audit who has access to shared storage ### What's next * [Volume Mounting Overview](/connecting/volume-mounting): Multi-provider volume mounting guide * [Volume API Reference](/api-reference#volumes): Create and manage volumes programmatically * [SSH Connection Setup](/connecting/ssh-connection): Secure instance access For questions, use chat support in the Spheron AI dashboard or contact Spheron support for infrastructure issues. ## Mounting shared storage Mount persistent storage volumes to your GPU instances across different providers. ### Overview Persistent storage volumes provide shared, network-attached storage that can be attached to your GPU instances. These volumes persist independently of your instances, so data is not lost when an instance terminates. Volumes attach to [CPU nodes](/concepts/cpu-nodes) as well as GPU instances. The volume step in the CPU deploy wizard is the same one the GPU wizard uses, and the provider rules below apply unchanged. **Key features:** * Volumes persist independently of instances; data is not lost when an instance terminates * A single volume can be attached to multiple instances simultaneously (provider-dependent) * Up to 10 volumes can be attached to a single instance on Spheron AI and Verda; Sesterce and Spheron MS are limited to one volume per instance * Provider-specific mounting protocols (NFS or block device) * Volumes can be attached and detached from running instances without data loss on Verda, Spheron AI, and Spheron ES; Sesterce and Spheron MS bind a volume at instance launch only * Billed by capacity provisioned, not by usage :::info[Volume pricing] Volume storage is billed separately from instance compute. See [Cost Optimization](/cost-optimization) for guidance on when to use volumes vs. instance-local NVMe storage. ::: ### Prerequisites Before mounting a volume, ensure you have: 1. Created a persistent storage volume via the Spheron dashboard (Create Volume page) 2. Attached the volume to your GPU instance 3. Retrieved the volume's connection details (virtual IP, mount path, protocol) 4. SSH access to your instance ### Provider-specific mounting guides Select your provider below for detailed mounting instructions: #### Verda **Protocol:** Network File System (NFS) **Status:** Available Mount shared filesystems on Verda instances using datacenter-region NFS endpoints and pseudopaths. [View Verda mounting guide](/connecting/volume-mounting/data-crunch) **Key features:** * NFS protocol with high-performance `nconnect` option * Datacenter-specific NFS endpoints (e.g., `nfs.fin-01.datacrunch.io`) * Pseudopath-based filesystem identification * Up to 10 volumes can be attached to a single instance * Supports concurrent multi-instance access within the same datacenter * Cluster-wide mounting via `pdsh` :::warning[Region constraint] Verda volume multi-attach only works within the same datacenter region. Volumes created in `Finland 1` cannot be mounted on instances in a different Verda region. Cross-region mounting fails silently; always deploy your instance and volume in the same region. ::: *** #### Sesterce **Protocol:** Block device (ext4) **Status:** Available Mount persistent block storage volumes on Sesterce instances by formatting and mounting raw block devices. [View Sesterce mounting guide](/connecting/volume-mounting/sesterce) **Key features:** * Direct-attached block storage with local disk throughput * UUID-based fstab configuration for stable boot persistence * ext4 filesystem for broad compatibility *** #### Spheron AI **Protocol:** Block device (ext4, xfs, or ntfs) **Status:** Available Mount persistent block storage volumes on Spheron AI instances by formatting and mounting raw block devices. Choose your preferred filesystem. [View Spheron AI mounting guide](/connecting/volume-mounting/spheron-ai) **Key features:** * Up to 10 volumes can be attached to a single instance * Up to 50 TB per volume (size cap is region-specific; the create-volume slider adapts to the chosen region) * Per-region pricing in the create-volume wizard * Direct-attached block storage with local disk throughput * Flexible filesystem choice: ext4, xfs, or ntfs * UUID-based fstab configuration with `nofail` for safe boot persistence * Available across Canada 1, Montreal 1, Norway 1, Oslo 1, and US regions :::info[Multi-volume attachment] Spheron AI and Verda both support attaching up to 10 volumes to a single instance. Sesterce and Spheron MS are limited to one volume per instance. ::: *** #### Spheron ES **Protocol:** virtiofs (shared filesystem) **Status:** Available Mount shared filesystems on Spheron ES (Extra Supply) instances using virtio-attached devices identified by a mount tag. [View Spheron ES mounting guide](/connecting/volume-mounting/spheron-es) **Key features:** * virtiofs protocol with directly attached shared filesystems * Mount tag based identification (copyable from the volume card) * Up to **256 TiB** per volume (`sizeInGb: 262144` on the API) * Same volume can be mounted on multiple instances simultaneously, read-write or read-only * Volumes can be resized in place without recreation or data migration (shrinking is not supported) * Attach at deploy time without a restart, or hot-attach with a brief VM restart (data preserved) * Multiple volumes can be attached to a single instance * Available across EU North 1 (Finland), EU West 1 (France), ME West 1 (Middle East), and US Central 1 (US) :::warning[Hot-attach restarts the instance] Attaching or detaching a Spheron ES volume on a running instance restarts the VM. Select the volume during deployment to avoid downtime. ::: *** #### Spheron MS **Protocol:** Block device (ext4) **Status:** Available Attach a block volume to a Spheron MS instance at deployment time, then format and mount it as a raw block device. [View Spheron MS mounting guide](/connecting/volume-mounting/spheron-ms) **Key features:** * Direct-attached block storage with local disk throughput * Up to 16 TB per volume, one volume per instance * Wired in before the machine boots, so the disk is present on first connection * UUID-based fstab configuration with `nofail` for safe boot persistence * Available across US, Canada, Norway, Poland, Israel, India, Japan, Singapore, and Australia regions :::warning[Attach happens at deployment only] A Spheron MS volume is selected during the deployment wizard and cannot be attached or detached afterwards. Size and name are fixed at creation, and the volume must be in the same region as the instance. Terminating the instance releases the volume for the next deployment. ::: *** #### Other providers **Status:** Coming soon Support for additional providers is in development. Each provider may use different protocols and mounting procedures optimized for their infrastructure. **Planned providers:** * Massed Compute Check back for updates, or use the chat widget on [app.spheron.ai](https://app.spheron.ai) if you need volume mounting support for a specific provider. ### General concepts #### Volume lifecycle ``` Create Volume → Attach to Instance → Mount → Use → Unmount → Detach → Delete ↓ ↓ ↓ ↓ ↓ ↓ ↓ Available Available Attached Attached Attached Available Deleted ``` #### Common operations **Creating volumes:** Create persistent storage volumes from the Create Volume page in the Spheron dashboard. Specify the provider, name, and size in GB. **Attaching volumes:** Attach a volume to a running instance from the volume details page in the dashboard. The volume and instance must use the same provider. **Mounting:** Follow the provider-specific mounting instructions in the guides linked above. **Detaching volumes:** Unmount the volume from the instance first, then detach it from the dashboard. Volume data is preserved after detachment. ### What's next * [Volume API Reference](/api-reference#volumes): Create and manage volumes programmatically * [SSH Connection Setup](/connecting/ssh-connection): Secure instance access * [Security Best Practices](/security): Secure your storage and data * [Getting Started](/getting-started): Complete deployment guide For questions, use the chat widget on [app.spheron.ai](https://app.spheron.ai). ## Sesterce: mounting shared storage Mount persistent block storage volumes on Sesterce instances using ext4-formatted block devices. ### Overview Sesterce persistent volumes attach as raw block devices (e.g., `/dev/vdb`) and format with the ext4 filesystem. A stable UUID identifies each volume, referenced in `/etc/fstab` for persistent mounting. **Protocol:** Block device (ext4) **Connection:** Directly attached block device **Performance:** Local disk throughput ### Prerequisites Before starting, ensure you have: 1. Created a volume with provider: `sesterce` via the Spheron dashboard (Create Volume page) 2. Attached the volume to your Sesterce instance 3. SSH access to your Sesterce instance (credentials in the instance's Details drawer) ### Mounting process ::::steps #### Connect to your instance SSH into your Sesterce GPU instance using the connection details from the instance's Details drawer: ```bash ssh ubuntu@ ``` See [SSH Connection Setup](/connecting/ssh-connection) for detailed connection instructions. #### Identify the new disk List all block devices to confirm the volume is visible and unmounted: ```bash lsblk -o NAME,SIZE,TYPE,FSTYPE,MOUNTPOINT ``` Expected output: ``` NAME SIZE TYPE FSTYPE MOUNTPOINT vda 100G disk ├─vda1 99.9G part ext4 / vdb 50G disk # new disk, no MOUNTPOINT ``` If the disk has no `FSTYPE` and no `MOUNTPOINT`, it is raw and ready to format. #### Format the disk Format the volume with the ext4 filesystem: ```bash sudo mkfs.ext4 /dev/vdb ``` :::warning This destroys all existing data on `/dev/vdb`. Verify you are targeting the correct device before running this command. ::: #### Create mount directory Create a directory where you'll mount the volume. Replace `` with your preferred directory name: ```bash sudo mkdir -p /mnt/ ``` Common choices include: * `/mnt/data`: simple and clear * `/mnt/storage`: standard mount location * `/mnt/datasets`: for ML/AI datasets * `/mnt/models`: for model checkpoints #### Mount the disk Mount the formatted disk to the mount point: ```bash sudo mount /dev/vdb /mnt/ ``` Verify it is now visible: ```bash df -h ``` Look for your volume in the output: ``` Filesystem Size Used Avail Use% Mounted on ... /dev/vdb 49G 24K 47G 1% /mnt/data ``` #### Persist the mount in `/etc/fstab` (recommended) Device names like `/dev/vdb` can change across reboots. Use the disk's UUID for a stable reference. Get the UUID: ```bash sudo blkid /dev/vdb ``` Example output: ``` /dev/vdb: UUID="a1b2c3d4-e5f6-7890-abcd-ef1234567890" TYPE="ext4" ``` Add the entry to `/etc/fstab` (replace the UUID with your own): ```bash echo 'UUID= /mnt/ ext4 defaults 0 2' | sudo tee -a /etc/fstab ``` **Field explanation:** | Field | Value | Meaning | | ----------- | -------------------- | ------------------------------ | | device | `UUID=...` | Identifies the disk by UUID | | mount point | `/mnt/` | Where the disk is accessible | | type | `ext4` | Filesystem type | | options | `defaults` | Standard mount options | | dump | `0` | Disable backup via `dump` | | pass | `2` | fsck order (2 = non-root disk) | Verify the fstab entry works: ```bash sudo mount -a ``` No errors confirms the entry is correct. #### Set permissions (optional) Make the mounted storage writable by your user: ```bash sudo chown sesterce:sesterce /mnt/ ``` Replace `sesterce:sesterce` with your username if different. :::: ### Use your mounted volume #### Access the storage Once mounted, use the volume like any local directory: ```bash # Navigate to the storage cd /mnt/data # Create files and directories mkdir my-project echo "Hello, storage!" > my-project/readme.txt # List contents ls -lh /mnt/data/ ``` #### Check storage usage ```bash # Check space on the mounted volume df -h /mnt/data # Check detailed disk usage du -sh /mnt/data/* ``` #### Work with large datasets Download datasets and checkpoints to the mounted volume. Data persists across instance restarts. ```bash # Example: Download dataset to storage cd /mnt/data wget https://example.com/large-dataset.tar.gz tar -xzf large-dataset.tar.gz ``` ### Unmount shared storage Unmount when swapping volumes, detaching the volume, or terminating the instance. #### Unmount the volume ```bash sudo umount /mnt/ ``` If you get a "target is busy" error, check for active processes: ```bash # Check what's using the storage lsof /mnt/ # Or use fuser fuser -m /mnt/ ``` #### Remove from file system table Remove the entry from `/etc/fstab` to prevent auto-mount on next boot: ```bash # Edit fstab manually sudo nano /etc/fstab # Or remove automatically with sed sudo sed -i '/UUID=/d' /etc/fstab ``` ### Troubleshooting #### Disk not visible in `lsblk` **Cause:** Volume not attached by the cloud provider. **Solution:** 1. Check the Spheron AI dashboard and confirm the volume is attached to your instance 2. Re-attach the volume if needed and reconnect to the instance #### `mkfs.ext4` fails **Cause:** Disk is already mounted. **Solution:** ```bash sudo umount /dev/vdb sudo mkfs.ext4 /dev/vdb ``` #### Volume not mounting on boot **Cause:** Missing or incorrect `/etc/fstab` entry. **Solution:** Verify the fstab entry exists and the UUID matches: ```bash sudo blkid /dev/vdb cat /etc/fstab sudo mount -fav ``` #### Permission denied when writing to disk **Cause:** Mount point ownership is root. **Solution:** ```bash sudo chown sesterce:sesterce /mnt/ ``` #### Check mount status ```bash # List all mounted filesystems mount | grep /mnt # Check filesystem integrity (disk must be unmounted) sudo fsck /dev/vdb # Verify fstab syntax sudo mount -fav ``` ### Best practices **Organization:** * Use descriptive mount points: `/mnt/data`, `/mnt/models`, `/mnt/datasets` * Create subdirectories for different projects * Document what data is stored where **Performance:** * Block storage provides local disk throughput; no network overhead * Use ext4 for general workloads; consider xfs for large file performance **Data safety:** * Maintain backups of critical data * Volumes persist independently of instances, but data can still be lost due to accidental deletion * Test backup and restore procedures **Security:** * Restrict access using filesystem permissions * Audit who has access to mounted storage ### What's next * [Volume Mounting Overview](/connecting/volume-mounting): Multi-provider volume mounting guide * [Volume API Reference](/api-reference#volumes): Create and manage volumes programmatically * [SSH Connection Setup](/connecting/ssh-connection): Secure instance access ## Spheron AI: mounting shared storage Mount persistent block storage volumes on Spheron AI instances using raw block devices and your choice of filesystem. ### Overview Spheron AI persistent volumes attach as raw block devices (e.g., `/dev/vdb`). You choose the filesystem when formatting the volume. A stable UUID identifies each volume, referenced in `/etc/fstab` for persistent mounting. **Protocol:** Block device (ext4, xfs, or ntfs) **Connection:** Directly attached block device **Performance:** Local disk throughput **Maximum size:** Up to 50 TB per volume (cap is region-specific; the create-volume slider adapts to the chosen region) **Regions:** Canada 1, Montreal 1, Norway 1, Oslo 1, US **Multi-volume support:** Attach up to 10 volumes to a single instance :::info[Multi-volume attachment] Spheron AI and Verda both support attaching up to 10 volumes to a single instance. Sesterce is limited to one volume per instance. On Spheron AI, each attached volume appears as a separate block device (`/dev/vdb`, `/dev/vdc`, `/dev/vdd`, ...) and is formatted and mounted independently. ::: ### Prerequisites Before starting, ensure you have: 1. Created a volume with provider: `spheron-ai` via the Spheron dashboard (Create Volume page) 2. Attached the volume to your Spheron AI instance 3. SSH access to your Spheron AI instance (credentials in the instance's Details drawer) ### Mounting process ::::steps #### Connect to your instance SSH into your Spheron AI GPU instance using the connection details from the instance's Details drawer: ```bash ssh ubuntu@ ``` See [SSH Connection Setup](/connecting/ssh-connection) for detailed connection instructions. #### Identify the new disk List all block devices to confirm the volume is visible and unmounted: ```bash lsblk -o NAME,SIZE,TYPE,FSTYPE,MOUNTPOINT ``` Expected output: ``` NAME SIZE TYPE FSTYPE MOUNTPOINT vda 100G disk ├─vda1 99.9G part ext4 / vdb 50G disk # new disk, no MOUNTPOINT ``` If the disk has no `FSTYPE` and no `MOUNTPOINT`, it is raw and ready to format. :::tip[Multiple volumes attached] When multiple volumes are attached to the same Spheron AI instance (up to 10), each one appears as a separate device: the first new volume is `/dev/vdb`, the second is `/dev/vdc`, the third is `/dev/vdd`, and so on. Repeat the steps below for each volume, substituting the correct device name and mount point. ::: #### Format the disk Format the volume with your preferred filesystem. Replace `[file-system-format]` with your desired type: ```bash sudo mkfs.[file-system-format] /dev/vdb ``` Common filesystem choices: | Filesystem | Best for | | ---------- | ------------------------------------------------------------------------------- | | `ext4` | General-purpose workloads on Linux. Robust, journaling, widely compatible. | | `xfs` | Large files and large filesystems. Strong performance in data center workloads. | | `ntfs` | Drives shared with Windows systems. Supports large files with journaling. | Example using ext4: ```bash sudo mkfs.ext4 /dev/vdb ``` :::warning This destroys all existing data on `/dev/vdb`. Verify you are targeting the correct device before running this command. ::: #### Create mount directory Create a directory where you'll mount the volume. Replace `` with the name of your volume as listed in the Spheron dashboard: ```bash sudo mkdir -p /mnt/ ``` :::tip To find the volume name, navigate to the Spheron dashboard, select the instance to which the volume is attached, and open the **Volumes** tab to see the volume's name. ::: Common choices include: * `/mnt/data`: simple and clear * `/mnt/storage`: standard mount location * `/mnt/datasets`: for ML/AI datasets * `/mnt/models`: for model checkpoints #### Mount the disk Mount the formatted disk to the mount point: ```bash sudo mount /dev/vdb /mnt/ ``` Verify it is now visible: ```bash df -h ``` Look for your volume in the output: ``` Filesystem Size Used Avail Use% Mounted on ... /dev/vdb 49G 24K 47G 1% /mnt/data ``` #### Verify the mount Confirm the volume is mounted correctly: ```bash mount | grep "" ``` Or inspect all block devices with filesystem details: ```bash lsblk -o NAME,SIZE,FSTYPE,MOUNTPOINT,LABEL | grep "" ``` #### Persist the mount in `/etc/fstab` (recommended) Device names like `/dev/vdb` can change across reboots or VM restores. Use the disk's UUID for a stable reference. Get the UUID: ```bash sudo blkid /dev/vdb ``` Example output: ``` /dev/vdb: UUID="a1b2c3d4-e5f6-7890-abcd-ef1234567890" TYPE="ext4" ``` Add the entry to `/etc/fstab` (replace the UUID and filesystem type with your own): ```bash echo 'UUID= /mnt/ ext4 defaults,nofail 0 2' | sudo tee -a /etc/fstab ``` **Field explanation:** | Field | Value | Meaning | | ----------- | -------------------- | ------------------------------------------------ | | device | `UUID=...` | Identifies the disk by UUID | | mount point | `/mnt/` | Where the disk is accessible | | type | `ext4` | Filesystem type | | options | `defaults,nofail` | Standard mount options with boot-safety fallback | | dump | `0` | Disable backup via `dump` | | pass | `2` | fsck order (2 = non-root disk) | :::warning If the volume is not always attached, keep the `nofail` option in your `/etc/fstab` entry. Without it, your VM may fail to boot when the volume is absent. ::: Verify the fstab entry works: ```bash sudo mount -a ``` No errors confirms the entry is correct. #### Set permissions (optional) Make the mounted storage writable by your user: ```bash sudo chown ubuntu:ubuntu /mnt/ ``` Replace `ubuntu:ubuntu` with your username if different. :::: ### Use your mounted volume #### Access the storage Once mounted, use the volume like any local directory: ```bash # Navigate to the storage cd /mnt/data # Create files and directories mkdir my-project echo "Hello, storage!" > my-project/readme.txt # List contents ls -lh /mnt/data/ ``` #### Check storage usage ```bash # Check space on the mounted volume df -h /mnt/data # Check detailed disk usage du -sh /mnt/data/* ``` #### Work with large datasets Download datasets and checkpoints to the mounted volume. Data persists across instance restarts. ```bash # Example: Download dataset to storage cd /mnt/data wget https://example.com/large-dataset.tar.gz tar -xzf large-dataset.tar.gz ``` ### Unmount shared storage Unmount when swapping volumes, detaching the volume, or terminating the instance. #### Unmount the volume ```bash sudo umount /mnt/ ``` If you get a "target is busy" error, check for active processes: ```bash # Check what's using the storage lsof /mnt/ # Or use fuser fuser -m /mnt/ ``` #### Remove from file system table Remove the entry from `/etc/fstab` to prevent auto-mount on next boot: ```bash # Edit fstab manually sudo nano /etc/fstab # Or remove automatically with sed sudo sed -i '/UUID=/d' /etc/fstab ``` ### Troubleshooting #### Disk not visible in `lsblk` **Cause:** Volume not attached by the cloud provider. **Solution:** 1. Check the Spheron AI dashboard and confirm the volume is attached to your instance 2. Re-attach the volume if needed and reconnect to the instance #### `mkfs` fails **Cause:** Disk is already mounted. **Solution:** ```bash sudo umount /dev/vdb sudo mkfs.ext4 /dev/vdb ``` #### Volume not mounting on boot **Cause:** Missing or incorrect `/etc/fstab` entry. **Solution:** Verify the fstab entry exists and the UUID matches: ```bash sudo blkid /dev/vdb cat /etc/fstab sudo mount -fav ``` #### VM fails to boot after adding fstab entry **Cause:** Volume is not attached and the fstab entry lacks the `nofail` option. **Solution:** Boot into recovery mode and add `nofail` to the mount options: ``` UUID= /mnt/ ext4 defaults,nofail 0 2 ``` #### Permission denied when writing to disk **Cause:** Mount point ownership is root. **Solution:** ```bash sudo chown ubuntu:ubuntu /mnt/ ``` #### Check mount status ```bash # List all mounted filesystems mount | grep /mnt # Check filesystem integrity (disk must be unmounted) sudo fsck /dev/vdb # Verify fstab syntax sudo mount -fav ``` ### Best practices **Organization:** * Use descriptive mount points: `/mnt/data`, `/mnt/models`, `/mnt/datasets` * Create subdirectories for different projects * Document what data is stored where **Performance:** * Block storage provides local disk throughput; no network overhead * Use ext4 for general workloads; consider xfs for large file performance **Data safety:** * Maintain backups of critical data * Volumes persist independently of instances, but data can still be lost due to accidental deletion * Always include `nofail` in `/etc/fstab` entries to prevent boot failures when volumes are detached * Test backup and restore procedures **Security:** * Restrict access using filesystem permissions * Audit who has access to mounted storage ### What's next * [Volume Mounting Overview](/connecting/volume-mounting): Multi-provider volume mounting guide * [Volume API Reference](/api-reference#volumes): Create and manage volumes programmatically * [SSH Connection Setup](/connecting/ssh-connection): Secure instance access ## Spheron ES: mounting shared storage Mount persistent shared filesystems on Spheron ES (Extra Supply) instances using the virtiofs protocol. ### Overview Spheron ES shared filesystems attach directly to the VM and expose a virtiofs device identified by a unique mount tag. Volumes can be mounted to multiple instances simultaneously, resized in place, and persist independently of the instance. **Protocol:** virtiofs **Connection:** Directly attached virtio filesystem **Identifier:** Mount tag from the volume card **Maximum size:** 256 TiB per volume (`sizeInGb: 262144` on the API) **Regions:** EU North 1 (Finland), EU West 1 (France), ME West 1 (Middle East), US Central 1 (US) **Multi-volume support:** Attach multiple volumes to a single instance **Volume behavior:** * Volumes selected at deploy time are mounted before the instance boots, so there is no restart. * Hot-attach or hot-detach on a running instance stops the VM, applies the change, and starts it back up. Data is preserved across the restart. * The same volume can be mounted on multiple instances at once, read-write or read-only. * Volumes can be grown in place after creation without recreating them or migrating data. Shrinking is not supported. * A volume's name is fixed at creation. To use a different name, create a new volume. :::info[Same-region requirement] Shared filesystems can only be mounted from instances in the same region as the volume. ::: :::warning[Hot-attach causes a restart] Attaching or detaching a volume on a running instance restarts the VM. To avoid downtime, select the volume during deployment so it is mounted before the instance boots. ::: ### Prerequisites Before starting, ensure you have: 1. Created a volume with provider: `spheron-es` via the Spheron dashboard (Create Volume page) 2. Attached the shared filesystem to your Spheron ES instance, either during deployment or via the volume details page 3. Retrieved the **mount tag** from the volume card in the Spheron AI dashboard 4. SSH access to your Spheron ES instance ### Mounting process :::steps #### Connect to your instance SSH into your Spheron ES GPU instance using the connection details from the instance's Details drawer: ```bash ssh ubuntu@ ``` See [SSH Connection Setup](/connecting/ssh-connection) for detailed connection instructions. #### Verify the device is visible Confirm the virtiofs device is present after the instance boots: ```bash sudo dmesg | grep virtiofs ``` You should see a line similar to: ```text virtiofs virtio3: virtio_fs_setup_dax: No cache capability ``` If no virtiofs device appears, the filesystem is not attached. Attach it from the volume details page in the Spheron AI dashboard, then retry. #### Create a mount point Create a directory where you'll mount the shared filesystem. Replace `` with your preferred directory name: ```bash sudo mkdir -p /mnt/ ``` Common choices include: * `/mnt/shared`: standard mount location * `/mnt/datasets`: for ML/AI datasets * `/mnt/models`: for model checkpoints #### Mount the filesystem Mount the shared filesystem using its mount tag. Replace the placeholders with your values: * ``: the mount tag shown on the volume card (e.g., `hkjhkh`) * ``: your mount directory name ```bash sudo mount -t virtiofs /mnt/ ``` **Example:** ```bash sudo mount -t virtiofs hkjhkh /mnt/shared ``` #### Set permissions Grant all users write access to the mounted directory: ```bash sudo chmod a+w /mnt/ ``` To restrict ownership to a specific user instead, use `chown`: ```bash sudo chown ubuntu:ubuntu /mnt/ ``` #### Verify the mount Confirm the filesystem mounted successfully: ```bash df -h /mnt/ ``` Expected output: ```text Filesystem Size Used Avail Use% Mounted on hkjhkh 50G 0 50G 0% /mnt/shared ``` #### Persist the mount in `/etc/fstab` (recommended) Add the filesystem to `/etc/fstab` so it remounts automatically on reboot. The `nofail` option is critical: without it, the VM will not boot if the filesystem is ever detached. ```bash echo " /mnt/ virtiofs rw,nofail 0 0" | sudo tee -a /etc/fstab ``` **Example:** ```bash echo "hkjhkh /mnt/shared virtiofs rw,nofail 0 0" | sudo tee -a /etc/fstab ``` ::: ### Find the mount tag The mount tag is shown on the volume card in the Spheron AI dashboard: 1. Open the **Volumes** page in the Spheron AI dashboard. 2. Select your volume from the list. 3. The **Mount Tag** is displayed on the volume card and can be copied with the copy icon. The mount tag is unique per volume and used directly as the source argument to `mount -t virtiofs`. ### Use your mounted volume #### Access the storage Once mounted, use the shared filesystem like any local directory: ```bash # Navigate to the storage cd /mnt/shared # Create files and directories mkdir my-project echo "Hello, storage!" > my-project/readme.txt # List contents ls -lh /mnt/shared/ ``` #### Check storage usage ```bash # Check space on the mounted filesystem df -h /mnt/shared # Check detailed disk usage du -sh /mnt/shared/* ``` #### Work with large datasets Download datasets and checkpoints to the mounted volume. Data persists across instance restarts and is accessible from other instances in the same region that share this volume. ```bash # Example: download a dataset to shared storage cd /mnt/shared wget https://example.com/large-dataset.tar.gz tar -xzf large-dataset.tar.gz ``` ### Mount to every node in a cluster To mount the shared filesystem across all nodes in a cluster at once, use `pdsh`. Replace the placeholders as above: ```bash pdsh -a "sudo mkdir -vp /mnt/ && echo ' /mnt/ virtiofs rw,nofail 0 0' | sudo tee -a /etc/fstab && sudo mount /mnt/" ``` ### Unmount shared storage Unmount when swapping volumes, detaching the filesystem, or terminating the instance. #### Unmount the filesystem ```bash sudo umount /mnt/ ``` If you get a "target is busy" error, check for active processes: ```bash # Check what's using the storage lsof /mnt/ # Or use fuser fuser -m /mnt/ ``` #### Remove from file system table Remove the entry from `/etc/fstab` to prevent auto-mount on next boot: ```bash # Edit fstab manually sudo nano /etc/fstab # Or remove the line by mount tag sudo sed -i '/.*virtiofs/d' /etc/fstab ``` ### Troubleshooting #### Mount fails with "wrong fs type, bad option, bad superblock" **Cause:** The mount tag is incorrect. **Solution:** 1. Open the **Volumes** page in the Spheron AI dashboard. 2. Select the volume and copy the **Mount Tag** from the volume card. 3. Retry the mount with the exact tag value. #### No virtiofs device in `dmesg` **Cause:** The filesystem is not attached to the VM. **Solution:** 1. Open the volume details page in the Spheron AI dashboard. 2. Attach the volume to the instance. Hot-attach restarts the VM. 3. After the instance boots, rerun `sudo dmesg | grep virtiofs`. #### Filesystem not mounting on boot **Cause:** The fstab entry is missing the `nofail` option, or the device is not ready when fstab mounts are processed. **Solution:** Ensure the fstab entry includes `nofail`. With `nofail`, the system continues to boot even if the filesystem is unavailable: ```text /mnt/ virtiofs rw,nofail 0 0 ``` #### Check mount status ```bash # List all virtiofs mounts mount | grep virtiofs # Verify fstab syntax without mounting sudo mount -fav ``` ### Best practices **Organization:** * Use descriptive mount points: `/mnt/data`, `/mnt/models`, `/mnt/datasets` * Create subdirectories for different projects * Document what data is stored where **Deployment:** * Select volumes at deploy time to avoid the hot-attach restart * Plan ahead for the volume name, since renaming is not supported after creation **Data safety:** * Maintain backups of critical data * Filesystems persist independently of instances, but data can still be lost due to accidental deletion * Test backup and restore procedures **Security:** * Restrict access using filesystem permissions * Only mount filesystems shared explicitly with your instance * Audit who has access to shared storage ### What's next * [Volume Mounting Overview](/connecting/volume-mounting): Multi-provider volume mounting guide * [Volume API Reference](/api-reference#volumes): Create and manage volumes programmatically * [SSH Connection Setup](/connecting/ssh-connection): Secure instance access For questions, use chat support in the Spheron AI dashboard or contact Spheron support for infrastructure issues. ## Spheron MS: mounting shared storage Attach a persistent block volume to a Spheron MS instance at deployment time, then format and mount it like any other block device. ### Overview A Spheron MS volume attaches only while the instance is being created. It is wired in before the machine boots, so the disk is already present the first time you connect. There is no attach or detach for an instance that is already running. **Protocol:** Block device (ext4) **Connection:** Directly attached block device **Maximum size:** 16 TB per volume **Volumes per instance:** One **Regions:** Selected per volume, and must match the instance region ### Volume rules These constraints come from the provider, and the deployment wizard enforces them before anything is created: * **A volume is chosen at deployment time, and only then.** Terminating the instance releases the volume, and you can then select it for your next deployment. * **One volume per instance.** * **Size and name are fixed at creation.** A Spheron MS volume cannot be resized or renamed afterwards. Create a new volume at the size you need and copy your data across. * **A volume and its instance must be in the same region.** The wizard does not offer a volume from a different region, and the API rejects the mismatch before anything is created. * **The boot disk comes with the machine type.** Each Spheron MS machine type ships a fixed boot disk, so its size is shown on the offer rather than being something you set. Pick a machine type with the disk you need, or attach a volume for the rest. :::warning[Plan the size before you create the volume] Because a Spheron MS volume cannot be resized, an undersized volume means creating a second one and copying data across. Size it for the dataset you expect to hold, not the one you have today. ::: ### Prerequisites Before starting, ensure you have: 1. Created a volume with provider `spheron-ms` in the region you intend to deploy into 2. Selected that volume during step 2 of the deployment wizard 3. SSH access to the instance (credentials in the instance's Details drawer) ### Mounting process ::::steps #### Connect to your instance ```bash ssh ubuntu@ ``` See [SSH connection setup](/connecting/ssh-connection) for detailed connection instructions. #### Identify the new disk ```bash lsblk -o NAME,SIZE,TYPE,FSTYPE,MOUNTPOINT ``` Expected output: ``` NAME SIZE TYPE FSTYPE MOUNTPOINT sda 512G disk ├─sda1 511G part ext4 / sdb 2.0T disk # attached volume, no MOUNTPOINT ``` A disk with no `FSTYPE` and no `MOUNTPOINT` is raw and ready to format. #### Format the disk ```bash sudo mkfs.ext4 /dev/sdb ``` :::warning This destroys all existing data on `/dev/sdb`. Confirm the device name against `lsblk` before running the command. Skip this step when reusing a volume that already holds data. ::: #### Create the mount directory ```bash sudo mkdir -p /mnt/data ``` #### Mount the disk ```bash sudo mount /dev/sdb /mnt/data df -h /mnt/data ``` #### Persist the mount in `/etc/fstab` Device names can change across reboots, so reference the disk by UUID: ```bash sudo blkid /dev/sdb ``` Add the entry, replacing the UUID with your own: ```bash echo 'UUID= /mnt/data ext4 defaults,nofail 0 2' | sudo tee -a /etc/fstab sudo mount -a ``` `nofail` lets the instance boot even if the volume is absent, which matters because a Spheron MS volume is attached only at creation. #### Set permissions ```bash sudo chown $USER:$USER /mnt/data ``` :::: ### Move data between volumes Resizing is not available, so growing your storage means creating a larger volume and copying data to it. Both volumes cannot be attached to one instance, so copy over the network: ```bash # From the old instance, with the old volume mounted rsync -avz --progress /mnt/data/ ubuntu@:/mnt/data/ ``` Deploy the new instance with the larger volume first, then copy, then terminate the old instance. ### Troubleshooting #### Issue: The volume does not appear in the deployment wizard **Symptoms**: The volumes step lists no volume, or omits the one you created. **Diagnosis**: The volume is in a different region from the offer you selected, or it is still attached to a live instance. **Resolution**: Create the volume in the same region as the offer, or terminate the instance currently holding it. A Spheron MS volume is released when its instance is terminated. #### Issue: There is no attach button on a running instance **Symptoms**: The instance panel offers no way to add a volume. **Diagnosis**: This is expected. Spheron MS supports attachment only at instance creation. **Resolution**: Terminate the instance and deploy a new one with the volume selected in step 2. #### Issue: Resize or rename returns an error **Symptoms**: `PATCH /api/volumes/{volumeId}` fails for a Spheron MS volume. **Diagnosis**: Size and name are fixed at creation on this provider. **Resolution**: Create a new volume at the size and name you want, then copy the data across. #### Issue: The disk is missing after a reboot **Symptoms**: `/mnt/data` is empty and `lsblk` shows no second disk. **Diagnosis**: The volume was released when the previous instance was terminated, and the current instance was deployed without it. **Resolution**: Redeploy with the volume selected during the wizard's volumes step. ### What's next * [Volume mounting overview](/connecting/volume-mounting): Multi-provider volume mounting guide * [Regions and providers](/concepts/regions-providers): Spheron MS regions and GPU inventory * [Volume API reference](/api-reference#volumes): Create and manage volumes programmatically * [SSH connection setup](/connecting/ssh-connection): Secure instance access ## CPU nodes CPU Node is a CPU-only instance with no GPU attached. Use it for build steps, data preparation, schedulers, API workers, control planes, and any other job that never touches a GPU. Prices start at $0.09 per hour, well below the cost of renting a GPU you do not use. CPU Node has its own page in the dashboard sidebar under **Compute**, next to **Deploy GPUs**. The page opens whether or not you are signed in. ### When to use a CPU node | Workload | Run it on | | --------------------------------------------------- | ------------ | | Data preprocessing, ETL, dataset sharding | CPU node | | Build and CI steps, container image builds | CPU node | | Schedulers, queue workers, cron jobs | CPU node | | API servers and control planes fronting a GPU fleet | CPU node | | Model training and fine-tuning | GPU instance | | LLM and diffusion inference | GPU instance | A CPU node runs no NVIDIA driver and reports no GPU. Commands such as `nvidia-smi` and `torch.cuda.is_available()` do not work. Deploy a [GPU instance](/concepts/instance-types) for anything that needs CUDA. ### Available sizes Every provider's CPU offer collapses onto a single **CPU NODE** entry, so there is no catalog to page through. The wizard lists every size the providers currently publish and shows the lowest available price for each one before you commit. | Provider | Sizes (vCPU / memory) | Instance types | Regions | | -------------- | ----------------------------------------------------------- | --------------- | -------------------------------------------------------------------------------------------------------------- | | Verda | 4/16, 8/32, 16/64, 32/128 GB | Spot, Dedicated | Finland 1, Finland 3 | | Spheron AI | 4/4, 8/8, 16/16, 16/32, 32/64 GB | Dedicated | Norway 1, Canada 1 | | Sesterce | 4/4, 4/16, 8/8, 8/32, 14/40, 16/16, 16/64, 28/80, 32/128 GB | Dedicated | Helsinki, Frankfurt, Oslo, London, Ashburn, Dallas, Des Moines, Houston, Kansas City, Calgary, Montreal, Tokyo | | Massed Compute | 8/32, 14/40, 28/80, 52/160 GB | Dedicated | us-central-2, us-central-3, us-east-5 | Availability varies by size and region. The wizard only offers sizes that the selected region can actually serve. Check the [Deploy CPU page](https://app.spheron.ai/deploy-cpu) for live inventory and pricing. ### Pricing Spot CPU nodes on Verda start at **$0.09/hr** for 4 vCPU with 16 GB of memory. Dedicated rates start at **$0.12/hr** on Massed Compute for 8 vCPU with 32 GB. Billing is per second, identical to GPU instances, and the order summary projects a full month from the hourly rate. The minimum runtime before manual termination applies to CPU nodes exactly as it does to GPU instances: 20 minutes by default, longer where the machine type sets its own. The wizard shows the figure before you deploy. See [Instance lifecycle](/concepts/instance-lifecycle#minimum-runtime-before-termination) for the full rule. #### Spot on CPU Verda CPU instances sell at spot rates as well as on demand. The spot and on-demand toggle behaves the same way it does for GPU offers: the provider can reclaim a spot node at any time, so checkpoint any long-running job to a [persistent volume](/connecting/volume-mounting). ### Deploy from the dashboard :::steps #### Open the Deploy CPU page In the [Spheron dashboard](https://app.spheron.ai), click **Deploy CPU** in the sidebar under **Compute**. There is no catalog and nothing to search. The page selects the single CPU Node option for you and goes straight to configuration. #### Configure the node (step 1) Answer the questions in order: 1. **Instance type:** Spot or Dedicated. 2. **Provider:** Verda, Sesterce, Spheron AI, or Massed Compute. 3. **Instance size:** vCPU count and memory. 4. **Region:** the regions that can serve the chosen size. 5. **Operating system:** the images that provider offers. GPU count, cluster networking, and the deployment type picker do not appear, because a CPU node has no answer for any of them. #### Add access and storage (step 2) Step 2 is identical to the GPU wizard: pick an [SSH key](/user-settings#ssh-keys), add an optional [startup script](/connecting), attach any [volumes](/connecting/volume-mounting), and review the order summary. #### Deploy Click **Deploy Instance**. If your balance is short, the configuration you built is held while you top up and restored when you return to Deploy CPU. ::: ### Operating systems CPU nodes list only images that make sense without a GPU. CUDA and other GPU driver images are excluded. | Provider | Images | | ---------- | ------------------------------------------------------------------------ | | Verda | Ubuntu 22.04, Ubuntu 24.04, Jupyter | | Spheron AI | Ubuntu Server 22.04 LTS, Ubuntu Server 24.04 LTS, AlmaLinux 9, Debian 12 | | Sesterce | Ubuntu 22.04 | ### Connect to a CPU node Connect over SSH exactly as you would to a GPU instance: ```bash # Copy the SSH command from the instance details panel ssh -i ~/.ssh/id_ed25519 root@ ``` The username varies by provider. See the [SSH connection guide](/connecting/ssh-connection) for details. Verify the machine after connecting: ```bash # vCPU count and model lscpu | grep -E "^CPU\(s\)|Model name" # Memory free -h # Disk df -h ``` ### How CPU nodes appear in the dashboard * **Instance cards** name the vCPU and memory where a GPU instance names its model, and carry a hardware icon so a CPU node and an accelerator are distinguishable at a glance. * **GPU count and video memory** are omitted entirely rather than shown blank. * **The GPU catalog** on Deploy GPUs lists GPUs only. CPU Node never appears there, so the result count and page count on that page cover GPU offers alone. ### Deploy through the API #### List CPU offers Narrow the catalog to CPU with `computeType=cpu`: ```bash curl -H "Authorization: Bearer $SPHERON_API_KEY" \ "https://app.spheron.ai/api/gpu-offers?computeType=cpu" ``` The response contains a single row with `gpuType: "CPU"` and `displayName: "CPU NODE"`. Every entry in its `offers` array reports `gpuCount: 0` and carries the `offerId` a deployment takes, along with `vcpus`, `memory`, `storage`, `price`, `os_options`, and the region in `clusters`. #### Create a CPU deployment Send `gpuType: "CPU"` with `gpuCount: 0`: ```bash curl -X POST "https://app.spheron.ai/api/deployments" \ -H "Authorization: Bearer $SPHERON_API_KEY" \ -H "Content-Type: application/json" \ -d '{ "provider": "data-crunch", "offerId": "CPU.4V.16G_FIN-01_200_spot", "gpuType": "CPU", "gpuCount": 0, "region": "Finland 1", "operatingSystem": "Ubuntu 22.04", "instanceType": "SPOT", "sshKeyId": "your_ssh_key_id" }' ``` Deployments created this way are stored as CPU nodes, so responses and usage records report a CPU node rather than an unnamed GPU. :::warning[gpuType must match the offer] Posting any GPU model name against a CPU `offerId` returns a `400` validation error. Send `"CPU"`, or omit `gpuType` entirely and let the platform resolve it from the offer. ::: See the [API reference](/api-reference#get-gpu-offers) for the full endpoint contract. ### Troubleshooting #### Issue: No regions available for CPU NODE **Symptoms**: The region list is empty and the wizard reports that the configuration is not available in any region. **Diagnosis**: The selected instance size is not stocked in any region for that provider and instance type. **Resolution**: Choose a different instance size, or switch between Spot and Dedicated. The wizard filters regions by the size you picked, not the other way around. #### Issue: nvidia-smi is not found **Symptoms**: `nvidia-smi: command not found` after connecting. **Diagnosis**: This is expected. A CPU node has no GPU and ships no NVIDIA driver. **Resolution**: Deploy a GPU instance from **Deploy GPUs** if your workload needs CUDA. #### Issue: Deployment rejected with an invalid GPU type error **Symptoms**: `POST /api/deployments` returns `400` naming a GPU type mismatch against a CPU offer. **Diagnosis**: The request sent a GPU model name in `gpuType` for an offer with `gpuCount: 0`. **Resolution**: Send `"gpuType": "CPU"` and `"gpuCount": 0`, or omit `gpuType` and let the platform resolve it. ### What's next * [Instance types](/concepts/instance-types): Spot and Dedicated trade-offs across CPU and GPU * [Regions and providers](/concepts/regions-providers): Provider capabilities and geographic coverage * [Cost optimization](/cost-optimization): Move non-GPU work off GPU instances * [Startup scripts](/connecting): Automate setup on first boot * [API reference](/api-reference#get-gpu-offers): Filter offers by compute type programmatically ## Concepts ### Platform Primitives #### [Instance Types](/concepts/instance-types) Spheron GPU offerings differ on two dimensions: **interruptibility** and **hardware isolation**. **Spot** instances run as VMs and can be reclaimed by the provider at any time. **Dedicated** instances carry a 99.95% SLA and are not reclaimed once deployed. Hardware isolation applies only to Dedicated instances, which come in two sub-types: * **VM**: Isolated virtual machine on shared physical hardware. The default for most GPU offers across all providers. * **Bare Metal**: Full physical server with no hypervisor. GPU count varies by offer and provider, from single-GPU up to multi-GPU servers. Identified by the `BAREMETAL` suffix in the GPU type name on the dashboard. Multi-GPU Bare Metal offers with an SXM form factor use NVLink or NVSwitch between GPUs, which is what distributed training depends on. All instance types enforce a minimum runtime before manual termination, 20 minutes by default. Some machine types carry a longer provider minimum, shown in the wizard before you deploy. *** #### [CPU Nodes](/concepts/cpu-nodes) Not every job needs a GPU. **CPU Node** is a CPU-only instance for build steps, data preparation, schedulers, API workers, and control planes, priced from $0.09 per hour. CPU Node has its own page in the dashboard sidebar under **Compute**, with its own wizard. Every provider's CPU offer collapses onto a single option, so there is no catalog to browse. Sizes run from 4 vCPU with 4 GB of memory up to 52 vCPU with 160 GB across Verda, Sesterce, Spheron AI, and Massed Compute, with spot pricing available on Verda. Through the API, CPU Node is a single offer row with `gpuType: "CPU"` and `gpuCount: 0`. Filter for it with `?computeType=cpu`. *** #### [Instance Lifecycle](/concepts/instance-lifecycle) An instance does not have to be destroyed to stop costing you money. **Stopping** releases the GPU while keeping the disk and its contents, and billing drops to a stopped rate that covers the retained disk. **Starting** brings it back on the same disk with the same public IP. **Restarting** reboots in place without changing what you are billed. Support varies: stopping works on Spheron AI and Spheron ES, restarting works on Spheron AI, Spheron MS, Spheron AM, and Massed Compute, and the two lists do not match. Reserved and bare metal instances support neither. Through the API, a stopped instance reports `status: "stopped"` and is part of the live set. *** #### [Regions & Providers](/concepts/regions-providers) Spheron sources capacity from seven providers: Verda, Sesterce, Spheron AI, Spheron ES, Spheron MS, Spheron AM, and Massed Compute. GPU availability, CPU Node availability, volume support, lifecycle controls, and startup scripts vary by provider. Most GPUs are NVIDIA. **Spheron AM** supplies AMD Instinct MI300X with 192 GB of HBM3e per GPU, which runs [ROCm](/connecting/rocm-amd) rather than CUDA. Intel Gaudi2 is available through Sesterce and Spheron MS. CPU Node runs on Verda (Finland 1, Finland 3), Sesterce (Helsinki, Frankfurt, Oslo, London, Ashburn, Dallas, Des Moines, Houston, Kansas City, Calgary, Montreal, Tokyo), Spheron AI (Norway 1, Canada 1), and Massed Compute (US regions). Persistent volumes are supported on: * **Verda** (EU Finland: Finland 1, Finland 2, Finland 3): up to 10 TB, NVMe\_Shared NFS-backed, can attach to multiple instances within the same datacenter region * **Spheron AI** (Canada 1, Montreal 1, Norway 1, Oslo 1, US): up to 50 TB block volumes, up to 10 per instance * **Spheron ES** (EU North 1, EU West 1, ME West 1, US Central 1): up to 256 TiB virtiofs shared volumes, multi-instance attach * **Sesterce** (EU regions): block volumes bound at instance launch * **Spheron MS** (US, Canada, Norway, Poland, Israel, India, Japan, Singapore, Australia): up to 16 TB block volumes, one per instance, bound at instance launch Spheron AM and Massed Compute do not support volumes. *** #### [Networking](/concepts/networking) Each instance gets a dedicated public IP for its deployment lifetime. There is no shared NAT or port forwarding. The IP address and SSH connection command are shown in the instance details panel in the dashboard. All ports are open by default. Access unauthenticated services (Jupyter, TensorBoard) via SSH tunneling or VS Code Remote port forwarding. Do not expose unauthenticated services directly on the public IP. *** #### [Teams](/concepts/teams) Teams let multiple users share a credit pool, SSH keys, and volumes. Three roles are available: Owner, Admin, and Member. Only Owner and Admin can manage billing. For programmatic access with team scoping, see the [API Reference](/api-reference). ## Instance lifecycle An instance does not have to be destroyed to stop costing you money. Stopping parks the machine: the GPU stops billing, the disk and everything on it stays exactly where it was, and you start it again when you need it. Restarting reboots a machine in place without changing what you are billed. Neither action is available on every provider, and the two do not line up with each other. The dashboard shows each control only where the provider can honour it. ### Stop, start, and restart compared | Action | What happens | Billing | Data on disk | Public IP | | --------- | -------------------------------------- | --------------------------- | ------------ | ------------ | | Stop | GPU is released, instance is preserved | Drops to the stopped rate | Preserved | Retained | | Start | Instance comes back on the same disk | Returns to the running rate | Preserved | Same address | | Restart | Machine reboots in place | Unchanged | Preserved | Same address | | Terminate | Instance and its disk are destroyed | Stops entirely | Lost | Released | Stopping is about money. Restarting is about a machine that needs a reboot. ### Provider support | Provider | Stop and start | Restart | | -------------- | ----------------------------------------- | ------------------------ | | Spheron AI | Yes, depending on machine type and region | Yes | | Spheron ES | Yes | No | | Spheron MS | No | Yes, on virtual machines | | Spheron AM | No | Yes | | Massed Compute | No | Yes | | Verda | No | No | | Sesterce | No | No | Restart is never synthesised from a stop followed by a start. That sequence releases the GPU and carries a completely different risk, so a provider without a real reboot operation does not offer the control at all. :::warning[A provider that cannot stop bills at the full rate] On Verda, Sesterce, Spheron MS, Spheron AM, and Massed Compute an instance keeps billing at the full hourly rate until you destroy it. Shutting the operating system down from inside the machine does not change the bill. Terminate the instance when you are finished with it. ::: #### Machine type and region limits on Spheron AI Spheron AI stops an instance by hibernating it, and hibernation support varies by machine type rather than by GPU model. Roughly half the catalog cannot hibernate, and no spot machine type can. One region refuses to shut instances down at all, even though other regions on the same provider stop normally. The deploy summary and the instance panel name which of the three limits applies, because the remedy differs each time: * **This machine type cannot be stopped.** Pick another machine type from the same provider. * **Instances in this region cannot be stopped.** Pick another region from the same provider. * **This provider does not support stopping.** Pick another provider. Check the note before you commit money to a deployment, not after. #### Instances that never support either action * **Reserved instances.** These are paid for off-app and administered by the Spheron team. Contact support to change one. * **Bare metal instances.** A bare metal server has no hypervisor, so there is nothing to pause or reboot through. ### What a stopped instance costs A stopped instance is billed for its disk, not its GPU. The stopped rate comes from the provider and covers the retained disk plus the public IP where the provider charges for one. Any discount on your account applies exactly as it does while the instance runs. Before you confirm a stop, the dialog quotes both rates, the saving as a percentage, a monthly figure for leaving the instance stopped, and an itemised list of what is still being charged. Stopped rates are shown to four decimal places, because at two decimal places most of them round to $0.00 and read as free. :::warning[A stopped instance is still destroyed at zero balance] A team that runs out of credit has every instance destroyed, stopped ones included. Stopping reduces the burn rate; it does not protect an instance indefinitely. Terminate an instance you have finished with. ::: Charges run on a five minute cycle. Stopping and starting both settle the elapsed time at the outgoing rate first, so a stop landing mid-cycle is not billed at the wrong rate for that slice. Usage figures and invoices pick stopped periods up with no change. ### Starting again depends on stock Some providers release the hardware while an instance is stopped, so a start can be refused while that machine type is out of stock. How likely that is depends on the provider: * **Spheron AI** does not reserve the hardware during hibernation. A start can fail when the machine type is unavailable. * **Spheron ES** keeps your quota occupied while the instance is stopped, so capacity is effectively held. A refused start is not destructive. The instance and its disk stay exactly as they were, and you try again when stock returns. The stop dialog states the risk before you commit. ### Restarting an instance A restart is a hard reboot on every provider that offers it, so anything held in memory is lost. Write checkpoints and flush open files before you restart. The dashboard confirms before it proceeds. Restart is available only on a running instance. Billing does not change, and the instance keeps its status throughout. ### How a stopped instance appears in the dashboard * The status badge is amber, between the running blue and the terminated grey. * The card and the details panel both show the stopped rate, not the running rate. * The public IP stays visible, so you do not have to start an instance to read the address back. * The SSH command is hidden until the instance runs again, because it will not connect otherwise. * Destroy stays available while the instance is stopped. Minimum runtime is judged against time actually spent running, not wall time since deployment. Stopping an instance does not serve out its minimum runtime. See [Minimum runtime before termination](#minimum-runtime-before-termination). ### Minimum runtime before termination An instance must run for a minimum period before you can terminate it manually. The default is **20 minutes**, and two things can change the number that actually applies: * **The machine type.** Some providers hold a machine for a minimum reservation and charge it in full whether or not you use the time. Where a machine type sets such a figure, it applies instead of the default when it is longer. It varies by machine type rather than by provider, so two configurations from the same provider can differ. * **Your account.** Support can set a different minimum for an account, or waive it entirely. The binding number is the larger of the two, and you never have to work it out. The deploy wizard names the provider and shows the figure before you deploy, and that is the same number enforced when you come to terminate. Two rules follow from this: * **Read the figure before deploying a short job.** Terminating early does not reduce a provider minimum, so a job shorter than the minimum costs the minimum. * **Stopping does not serve out the minimum.** It counts time actually spent running, so an instance you stop after 5 minutes still owes the balance in running time before it can be terminated. Through the API, call [can-terminate](/api-reference#check-if-deployment-can-be-terminated) before terminating. Its `minimumRuntime` is the number that applies to that specific deployment, so read it rather than assuming 20. ### Lifecycle through the API All five endpoints authenticate with your API key and act on a deployment you own or that belongs to your team. #### Quote the cost of stopping ```bash curl -X GET "https://app.spheron.ai/api/deployments//pause-quote" \ -H "Authorization: Bearer " ``` ```json { "hourlyRate": 0.0412, "originalHourlyRate": 0.0412, "currentHourlyRate": 2.45, "breakdown": [ { "label": "Root disk (512 GB)", "amount": 0.0362 }, { "label": "Public IP (retained)", "amount": 0.005 } ] } ``` `hourlyRate` is what you pay while stopped, `currentHourlyRate` is what you pay now, and the quote changes nothing on its own. #### Stop, start, and restart ```bash # Stop the instance and drop to the stopped rate curl -X POST "https://app.spheron.ai/api/deployments//pause" \ -H "Authorization: Bearer " # Start it again on the same disk curl -X POST "https://app.spheron.ai/api/deployments//resume" \ -H "Authorization: Bearer " # Reboot in place curl -X POST "https://app.spheron.ai/api/deployments//restart" \ -H "Authorization: Bearer " ``` Each returns the updated deployment object. Asking a provider for an action it cannot perform returns a refusal that names the limit rather than a generic failure. #### Poll a restart in progress ```bash curl -X GET "https://app.spheron.ai/api/deployments//reboot-status" \ -H "Authorization: Bearer " ``` ```json { "restarting": true, "since": "2026-09-08T10:31:04Z" } ``` #### Find stopped instances A stopped instance is part of the live set. `?status=active` includes it alongside running and deploying instances, and `?status=stopped` narrows to the stopped ones. ```bash curl -X GET "https://app.spheron.ai/api/deployments?status=stopped" \ -H "Authorization: Bearer " ``` See the [API reference](/api-reference#instance-lifecycle) for full request and response details. ### Troubleshooting #### Issue: The Stop button is missing **Symptoms**: An instance shows Destroy but no Stop control. **Diagnosis**: The provider, the machine type, or the region cannot stop an instance in a way that reduces the bill. **Resolution**: Read the note in the instance panel. It names which of the three applies. Deploy on Spheron AI or Spheron ES if you need to stop instances, and check the deploy summary before committing. #### Issue: Starting a stopped instance fails **Symptoms**: The start request is refused with a capacity message. **Diagnosis**: The provider released the hardware while the instance was stopped and the machine type is currently out of stock. **Resolution**: Wait and try again. Nothing is lost. Set a stock notification for the machine type, or deploy on Spheron ES, which holds capacity while an instance is stopped. #### Issue: A stop request times out **Symptoms**: The request does not return before the client gives up. **Diagnosis**: Writing a machine's memory to disk routinely outlives the request. A timeout usually means the work was accepted and is still running. **Resolution**: Check the instance status again in a minute. The dashboard reports the settled state once the provider confirms it. #### Issue: An instance was stopped without you asking **Symptoms**: The instance reads as stopped and bills at the stopped rate. **Diagnosis**: The provider parked the machine from its side. **Resolution**: Start it again from the dashboard or the API. You are charged the stopped rate for the period it sat stopped, not the running rate. ### What's next * [Instance types](/concepts/instance-types): Spot, Dedicated, Bare Metal, and CPU Node * [Regions and providers](/concepts/regions-providers): Which provider supports which lifecycle action * [Cost optimization](/cost-optimization): Stop, resize, and reserve to cut spend * [Billing](/billing): How stopped periods appear in usage and invoices * [API reference](/api-reference#instance-lifecycle): Lifecycle endpoint details ## Instance Types Spheron instances are organized along three axes: **compute type**, **interruptibility**, and **hardware isolation**. **Compute type** determines whether the instance carries an accelerator. **GPU instances** are deployed from **Deploy GPUs** and are the subject of most of this page. **CPU nodes** carry no GPU at all and are deployed from their own **Deploy CPU** page, from $0.09 per hour. See [CPU Nodes](/concepts/cpu-nodes) for sizes, regions, and the CPU deploy flow. **Interruptibility** determines whether a running instance can be reclaimed by the provider. **Spot** instances can be interrupted at any time. **Dedicated** instances carry a 99.95% SLA and are not reclaimed after deployment. Both apply to CPU nodes as well as GPU instances. **Hardware isolation** determines how your workload accesses the underlying hardware. Spot always runs in a VM. Dedicated instances come in two sub-types: * **VM**: Isolated virtual machine on shared physical hardware. This is the default for most GPU offers across all providers. * **Bare Metal**: Full access to a physical server with no hypervisor layer. GPU count varies by offer and provider, from single-GPU up to multi-GPU servers. Identified by the `BAREMETAL` suffix in the GPU type name on the dashboard. ### Decision Matrix | Category | Sub-type | Interruption Risk | Hardware | Interconnect | Best For | Relative Price | | ------------- | ---------------------- | ---------------------------------- | ------------------------------------------ | ------------------------------- | ----------------------------------------------------------------------------------------------- | -------------- | | **Spot** | VM | Yes (provider can reclaim anytime) | Shared (VM) | N/A | Experiments, fault-tolerant batch jobs with checkpointing | Lowest | | **Dedicated** | VM | No (99.95% SLA) | Shared (VM) | N/A | Production inference, interactive sessions | Medium | | **Dedicated** | Bare Metal | No (99.95% SLA) | Full physical server (single or multi-GPU) | NVLink / NVSwitch on SXM offers | Workloads requiring no virtualization overhead; multi-GPU distributed training (DDP, DeepSpeed) | Medium-High | | **CPU Node** | VM (Spot or Dedicated) | Spot only | No GPU; from 4 vCPU | N/A | Data prep, build steps, schedulers, API workers, control planes | From $0.09/hr | :::info[Termination Requirements] All instance types, CPU nodes included, enforce a minimum runtime before manual termination is permitted. The default is **20 minutes**, and some machine types carry a longer minimum set by the provider, charged in full even if you terminate early. The deploy wizard shows the figure that applies before you commit. See [Instance lifecycle](/concepts/instance-lifecycle#minimum-runtime-before-termination). Only fully running instances can be terminated manually. Instances in the deploying state cannot be terminated; wait for deployment to complete or fail before attempting termination. Instances in the deploying state do not incur charges; billing begins once the instance is running. Factor in the minimum runtime when calculating costs for short-duration workloads. ::: ### Spot **Spot** instances are VM-based, typically 30 to 60% cheaper than Dedicated. The provider can reclaim them at any time. **When to use Spot:** * Experiments and prototyping * Batch training jobs with checkpointing enabled * Fault-tolerant workloads with checkpointing to a persistent volume **Handling interruption:** Save checkpoints to a persistent volume at regular intervals to resume training if the instance is reclaimed: ```python import torch # Save checkpoint every N steps to a mounted volume if step % checkpoint_interval == 0: torch.save({ 'step': step, 'model_state_dict': model.state_dict(), 'optimizer_state_dict': optimizer.state_dict(), }, '/checkpoints/checkpoint_latest.pt') ``` See the [Volume Mounting guides](/connecting/volume-mounting) to set up a persistent volume at `/checkpoints`. :::warning Do not use **Spot** for production workloads or multi-day training runs that lack checkpointing. ::: ### Dedicated **Dedicated** instances carry a 99.95% SLA and are not reclaimed by the provider after deployment. Two hardware sub-types are available under Dedicated. #### VM **Dedicated VM** is the standard virtualized offering. Your workload runs in an isolated VM on shared physical hardware. This is the most common instance type across providers and covers the majority of GPU offers on the platform. **When to use Dedicated VM:** * Production inference servers * Interactive training sessions * Demos and customer-facing workloads * Any job requiring uninterrupted runtime without needing bare-metal performance #### Bare Metal **Dedicated Bare Metal** gives you full access to a physical server with no hypervisor or VM layer. You get the entire machine, which eliminates virtualization overhead and provides predictable hardware performance. GPU count varies by offer and provider; Bare Metal servers range from single-GPU configurations up to multi-GPU servers. Bare Metal GPU offers display with the `BAREMETAL` suffix in the GPU type name on the dashboard. They appear alongside standard VM offers in the GPU offers list; there is no separate section or tab for them. **When to use Dedicated Bare Metal:** * Workloads sensitive to virtualization overhead * Use cases that require direct hardware access for performance or compliance reasons :::warning[Bare Metal cannot be stopped or restarted] A bare metal server has no hypervisor, so it can be neither stopped nor rebooted through the platform. It bills at the full hourly rate until you terminate it. See [Instance lifecycle](/concepts/instance-lifecycle). ::: ##### On the Dashboard 1. Open the [Spheron dashboard](https://app.spheron.ai) and go to **Deploy GPUs**. 2. Browse the GPU offers list. Look for the `BAREMETAL` suffix in the **GPU Type** field of each offer card. 3. Select the matching offer, complete the deployment form (OS image, SSH key, optional startup script), and deploy. ##### Multi-GPU Bare Metal Multi-GPU Bare Metal offers give a training job every GPU on a single host with no hypervisor layer. On SXM offers, the GPUs are connected by NVLink or NVSwitch, which provides the GPU-to-GPU bandwidth that all-reduce-heavy workloads depend on: | Form factor | Intra-node interconnect | Notes | | ------------------------------------- | ----------------------- | ------------------------------------------------------------------------ | | SXM (B200 SXM6, H200 SXM5, H100 SXM5) | NVLink / NVSwitch | Highest GPU-to-GPU bandwidth; optimal for DDP and DeepSpeed ZeRO-3 | | PCIe (H100 PCIE, A100 PCIE) | PCIe lanes | Lower cost; suitable when gradient synchronization is not the bottleneck | **When to use multi-GPU Bare Metal:** * Large-scale distributed training (PyTorch DDP, DeepSpeed ZeRO-3) * Multi-GPU jobs requiring maximum GPU-to-GPU bandwidth (choose an SXM offer) See the [Distributed Training guide](/quick-guides/training/distributed-training) for setup details. ### CPU Node **CPU Node** is a CPU-only instance with no GPU attached. It is not a variant of a GPU offer: it has its own page in the dashboard sidebar under **Compute**, its own wizard, and no GPU count, cluster networking, or deployment type to choose. Sizes start at 4 vCPU with 4 GB of memory. Verda sells CPU nodes at spot rates as well as on demand; Sesterce, Spheron AI, and Massed Compute offer them on demand only. **When to use CPU Node:** * Data preprocessing, ETL, and dataset sharding * Build steps, CI jobs, and container image builds * Schedulers, queue workers, and cron jobs * API servers and control planes that front a GPU fleet See [CPU Nodes](/concepts/cpu-nodes) for the full size and region matrix, pricing, and the CPU deployment API. ### Silicon vendor The catalog is no longer NVIDIA only. Offers and instance cards carry a vendor mark so you can tell at a glance what you are renting: | Vendor | Parts on the platform | Compute stack | | ------ | ---------------------------------------------------- | ---------------------------- | | NVIDIA | B300, B200, H200, H100, A100, L40S, RTX, V100, GH200 | CUDA | | AMD | Instinct MI300X (Spheron AM) | [ROCm](/connecting/rocm-amd) | | Intel | Gaudi2 (Sesterce, Spheron MS) | oneAPI / SynapseAI | An AMD or Intel instance needs a different software stack from an NVIDIA one. `nvidia-smi` and CUDA-only wheels do not work on them. Read [ROCm and AMD Instinct](/connecting/rocm-amd) before deploying an MI300X. ### Stopping and restarting by instance type What an instance can do after it is running depends on its type as well as its provider: | Instance type | Stop and start | Restart | | -------------------- | ------------------------------- | ------------------ | | Spot | No | Provider-dependent | | Dedicated VM | Provider-dependent | Provider-dependent | | Dedicated Bare Metal | No | No | | CPU Node | Provider-dependent | Provider-dependent | | Reserved | No, managed by the Spheron team | No | Spot machine types cannot be stopped, because the hardware is not held for you in the first place. See [Instance lifecycle](/concepts/instance-lifecycle) for the per-provider matrix and the billing rules. ### Selecting Instance Type via Dashboard When deploying from the [Spheron dashboard](https://app.spheron.ai): 1. Go to **Deploy GPUs** and browse the GPU offers list. 2. Each offer card shows the GPU model, vCPUs, RAM, storage, and price. 3. Identify the offering type by the offer details: * **Spot**: labeled as interruptible; typically shows a spot price alongside the regular price. * **Dedicated VM**: standard VM price with no interruption risk; the most common offering across providers. * **Dedicated Bare Metal**: identified by `BAREMETAL` in the GPU type name on the dashboard (e.g., `H100_SXM5_BAREMETAL`). For distributed training, check the GPU count on the offer card and prefer an SXM form factor. 4. Select the offer that matches your workload requirements and click **Deploy**. :::tip See the [Decision Matrix](#decision-matrix) above before browsing offers. ::: ### What's next * [CPU Nodes](/concepts/cpu-nodes): CPU-only instances for work that never touches a GPU * [Distributed Training guide](/quick-guides/training/distributed-training): Multi-GPU bare-metal setup * [Regions and Providers](/concepts/regions-providers): GPU tiers and capabilities per provider * [Volume Mounting](/connecting/volume-mounting): Persistent storage for checkpoints * [Instance Lifecycle](/concepts/instance-lifecycle): Stop, start, and restart support by type and provider * [ROCm and AMD Instinct](/connecting/rocm-amd): Running workloads on AMD MI300X GPUs * [Cost Optimization](/cost-optimization): Choosing the right instance type for your budget * [API Reference](/api-reference#get-gpu-offers): Filter GPU offers by instance type programmatically ## Networking ### Dedicated Public IP Every Spheron GPU instance receives a **dedicated public IP address** when deployed. There is no shared IP, NAT, or port forwarding. Each instance has its own routable IP for the lifetime of the deployment. When a deployment reaches `running` status, the IP address and SSH connection command are shown in the instance details panel in the dashboard. :::info[Provider differences] The SSH username may vary by provider. All providers assign a dedicated public IP with standard SSH on port 22. Use the SSH command shown in the instance details panel in the dashboard: * **Spheron AI**: `ssh ubuntu@`, port 22 * **Sesterce / Verda / Massed Compute**: `ssh @`, port 22 ::: ### SSH Access ```bash # Use the SSH command from the instance details panel in the dashboard ssh ubuntu@198.51.100.42 # Or with an explicit key ssh -i ~/.ssh/id_ed25519 ubuntu@198.51.100.42 ``` See [SSH Connection](/connecting/ssh-connection) for key setup and troubleshooting. ### Port Access All ports on your instance are open by default via its dedicated public IP. You can reach any service directly without any firewall configuration: ```bash curl http://198.51.100.42:8000/v1/completions ``` :::warning[Security] Because all ports are open by default, **do not expose inference servers, Jupyter notebooks, or other unauthenticated services publicly without adding authentication**. Use SSH tunneling for development (see below). If you must expose a service publicly, add token-based authentication before doing so. To restrict access, you can close specific ports using `ufw` in your startup script or after connecting: ```bash # Allow only SSH and close everything else ufw default deny incoming ufw allow 22/tcp ufw enable ``` ::: ### SSH Tunneling SSH tunneling forwards remote ports to your local machine without opening firewall rules or exposing services publicly. Forward a remote port to your local machine: ```bash # Forward port 8888 (Jupyter) to localhost ssh -L 8888:localhost:8888 ubuntu@ # Forward multiple ports at once ssh -L 8888:localhost:8888 -L 8000:localhost:8000 ubuntu@ ``` Then open `http://localhost:8888` in your browser. ### VS Code Port Forwarding If you use [VS Code Remote SSH](/connecting/vscode-remote), the **Ports** tab in VS Code lets you forward ports visually without typing SSH tunnel commands. Use this to forward Jupyter (8888) and TensorBoard (6006). ### What's next * [SSH Connection](/connecting/ssh-connection): Key setup and connection troubleshooting * [VS Code Remote](/connecting/vscode-remote): Remote development and port forwarding panel * [Security Best Practices](/security): Secure your instances and data * [Startup Script](/connecting): Cloud-init examples including firewall configuration * [API Reference](/api-reference#deployments): Retrieve IP address and SSH connection details programmatically ## Regions & Providers Spheron sources GPU and CPU capacity from seven providers across North America, Europe, the Middle East, and Asia Pacific. Most GPUs are NVIDIA; Spheron AM supplies AMD Instinct, and Intel Gaudi2 is available through Sesterce and Spheron MS. GPU inventory changes as providers add and withdraw hardware. The tables below list representative capacity; check the [GPU catalog](https://app.spheron.ai) for live availability and pricing. ### Provider Capabilities | Provider | Instance Types | CPU Node | Volume Support | GPU Tiers | Regions | | -------------- | ----------------------------- | ------------------------ | ------------------------------------------------------- | ----------------------------------------------------------------------------------------------------------------------------------------------------------------------- | ----------------------------------------------------------------------------------------------------------- | | Verda | Spot, Dedicated | Yes (Spot and Dedicated) | NFS volumes (up to 10 TB, multi-instance) | B300 SXM6, A100 80GB SXM4, RTX Pro 6000, A6000, V100 | EU (Finland 1, Finland 2, Finland 3) | | Sesterce | Dedicated | Yes (Dedicated) | Block volumes (one per instance, bound at launch) | B300 SXM6, H200 SXM5, H100 (SXM5/PCIe), GH200, Gaudi2, A100 80GB (SXM4/PCIe), L40S, L40, RTX 5090, RTX 4090, RTX Pro 6000, A6000, A5000, A4000, A40, A16, A10, L4, V100 | North America, EU, India, Japan, Singapore, Australia | | Spheron AI | Spot, Dedicated | Yes (Dedicated) | Block volumes (up to 50 TB, up to 10 per instance) | H100 (NVL/PCIe), A100 80GB (NVL/PCIe/SXM4), L40, RTX 4090 | Canada 1, Montreal 1, Norway 1, Oslo 1, US (Tier 3 DC) | | Spheron ES | Spot, Dedicated | No | virtiofs shared volumes (up to 256 TiB, multi-instance) | B300 SXM6, B200 SXM6, H200 SXM5, H100 SXM5, L40S, RTX Pro 6000 | EU North 1 (Finland), EU West 1 (France), UK South 1, ME West 1 (Middle East), US Central 1 (US); Tier 3 DC | | Spheron MS | Dedicated (VM and bare metal) | No | Block volumes (one per instance, bound at launch) | H200 SXM5, H100 (SXM5/PCIe), A100 80GB (SXM4/PCIe), A100 40GB (SXM4/PCIe), RTX Pro 6000, RTX 5090, RTX 4090, L40S, L4, Gaudi2, A6000, A5000, A4000, A16, A10, V100 | US, Canada, Norway, Poland, Israel, India, Japan, Singapore, Australia | | Spheron AM | Dedicated | No | No | AMD Instinct MI300X (192 GB HBM3e), in 1x, 2x, and 4x | Michigan 1 (US) | | Massed Compute | Dedicated | Yes (Dedicated) | No | H100 PCIe, A100 80GB PCIe, L40S, L40, RTX 6000 Ada, RTX Pro 6000, A6000, A30 | US regions (us-central, us-east) | ### Instance Lifecycle Support Stopping an instance keeps its disk while the GPU stops billing. Restarting reboots it in place. Neither is available on every provider, and the two do not line up with each other. | Provider | Stop and start | Restart | | -------------- | ----------------------------------------- | ------------------------ | | Spheron AI | Yes, depending on machine type and region | Yes | | Spheron ES | Yes | No | | Spheron MS | No | Yes, on virtual machines | | Spheron AM | No | Yes | | Massed Compute | No | Yes | | Verda | No | No | | Sesterce | No | No | On a provider that cannot stop an instance, the instance bills at the full hourly rate until you destroy it. Some machine types also carry a provider minimum runtime longer than the 20 minute default, charged in full even if you terminate early; the deploy wizard shows the figure before you commit. See [Instance lifecycle](/concepts/instance-lifecycle) for stopped rates, capacity risk on start, and the API endpoints. ### Provider Details #### Verda Verda operates in EU regions across three Finland data centers: `Finland 1`, `Finland 2`, and `Finland 3`. It provides both Spot and Dedicated instances with NFS volume support. **CPU Node**: Verda is the only provider offering CPU nodes at spot rates, from $0.09/hr. Sizes run 4 vCPU / 16 GB, 8 vCPU / 32 GB, 16 vCPU / 64 GB, and 32 vCPU / 128 GB. See [CPU Nodes](/concepts/cpu-nodes). Verda volumes (`NVMe_Shared` NFS type) support **multi-instance attachment**: a single volume can be mounted on multiple GPU instances simultaneously. Each instance supports at most one shared volume. **Local storage for Dedicated instances**: When deploying a Verda Dedicated instance you choose between two root-disk sizes: **500 GB** (default) or **1 TB**. Select 1 TB when your workload requires more local dataset or checkpoint space than the default provides. :::warning[Volume Region Constraint] Verda volume multi-attach only works within the same datacenter region. A volume created in `Finland 1` cannot be mounted on an instance in `Finland 2` or `Finland 3`. Cross-region mounting fails silently; always deploy your instance and volume in the same region. ::: #### Sesterce Sesterce provides Dedicated GPU instances across North America, Europe, India, Japan, Singapore, and Australia (GDPR, SOC 2 Type II, ISO 27001 certified). Inventory spans B300 SXM6 and H200 SXM5 at the high end down to L4 and A10 for inference. Sesterce volumes attach as raw block devices formatted with ext4. A volume binds at instance creation and cannot be attached or detached afterwards, and each instance takes a single volume. See the [Sesterce volume mounting guide](/connecting/volume-mounting/sesterce). **CPU Node**: Sesterce offers Dedicated CPU nodes across the widest region choice of any provider, from 4 vCPU / 4 GB up to 32 vCPU / 128 GB, in Europe (Helsinki, Frankfurt, Oslo, London), North America (Ashburn, Dallas, Des Moines, Houston, Kansas City, Calgary, Montreal), and Tokyo. #### Spheron AI Spheron AI provides on-demand and spot GPU instances across North America and Europe, sourced from Tier 3 data centers. Current inventory includes H100 (NVL/PCIe), A100 80GB (NVL/PCIe/SXM4), L40, and RTX 4090 across **Canada 1**, **Montreal 1**, **Norway 1**, **Oslo 1**, and the United States. Stock rotates; check the catalog for what is deployable right now. Startup scripts (cloud-init) are fully supported. Spheron AI volumes are block-device backed and can be created up to **50 TB** per volume in the new regions, with up to 10 volumes attached to a single instance. See the [Spheron AI volume mounting guide](/connecting/volume-mounting/spheron-ai) for setup. The size slider in the create-volume wizard adapts to the per-region storage ceiling. **OS images**: 11 OS images are available, including Ubuntu 22.04/24.04, AlmaLinux 9, Debian 12, and CUDA-enabled variants (R535, R550, R570). The default is Ubuntu Server 22.04 LTS with CUDA 12.8 and Docker pre-installed. **SSH access**: Port 22 opens automatically on every new Spheron AI instance; no firewall configuration is needed for SSH. **CPU Node**: Spheron AI offers Dedicated CPU nodes from 4 vCPU / 4 GB up to 32 vCPU / 64 GB in **Norway 1** and **Canada 1**. #### Spheron ES Spheron ES (Extra Supply) provides on-demand and spot GPU instances across five regions: **EU North 1** (Finland), **EU West 1** (France), **UK South 1** (United Kingdom), **ME West 1** (Middle East), and **US Central 1** (United States). Inventory currently spans B300 SXM6, B200 SXM6, H200 SXM5, H100 SXM5, L40S, and RTX Pro 6000, all flagged with the Tier 3 DC compliance badge. Spheron ES does not offer CPU nodes. Deploy CPU work on Verda, Sesterce, Spheron AI, or Massed Compute. Shared volumes use the virtiofs protocol and support multi-instance attach, in-place resize, and up to **256 TiB** per volume. See the [Spheron ES volume mounting guide](/connecting/volume-mounting/spheron-es) for setup. #### Spheron MS Spheron MS (Multi Supply) provides Dedicated GPU instances across a wider geographic footprint than any other provider on the platform: the United States (Austin, Ashburn, Chicago, Culpeper, Dallas, Dulles, Houston, New York, Phoenix, Salt Lake City, San Jose), Canada (Calgary), Norway (Oslo), Poland (Warsaw), Israel (Jerusalem), India (Mumbai), Japan (Tokyo), Singapore, and Australia (Sydney). Inventory runs from H200 SXM5 and H100 SXM5 at the high end down to L4 and A10 for inference, and includes Gaudi2. Each offer names its region, and the region on the offer is the region you deploy into. A machine that is out of stock shows as sold out rather than disappearing, so you can set a stock notification instead of wondering where a GPU went. **Instance types**: Dedicated only. Spheron MS does not offer spot pricing. Where an offer is a full physical server it is listed as bare metal and labelled on the card. See [Instance types](/concepts/instance-types). **Volumes**: A Spheron MS volume is selected during deployment and only then. There is no attach or detach for an instance that is already running, each instance takes one volume, and the volume must be in the same region as the instance. Size and name are fixed at creation. See the [Spheron MS volume mounting guide](/connecting/volume-mounting/spheron-ms). **Boot disk**: Each machine type ships a fixed boot disk, so its size appears on the offer rather than being something you set. Pick a machine type with the disk you need, or attach a volume for the rest. **Lifecycle**: Spheron MS cannot stop an instance, so an instance bills at the full hourly rate until you destroy it. Restart is available on virtual machines and reboots in place without changing billing. Bare metal instances support neither. **OS images**: Ubuntu 20.04, 22.04, and 24.04, with CUDA 12.0, 12.2, 12.4, 12.8, and 13.0 variants. Startup scripts (cloud-init) are supported on every offer. **CPU Node**: Spheron MS does not offer CPU nodes. Deploy CPU work on Verda, Sesterce, Spheron AI, or Massed Compute. #### Spheron AM Spheron AM supplies **AMD Instinct MI300X**, the first non-NVIDIA silicon on the platform. Each GPU carries 192 GB of HBM3e, and the catalog publishes 1x, 2x, and 4x GPU configurations from a single region, **Michigan 1** in the United States. The 192 GB per GPU is the reason to choose it: a model that needs several 80 GB NVIDIA cards to hold its weights can fit on fewer MI300X GPUs, which changes how you shard it. **Compute stack**: These machines run ROCm, not CUDA. Most PyTorch and TensorFlow code runs unchanged, but `nvidia-smi` does not exist and CUDA-only wheels and Docker images do not work. See [ROCm and AMD Instinct](/connecting/rocm-amd) before you deploy. **Instance types**: Dedicated only. Spheron AM has no spot option. **OS images**: One image, Ubuntu with ROCm plus Docker or Podman. There is no image picker, because the machine type determines what it boots. Startup scripts (cloud-init) are supported. **Boot disk**: Fixed by the machine type, so its size appears on the offer rather than being something you set. **Volumes**: Not available. A deployment that asks for a volume is refused rather than created without it. Keep anything that must survive termination off the instance. **Lifecycle**: Restart reboots in place. Stopping is not available, so an instance bills at the full hourly rate until it is destroyed. Terminate an instance you have finished with. **Minimum runtime**: Each machine type carries its own minimum reservation, which can exceed the 20 minute default and is charged in full even if you terminate early. The deploy wizard shows the figure before you commit. **CPU Node**: Spheron AM does not offer CPU nodes. #### Massed Compute Massed Compute provides Dedicated GPU instances in US regions (`us-central-1` through `us-central-9` and `us-east-1`) with H100 PCIe, A100 80GB PCIe, L40S, L40, RTX 6000 Ada, RTX Pro 6000, A6000, and A30 configurations. Massed Compute does not support volume mounting. **CPU Node**: Massed Compute offers Dedicated CPU nodes at 8 vCPU / 32 GB, 14 vCPU / 40 GB, 28 vCPU / 80 GB, and 52 vCPU / 160 GB, from $0.12/hr, in us-central-2, us-central-3, and us-east-5. See [CPU Nodes](/concepts/cpu-nodes). Compliance certifications: HIPAA, SOC 2 Type II. ### Region Selection Guidance * **Lowest SSH latency:** Choose the provider and region geographically closest to you * **GDPR / EU data requirements:** Use Verda (Finland, ISO 27001) or Sesterce (EU regions) * **Asia Pacific presence:** Sesterce or Spheron MS (India, Japan, Singapore, Australia) * **H200 SXM5:** Spheron ES (EU North 1, EU West 1, UK South 1, ME West 1, US Central 1), Sesterce, or Spheron MS * **B300 SXM6:** Spheron ES, Verda, or Sesterce * **B200 SXM6:** Spheron ES (EU North 1, EU West 1, UK South 1, ME West 1, US Central 1) * **Multi-GPU bare-metal training:** Spheron ES (B300 SXM6, B200 SXM6, H200 SXM5, H100 SXM5) or Sesterce (H100 SXM5, RTX Pro 6000 Bare Metal) * **CPU-only workloads:** Verda (Finland, spot and dedicated), Sesterce (widest region choice), Spheron AI (Norway 1, Canada 1), or Massed Compute (US) * **Shared persistent volumes:** Verda (multi-instance NFS attach within the same region) or Spheron ES (multi-instance virtiofs, up to 256 TiB per volume) * **Largest block volumes:** Spheron AI (up to 50 TB per volume, up to 10 volumes per instance) * **Widest choice of cities:** Spheron MS, which lists GPUs in 19 locations across nine countries * **AMD Instinct MI300X, or the most GPU memory per card:** Spheron AM (192 GB HBM3e per GPU, Michigan 1); see [ROCm and AMD Instinct](/connecting/rocm-amd) * **Intel Gaudi2:** Sesterce or Spheron MS * **Stopping an instance to pause GPU billing:** Spheron AI or Spheron ES; see [Instance lifecycle](/concepts/instance-lifecycle) * **Reserved GPU requests:** Select "Any Location" when submitting reserved GPU requests to maximize provider competition and get the best price ### What's next * [API Reference](/api-reference#get-providers): Query available providers and GPU offers programmatically * [Instance Types](/concepts/instance-types): Spot vs Dedicated, and hardware isolation categories * [CPU Nodes](/concepts/cpu-nodes): CPU-only instances, sizes, and regions * [Distributed Training](/quick-guides/training/distributed-training): Multi-GPU bare-metal setup * [Instance Lifecycle](/concepts/instance-lifecycle): Stop, start, and restart support by provider * [ROCm and AMD Instinct](/connecting/rocm-amd): Running workloads on MI300X * [Volume Mounting](/connecting/volume-mounting): Shared storage for Verda, Sesterce, Spheron AI, Spheron ES, and Spheron MS * [Reserved GPUs](/reserved-gpus): Long-term GPU reservations ## Teams Teams let multiple users share a GPU credit pool, SSH keys, volumes, and deployments under a single account. ### Creating a Team 1. Go to [app.spheron.ai](https://app.spheron.ai) → **Settings** 2. Navigate to the **Teams** section 3. Click **Create Team** and enter a name 4. Invite members by email; Spheron sends them an invitation link ### Roles | Role | Permissions | | ---------- | ---------------------------------------------------------------------------------------- | | **Owner** | Full control: manage members, billing, and all resources | | **Admin** | Deploy instances, manage SSH keys and volumes, manage billing (saved cards, auto top-up) | | **Member** | Read-only or deploy-only depending on team configuration | ### Team Resources Resources created within a team context are shared across all team members. SSH keys, volumes, and deployments created under a team are visible to everyone on the team. * **SSH keys** added under a team are available to all members when deploying instances * **Volumes** created under a team are accessible to all members * **Deployments** launched under a team are visible to all members and billed from the shared credit pool For programmatic deployment and resource management with team scoping, see the [API Reference](/api-reference). ### Auto Top-Up Auto top-up charges your saved card when your team balance drops below a configured threshold, keeping deployments from stopping due to insufficient credits. **Configuration (Owner / Admin only)**: 1. Go to **Settings → Billing** on [app.spheron.ai](https://app.spheron.ai) 2. Add a payment card via Stripe's hosted setup flow 3. Enable auto top-up and set your **threshold** (the balance level that triggers a charge, min $5 to max $500) and **top-up amount** (min $15 to max $5,000) After each credit deduction cycle, Spheron checks your balance. If it falls below the threshold, Spheron charges your card and adds credits immediately. A 5-minute cooldown prevents double-charging. :::info If a charge fails (e.g. card declined), auto top-up is automatically disabled and a notification email is sent. Re-enable it from the billing page after updating your payment method. ::: ### Viewing Balances View credit balances for all teams from the **Billing** page in the dashboard. Each team's balance is shown separately under its name. ### API Access API key generation is controlled through a whitelist. If you cannot create an API key in **Settings → API Keys**, contact Spheron support to request access. Once approved, your whitelist status is visible in the settings interface. A single API key can be used to interact with multiple teams. See the [API Reference](/api-reference) for full details. ### What's next * [API Reference](/api-reference): Full API documentation including team-scoped endpoints * [Billing](/billing): Team credit pools and discount information * [SSH Connection](/connecting/ssh-connection): Key setup and management * [Cost Optimization](/cost-optimization): Team discount program