Workload security
Container sandbox#
Every job is one container started by the daemon with a fixed, audited argument list. There is no option — in the job spec or the host configuration — that removes any of these restrictions.
--gpus "device=<assigned GPU UUIDs>" # only the reserved GPUs
--network none # or the job's internal egress network
--read-only --tmpfs /tmp:rw,nosuid,nodev,size=…
--cap-drop ALL --security-opt no-new-privileges
--user 65534:65534 # nobody, never root
--pids-limit … --memory … --memory-swap … # no swap beyond the limit
--cpus … --ipc private --shm-size … --cgroupns private
--mount type=bind,source=<job dir>/input,target=/input,readonly
--mount type=bind,source=<job dir>/output,target=/output
--init --ulimit core=0 --pull never
--runtime runsc # when gVisor (with --nvproxy) is installed| Never granted | Why |
|---|---|
--privileged | Would expose every device and disable confinement. |
| Host PID / network / IPC / UTS / user namespaces | No visibility of host processes, interfaces or users. |
| Docker socket, host paths, extra devices | The only mounts are the job's own input (read-only) and output directories. |
| Added capabilities | All Linux capabilities are dropped. |
Requests for any of these in a job spec (privileged, hostNetwork, capAdd, devices, mounts…) are refused by the workload policy before the job is ever offered to a host. Images are pulled before the run and started with --pull never; when a job pins a digest, the daemon refuses an image whose digest doesn't match.
runsc runtime with --nvproxy, jobs run under it for a user-space kernel boundary. Hosts without it run under runc with the restrictions above; the machine's runtime is reported to the coordinator.GPU isolation#
- The scheduler reserves specific GPUs (by UUID) for one assignment; a database constraint makes double-booking a GPU impossible.
- The container sees only those UUIDs (
--gpus device=…,NVIDIA_VISIBLE_DEVICES). Jobs can't setCUDA_VISIBLE_DEVICES,NVIDIA_*orGPUFARM_*variables. - V1 keeps every GPU of a job on one physical machine; no job shares a GPU with another job.
- GPUs over the owner's temperature cap, flagged by anti-spoofing checks, or in a health back-off are never offered work.
Network policy#
The default is no network: the container has only a loopback interface. A job may request { "mode": "allowlist", "allow": ["huggingface.co"] } to reach specific public hosts.
- Allowlists accept public DNS names only — no IP addresses, ports, wildcards or local names (localhost, .local, .internal, .lan, .home.arpa…). The policy also rejects private and LAN ranges.
- An allowlisted job runs on its own
--internalDocker bridge network (no route off the host, inter-container traffic disabled). Its only exit is the daemon's HTTPCONNECTproxy on that bridge's gateway, which accepts peers from the job's subnet only. - For each connection the proxy checks the name against the allowlist (port 443 unless the entry names one), resolves it itself and refuses if any address is private, loopback, link-local (including cloud metadata endpoints), CGNAT, multicast or otherwise non-public — then connects to that vetted address, so DNS rebinding can't swap it.
- Only TLS tunnels leave the host; plain-HTTP proxying is refused. Workloads can't scan or reach the host's LAN, the host itself, or other jobs.
Inputs and outputs#
- Inputs and outputs live in a private object-storage bucket. Nothing is public.
- A host gets short-lived signed URLs only for the inputs of the job it accepted, and signed upload URLs only for that job's output and log paths.
- Customers download through signed URLs too (120 s from the API). Every artifact carries its SHA-256; the server re-hashes outputs from storage before verification.
- Outputs are bounded by the job's output rules (≤ 5 GiB each) and artifacts expire automatically.
- Environment variables are visible to the host machine, so names that look like secrets (
*_TOKEN,*PASSWORD*,PRIVATE_KEY…) are rejected. Never put credentials in a job spec.
Host key isolation#
- Each daemon generates its own secp256k1 host key. It signs only login challenges, benchmark reports and job receipts — it holds no funds and is never a payout wallet.
- The key is stored in the OS keystore (macOS Keychain / Linux Secret Service) or an encrypted file, never in the job directory, and never mounted into a container.
- Payouts go to the owner's wallet, which never touches the machine. The owner authorizes the host key with a signature; revoking a machine in the dashboard ends its sessions.
- Daemon updates are accepted only when the release's SHA-256 and Ed25519 signature verify against the GPUFarm release key.
See the host guide for installation and release verification.
Abuse prevention#
- Every job passes the workload policy before it can be funded: banned images and digests, known miner/cracker/scanner names and signatures in the image, command and environment (xmrig, ethminer, stratum+tcp, hashcat, hydra, masscan, nmap…), privilege requests and LAN egress.
- Scan results are recorded per image; questionable workloads are held for review instead of scheduled.
- Benchmarks, telemetry and job history are monitored for spoofed hardware and abnormal usage; flagged GPUs stop receiving work.
- Administrators act on fraud flags, abuse reports and banned container hashes; every administrative action is written to an append-only audit log.
What is prohibited is listed in the acceptable use policy.
Host privacy#
GPUFarm never stores or shows a host's IP address, exact location, machine username or local network details. Hosts choose a coarse region (such as Europe West or US East) and a public name. Customers see the farm or host name, GPU details, region and measured reliability — nothing else.