# Quick Start: Rent Your First GPU

## What We're Building

A Python script that finds an available GPU server, rents it, connects via SSH, runs a CUDA test, and releases the resources — all in under 5 minutes.

## Prerequisites

* Clore.ai account with API key ([get one here](https://clore.ai))
* Python 3.10+
* `requests` library (`pip install requests`)
* SSH client

## Step 1: Set Up the Clore Client

> 📦 **Using the standard Clore API client.** See [Clore API Client Reference](https://docs.clore.ai/dev/reference/clore-client) for the full implementation and setup instructions. Save it as `clore_client.py` in your project.

```python
from clore_client import CloreClient

client = CloreClient(api_key="your-api-key")
```

## Step 2: Find an Available GPU

```python
# find_gpu.py
from clore_client import CloreClient

def find_cheapest_gpu(client: CloreClient, gpu_type: str = "RTX 4090", 
                       max_price_usd: float = 0.50) -> dict:
    """Find the cheapest available GPU of specified type."""
    
    servers = client.get_marketplace()
    
    # Filter: available, matches GPU type, within price range
    candidates = []
    for server in servers:
        if server.get("rented"):
            continue
        
        gpu_array = server.get("gpu_array", [])
        if not any(gpu_type in gpu for gpu in gpu_array):
            continue
        
        # Get USD price (on-demand)
        price_usd = server.get("price", {}).get("usd", {}).get("on_demand_clore")
        if price_usd and price_usd <= max_price_usd:
            candidates.append({
                "id": server["id"],
                "gpus": gpu_array,
                "price_usd": price_usd,
                "reliability": server.get("reliability", 0),
                "specs": server.get("specs", {})
            })
    
    if not candidates:
        raise Exception(f"No {gpu_type} available under ${max_price_usd}/hr")
    
    # Sort by price, then reliability
    candidates.sort(key=lambda x: (x["price_usd"], -x["reliability"]))
    
    return candidates[0]

if __name__ == "__main__":
    client = CloreClient("YOUR_API_KEY")
    
    gpu = find_cheapest_gpu(client, "RTX 4090", max_price_usd=0.50)
    print(f"Found: Server {gpu['id']}")
    print(f"GPUs: {gpu['gpus']}")
    print(f"Price: ${gpu['price_usd']:.2f}/hr")
    print(f"Reliability: {gpu['reliability']}%")
```

## Step 3: Rent the GPU

```python
# rent_gpu.py
import time
from clore_client import CloreClient
from find_gpu import find_cheapest_gpu

def rent_gpu(client: CloreClient, server_id: int, ssh_password: str) -> dict:
    """Rent a GPU server and wait for it to be ready."""
    
    print(f"Creating order for server {server_id}...")
    
    order = client.create_order(
        server_id=server_id,
        image="nvidia/cuda:12.8.0-base-ubuntu22.04",
        order_type="on-demand",
        currency="CLORE-Blockchain",
        ssh_password=ssh_password,
        ports={"22": "tcp", "8888": "http"},
        env={"NVIDIA_VISIBLE_DEVICES": "all"}
    )
    
    order_id = order["order_id"]
    print(f"Order created: {order_id}")
    
    # Wait for order to become active
    print("Waiting for server to start...")
    for _ in range(60):  # Max 2 minutes
        orders = client.get_orders()
        current = next((o for o in orders if o["order_id"] == order_id), None)
        
        if current and current.get("status") == "running":
            return current
        
        time.sleep(2)
    
    raise Exception("Timeout waiting for server to start")

if __name__ == "__main__":
    client = CloreClient("YOUR_API_KEY")
    
    # Find cheapest RTX 4090
    gpu = find_cheapest_gpu(client, "RTX 4090", max_price_usd=0.50)
    print(f"Selected server {gpu['id']} at ${gpu['price_usd']:.2f}/hr")
    
    # Rent it
    order = rent_gpu(client, gpu["id"], ssh_password="MySecurePass123!")
    
    print("\n✅ Server is ready!")
    print(f"SSH: {order['connection']['ssh']}")
    print(f"Order ID: {order['order_id']}")
```

## Step 4: Connect and Run CUDA Test

```python
# test_gpu.py
import subprocess
import sys

def run_cuda_test(ssh_host: str, ssh_port: int, password: str):
    """Connect via SSH and run nvidia-smi."""
    
    # Using sshpass for password auth (install: apt install sshpass)
    ssh_cmd = f"""sshpass -p '{password}' ssh -o StrictHostKeyChecking=no \
        -p {ssh_port} root@{ssh_host} \
        'nvidia-smi && python3 -c "import torch; print(f\"CUDA available: {torch.cuda.is_available()}\")"'
    """
    
    print("Connecting and testing GPU...")
    result = subprocess.run(ssh_cmd, shell=True, capture_output=True, text=True)
    
    if result.returncode == 0:
        print(result.stdout)
    else:
        print(f"Error: {result.stderr}")
        
if __name__ == "__main__":
    # Parse SSH connection string like "ssh root@host -p 12345"
    # From order["connection"]["ssh"]
    ssh_host = sys.argv[1] if len(sys.argv) > 1 else "example.clore.ai"
    ssh_port = int(sys.argv[2]) if len(sys.argv) > 2 else 22
    password = sys.argv[3] if len(sys.argv) > 3 else "MySecurePass123!"
    
    run_cuda_test(ssh_host, ssh_port, password)
```

## Step 5: Clean Up

```python
# cleanup.py
from clore_client import CloreClient

def cleanup_order(client: CloreClient, order_id: int):
    """Cancel order and show final cost."""
    
    # Get order details before canceling
    orders = client.get_orders()
    order = next((o for o in orders if o["order_id"] == order_id), None)
    
    if not order:
        print(f"Order {order_id} not found")
        return
    
    # Calculate duration
    duration_minutes = (order.get("ended", 0) - order.get("started", 0)) / 60
    if duration_minutes <= 0:
        import time
        duration_minutes = (time.time() - order.get("started", 0)) / 60
    
    # Cancel
    client.cancel_order(order_id)
    print(f"✅ Order {order_id} cancelled")
    print(f"Duration: {duration_minutes:.1f} minutes")
    print(f"Estimated cost: ~${order.get('price', 0) * duration_minutes / 60:.4f}")

if __name__ == "__main__":
    import sys
    client = CloreClient("YOUR_API_KEY")
    order_id = int(sys.argv[1]) if len(sys.argv) > 1 else 12345
    cleanup_order(client, order_id)
```

## Full Script: End-to-End GPU Rental

```python
#!/usr/bin/env python3
"""
Complete GPU rental workflow: Find → Rent → Test → Cleanup
Usage: python quick_start.py YOUR_API_KEY
"""

import requests
import time
import subprocess
import sys
from typing import Optional, Dict, Any, List

def find_cheapest_gpu(client: CloreClient, gpu_type: str = "RTX", 
                       max_price_usd: float = 1.0) -> dict:
    """Find cheapest available GPU."""
    servers = client.get_marketplace()
    
    candidates = []
    for s in servers:
        if s.get("rented"):
            continue
        gpus = s.get("gpu_array", [])
        if not any(gpu_type in g for g in gpus):
            continue
        price = s.get("price", {}).get("usd", {}).get("on_demand_clore")
        if price and price <= max_price_usd:
            candidates.append({"id": s["id"], "gpus": gpus, "price": price})
    
    if not candidates:
        raise Exception(f"No {gpu_type} GPU under ${max_price_usd}/hr")
    
    return min(candidates, key=lambda x: x["price"])

def wait_for_ready(client: CloreClient, order_id: int, timeout: int = 120) -> dict:
    """Wait for order to become active."""
    for _ in range(timeout // 2):
        orders = client.get_orders()
        order = next((o for o in orders if o["order_id"] == order_id), None)
        if order and order.get("status") == "running":
            return order
        time.sleep(2)
    raise Exception("Timeout waiting for server")

def main():
    if len(sys.argv) < 2:
        print("Usage: python quick_start.py YOUR_API_KEY")
        sys.exit(1)
    
    api_key = sys.argv[1]
    ssh_password = "CloreQuickStart123!"
    
    client = CloreClient(api_key)
    
    # Check balance
    print("💰 Checking balance...")
    wallets = client.get_wallets()
    clore_balance = next((w["balance"] for w in wallets if "CLORE" in w["name"]), 0)
    print(f"   CLORE balance: {clore_balance:.2f}")
    
    if clore_balance < 5:
        print("❌ Insufficient balance (need at least 5 CLORE)")
        sys.exit(1)
    
    # Find GPU
    print("\n🔍 Finding cheapest GPU...")
    try:
        gpu = find_cheapest_gpu(client, "RTX", max_price_usd=0.80)
    except Exception as e:
        gpu = find_cheapest_gpu(client, "GTX", max_price_usd=0.50)
    
    print(f"   Found: Server {gpu['id']}")
    print(f"   GPUs: {', '.join(gpu['gpus'])}")
    print(f"   Price: ${gpu['price']:.2f}/hr")
    
    # Rent
    print("\n🚀 Creating rental order...")
    order = client.create_order(
        gpu["id"],
        ssh_password=ssh_password,
        ports={"22": "tcp"}
    )
    order_id = order["order_id"]
    print(f"   Order ID: {order_id}")
    
    # Wait
    print("\n⏳ Waiting for server to start...")
    active_order = wait_for_ready(client, order_id)
    
    ssh_info = active_order["connection"]["ssh"]
    print(f"\n✅ Server ready!")
    print(f"   SSH: {ssh_info}")
    print(f"   Password: {ssh_password}")
    
    # Quick test
    print("\n🧪 Running GPU test...")
    print("   (Connect manually and run: nvidia-smi)")
    
    # Prompt for cleanup
    input("\n⏸️  Press Enter to cancel order and clean up...")
    
    # Cleanup
    print("\n🧹 Cancelling order...")
    client.cancel_order(order_id)
    print("   Done!")
    
    # Final stats
    duration = (time.time() - active_order.get("started", time.time())) / 60
    cost = gpu["price"] * duration / 60
    print(f"\n📊 Summary:")
    print(f"   Duration: {duration:.1f} minutes")
    print(f"   Estimated cost: ${cost:.4f}")

if __name__ == "__main__":
    main()
```

## Running the Script

```bash
# Install dependencies
pip install requests

# Run
python quick_start.py YOUR_API_KEY

## Cost Comparison

| GPU | Clore.ai | AWS | Savings |
|-----|----------|-----|---------|
| RTX 4090 | ~$0.35/hr | N/A | ∞ |
| A100 40GB | ~$1.50/hr | ~$4.10/hr | 63% |
| RTX 3090 | ~$0.20/hr | N/A | ∞ |

> 💡 For a full breakdown of GPU cloud pricing across providers, see [Cheapest GPU Cloud in 2026: Clore.ai vs Vast.ai vs RunPod](https://blog.clore.ai/cheapest-gpu-cloud-in-2026-cloreai-vs-vastai-vs-runpod-honest-comparison/)

## Next Steps

- [Setting Up Your Development Environment](dev-environment.md)
- [Automating GPU Rental with Python](automation-basics.md)
- [Understanding Spot vs On-Demand](spot-vs-ondemand.md)
```
