Join our community of builders on Discord!

Run a Worker on Testnet with the CLI

This guide takes a bare Linux host to a Testnet worker that claims and serves inference jobs. You install one binary, write one config file, run lightchain-worker init, and start a systemd service. Docker is optional: see Docker Compose recipe at the end. A worker claims jobs on-chain through sortition, runs them on your own Ollama, streams tokens to the consumer through the public worker gateway, and settles the result on-chain. It needs no inbound ports, no VPN and no allowlist. Dispatcher-free Mode explains how sortition works. This is the quicker of the two Testnet guides. Run a Worker on Testnet sets up the same worker by hand, with the Docker image and cast.

Prerequisites

  • A Linux host (amd64 or arm64) with a GPU, running Ollama. There are macOS builds too, but to serve jobs use a Linux machine with a GPU.
  • Outbound HTTPS and WSS access.
  • Testnet LCAI: 5,000 LCAI stake (the on-chain minimum, AIConfig.getMinWorkerStake()) plus a gas buffer of 50 LCAI. init asks for at least 5,050 LCAI; send about 5,060 LCAI so the balance stays above the buffer after registering. Ask the Lightchain AI team or the community channels for testnet LCAI.

Step 1: Install the CLI

CodeBASH
The installer picks the build for your OS and CPU, checks its SHA-256 against the release's checksums.txt, and installs /usr/local/bin/lightchain-worker. It does nothing else: no service, no config, no keys. To pin a release or install elsewhere, pass LIGHTCHAIN_WORKER_VERSION or INSTALL_DIR after sudo, which drops the caller's environment: … | sudo LIGHTCHAIN_WORKER_VERSION=v1.2.3 sh. To check the installer before you run it, download install.sh and checksums.txt from the same release and compare sha256sum install.sh with its line in checksums.txt. lightchain-worker is the whole worker: init sets it up, run serves, and the other commands (preflight, status, balance, deregister, ...) manage it. Run lightchain-worker help for the list.

Step 2: Pull your models into Ollama

On-chain, a model's id is keccak256 of its name, and the worker passes that same name to Ollama. So each name you serve must be on the testnet's model list, and Ollama must have a model under exactly that name. The live list is at https://chat-api.testnet.lightchain.ai/api/indexer/models. It shows each model by its id; the names are in Whitelisted models.
CodeBASH

Step 3: Write the config file

One environment file holds everything: init reads it, and the systemd service reads it too. The command below creates it with a random keystore password. Replace SUPPORTED_MODELS with the names you pulled, comma-separated.
CodeBASH
There is no REDIS_URL: the external profile streams results over an authenticated WebSocket to the gateway and sends heartbeats and drain over gateway HTTPS. The CLI reads its configuration from the environment. This shell function loads the file for each command; define it once per shell:
CodeBASH

Step 4: Run init

CodeBASH
init works through four steps. Each step first checks what is already done, so you can stop at any point and run lcw init again.
  1. Worker key. With no keystore at WORKER_KEYSTORE_PATH yet, init asks whether to generate a new key or import one. To import, put the hex private key in a file only root can read, answer i, and give the file's path; init reads it without printing it, and you can delete the file afterwards. The keystore is written in the standard geth format with mode 0600. init prints the worker address, never the key.
  2. Register with stake. init checks the model names against the chain and your balance against the stake before it spends anything. If the address is not funded yet, it tells you how much to send:
    CodeTEXT
    Fund the address and run lcw init again. Send a little more than the minimum it names, since registering spends some gas; otherwise preflight later warns that the balance is below the 50 LCAI buffer. It asks you to confirm the stake, then registers the worker. That publishes the encryption key (created now at ENCRYPTION_KEYSTORE_PATH), stakes the minimum, and adds your models. Set WORKER_STAKE (in wei) only to stake more than the minimum.
  3. Add models. Any model in SUPPORTED_MODELS that the worker does not serve on-chain yet is added. To serve another model later, pull it, append it to SUPPORTED_MODELS, and run lcw init again.
  4. Preflight. The read-only go-live check runs last: RPC and chain id, registration, suspension, stake, balance, encryption key against the on-chain key, each model's on-chain state, gateway login, Ollama tags and the beacon API. Each failing line says what to fix. A ready worker ends like this:
    CodeTEXT
