Skip to main content

icefold-runner

A self-hosted execution runner for IceFold nodes — like a GitHub self-hosted CI runner. You start it on your own machine; it reverse-connects to an IceFold server (so it works behind NAT with no inbound ports, no public IP, no tunnel), receives node-execution jobs, runs them locally, and streams results back.

It is the place where your uploaded node code runs — on your hardware, with full subprocess / ffmpeg / GPU / any-dependency access. The IceFold server never executes third-party code; it only renders it into bundles for a runner.

How it works

   your machine (private, behind NAT)              IceFold server (public)
 ┌──────────────────────────────────┐  reverse WSS  ┌───────────────────────────┐
 │ icefold-runner                    │ ───────────► │ /v1/ws/worker?worker_id=…   │
 │  • dials out, token auth          │  node_exec ◄─│ routes node runs (per user) │
 │  • reconnect + keepalive          │  node_done ─►│                             │
 │  • bundle runner:                 │              │                             │
 │    GET /v1/bundles/<hash>         │   HTTP pull  │ /files  /scratch            │
 │    import bundle + preflight deps │ ◄──────────► │ /v1/workers/output          │
 │    await __icefold_run__          │              │                             │
 └──────────────────────────────────┘   HTTP push  └───────────────────────────┘
  • Control plane rides the reverse WebSocket (node_exec / cancelnode_status / node_done / missing_dep) as plain JSON text frames — TLS (wss) is the confidentiality layer. The runner token travels in the X-Worker-Token request header; only the non-secret worker_id is in the query string. Each node_exec frame carries a bundle_hash, the selected variant's inputs, and the confirmed variant input storage needed by the bundle's typed runtime — never node source.
  • Bulk media + bundles ride plain HTTP: the runner GETs inputs from the server's /files and /scratch mounts and node bundles from /v1/bundles/<hash> (sha256-addressed, cached locally as runner_work_dir/bundles/<hash>.py, re-hashed on every download), runs the bundle, POSTs products back to /v1/workers/output (which returns server-canonical paths and accepts at most 2 GiB per product).
  • The runner ships no node implementations and never compiles user source. The IceFold server renders every node (your custom ones and the platform's built-in ones) into a self-contained .py bundle, with python_deps / binary_deps declared in the bundle header. The runner imports the bundle, pre-flights the deps (sending back a structured missing_dep reply with platform-aware install hints if anything is absent), and awaits __icefold_run__(inputs, ctx_dict). So when the server adds or upgrades nodes, the runner does not need an upgrade. Runner protocol or agent changes are released as a new runner version.
  • Variant planning / dimension & provider resolution all stay on the server; each job is a single already-sliced leaf call.
  • Transient WebSocket loss does not restart a node. Recovery-capable server and runner versions negotiate this in worker_ready: the runner keeps the task alive, the server reattaches its pending call_id, and terminal frames plus host callbacks replay by id. If the runner process itself is lost, the server automatically resubmits the same call_id to a replacement runner. Older peers do not advertise recovery, so rolling upgrades retain the legacy cancel-on-disconnect behaviour instead of guessing across protocol versions.
  • Pre-execution transfer failures can move once to a different runner. The runner retries transient input and bundle downloads locally first. If those attempts are exhausted before node code starts, runner 0.2.7+ marks the terminal result as safe to retry; a compatible server may then exclude that runner and dispatch one fresh call to a peer. Structured dependency-preflight failures are safe for the same reason. Node, provider, timeout, upload, and other post-start failures never carry this hint.

Install

Requires only Python ≥ 3.11 (it pulls in icefold-sdk).

The runner itself ships no node tooling. A node declares what it needs in its bundle header — binary_deps (for example, IceFold video nodes use google-chrome, ffmpeg, and ffprobe on PATH) and python_deps (whatever your custom nodes import) — and the runner pre-flights those before each run, replying with a platform-aware install hint (missing_dep) for anything absent. So you install a node's dependencies only when you actually run a job that needs them, and the runner tells you exactly what to install.

pip install icefold-runner          # pulls in icefold-sdk

From source:

git clone <this-repo> icefold-runner
cd icefold-runner
python -m venv .venv && . .venv/bin/activate
pip install -e .

Run

Generate a token in the IceFold app (Settings → Runners), then:

install -m 600 /dev/null ~/.icefold-runner-token
read -rsp 'Runner token: ' ICEFOLD_TOKEN_INPUT
printf '%s' "$ICEFOLD_TOKEN_INPUT" > ~/.icefold-runner-token
unset ICEFOLD_TOKEN_INPUT
icefold-runner --token-file ~/.icefold-runner-token

That's it — the token (GitHub-CI style) encodes + signs your IceFold user id, so there's no server URL or user id to pass. The server is built in.

Every flag also reads an env var:

flag env meaning
--token-file ICEFOLD_RUNNER_TOKEN_FILE path to a mode-0600 runner token file
ICEFOLD_RUNNER_TOKEN runner token via environment (the insecure --token flag is rejected)
--runner-id ICEFOLD_RUNNER_ID stable id override (default: fresh process id)
--work-dir ICEFOLD_RUNNER_DIR scratch for staged inputs + products
--concurrency ICEFOLD_RUNNER_CONCURRENCY CPU-lane slots for ffmpeg/Pillow work (default: detected CPUs, capped at 8)
--gpu-concurrency ICEFOLD_RUNNER_GPU_CONCURRENCY GPU-lane slots (default: 1)

The runner honors standard proxy env vars (HTTPS_PROXY, ALL_PROXY, …) for reaching the server, including HTTP and SOCKS proxies. It reconnects automatically with backoff; an auth rejection is fatal.

The runner advertises both effective lane widths in its WebSocket hello frame. Servers that understand these fields can fill a high-capacity runner before using a smaller backup; older servers safely ignore the extra fields. A newer server treats an older runner that does not advertise capacity as one slot.

Self-hosting / dev: point the runner at a different server with the ICEFOLD_RUNNER_SERVER env var (e.g. ws://127.0.0.1:7000).

Layout

icefold_runner/      the runner agent (connection, file staging, bundle exec)
  client.py            reverse-WS client: dial / auth / reconnect / keepalive
  runner.py            fetch /v1/bundles/<hash>, preflight deps, await __icefold_run__
  __main__.py          CLI entrypoint (icefold-runner)

The runner imports the bundle on demand; the bundle is self-contained and already inlines whatever it needs (the author's function body, the Inputs / Output dataclasses, and a minimal NodeContext shim). The only runtime dependency on icefold-sdk is the wire protocol + a small helper kit (get_file_id / run_blocking / write_text), used by the runner agent itself, not by node code.

Security model

  • Node code runs unsandboxed here — it's your machine, your risk. That's the point: code the server refuses to execute (subprocess/ffmpeg/native deps and anything third-party) runs on the runner instead. The runner downloads each bundle from the server and executes it; it verifies the bundle's sha256 matches the requested hash, but the bundle itself is whatever the server you authenticated to sends. Only point a runner at a server you trust.
  • The runner only talks to the one server you point it at, authenticated by its runner token; it pulls input files and pushes products over HTTP to that host.

Download files

Download the file for your platform. If you're not sure which to choose, learn more about installing packages.

Source Distribution

icefold_runner-0.2.7.tar.gz (32.9 kB view details)

Uploaded Source

Built Distribution

If you're not sure about the file name format, learn more about wheel file names.

icefold_runner-0.2.7-py3-none-any.whl (31.8 kB view details)

Uploaded Python 3

File details

Details for the file icefold_runner-0.2.7.tar.gz.

File metadata

  • Download URL: icefold_runner-0.2.7.tar.gz
  • Upload date:
  • Size: 32.9 kB
  • Tags: Source
  • Uploaded using Trusted Publishing? No
  • Uploaded via: uv/0.11.3 {"installer":{"name":"uv","version":"0.11.3","subcommand":["publish"]},"python":null,"implementation":{"name":null,"version":null},"distro":{"name":"Ubuntu","version":"24.04","id":"noble","libc":null},"system":{"name":null,"release":null},"cpu":null,"openssl_version":null,"setuptools_version":null,"rustc_version":null,"ci":null}

File hashes

Hashes for icefold_runner-0.2.7.tar.gz
Algorithm Hash digest
SHA256 2fb11c9ee355f3ad344df8189cd91da2e2ea6c5aa50f8bbf326b70944a40759a
MD5 df544b878310e1ca20bf343800c2d9cc
BLAKE2b-256 7a3e70d951fe066b6f82c0f03bf85d141960047edd51d6c95c7b3bc6adc75ddb

See more details on using hashes here.

File details

Details for the file icefold_runner-0.2.7-py3-none-any.whl.

File metadata

  • Download URL: icefold_runner-0.2.7-py3-none-any.whl
  • Upload date:
  • Size: 31.8 kB
  • Tags: Python 3
  • Uploaded using Trusted Publishing? No
  • Uploaded via: uv/0.11.3 {"installer":{"name":"uv","version":"0.11.3","subcommand":["publish"]},"python":null,"implementation":{"name":null,"version":null},"distro":{"name":"Ubuntu","version":"24.04","id":"noble","libc":null},"system":{"name":null,"release":null},"cpu":null,"openssl_version":null,"setuptools_version":null,"rustc_version":null,"ci":null}

File hashes

Hashes for icefold_runner-0.2.7-py3-none-any.whl
Algorithm Hash digest
SHA256 d54d9594ac7b4025d850fd3ddf42c8b14b9418a580c2479b9b4c438ccfa57776
MD5 96a75442decd536008f837fe6cd9e3dd
BLAKE2b-256 625556fe987f25cf1e34406e668fc376db5ecad94baca41774536575f014541b

See more details on using hashes here.

Release history Release notifications | RSS feed

0.3.5

2 files

0.3.4

2 files

0.3.3

1 file

0.3.2

2 files

0.3.1

2 files

0.3.0

2 files

0.2.8

2 files

This release

0.2.7 This release

2 files

0.2.6

1 file

0.2.5

2 files

0.2.4

2 files

0.2.3

2 files

0.2.2

2 files

0.2.1

2 files

0.2.0

2 files

0.1.11

2 files

0.1.9

2 files

0.1.8

2 files

0.1.7

2 files

0.1.6

2 files

0.1.5

2 files

0.1.4

2 files

0.1.3

2 files

0.1.2

2 files

0.1.1

2 files

0.1.0

2 files

Anthropic, PBC Visionary sponsor Bloomberg Visionary sponsor Hudson River Trading Visionary sponsor Meta Visionary sponsor NVIDIA Visionary sponsor Microsoft Sustainability sponsor Depot Continuous Integration AWS Cloud computing and Security Sponsor Datadog Monitoring Fastly CDN Google Download Analytics Sentry Error logging StatusPage Status page