Docs › Machines in the cloud, only while they work
Machines in the cloud, only while they work
Beta. Cloud machines work and are part of the licence, but they are newer than the core and may change between versions. They need an account and a credential at the provider, which bills you directly (see Requirements).
A GPU with 24 GB in the cloud makes an AI clip in 1 to 3 minutes that a home card with 8 GB takes 5 to 15 minutes over, and a 16-core cloud machine runs a test suite that would keep a laptop busy. Kept on all day a cloud machine costs more than it's worth; started only when a job needs it and stopped after a short idle time, it costs cents per video or test run, and while it is stopped only its disk is paid for.
With only one Mac and no second machine, start with the quick way: one command or four short steps in the dashboard, and a machine for builds and tests is yours by the minute, with a spend limit.
Sparehand makes such machines at four providers, with or without a GPU, from the dashboard (Add a machine → Cloud provider) or with sparehand cloud add. To Sparehand a cloud machine is a worker like any other, with a file that says where it lives and what it costs:
| Runpod | AWS | Azure | Google Cloud | |
|---|---|---|---|---|
| Made by | Sparehand, through the API | Sparehand, through the API | Sparehand, through the API | Sparehand, through the Compute Engine API (or by hand with gcloud, under a disclosure) |
| The picker shows | Every GPU on Secure Cloud and every CPU flavour, with stock per data centre | Every instance type the region offers (hundreds), with on-demand and Spot prices | Every VM size the subscription may use in the region, with retail and Spot prices | Every machine type in the project's zones (e2, n2, c2d, c3, n1 with a T4, g2 with an L4, a2 with an A100…) |
| Recommended | RTX A5000 24 GB (~$0.27/h), L4, 4090 | g4dn (T4), g5 (A10G), g6 (L4, ~$0.81/h); c6i, c7i | NC4as T4 v3 (~$0.53/h), NC24ads A100 v4; D4s–D16s v5 | g2-standard-4 (L4, ~$0.71/h), n1-standard-4 + T4, a2-highgpu-1g; e2, n2, c2d, c3 |
| Spot | No (Secure Cloud on-demand pods) | Yes: stopped, never deleted, when taken back | Yes: deallocated when taken back | Yes: stopped when taken back |
| Stopped costs | The volume: $0.07 a GB a month ($0.14 in data centres with only the high-performance tier) | The disk: about $0.08 a GB a month | The disk (about $0.075 a GB a month) and a static address (about $3.65 a month) | The disk: about $12 a month for 150 GB |
| Stops itself when idle | No: the hub stops it | Yes (a timer on the VM); the hub is the safety net | Yes; the hub is the safety net | Yes; the hub is the safety net |
| Credential | An API key | An access key (id and secret) | A service principal (or the az CLI's login) | A service account's JSON key (or gcloud's login) |
| Prerequisites | A few dollars of credit | GPU quota (starts at 0); Spot capacity isn't promised | GPU quota (starts at 0); a pay-as-you-go subscription | Billing enabled (a trial can't have a GPU), GPU quota (starts at 0): the picker checks both first |
Prices are the providers' list prices read on 20 October 2026; the picker and sparehand cloud catalog show today's: Runpod's catalog, AWS's price list and Spot history and Azure's retail price list are read live; Google's are list prices for us-central1 (other regions differ a little).
sparehand cloud key runpod # the API key, into this Mac's Keychain (asked in the terminal)
sparehand cloud catalog runpod # the machines offered: price an hour, Spot price, stock per region
sparehand cloud add gpu --runpod --machine "NVIDIA RTX A5000" --disk 80 --idle 15
sparehand cloud add build --aws --machine c6i.2xlarge --region eu-west-1 --spot --studio auto
sparehand cloud add t4 --azure --machine Standard_NC4as_T4_v3 --region westeurope --spot
sparehand cloud checks gcp --json '{"project":"my-project","region":"europe-west4","machine":"g2-standard-4"}' # billing, quotas, what blocks it
sparehand cloud add l4 --gcp --project my-project --machine g2-standard-4 --region europe-west4 --spot
sparehand studio install gpu --with pictures,clips,clips14b # ComfyUI and the models, onto the GPU machine
sparehand cloud # gpu: stopped · Runpod … · 0.8 h today, about $1.20 this month …
sparehand run --gpu python x.py # no home GPU free → "starting gpu (about 1–2 min, ~$0.27/h…)"
sparehand run npm test # no home worker free → a CPU machine with FOR=all is started
sparehand cloud stop gpu # now, instead of after the idle time
No second machine? Rent one by the minute
The shortest way to a second machine: a CPU machine at Runpod for builds and tests, made, started and stopped by Sparehand. It takes about two minutes once you have a Runpod account. Runpod is the provider here because it asks for the least: an account, a few dollars of prepaid credit and an API key. There is no quota to ask for, no billing account to switch on and no command-line tool to install, which the other three providers all need.
Before you start, at Runpod, once:
- Create an account at runpod.io.
- Add credit under Billing. The least is $10. Runpod is prepaid, so it can't take more than you put in, unless you turn on auto-pay there.
- Make an API key under Settings → API Keys that may read and write pods and storage.
In the dashboard: on the Machines tab, while this Mac is the only machine, press Rent a machine… (later: Add a machine → Rent one by the minute).
- Sign in to Runpod: paste the API key. This Mac keeps it in its Keychain and never shows it again.
- Choose a size and a limit: Small (4 vCPU), Medium (8 vCPU, recommended) or Large (16 vCPU), each with its price an hour, read from Runpod now; the spend limit in dollars of running time a month (10); the idle minutes (10) and the name. Under them, the checks that run before anything is made, each with what to do when it fails:
| Check | When it fails | What to do | | --- | --- | --- | | API key | Runpod refuses the key | Make a new key under Settings → API Keys, with read and write for pods and storage, and paste it | | Credit | The balance is under an hour's worth of the size (Runpod makes no machine then) | Add credit under Billing, then Check again | | Stock | No machine of that size is free right now | Choose another size, or try again in a few minutes |
A balance under the limit, or a key that may not read the balance, is a note, not a refusal.
- What is made, and what it costs: a 20 GB network volume (about $1.40 a month for as long as it exists, whether the machine runs or not) and a machine for each use (its price an hour, only while it runs); the most it can cost a month; and what keeps it safe. Nothing has been made until you press Rent.
- Making it, step by step, with a Stop.
In a terminal, the same in one command:
sparehand cloud rent # asks for the API key once, checks, sums up, asks, makes "rented"
sparehand cloud rent build --size large --limit 20 --idle 15 --yes
sparehand cloud rent --check # only the checks, the sizes and the costs: nothing is made
Then sparehand run --or-local npm test from a project's folder: with no other machine free, the first job makes the machine and waits for it (a minute or two), and while it runs the next jobs go straight there.
What keeps the cost down, all on from the start:
- The idle stop. After 10 minutes without a job the machine is terminated; only the volume stays, with your checkouts and caches, and the next job makes a machine on it again.
- The spend limit. At the limit the machine takes no new job and is stopped once it has none; a job still running then gets until 10% past the limit, and then the machine is stopped under it (the job is handed back and runs on this Mac). The limit counts running time, at the price an hour; the volume's month is on top. Change it with Edit on the card or
sparehand cloud set NAME max-spend-month 20. - Runpod's own stop. The credit is prepaid: when it runs out, Runpod stops the machine.
- The card under Machines says whether it is running now and at what price, what it has cost this month against the limit, and what stays while it doesn't run.
This Mac does the stopping, so keep the Sparehand app or the dashboard running while a job runs there: a Mac that is asleep or off can't stop a running machine, and then only Runpod's credit bounds the cost.
Giving it back: More → Delete it at Runpod… on its card, or sparehand cloud remove NAME --delete, deletes the machine and its volume, so nothing is billed for it any more. Remove alone only forgets it on this Mac: the volume stays at Runpod and goes on costing.
From the dashboard
Add a machine → Cloud provider. A card per provider, with its mark, what it offers and a link to create an account there (Runpod's is Sparehand's referral link; the others are plain). Then:
- The credential, once: the fields the provider needs (Runpod's API key; AWS's access key id and secret; Azure's tenant, client id, secret and subscription, or nothing when the hub's
azCLI is signed in). They go to the hub once, which checks them against the provider's API, keeps them in its Keychain and never shows them again. Change on the card replaces them. Under the fields, what the provider needs before a first GPU machine (quota, billing). - The machine: With a GPU (pictures, clips, AI models) or CPU only (builds and tests), then the whole catalogue the provider's API returns (nothing is hidden; a few are marked recommended), each with its memory, price an hour, Spot price and, where the provider says, stock, with a search box and filters (GPU memory at least, region, price at most). Then the region (nearest first, from your browser's time zone; in stock first; on Google Cloud the project and the zone too), the name, the disk or volume in GB, Spot (AWS, Azure, Google), the idle minutes (15), the caps (3 hours a day, $30 a month), Also set it up for Studio (a GPU machine: ComfyUI with the picture and clip models, with the GB it needs on the disk or volume; for a card with 16 GB or more also Studio's bigger models, each with its size: better clips, Wan 2.2 14B in Q8,
clips14b-q8, about 31 GB more, ticked; better pictures, FLUX.2 [klein] 9B,pictures9b, about 18 GB more, not ticked: its FLUX licence is non-commercial, so pictures made with it can't be used commercially, and a monetized YouTube channel counts. With it there, Studio uses it on that machine by itself for your own productions, and for a member's only when you allow it on approving. Left as offered, the disk grows to fit what's ticked; one set smaller says how big it must be, and nothing is made until it fits) and Studio uses it only when a storyboard picks it (on: a production has to tick it under Paid machines; off: Studio may pick it by itself, like a home machine). On Runpod also a pod per use (the default) or keep the pod between jobs, the machines also accepted when the chosen one has no stock, and Secure or Community Cloud (see Runpod: the volume stays below). The price line follows every change. On Google Cloud, Check billing and quotas (also run before Make it) reads the project's billing and the GPU and CPU quotas in that region and says what blocks the machine, with a link to the quota page; when only the GPU is blocked, a CPU machine can still be made. - Making it, step by step, with a Stop: the credential, the machine and region, what the provider needs first (a volume at Runpod; a key pair, a security group that lets only the hub's address in, and the image at AWS; a resource group, network, firewall rule, static address and NIC at Azure), the machine itself, the NVIDIA driver (Azure), the first SSH answer, the tools and Node 22 on it, the pairing, then Studio's install when asked. You can close the dialog: it goes on, and the machine shows under Machines when it is paired.
The machine's card then has a Cloud (Runpod | AWS | Azure | Google Cloud) tag with the provider's mark, Studio only when chosen when so, its price an hour, what it cost today and this month (Sparehand's estimates), and Start and Stop (on a Runpod worker with a pod per use, Start now makes a pod without waiting for a job, and Terminate now ends it; the card says no pod now in between).
From the terminal
sparehand cloud rent [NAME] [--size small|medium|large] [--limit USD] [--idle MIN] [--yes] [--check] # a CPU machine by the minute, in one command (above)
sparehand cloud key runpod|aws|azure|gcp # asks for the credential (gcp: the path to the JSON key); --status says whether there is one; --forget removes it
sparehand cloud catalog runpod|aws|azure|gcp [--region R] [--project P] [--cloud secure|community] # every machine: name, kind, memory, $/h, Spot $/h, stock, where, * recommended
sparehand cloud checks gcp --json '{…}' # Google Cloud: billing and quotas, what blocks that machine (JSON)
sparehand cloud add NAME --runpod|--aws|--azure|--gcp [--machine SIZE] [--region R] [--zone Z] [--project P] [--disk GB] [--spot]
[--price USD/h] [--idle 15] [--max-hours-day 3] [--max-spend-month 30] [--for gpu|all] [--studio chosen|auto]
sparehand cloud add NAME --runpod … [--mode fresh|keep] [--gpus "A,B,C"] [--cloud secure|community] # Runpod: a pod per use (default) or one kept; the machines it may take; the cloud tier
sparehand cloud add NAME --runpod --pod POD-ID | --volume-id VOL-ID # an existing Runpod pod or network volume (made by hand, or by a run that didn't finish)
sparehand cloud remove NAME --delete # delete the machine and what was made for it at the provider, and forget the worker
sparehand cloud trust NAME # accept the machine's new SSH key (after a reset or a remade machine)
Without --machine, an RTX A5000 (Runpod), a g6.xlarge (AWS), an NC4as T4 v3 (Azure) or a g2-standard-4 (Google); without --region, Runpod takes the data centre with the most of that machine free, the others need one (Google also takes --zone; without it, the region's first zone that has the machine). --for defaults to gpu for a GPU machine (only GPU jobs start it or go to it) and all for a CPU one. On a hub without a Keychain (Linux), put the credential in the environment as SPAREHAND_RUNPOD_KEY, SPAREHAND_AWS_KEY (ID:SECRET), SPAREHAND_AZURE_KEY (TENANT:CLIENT:SECRET:SUBSCRIPTION) or SPAREHAND_GCP_KEY (the JSON key, or it as base64); Sparehand never writes one to a file. Azure and Google also take the az and gcloud CLIs' own logins when nothing is pasted.
What each provider makes
Each provider is a small module (lib/cloud/runpod.mjs, aws.mjs, azure.mjs), run by the engine through lib/cloud/cli.mjs; adding a provider means another such module and a card in app/cloud.mjs.
- Runpod: a network volume (
sparehand-NAME, your size) in the data centre, in the tier it offers (a data centre without network volumes is refused); a pod (sparehand-NAME): Secure Cloud, one GPU or the CPU flavour and vCPU count, Runpod's official PyTorch template (runpod-torch-v280, imagerunpod/pytorch:1.0.2-cu1281-torch280-ubuntu2404), the volume at/workspace, a 20 GB container disk, ports22/tcpand8888/http, SSH on with this hub's public key asPUBLIC_KEY. On the pod, as root (lib/worker-runpod-prepare.sh): rsync, git, zsh and util-linux from apt, Node 22 from nodejs.org's official tarball into/usr/local(its checksum checked), and/root/.sparehandlinked to/workspace/sparehandon the volume, so the run folders, caches, Studio's models and the pause flag survive a stop or a new pod. Pairing:sparehand add NAME NAME --jobs 1 --cpus 8(a pod sees its host's CPUs; a CPU pod gets its own vCPU count). By default the pod is made for each use and terminated when idle (next section). - AWS (EC2): a key pair
sparehand-NAMEwith this hub's public key; a security groupsparehand-NAMEthat lets only the hub's public address in on port 22; the newest image (AWS's Deep Learning Base AMI with the NVIDIA driver for a GPU machine, Canonical's Ubuntu 24.04 for a CPU one); the instance, with a gp3 root disk of your size, stopping on shutdown, taggedsparehand=NAME; with--spot, a persistent Spot request that stops (never terminates) the instance when AWS takes it back. On it, asubuntuwith sudo (lib/worker-cloud-prepare.sh): rsync, git, zsh, Node 22. - Azure: a resource group
sparehand-NAMEof its own (so--deleteremoves everything): a virtual network, a network security group that lets only the hub's address in on port 22, a static public address (so the address stays the same across stops), a NIC and the VM (Ubuntu 24.04 from Canonical, the userazureuserwith this hub's key only, a Standard SSD of your size, deleted with the VM); with--spot, a Spot VM that is deallocated when Azure takes it back; on a GPU VM, Microsoft's NVIDIA driver extension (several minutes). On it, asazureuserwith sudo: rsync, git, zsh, Node 22. - Google Cloud (Compute Engine): a network
sparehand-net(auto subnets, shared by every machine); a firewall rulesparehand-ssh-NAMEthat lets only the hub's public address in on port 22, by tag; the VMsparehand-NAME(the newest Deep Learning image with the NVIDIA driver for a GPU machine, Ubuntu 24.04 for a CPU one; a balanced disk of your size; the hub's key for the usersparehand, who gets sudo from Google's guest agent; no service account; with--spot, a Spot VM that is stopped, never deleted, when Google takes it back; an n1 machine takes its T4 as a guest accelerator). On it, assparehandwith sudo: rsync, git, zsh, Node 22, and the idle timer. Before anything is made, billing and quotas are read (sparehand cloud checks gcp): billing not enabled, "GPUs (all regions)" at 0, the card's own quota in the region (NVIDIA_L4_GPUS, or thePREEMPTIBLE_one for Spot) or the CPU quota too small each stop the create with a sentence saying what to ask for. A VM made by hand with the gcloud commands (anINSTANCEline in its cloud file) still goes through gcloud, as before.
When a step fails, nothing is left running: at Runpod a volume made a moment ago is deleted again; a machine that was made is stopped, kept, and the message says how to try again or delete it (sparehand cloud remove NAME --delete). The dashboard's Stop does the same.
Runpod: the volume stays, the pod is made for each use
A stopped Runpod pod is bound to the host it ran on and starts again only when that host has a free GPU; it can refuse for hours ("not enough free GPUs on the host machine") while the volume and container disk keep costing. So a Runpod worker has two ways to run, the cloud file's MODE:
- A pod per use (
fresh, the default): the network volume is the durable thing (the models at/workspace,~/.sparehandlinked onto it). The pod is disposable: a start makes a new pod from the template with the volume attached, this hub's key asPUBLIC_KEY, on the first machine of the worker's list with stock in the volume's data centre; pins its new SSH key; runs the prepare step (about a minute all in all); the worker keeps its name and pairing. The idle stop terminates the pod (DELETE), so between uses only the volume is billed, and the next job (or Start now) makes a new one. Between uses the card says no pod now,sparehand cloudsays no pod: the volume waits, a start makes one, and the file hasID=none. - Keep the pod between jobs (
keep): the pod is stopped and started, as before. Cheaper to resume (the container disk with the tools stays) and a few seconds faster, but a stopped pod may refuse to start when its host is full; Sparehand then says so and the job goes on elsewhere.
The machines it may take (GPUS, --gpus "NVIDIA RTX A5000,NVIDIA L4,NVIDIA A40"; in the wizard, also accept): at each start the first with stock in the volume's data centre wins; when none is free, the start says which were tried and the next job tries again (Runpod's stock changes within minutes). MACHINE is the one taken last time, tried first. Secure or Community Cloud (CLOUD, --cloud): Community pods are cheaper, on hosts run by others; the catalog shows the prices of the tier chosen.
An existing worker: a pod paired by hand (or one made before this) becomes a pod-per-use worker with sparehand cloud add NAME --runpod --pod POD-ID --gpus "…": its volume is taken over, the file starts with no pod, a fresh pod is made on the volume and the worker is paired again under its name. The old pod is left alone: Sparehand never terminates a pod it didn't make; the step tells you to terminate it in Runpod's console when you don't need it (its volume stays). A volume alone works too: --volume-id VOL-ID --gpus "…". --mode keep keeps the pod instead.
Reaching it: the address and the SSH key
A Runpod pod gets a new public IP and SSH port each time it starts (a pod made for this use gets a new SSH key too, pinned anew); an AWS instance a new public IP; an Azure VM keeps its static one. After each look at a running machine (the dashboard polls every few seconds, and sparehand cloud start waits for it), the hub rewrites the worker's block in ~/.ssh/config:
# sparehand cloud worker NAME
Host NAME
HostName 198.51.100.7
Port 22140
User root
UserKnownHostsFile ~/.ssh/sparehand-cloud/NAME.known_hosts
StrictHostKeyChecking yes
# end sparehand cloud worker NAME
The machine's SSH key is read once, when it is made, and pinned in that file for any address (* ssh-ed25519 …), so a new address needs no new check and a changed key is refused: the worker then shows offline and sparehand doctor says the key changed. After a reset or a remade machine, sparehand cloud trust NAME pins the key it offers now. sparehand hostkey HOST --port N and sparehand trust HOST SHA256:… --port N do the same by hand for any machine whose SSH isn't on port 22.
Stopping and starting
- Idle: a Google, AWS or Azure VM runs a small timer (
lib/worker-cloud-idle.sh, set up before its first job, which needs passwordless sudo there: the images' default users have it) that powers the VM off afterIDLE_MINminutes with no Sparehand job, nobody at a terminal and the GPU idle; it refuses to install on anything that isn't a cloud VM (the firmware says). The hub is the safety net,IDLE_MIN+ 5 minutes after the last job. A Runpod pod can't stop itself (it has no credentials for Runpod's API, and should have none), so the hub stops it (a pod per use: terminates it) afterIDLE_MINminutes, whenever it looks at the worker: the dashboard's poll,sparehand status, a job. Keep the dashboard or the Mac app running; a hub that is asleep doesn't look, and a pod keeps costing until it does.
Change the idle time, or the caps, of a cloud worker that exists already:
bash sparehand cloud set gpu idle 45 # 5 to 1440 minutes without a job sparehand cloud set gpu max-hours-day 6 # 0: no cap sparehand cloud set gpu max-spend-month 50
A running VM's own timer takes the new idle time at once; a stopped one gets it before its next job.
- A job:
sparehand runthat finds no home worker free starts a cloud worker the job is for (FOR=gpu: a GPU job;FOR=all: any), unless a cap is reached or it is paused. Starting takes about a minute; the job goes to whichever machine is free first. - Studio: a cloud worker made with Studio only when chosen (the default) is never used by a production that didn't tick it under Paid machines on its storyboard, so no clip or picture lands on a paid machine by surprise; with auto, Studio treats it like a home machine.
- Pause:
sparehand pause NAMEon a stopped machine is remembered by the hub, so it isn't started for jobs; on a running one the machine's own flag is set too. - By hand:
sparehand cloud start NAME [--wait],sparehand cloud stop NAME, or the card (Start now and Terminate now on a pod per use). - Taken back: a Spot machine (AWS, Azure, Google) can be taken back at any time; it is stopped or deallocated, its disk kept. During a job, the job's connection ends; Sparehand sees the machine stopped (and that it didn't stop it itself), says so, and a caller that can wait (
SPAREHAND_WAIT, as Studio's clips have) gets the job run again, up to twice, on the machine started again or on whichever is free first. A kept Runpod pod (MODE=keep) is bound to its host; when that host has no GPU free, Runpod refuses the start and Sparehand says so. A pod per use has no such host: it is made wherever its list has stock. - Container disk vs volume (Runpod): a stop keeps the container disk (the tools) and the volume; a terminate loses the container disk (the prepare step puts the tools back in about a minute) but keeps the volume until it is deleted too (
cloud remove --delete).
Google Cloud by hand
The dashboard and sparehand cloud add NAME --gcp make the VM for you (above). The by-hand way, under Do it by hand instead on the card: sparehand cloud setup [--project P] [--zone Z] [--instance NAME] prints each step with the exact commands, which cost money. In short:
- gcloud on the hub, logged in with your own account (
gcloud auth login). A free trial account must be upgraded to a paid one before it can have a GPU (the remaining credit is kept). - GPU quota, which starts at 0: in the console, IAM & Admin → Quotas, ask for "GPUs (all regions)" = 1 and "Preemptible NVIDIA L4 GPUs" = 1 in the region (and "NVIDIA L4 GPUs" = 1 for the on-demand fallback below). A CPU-only VM needs none of this.
- A network that lets nothing in from the internet, except SSH from Google's IAP range for the first login.
- The VM:
g2-standard-8,--provisioning-model=SPOT --instance-termination-action=STOP(when Google takes it back it is stopped, never deleted),--max-run-duration=4h(Google stops it after 4 hours in one go, whatever happens), a Deep Learning VM image with the NVIDIA driver, a 150 GB balanced disk, no service account. For builds and tests: a machine type likec2d-standard-8, a plain Ubuntu image, and--for allbelow. - Tailscale on it, then pair it like a server (the app: Add a machine → Server, with its Tailscale name), so the hub's key is the only way in.
sparehand cloud add NAME --gcp --project P --zone Z --instance I --price USD-AN-HOUR, and for a GPU VMsparehand studio install NAME --with pictures,clips,clips14b. ComfyUI and the models live on its disk, so they survive every stop.- A budget alert in Google Cloud (Billing → Budgets & alerts, e.g. $20 a month, alerts at 50, 90 and 100%). Sparehand can't set it for you, and it only warns: Sparehand's caps are what keep the VM from running.
A VM made by hand is started and stopped through gcloud compute instances describe|start|stop| set-scheduling with your own login, for that instance only; Sparehand stores no Google credentials for it. Sparehand looks for gcloud on the PATH and in the usual install places (Homebrew, ~/google-cloud-sdk); SPAREHAND_GCLOUD names another one. One made through the API uses the service account key (or gcloud's login) like the other providers.
Another size
A cloud worker can get more or fewer CPUs and memory, or another graphics card, without being removed and added again: Resize… under More on its card, Resize… on its page in the Mac app (Machines → the machine → In the cloud), or in a terminal:
sparehand cloud resize cpu-cloud # its size now, and the sizes it can change to, each with its price an hour
sparehand cloud resize cpu-cloud --all # also the ones it can't change to, each with the reason
sparehand cloud resize cpu-cloud c2d-standard-16 # change it (asks first; --yes skips the question)
sparehand cloud resize cpu-cloud c2d-standard-16 --stop --yes # also when it is running: stopped first
The list comes from the provider at that moment: what its zone, region or data centre offers for a machine of its kind (a GPU machine stays a GPU machine, since its disk has the driver; a Spot machine stays Spot), with the price an hour of each. A size that can't be used says why, and a size the month's spend limit no longer covers an hour of is marked; the others say how many hours of them the limit still buys.
What a resize does depends on the provider:
| Provider | What changes | Limits |
|---|---|---|
| Google Cloud | The VM's machine type, while it is stopped (instances.setMachineType); the card on an N1 machine with instances.setMachineResources. Its disk, address and name stay. A VM made by hand (INSTANCE in its cloud file) is changed the same way, with gcloud's own login. | In place only among the first two generations of machine families (N1, E2, N2, N2D, C2D, T2D) or inside the VM's own family. To or from a third-generation family (C3, N4: other disks and network card), an Arm family or A2, Google wants a new VM, and the list says so. A card is never taken off. |
| AWS | The instance type, while it is stopped (ModifyInstanceAttribute). | The same processor architecture. A Spot instance can't change: its type is fixed in its Spot request. |
| Azure | The VM's size, while it is deallocated. | The sizes Azure offers for that VM, and that the subscription may use in the region. |
| Runpod | Nothing at Runpod: a pod can't change its GPU or CPUs. The worker's size is what its next pod is made as. --also "A,B" are the others it may take when the first has none free (--only: none), and for a GPU pod --min-vcpu N --min-ram GB are the least its host must give it (0: whatever it gives). | Any machine of its kind that Runpod lists; the ones free in the volume's data centre right now come first, and the others say "none free" (Runpod doesn't say which machines a data centre never has, so keep a second choice in --also). With MODE=keep the stopped pod is deleted, since it is bound to its machine; the volume and what is on it stay, and the next start makes a pod. |
Before anything changes: no job may run on the machine (it is refused with a sentence, and nothing is stopped), and a running machine is stopped first, which the terminal asks about (or takes --stop) and the dialogs say. While its size changes, no job starts it. Afterwards:
- Its price an hour in the cloud file (
PRICE_HOUR) is the new size's, so the hours it runs count against the spend limit at the new price, and Studio's estimates use it. The limit itself stays; raise it withsparehand cloud set NAME max-spend-month USDwhen the bigger machine should run as long as the smaller one did. Google's prices are estimates from its list prices: give your own figure with--price USD. - Its job limit follows its CPUs, in proportion (2 jobs on 8 CPUs become 4 on 16;
--jobs Nchooses, andsparehand set NAME jobs Nchanges it later). A Runpod CPU pod's CPUs a job follow its vCPUs. - It stays stopped until a job needs it (
sparehand cloud start NAMEstarts it now).
The cloud file
sparehand cloud add writes ~/.config/sparehand/cloud/NAME. Edit it by hand or run add again:
| Line | Default | Meaning (cloud add option) |
|---|---|---|
PROVIDER | runpod, aws, azure or gcp (Google Cloud, --gcp). | |
ID, REGION, MACHINE, KIND | The machine's id at the provider (a pod id, an instance id, a VM name; none on a Runpod worker between uses), its region, its size as the provider names it, gpu or cpu. A Google VM made through the API also has PROJECT, ZONE and FIREWALL. | |
VOLUME | Runpod: the network volume's id. | |
MODE | fresh | Runpod: fresh, a pod per use (made on the volume when needed, terminated when idle), or keep, the pod stopped and started (--mode). |
GPUS | the machine | Runpod: the machines the worker may take, comma-separated, first with stock wins (--gpus). |
MIN_VCPU, MIN_RAM | Runpod, a GPU pod: the least vCPUs and GB of memory its host must give it (sparehand cloud resize NAME SIZE --min-vcpu N --min-ram GB; 0 or absent: whatever the host gives). | |
CLOUD | SECURE | Runpod: SECURE or COMMUNITY (--cloud). |
SG, KEYPAIR | AWS: the security group and the key pair made for it. | |
RG | Azure: its resource group. | |
SPOT | no | yes: a Spot machine (--spot). |
ACCOUNT, PROJECT, ZONE, INSTANCE | A Google Cloud VM made by hand: the login gcloud uses, where the VM is (--account, --project, --zone, --instance); INSTANCE is what makes it the gcloud kind. | |
PRICE_HOUR | the catalog's | USD an hour while it runs (the Spot price for a Spot machine), for the estimates and the monthly cap (--price). |
DISK_MONTH | the provider's | USD a month for its disk or volume (and Azure's address), paid even while stopped (--disk-month). |
FOR | gpu for a GPU machine, all for a CPU one | gpu: only GPU jobs start it or go to it. all: any job, when every other worker is full; a GPU job starts it only once it has shown an NVIDIA GPU (--for). |
STUDIO | chosen | chosen: Studio uses it only when a storyboard picks it. auto: like a home machine (--studio). |
IDLE_MIN | 15 | Minutes without a job before it stops (--idle, 5 to 1440; change it later with sparehand cloud set NAME idle MIN, the dashboard's Edit or the app's Settings → Machines). |
MAX_HOURS_DAY | 3 | Hours it may run a day; 0: no cap (--max-hours-day). |
MAX_SPEND_MONTH | 30 | USD it may cost a month at PRICE_HOUR; 0: no cap (--max-spend-month). |
ON_FULL | wait | Google Cloud: when Google has no Spot L4 free, wait (the job goes on as if there were no cloud worker) or standard (start it on-demand this time, about 2.5 times the price; Spot again next time) (--on-full). |
Each line is checked; nothing in the file is ever run. No credential is ever in it.
Starting it when a job needs it
In sparehand run, after the home workers (and Wake-on-LAN) had their chance:
- No worker is free, and the job is one the cloud worker is for (a GPU job, or any with
FOR=all), it isn't paused, and no cap is reached: Sparehand asks the provider to start it and says[sparehand] no GPU worker free; starting gpu (about 1–2 min, ~$0.27/h while it runs)… - It looks again every few seconds, up to
SPAREHAND_CLOUD_WAIT(240) seconds, and the job goes to whichever machine is free first, a home worker too. - If the start fails (no quota or capacity, a credential refused, no GPU free on the pod's machine) it says why and goes on as if there were no cloud worker: a clip then waits for the home GPU, as before.
A job sent by a coding agent's hook (SPAREHAND_FROM_AGENT=1) never starts it: the agent has two minutes, and would spend them waiting for the boot. SPAREHAND_CLOUD=0 turns starting off altogether. SPAREHAND_CLOUD_AFTER=120 gives a home worker that is merely busy two minutes to free up before the cloud one is started (default 0: start it at once).
Cost and caps
- Running: time ×
PRICE_HOUR. Runpod bills by the minute, AWS, Azure and Google by the second (a minute at least). The catalog and the card show the providers' prices now. - Stopped: the volume or the disk (and Azure's static address). No static address is used at Runpod, AWS or Google.
- Caps: past
MAX_HOURS_DAYhours today, orMAX_SPEND_MONTHUSD this month, Sparehand doesn't start it for jobs, and one that is running is stopped once it has no job. 10% pastMAX_SPEND_MONTHit is stopped even with a job running (the job is handed back).sparehand cloud start NAME --over-cap(the dashboard's Start anyway) lifts the caps for the rest of the day.0means no cap; a machine made withsparehand cloud renthas the monthly limit as its only cap. - The figures are Sparehand's estimates, from the runs it has seen (Google's own start and stop times; for the others, the start the hub saw and the moment it saw the machine stopped) and your
PRICE_HOUR, not the provider's bill. A start made in the provider's console counts once Sparehand next looks at the machine. A budget alert (Google, AWS Budgets, Azure Cost Management) or the provider's balance page is what watches the real bill.
What the dashboard shows
The machine card has a Cloud (provider) tag with the provider's mark and these states:
| State | Card |
|---|---|
| Stopped | costs only its volume or disk; starts by itself when a job needs it · Start |
| Starting… | a minute or two |
| running | the usual load, memory, GPU and jobs · Stop |
| Stopping… |
and its cost: Now (Running: $0.16 an hour, or Not running: only its volume, about $1.40 a month), This month (the estimate against the spend limit, with a bar that turns orange at 60% and red at 80%), Today (hours and estimate) and, when a cap is reached, which one (with Start anyway). Edit changes the idle minutes and the spend limit. More → Resize… lists the sizes it can change to with their price an hour, says what happens (stopped first, the new price, what the spend limit still buys) and changes it (Another size). More → Delete it at … gives a machine Sparehand made back to its provider (deleted there, with its volume or disk). A member (see credits.md) sees the card but can't press anything on it. The activity log has Started gpu in the cloud, Stopped…, didn't start…, Changed gpu's size, gpu has a new address in the cloud and gpu was stopped by its provider during a job.
sparehand tsv gives a cloud worker the states stopped, starting and stopping besides up, offline and disabled, and eight more columns: provider, price, hours today, spend this month, the cap reached and the Studio rule, and, as the line's last two, what stays costs a month and the monthly spend limit (configuration.md).
Reachability and security
- Runpod: the pod is reached at its public IP and the port Runpod maps to its SSH, straight from the hub; only the hub's key gets in (root, key only). Everything else on the pod is closed except port 8888 (JupyterLab, which the template may start; it isn't used).
- AWS and Azure: the VM's firewall (the security group, the network security group) lets only the hub's public address in, on port 22; the VM's own user with the hub's key only. When your home's public address changes, the hub is locked out until the rule is changed in the provider's console (or the machine is made again).
- Google Cloud: a VM made through the API has a firewall rule that lets only the hub's public address reach port 22, and the user
sparehandwith the hub's key only. One made by hand joins your tailnet and its SSH host is its Tailscale name, which stays the same across stops. Tailscale needs no open port, so the VM's firewall lets nothing in from the internet; only Google's IAP range may reach port 22, for the first login. Its SSH accepts only the hub's key (pairing,sparehand lock). Tag it in your tailnet's access rules so it can't reach the hub or your other devices. - The credentials on the hub (Runpod's key, AWS's access key, Azure's service principal, your gcloud login) can make and delete machines on your accounts: anyone who can run commands as you on the hub can use them, as with any key in your Keychain. The hub sends each API only machine, catalog and billing requests.
- All are workers like any other (security.md): they trust the hub, and the hub trusts nothing from them but status numbers.
.envfiles are never copied to them. - What leaves the house: the checkout a job needs. For a Studio clip, that is the scene's picture and its prompt, and the clip comes back. With a cloud worker that is in the provider's data centre, not on your own machine.
Not there yet
- Other providers (Lambda, Vast): the provider modules and cards keep room for them.
- Google's prices per region (today's are the us-central1 list) and live stock at AWS, Azure and Google (they say only when asked to run).
- Better clip settings on 24 GB (the 14B model at 720p, fp8 instead of GGUF): a Studio change once it runs there.
- Moving a machine to another region when one has no capacity: its disk or volume lives in one.
- Resizing across what a provider won't change in place (a Google VM to a third-generation family, a GPU VM to a CPU one, an AWS Spot instance): that takes a new machine, so remove it and add one.