Back up /etc/lightchain/worker/: the keystore, the encryption key, and the env file that holds their password. If you lose the encryption key after registering, the worker cannot serve sessions encrypted to it.
For an unattended run, init --generate (or --import-key-file FILE) answers the key question and --yes confirms the stake.

Step 5: Run it as a service

CodeBASH
These startup lines confirm the external profile is active:
CodeTEXT
On its first start the worker does not read the chain's history: it starts its session and job cursors 2000 blocks behind the chain head (SORTITION_SESSION_LOOKBACK_BLOCKS), so it can claim as soon as it is eligible. A claim logs claimed session request. From then on the worker serves its jobs on Ollama, streams tokens through the gateway, and submits the result as an on-chain blob.

Day to day

TaskCommand
Check everythinglcw preflight
Registration and key statuslcw status
Add a modelollama pull NAME, append it to SUPPORTED_MODELS, lcw init, sudo systemctl restart lightchain-worker
Earningslcw balance; lcw withdraw moves them to the worker address
Stake under the minimum after a slashlcw top-up-stake AMOUNT adds AMOUNT LCAI to the stake after asking (lcw top-up-stake --yes AMOUNT does not ask); lcw preflight shows how much is missing. Needs a release newer than v0.0.1
Back from a suspensionlcw reinstate, once the cooldown is over and the stake is back at the minimum. Needs a release newer than v0.0.1
AlertsWorker Alerts (watch) posts to Discord when the worker needs attention
Upgradere-run the installer, then sudo systemctl restart lightchain-worker
Stopsudo systemctl stop lightchain-worker drains first: no new sessions, and in-flight jobs get up to SHUTDOWN_TIMEOUT to finish
Leavestop the service, then lcw deregister returns the stake once no jobs are active
Fees accrue in JobRegistry, and the worker settles them to its balance after the dispute window. A timeout or a lost dispute counts as an offense, and three offenses suspend the worker for 7 days. On Testnet the slash rates are currently 0, so an offense takes no stake; on a network with non-zero rates it also takes a share of the minimum stake. Keep the host up and the models loaded, and avoid killing the service mid-job. These pages cover each topic in depth. Their examples use the Docker setup from the other guides.

Troubleshooting

Run lcw preflight first; each [FAIL] line names its fix.
SymptomCause and fix
init: … is not on this network's model listThe name must match the testnet list exactly, tag included (llama3-8b, not llama3:8b)
init: cannot open the worker key …WORKER_KEYSTORE_PASSWORD is not the password the keystore was created with
init: cannot reach the chain RPCCheck RPC_URL and the host's outbound access
[FAIL] ollama … not pulledollama pull the name, or ollama cp a pulled model to it
[FAIL] gateway … 403 worker not registeredRegistration missing, or the env file points at another keystore
Registered but never claimsA model was not added for this worker, or the worker is suspended

Docker Compose recipe

The image registry.lightchain.ai/testnet/worker:latest carries the same CLI (/bin/lightchain-worker) and the worker (/bin/worker, its entrypoint). The env file above works unchanged except for OLLAMA_URL=http://host.docker.internal:11434. Mount the two directories at the same paths, owned by the image's user (uid 1000):
CodeYAML
CodeBASH
sudo is needed because the env file is readable by its owner only. init in the container needs an image built from a worker release that has the command.

Testnet reference

ItemValue
Chain ID8200
RPChttps://rpc.testnet.lightchain.ai
Beacon APIhttps://beacon.testnet.lightchain.ai
Worker gatewayhttps://worker-gateway.testnet.lightchain.ai
WorkerRegistry0x0000000000000000000000000000000000001002
JobRegistry0x531b3A87c5D785441B9cF55b98169F20FD9056a7
SessionManager0x86AdA80864e87dE2275200FeE905b5C32b32Bf68
AIConfig0xeCF4Ca5Ba6D97ae586993e170764a1E92231b67e
Model listhttps://chat-api.testnet.lightchain.ai/api/indexer/models