Skip to main content

alyxruntime

Use any other computer's CPU/GPU as your Jupyter runtime - like Colab's "connect to local runtime", but for any machine you control, from the command line or from Python.

 your laptop        Cloudflare edge            GPU box (host) - no open ports, outbound only
 ┌────────────┐ https ┌───────────────┐ tunnel ┌─────────────────────────────────────────┐
 │ alyxruntime│ ────► │ *.trycloudflare│ ◄──────│ cloudflared ─► IP-allowlist gate        │
 │  connect   │ +token│     .com       │        │                  └─► Jupyter (loopback) │
 └────────────┘       └───────────────┘        │                        └─► kernel (GPU) │
                                                └─────────────────────────────────────────┘

The host talks out to Cloudflare through cloudflared, so there is no port forwarding, no public IP, and HTTPS is included - it works from behind home routers, NAT and most firewalls.

Install

pip install "alyxruntime[host]"   # on the machine that SHARES its GPU/CPU
pip install alyxruntime           # on the machine that CONNECTS (lighter)

Usage

On the host (the machine with the GPU):

alyxruntime stream --allowed_ip 203.0.113.7                # your client's public IP
alyxruntime stream --allowed_ip 203.0.113.7 10.0.0.0/24    # several IPs / CIDR ranges
alyxruntime stream --allowed_ip all                        # any IP - the token is the only gate

It starts a Cloudflare quick tunnel (if cloudflared is missing it offers to download the official binary, or pass --install-cloudflared) and prints a ready-to-paste command with a random access token:

alyxruntime connect 'https://random-words.trycloudflare.com/?token=...'

Not sure what your public IP is? Run alyxruntime connect from the client anyway: the host replies access denied for IP x.x.x.x. Ask the host to add it with --allowed_ip x.x.x.x.

On the client:

alyxruntime connect https://my-host:8765/?token=XXXX   # verifies, shows remote CPU/RAM/GPU, saves session
alyxruntime run train.py            # run a script   (also .ipynb, `-c "code"`, or stdin with `-`)
alyxruntime shell                   # interactive prompt; variables persist between commands
alyxruntime info                    # remote CPU / RAM / GPU
alyxruntime upload data.csv         # copy files to the host's working dir
alyxruntime download model.pt
alyxruntime restart                 # fresh kernel
alyxruntime disconnect --kill-kernel

Plots (plt.show()) are saved locally to ./alyx_outputs/. VS Code / JupyterLab also work: Select Kernel -> Existing Jupyter Server -> paste the same URL.

From Python

from alyxruntime import Runtime

rt = Runtime.connect("https://my-host:8765/?token=XXXX")
rt.run("import torch; print(torch.cuda.is_available())")
res = rt.run("2 + 2", echo=False);  print(res.results)     # ['4']
rt.upload("data.csv"); rt.download("out.pt")

Host side from Python: from alyxruntime import serve; serve(allowed_ip=["203.0.113.7"]).

Stable URL (named tunnel)

Quick tunnels get a new random URL every run. For a fixed hostname, create a tunnel in the Cloudflare dashboard (Zero Trust -> Networks -> Tunnels), point a public hostname at http://localhost:9000, then:

alyxruntime stream --tunnel-token <TOKEN> --public-url https://gpu.example.com --port 9000 \
                   --allowed_ip 203.0.113.7

stream options

flag meaning
--allowed_ip IP [IP...] public IPs / CIDR ranges (v4 or v6) allowed to connect, as seen by Cloudflare, or the word all (same as --allow-any). Required in tunnel mode.
--allow-any accept any IP (the token is then your only protection)
--no-tunnel skip Cloudflare; listen directly on --host:--port (you handle NAT; loopback is always allowed in this mode)
--install-cloudflared download cloudflared automatically if it's missing
--tunnel-token / --public-url / --port use a named tunnel with a stable hostname (see above)
--token fixed access token instead of a random one
--root-dir directory the client can see (default: current dir)
--tls-cert / --tls-key HTTPS for --no-tunnel mode (not needed with a tunnel)
--public-host hostname/IP to print in the connect URL with --no-tunnel

Security - please read

A runtime is remote code execution by design: whoever connects runs arbitrary code as the host user.

  • Two independent gates: the IP allowlist and a random token.
  • How the allowlist works with a tunnel: cloudflared reaches the host from 127.0.0.1, so the socket address is useless for filtering. The gate instead reads the CF-Connecting-IP header, which Cloudflare's edge sets itself, and checks every request against --allowed_ip. Requests with no such header (anything not coming through the tunnel) are refused, loopback gets no special pass, and each request is forced to Connection: close so one vetted connection can't be reused by someone else.
  • The quick-tunnel URL is public: anyone who learns it can reach the gate (and be refused). Treat the token like a password, and don't paste the connect line in public places.
  • Traffic passes through Cloudflare's network (TLS to Cloudflare, then Cloudflare -> your host over the tunnel); Cloudflare can technically see it. If that's unacceptable, use --no-tunnel with your own VPN.
  • IP allowlisting trusts that Cloudflare reports the true client IP. It won't protect against someone sharing your NAT/VPN exit IP, and mobile/CGNAT or rotating-IP connections will need a CIDR range.
  • Local users on the host can reach the gate on its loopback port and are trusted like the host user.
  • Don't run stream as root unless you mean it. The client's saved token lives in ~/.alyxruntime/session.json (0600).
  • Cloudflare's free quick tunnels are meant for development: no uptime guarantee, and you should read Cloudflare's terms before using them for anything heavy or long-lived (use a named tunnel for that).

Web UI (Colab-style notebook)

alyxruntime connect <url>   # once (or use the Connect button in the UI)
alyxruntime ui              # opens http://127.0.0.1:8899 - notebook cells run on the remote GPU/CPU

Code/text cells, Shift+Enter / Ctrl+Enter, streaming output and plots, run all / interrupt / restart, remote file browser with upload/download, open/download .ipynb, dark mode. Notebooks autosave in the browser. The UI only listens on 127.0.0.1 and requires a per-launch secret, so other websites can't drive your runtime.

Metadata

Release files for alyxruntime 0.2.0

For a detailed explanation of source distributions (sdists) and built distributions (wheels), please see the package formats documentation.

Source distribution (sdist)

Source distribution for alyxruntime 0.2.0
File Size Uploaded Provenance Actions
alyxruntime-0.2.0.tar.gz 30.2 kB Without provenance Details for alyxruntime-0.2.0.tar.gz

Built distribution (wheel)

Table of built distributions (wheels) for alyxruntime 0.2.0
File Interpreter ABI Platform Actions
alyxruntime-0.2.0-py3-none-any.whl Python 3 none any Details for alyxruntime-0.2.0-py3-none-any.whl

Total release size: 60.7 kB

Release files / alyxruntime-0.2.0.tar.gz

Download URL alyxruntime-0.2.0.tar.gz
Size 30.2 kB
Tags Source
SHA-256 checksum
How to use checksums
0f0fb908060388161204a32b2ca6f3ee8e6e0897b9786cc54862e2d7b53c6a2f
BLAKE2b-256 checksum
How to use checksums
19d8e5be77f71f7990940cbcef874f99f4fc8cc43fb2dd20e42817d1509ad6ba
Upload date
Uploaded using Trusted Publishing?
What is trusted publishing?
No
Uploaded via twine/7.0.0 CPython/3.11.0

Release files / alyxruntime-0.2.0-py3-none-any.whl

Download URL alyxruntime-0.2.0-py3-none-any.whl
Size 30.5 kB
Tags Python 3
SHA-256 checksum
How to use checksums
4065c54a5624d4c0053372a969f78162c1446d62cc6348c96a66275c35ebd76d
BLAKE2b-256 checksum
How to use checksums
ee0b8decaeaffeb534e8997bc587a320bbf3e5b284eb718d330bb38332e7e120
Upload date
Uploaded using Trusted Publishing?
What is trusted publishing?
No
Uploaded via twine/7.0.0 CPython/3.11.0

Security for alyxruntime 0.2.0

Provenance

Provenance describes where a file came from. On PyPI, provenance is shared via attestations, which provide a verifiable record of the build or publishing details. View details, limitations and caveats.

No provenance found

None of the files in this release were uploaded with provenance metadata.

A note on package security

PyPI is a repository for distributing packages, not a service for auditing them. While third-party security researchers and our staff do their best to detect and remove malicious packages, PyPI cannot guarantee the quality, security or suitability of any given package.

To learn more about protecting yourself from malicious actors, visit our package security documentation.

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