A node becomes a provider when it offers one model source to the network, reachable at a public HTTPS URL, and is paid in USDG through the escrow. Buyer and seller are two views of the same node.
Honest status: the pieces below are real and tested on the Robinhood testnet with the test token
MockUSDG(paid trades settled locally, between two nodes, and once through a Cloudflare tunnel). A seller backed by a real model reached from a second machine on another network has not been run yet. Mainnet is untouched. Read STATUS first.
What you need#
| Need | Notes |
|---|---|
| A model source | Ollama on the same machine is the simple path: OLLAMA |
A public HTTPS URL for /p2p/* |
Caddy or a Cloudflare tunnel in front of the node. Without it you cannot be reached (no relay or NAT traversal yet) |
| Testnet ETH in the node wallet | Gas for redeeming vouchers; you pay it. Faucets are listed in Payments (login required, a human step) |
| A payout address | ELYRA_PAYOUT: where swept USDG goes. Without it earnings stay in the node wallet |
| Backups | The data dir holds identity and wallet; set ELYRA_PASSPHRASE and back it up |
Steps#
- Install and run the node as a service: INSTALL. Use
--no-demoso no simulated peers appear. - Attach the model source (Connect → Detect local, or
ELYRA_UPSTREAM_URL). - Expose only
/p2p/*and/healthzover HTTPS:The panel text mentionsseller.example.com { @p2p path /p2p/* /healthz handle @p2p { reverse_proxy 127.0.0.1:8545 } respond 404 }--host 0.0.0.0; prefer this loopback + proxy layout. The node's own guard blocks/apiand/v1from non-loopback, but do not rely on one guard. - Configure:
ELYRA_PUBLIC_URL,ELYRA_PROVIDE=1,ELYRA_PROVIDE_PRICE,ELYRA_PAYOUT,ELYRA_NETWORK,ELYRA_ESCROW(CONFIGURATION); or use the Provide view. - Fund the wallet with testnet ETH (address on Payments).
- Verify from outside:
curl https://seller.example.com/p2p/helloreturns signed JSON listing your model;curl -i https://seller.example.com/api/statusmust return 404 (not data, not 403). - From a buyer node: Network → add
https://seller.example.com; it should appearLIVEwith your model. Deposit mock USDG, send a request, and check the receipt and an on-chain redeem (explorer link under Payments).
How you are paid#
- The buyer's node sends a sealed, signed request; you answer and return a signed receipt (model, tokens, price, amount).
- The buyer verifies it (signature, parties, price within 5% of the quote, amount = price x tokens, token count not inflated) before signing a cumulative voucher.
- You redeem the latest voucher on-chain; the escrow pays you exactly that amount of USDG.
Money is USD per million tokens, rounded to 1e-8, settled in 6-decimal USDG: no oracle, no exchange rate. Gas is ETH.
Risk controls (provider side)#
| Control | Default | Why |
|---|---|---|
creditUsd |
$0.50 | A consumer can drain its own deposit through a second address (documented limitation F3), so you never serve more unpaid usage per wallet than you can lose, including the next request's worst case |
autoRedeem / autoRedeemUsd |
on / $0.25, plus a 60 s sweeper | Keeps unredeemed exposure small |
| On-chain deposit check | always, fail-closed | Before creating any state your node reads the wallet's deposit; if the RPC is down it answers 503 |
maxConcurrent, ratePerMin, deny |
4, 120, none | Capacity and abuse limits |
On SIGTERM the node redeems what it holds (bounded to 20 s) before exiting.
Privacy: what you can and cannot claim#
A normal seller can read prompts: label it none. Do not set the TEE claim unless you really run the official image in Google Confidential Space; even then buyers only treat you as private when a Google-signed attestation passes their trust list, and that path has only been proven against a simulated Google (TEE). Sealed transport hides prompts from the network, not from you.
Pricing#
Your price per MTok must exceed your cost per MTok actually served. Start on a cheap CPU box with a small model; rent a GPU only after a buyer exists. A 1B model on 8 CPU cores answered a short prompt in about 1 s warm.
Things that bite#
- Gossip refuses private/LAN peer URLs unless
--allow-private-peers(operator-typed peers are exempt). - Both sides must use the same escrow or there is no route.
- Real USDG (mainnet) is unaudited territory: the escrow is unaudited and the USDG supply controller can burn from any address. Mainnet needs
--allow-mainnetand your informed decision. - Mock USDG is minted by anyone and has no value.