Guide 08. By Nicolas Dao · Last reviewed

A GPU box next to the agent box

My agents run on a cheap VPS with no GPU. How do I add an NVIDIA GPU that I stop at night, that keeps every tool and login, and that's ready again in seconds?

A Runpod pod beside the VPS, both built from one infrastructure-as-code repo. Everything that matters lives on a network volume for about $3.50 a month, a start script rebuilds the rest in about 30 seconds, and Python environments run from the local disk and are kept as one archive. A reminder, not an automatic stop, because agent sessions run for hours.

Scenario: Claude Code and Codex run around the clock on an always-on Hostinger VPS with no GPU. A proof of concept needs a serious NVIDIA card for a few weeks: open-source vision models (SAM 2.1, video matting, depth estimation) on frame-by-frame video, with an agent working inside the box, installing things, running experiments and iterating. The GPU should cost nothing at night, and the box should come back in the morning exactly as it was.

Two machines, one repo

The VPS (agents) The pod (GPU)
Role Everything by default: agents 24/7, web work, scheduled jobs Only the work that needs an NVIDIA GPU
Kind A VM, always on, flat yearly price A container, $0.89 an hour while running, stopped when idle
Hardware 8 vCPU, 32 GB of RAM, no GPU RTX 4090 (24 GB), 13.6 CPUs, about 61 GB of RAM
Location Malaysia Romania (EU-RO-1)
What persists The whole disk Only the network volume, at /workspace
How I reach it vps <session> from the laptop, over Tailscale gpu <session> from the laptop, over plain SSH

Both are built from the same infrastructure-as-code repo: the same tools, aliases, Claude Code settings and agent skills. From the laptop they feel the same.

What I chose on Runpod

  • Secure Cloud, on demand. Community Cloud was cheaper, but it can't use network volumes and had no 4090s in stock; spot pods are retired.
  • RTX 4090, with L40S, RTX A6000 and RTX PRO cards as fallbacks in the same data center if the 4090s run out.
  • Runpod's official PyTorch template: CUDA 12.8, PyTorch 2.8 and the NVIDIA drivers on Ubuntu 24.04, the VPS's OS.
  • Two disks. A 50 GB container disk, wiped at every stop and free while stopped, and a 50 GB network volume at /workspace, kept. I started at 100 GB and went down to 50: a volume can grow later, never shrink.
  • EU-RO-1, because it had both 4090 stock and network volumes. The closest data center, in Japan, had no 4090s that day.
  • Set up by the agent. Through Runpod's MCP server, connected with OAuth from Claude Code, Claude checked live stock per data center, created the volume and the pod, and asked me before anything that cost money.

What survives a stop

A pod is a container, and a stop wipes everything except the network volume. The design follows from that:

  1. The home folder stays on the local disk; the tool folders live on the volume. ~/.local, ~/.claude, ~/.config, ~/.cache and the like are links into the volume, so Claude Code, Codex, the GitHub login and the agent skills are installed once and survive every stop. The home itself can't move: the volume refuses chown and shows every file as writable by everyone, and SSH rejects keys in a folder like that.
  2. A start script re-applies the rest on every start, in about 30 seconds: the user account, the system packages (from a download cache on the volume), the dotfiles and the Git settings.
  3. Python environments run from the fast local disk and are kept on the volume as one compressed archive, restored in about 2 seconds after a start.
  4. New sessions start in /workspace, so files land on the volume by default.

When Runpod refused to restart the stopped pod one morning ("There are not enough free GPUs on the host machine to start this pod"), I created a new pod on the same volume and was working again 27 seconds later: same tools, same logins, same files, same SSH host key. Without the volume, that morning would have been painful.

Measured: the volume against the local disk

On the network volume On the local disk
pip install, 1.8 GB in about 19,000 files 10.5 minutes 22 seconds
import transformers 26 seconds, every time 0.9 seconds
Copying a config repo of about 1,250 files Over an hour, about a file a second

One big file is fast; thousands of small ones are not. That's why each environment lives on the volume as a single archive (1.8 GB compressed to 516 MB) and runs from the local disk.

The container also misreports its size. nproc said 32 CPUs and free well over 100 GB, against real limits of 13.6 CPUs and about 61 GB. A frame job with its worker pool sized from nproc ran at 5.8 frames a second; sized to the real limit, 14.3.

Day to day

Command, from the laptop What it does
gpu start, gpu stop, gpu status Start, stop and check the pod, with its uptime and running cost
gpu dof Join or create a terminal session called "dof" on the pod
gpu, gpuls, gpukill Pick, list or end sessions, the same as for the VPS
gpu create Put a new pod on the same volume when the old one can't restart
/gpu-push, /gpu-pull Claude Code skills that copy files to and from the pod, with checksums

A small helper reads the pod's address from Runpod's API after each start and rewrites the laptop's SSH settings, because the port changes every time.

The two machines look different on purpose: the pod has a magenta status bar showing its uptime and running cost (for example "GPU · up 3h12m · ~$2.85"), tab titles starting with "GPU", and its own prompt. The VPS is green.

A reminder, not an automatic stop

Agent sessions legitimately run for many hours, so an automatic shutdown would kill real work. Instead, the pod sends a phone notification after 8 hours, then every 4 hours, with the running cost. Stopping is a human decision. Billing is per second, but the risk is a forgotten pod: about $21 a day at $0.89 an hour.

What it costs

Item Cost
The RTX 4090, while running $0.89 an hour, billed per second
An 11-hour session about $9.90
A 9-hour session about $7.94
The 50 GB network volume, all month about $3.50 ($0.07 per GB)
Data in and out free
The whole proof of concept, first estimate $15 to $25 of GPU time

Prices checked on 1 November 2026 (Runpod pricing); the 4090 was $0.69 an hour in July.

Lessons

  • Treat the pod as cattle. Everything that isn't on the volume must be rebuilt by a script, including system libraries: MediaPipe needed libegl1 and libgles2, and installed by hand they would have vanished at the next stop.
  • Test the full stop-and-start cycle early. It found three bugs in the start script that a normal boot never showed.
  • Don't reuse the VM's provisioning script. There's no systemd, no Docker of your own, no swap and no UDP, so Mosh doesn't work and Tailscale runs only in userspace mode. The pod has its own, container-safe script in the same repo.
  • Keep the image's PyTorch. uv installed a second one (about 5 GB) over it, and pip's build isolation downloaded a third with CUDA 13 just to build SAM 2. Use pip with a constraints file pinning the image's torch, and --no-build-isolation.
  • Commit config changes immediately when agents work on the box. One agent's uncommitted edit was lost to a careless git reset --hard while syncing.

Every gotcha above, with its fix, is also on the Runpod entry. When the GPU work is on a client's data rather than my own experiments, it moves to AWS: Runpod or AWS for a GPU?

Want this stack in your AWS account?

Cloudless Labs is a Sydney consultancy. We migrate on-premises systems to AWS, build serverless apps on this stack, and coach teams to ship with Claude Code and Codex.

Talk to us

Contact Us

For general inquiries, please contact us at:

For e-learning capabilities, please contact: