|
| 1 | +# Serve and call a worker over Iroh |
| 2 | + |
| 3 | +VGI supports two authenticated Iroh endpoint forms: |
| 4 | + |
| 5 | +- `iroh://<endpoint-id>` keeps stream state on one connection. |
| 6 | +- `httpi://<endpoint-id>[/prefix]` preserves VGI's stateless HTTP exchanges, |
| 7 | + continuation tokens, request/response budgets, authentication headers, and |
| 8 | + externalized batches. |
| 9 | + |
| 10 | +Install the optional native client binding: |
| 11 | + |
| 12 | +```console |
| 13 | +pip install 'vgi-python[iroh]' |
| 14 | +``` |
| 15 | + |
| 16 | +## Start a raw upstream |
| 17 | + |
| 18 | +The language-neutral `vgi-iroh-bridge` owns the public Iroh endpoint. The |
| 19 | +Python process binds only loopback and requires the bridge's PROXY-v2 identity |
| 20 | +preamble: |
| 21 | + |
| 22 | +```console |
| 23 | +vgi-serve my_worker.py \ |
| 24 | + --iroh-raw-upstream 127.0.0.1:9400 \ |
| 25 | + --iroh-issuer production |
| 26 | +``` |
| 27 | + |
| 28 | +In another process: |
| 29 | + |
| 30 | +```console |
| 31 | +vgi-iroh-bridge \ |
| 32 | + --secret-key-file /run/secrets/vgi-iroh-key \ |
| 33 | + --raw-upstream tcp://127.0.0.1:9400 |
| 34 | +``` |
| 35 | + |
| 36 | +The bridge prints its EndpointId as the first stdout line. Development may use |
| 37 | +`--ephemeral`; a production endpoint must use a persistent secret key. |
| 38 | +The raw Iroh listener also enables standard RPC method description so |
| 39 | +standalone clients in other VGI languages can bootstrap directly. |
| 40 | + |
| 41 | +## Start an HTTP upstream |
| 42 | + |
| 43 | +HTTP-over-Iroh is the preferred mode for horizontally scaled workers: |
| 44 | + |
| 45 | +```console |
| 46 | +vgi-serve my_worker.py \ |
| 47 | + --http --host 127.0.0.1 --port 9401 \ |
| 48 | + --iroh-issuer production |
| 49 | + |
| 50 | +vgi-iroh-bridge \ |
| 51 | + --secret-key-file /run/secrets/vgi-iroh-key \ |
| 52 | + --http-upstream http://127.0.0.1:9401 |
| 53 | +``` |
| 54 | + |
| 55 | +`--iroh-issuer` makes the worker trust exactly `127.0.0.1` by default and |
| 56 | +promotes the bridge-verified EndpointId to `CallContext.auth`. Use repeated |
| 57 | +`--iroh-trusted-proxy <exact-ip>` when the immediate bridge address differs. |
| 58 | +Use `--iroh-observe` to expose evidence without authenticating from it. |
| 59 | + |
| 60 | +Never expose the bridge-facing listener as a general public HTTP or TCP |
| 61 | +listener. If another proxy sits between the bridge and worker, isolate that |
| 62 | +route, clear client-supplied `VGI-Forwarded-Iroh-Endpoint` fields on every other |
| 63 | +route, and configure the worker to trust only the intermediary's exact address. |
| 64 | + |
| 65 | +## Connect |
| 66 | + |
| 67 | +The same high-level client accepts both endpoint schemes: |
| 68 | + |
| 69 | +```python |
| 70 | +from vgi.client import Client |
| 71 | + |
| 72 | +with Client.from_iroh("iroh://<endpoint-id>") as client: |
| 73 | + print(client.catalogs()) |
| 74 | + |
| 75 | +with Client.from_iroh("httpi://<endpoint-id>/vgi") as client: |
| 76 | + print(client.catalogs()) |
| 77 | +``` |
| 78 | + |
| 79 | +For a private relay: |
| 80 | + |
| 81 | +```python |
| 82 | +client = Client.from_iroh( |
| 83 | + "httpi://<endpoint-id>/vgi", |
| 84 | + relay_urls=["https://relay.example.com"], |
| 85 | + remote_relay_url="https://relay.example.com", |
| 86 | +) |
| 87 | +``` |
| 88 | + |
| 89 | +The local relay set and the remote relay hint are distinct. `no_relay=True` |
| 90 | +disables relays and requires a working direct path; it never falls back to the |
| 91 | +public relay network. |
0 commit comments