How do I run a setup script when a cloud GPU starts?
Short answer: When you order a Raw GPU on https://cloudgpu.app/deploy, open Startup script (optional) and paste a bash script; through the REST API, send it as setup_script in POST /v1/gpu/instances. CloudGPU runs it once, as root, in the background after the instance is handed over, so you can SSH in while it runs. Output goes to /root/cloudgpu-setup.log, the script is saved at /root/cloudgpu-setup.sh, and the limit is 16 KB; for anything bigger, git clone your repo from the script (/deploy and API docs, read 2026-11-03).
What the startup script does
| Language | bash |
| Runs as | root |
| Runs | once, in the background, after the instance is handed over |
| While it runs | you can SSH in and use JupyterLab |
| Log | /root/cloudgpu-setup.log |
| Saved copy | /root/cloudgpu-setup.sh |
| Size limit | 16 KB (the box on /deploy counts up to 16,384 characters) |
| Where to set it | /deploy → Raw GPU → Startup script (optional), or setup_script in the REST API |
Because data on an instance is deleted when you destroy it, a startup script is a simple way to get the same environment back on the next instance: the same packages, the same models, the same repo.
Step 1: Write the script
Start with strict mode and a marker file, so you can tell whether it finished and where it stopped:
#!/usr/bin/env bash
set -euxo pipefail # stop on the first error and echo each command into the log
cd /root
# 1) packages
apt-get update && apt-get install -y tmux aria2
pip install -U uv "huggingface_hub"
# 2) your code
git clone --depth 1 https://github.com/<you>/<project>.git /root/project
# 3) models (public repo; see the token note below for gated ones)
export HF_XET_HIGH_PERFORMANCE=1
hf download Qwen/Qwen2.5-7B-Instruct --local-dir /root/models/qwen2.5-7b-instruct
touch /root/SETUP_DONE # marker: everything above succeeded
Tips:
- Keep it short and move the rest into your repo. Over 16 KB, clone a repo and run
bash /root/project/setup.shfrom the script. - Use absolute paths. Write to
/root/...instead of relying on the current folder. - Install packages before large downloads, and install Python packages into a virtual environment if the system Python refuses (
uv venv /root/env && . /root/env/bin/activate). - Long-running services: start them in
tmuxso they outlive the script, for exampletmux new -d -s app 'bash /root/project/serve.sh'.
Step 2: Add it at order time on /deploy
- Open /deploy and choose Raw GPU and a card.
- Expand Startup script (optional) and paste the script. The counter shows how much of the 16,384 characters you use.
- Deploy. When the instance row shows SSH details, you can log in while the script works.
Step 3: Or send it through the REST API
POST /v1/gpu/instances takes setup_script next to gpu_model, the template and the auto-shutdown limits max_minutes, max_spend_usd and idle_minutes (API docs, read 2026-11-03). jq turns a local file into a correctly escaped JSON string:
jq -n --rawfile s setup.sh \
'{gpu_model: "RTX 4090", max_minutes: 120, max_spend_usd: 2, idle_minutes: 30, setup_script: $s}' \
| curl -sS -X POST https://cloudgpu.app/v1/gpu/instances \
-H "Authorization: Bearer $CLOUDGPU_API_KEY" \
-H "Content-Type: application/json" -d @-
The call returns 202 with status creating. Poll GET /v1/gpu/instances/{id} until the status is running; the SSH host, port and password are filled in then. gpu_model can also be "auto", which lets CloudGPU choose an available GPU that can run the request. GET /v1/gpu/templates lists template ids if you want a template instead of a plain GPU. For AI coding assistants, the same API is wrapped by the CloudGPU MCP server (npx -y cloudgpu-mcp).
Step 4: Watch the log and check the result
tail -f /root/cloudgpu-setup.log # Ctrl-C stops following, not the script
ls /root/SETUP_DONE && echo "setup finished"
ps aux | grep -v grep | grep cloudgpu-setup # still running?
If the script failed, the last lines of the log show the command that stopped it (that is what set -x is for). Fix the command, then run the saved copy by hand; it runs automatically only once:
bash /root/cloudgpu-setup.sh 2>&1 | tee -a /root/cloudgpu-setup.log
Write your script so that running it twice is harmless: hf download skips files that are already complete, and git clone into an existing folder fails, so guard it with [ -d /root/project ] || git clone ....
Secrets and tokens
The script is stored on the instance at /root/cloudgpu-setup.sh, and anything you echo ends up in the log. Avoid long-lived secrets in it. For a gated Hugging Face model, either log in after the instance is ready (read -rs HF_TOKEN && export HF_TOKEN) and run the download then, or use a fine-grained, read-only token that you revoke after the session. Turn off set -x around any line that uses a secret (set +x … set -x) so it is not printed to the log.
Billing
The instance is billed per minute, rounded up, with a 1-minute minimum, while the script runs and afterwards; billing stops when you destroy the instance. The API limits max_minutes, max_spend_usd and idle_minutes are enforced by CloudGPU’s servers even if your client disconnects.
Frequently asked questions
When does the CloudGPU startup script run?
Once, as root, in the background after the instance is handed over to you. You can SSH in while it runs.
Where is the startup script output?
In /root/cloudgpu-setup.log on the instance. The script itself is saved at /root/cloudgpu-setup.sh.
How large can the startup script be?
Up to 16 KB. For anything bigger, git clone your repository from the script and run a script from the repo.
Can I set the startup script through the API?
Yes. Send it as setup_script (bash, up to 16 KB) in POST /v1/gpu/instances, together with gpu_model and optional limits such as max_minutes, max_spend_usd and idle_minutes.
Does the startup script run again if I rerun it by hand?
It runs automatically only once. You can run the saved copy yourself with bash /root/cloudgpu-setup.sh; write it so that a second run is harmless.
Sources (read 2026-11-03, Asia/Shanghai)
- CloudGPU /deploy, Raw GPU panel (“Runs once as root after the machine is handed over, in the background; you can SSH in while it runs. Output goes to /root/cloudgpu-setup.log and the script is saved at /root/cloudgpu-setup.sh. Up to 16 KB”): https://cloudgpu.app/deploy
- CloudGPU API docs, GPU instances (setup_script, max_minutes, max_spend_usd, idle_minutes, 202 creating, polling): https://cloudgpu.app/api/docs#gpu
- CloudGPU MCP server: https://cloudgpu.app/docs/mcp
- jq manual (–rawfile): https://jqlang.org/manual/
The Deploy page lists the cards you can start. Prices are on https://cloudgpu.app/pricing and are not repeated here.
Last updated: 2026-11-03 (Asia/Shanghai).