Self-hosted execution runner for IceFold nodes (reverse-connects to an IceFold server, like a self-hosted CI runner).
Project description
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/cancel→node_status/node_done/missing_dep) as plain JSON text frames — TLS (wss) is the confidentiality layer. The runner token travels in theX-Worker-Tokenrequest header; only the non-secretworker_idis in the query string. Eachnode_execframe only carries abundle_hashand a single already-sliced variant — no source. - Bulk media + bundles ride plain HTTP: the runner GETs inputs from the
server's
/filesand/scratchmounts and node bundles from/v1/bundles/<hash>(sha256-addressed, cached locally asrunner_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
.pybundle, withpython_deps/binary_depsdeclared in the bundle header. The runner imports the bundle, pre-flights the deps (sending back a structuredmissing_depreply 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.
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 (e.g. ffmpeg / ffprobe on PATH for media
nodes) 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:
icefold-runner --token <your-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 |
ICEFOLD_RUNNER_TOKEN |
runner token from the IceFold app |
--runner-id |
ICEFOLD_RUNNER_ID |
stable id (default: hostname) |
--work-dir |
ICEFOLD_RUNNER_DIR |
scratch for staged inputs + products |
The runner honors standard proxy env vars (HTTPS_PROXY, …) for reaching the
server. It reconnects automatically with backoff; an auth rejection is fatal.
Self-hosting / dev: point the runner at a different server with the
ICEFOLD_RUNNER_SERVERenv 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.
Project details
Release history Release notifications | RSS feed
Download files
Download the file for your platform. If you're not sure which to choose, learn more about installing packages.
Source Distribution
Built Distribution
Filter files by name, interpreter, ABI, and platform.
If you're not sure about the file name format, learn more about wheel file names.
Copy a direct link to the current filters
File details
Details for the file icefold_runner-0.1.11.tar.gz.
File metadata
- Download URL: icefold_runner-0.1.11.tar.gz
- Upload date:
- Size: 26.4 kB
- Tags: Source
- Uploaded using Trusted Publishing? No
- Uploaded via: twine/6.2.0 CPython/3.12.3
File hashes
| Algorithm | Hash digest | |
|---|---|---|
| SHA256 |
57f150a480b06f6929174b362b4a2409ba48ab11bd19dbe3b110c008da365e4e
|
|
| MD5 |
16212c87c14fa78a93aef28667ca5652
|
|
| BLAKE2b-256 |
b54fac17c9a92785b1ddac2462d55378c05edde585eb547ae02740f8babf16fe
|
File details
Details for the file icefold_runner-0.1.11-py3-none-any.whl.
File metadata
- Download URL: icefold_runner-0.1.11-py3-none-any.whl
- Upload date:
- Size: 26.8 kB
- Tags: Python 3
- Uploaded using Trusted Publishing? No
- Uploaded via: twine/6.2.0 CPython/3.12.3
File hashes
| Algorithm | Hash digest | |
|---|---|---|
| SHA256 |
934c73fd85a3feb79dcecb9ba9e5d9d9a5eb0c7d7009c2e431f77986a34c74db
|
|
| MD5 |
3310cdeb3e9e83a9979ceb99b6541a84
|
|
| BLAKE2b-256 |
3077d1c6747058750355bad14f7cc2b07e61b1ded71a5830b5660848d7f56cc0
|