Skip to content

lightchain-protocol/lightchain-worker-toolkit

Repository files navigation

lightchain-worker-toolkit

Lightchain worker on your own hardware — Windows, macOS, or Linux — with every gotcha we hit in production already fixed.

lint license docs status

This repo is the PowerShell + Bash automation I wish existed when I onboarded my first Lightchain worker. The official docs at workers-testnet.lightchain.ai/run-node are correct, but they assume a bash shell, leave several real-world failure modes undocumented, and require a lot of copy-paste-edit-pray. This toolkit replaces all of that with idempotent scripts, layered docs, and a battle-tested troubleshooting guide.


Table of contents


What you get

Layer What's in this repo
Scripts 16 PowerShell scripts + 16 Bash scripts that automate every phase of the official onboarding (key gen → register → run) and the day-2 ops (status, sweep, deregister, tail).
Docs 9 guides covering architecture, per-OS installation, deep dives into each phase, day-2 operations, troubleshooting, security, and FAQ.
Examples systemd unit for unattended Linux operation, docker-compose alternative, full env-var reference.
Repo hygiene MIT license, CONTRIBUTING guide, SECURITY policy, CHANGELOG, .gitignore that actually protects your keys, .gitattributes for cross-OS line endings, .editorconfig, GitHub Actions for PowerShell + Bash + Markdown linting, issue/PR templates.

Everything in scripts/ is idempotent: each phase script can be safely re-run, and refuses to do destructive things (overwrite keystore, send LCAI to wrong address) without explicit confirmation.

Who this is for

  • Solo operators who want to run one or two workers on a home machine and earn $LCAI for serving llama3-8b inference jobs.
  • Operators on Windows who don't want to install WSL2 just to run Linux-shell commands.
  • Operators on Linux/macOS who want a clean, scripted alternative to the copy-paste docker run lines.
  • Anyone who's already hit one of the gotchas in docs/troubleshooting.md and wants to skip the hours of debugging.

Not for: people building inference clients (you want the dispatcher API), people running validators / chain nodes (different stack, different image, separate access), or people who want managed hosting (try a cloud provider).

Status

Capability Status
Mainnet onboarding (Windows) ✅ Verified end-to-end on RTX 5060 Ti + Windows 11.
Mainnet onboarding (Linux) ✅ Verified on Ubuntu 24.04 + RTX 4070.
Mainnet onboarding (macOS) ✅ Verified on M2 Pro 16GB.
Testnet onboarding ✅ Same scripts, flip NETWORK=testnet.
Multi-worker on one host ✅ Documented in operations.md.
Job processing ✅ Confirmed (stage 1 → 8 → job completed).
Sweep / deregister ✅ Working.
Auto-restart on host reboot ✅ Container has --restart always; systemd example included.

Quick start (TL;DR)

You'll need: Docker Desktop, Ollama, Foundry's cast, an 8+ GB GPU, and 50,005 LCAI in a funder wallet (for mainnet).

Windows (PowerShell)

# One-time install (run as admin)
winget install --id Docker.DockerDesktop --exact -e --silent
winget install --id Ollama.Ollama --exact -e --silent
# Foundry: see docs/installation-windows.md (~30 seconds)

# Clone this toolkit
git clone https://github.com/lightchain/lightchain-worker-toolkit.git
cd lightchain-worker-toolkit

# Onboard
.\scripts\powershell\00-generate-key.ps1
.\scripts\powershell\01-resolve-addresses.ps1
.\scripts\powershell\02-prepare-ollama.ps1
.\scripts\powershell\03-pull-image.ps1
.\scripts\powershell\04-import-key.ps1
.\scripts\powershell\05-generate-ecdh.ps1
$env:FUNDER_PRIVKEY = "0xYOUR_FUNDER_KEY"
.\scripts\powershell\06-fund-worker.ps1            # type 'send'
.\scripts\powershell\07-register.ps1               # type 'register' - 50k LCAI staked
.\scripts\powershell\08-run-worker.ps1 -NoTail

# You're live. Watch jobs flow in:
.\scripts\powershell\tail-jobs.ps1

Linux / macOS (Bash)

macOS: Apple ships bash 3.2 (from 2007). Two of the scripts use bash 4+ syntax and will error with bad substitution. Install a modern bash before running the toolkit: brew install bash && echo 'export PATH="/opt/homebrew/bin:$PATH"' >> ~/.zshrc && source ~/.zshrc. See docs/installation-macos.md for details.

# One-time install (Ubuntu/Debian)
sudo apt-get install -y docker.io
curl -fsSL https://ollama.com/install.sh | sh
curl -L https://foundry.paradigm.xyz | bash && ~/.foundry/bin/foundryup

# Clone this toolkit
git clone https://github.com/lightchain/lightchain-worker-toolkit.git
cd lightchain-worker-toolkit

# Onboard
./scripts/bash/00-generate-key.sh
./scripts/bash/01-resolve-addresses.sh
./scripts/bash/02-prepare-ollama.sh
./scripts/bash/03-pull-image.sh
./scripts/bash/04-import-key.sh
./scripts/bash/05-generate-ecdh.sh
export FUNDER_PRIVKEY=0xYOUR_FUNDER_KEY
./scripts/bash/06-fund-worker.sh                   # type 'send'
./scripts/bash/07-register.sh                      # type 'register' - 50k LCAI staked
./scripts/bash/08-run-worker.sh --no-tail

# You're live. Watch jobs flow in:
./scripts/bash/tail-jobs.sh

Want to play it safe first? Set $env:NETWORK = "testnet" (PowerShell) or export NETWORK=testnet (Bash) before Phase 01, claim free LCAI from the faucet, and run the whole flow with zero financial risk.

Repository layout

.
├── README.md                            # ← you are here
├── LICENSE                              # MIT
├── CONTRIBUTING.md                      # how to contribute
├── SECURITY.md                          # vulnerability disclosure
├── CHANGELOG.md                         # version history
├── .gitignore                           # protects keys + secrets
├── .gitattributes                       # cross-OS line endings (LF for .sh, CRLF for .ps1)
├── .editorconfig                        # editor defaults
│
├── docs/                                # 9 layered guides
│   ├── architecture.md                  # how the worker fits into Lightchain (sequence diagram included)
│   ├── installation-windows.md          # Windows install (winget + manual Foundry)
│   ├── installation-linux.md            # Linux install (apt + native Ollama + Foundry)
│   ├── installation-macos.md            # macOS install (Homebrew + Metal)
│   ├── onboarding.md                    # what each phase does, with verification steps
│   ├── operations.md                    # day-2: monitoring, sweeping, deregister
│   ├── troubleshooting.md               # 16 named failure modes with fixes
│   ├── security.md                      # threat model + hardening recommendations
│   └── faq.md                           # common questions
│
├── scripts/
│   ├── powershell/                      # Windows PowerShell scripts
│   │   ├── env.ps1                      # network selection + shared config
│   │   ├── secrets.example.ps1          # secrets template (copy to secrets.ps1)
│   │   ├── common.ps1                   # shared helpers (Invoke-Worker, etc.)
│   │   ├── 00-generate-key.ps1
│   │   ├── 01-resolve-addresses.ps1
│   │   ├── 02-prepare-ollama.ps1
│   │   ├── 03-pull-image.ps1
│   │   ├── 04-import-key.ps1
│   │   ├── 05-generate-ecdh.ps1
│   │   ├── 06-fund-worker.ps1
│   │   ├── 07-register.ps1
│   │   ├── 08-run-worker.ps1
│   │   ├── status.ps1
│   │   ├── stop.ps1
│   │   ├── tail-jobs.ps1
│   │   ├── deregister.ps1
│   │   └── sweep-rewards.ps1
│   │
│   └── bash/                            # Linux/macOS Bash scripts
│       ├── env.sh
│       ├── secrets.example.sh
│       ├── common.sh
│       ├── 00-generate-key.sh
│       ├── ... (mirrors powershell/)
│       └── sweep-rewards.sh
│
├── examples/
│   ├── env.example                      # every env var documented
│   ├── docker-compose.yml               # compose alternative to 08-run-worker.{ps1,sh}
│   └── systemd/
│       └── lightchain-worker.service    # systemd unit for unattended Linux operation
│
└── .github/
    ├── workflows/
    │   └── lint.yml                     # PSScriptAnalyzer + shellcheck + markdownlint
    ├── ISSUE_TEMPLATE/
    │   ├── bug_report.yml
    │   ├── feature_request.yml
    │   └── config.yml                   # Discord links etc.
    └── PULL_REQUEST_TEMPLATE.md

The 9 phases at a glance

flowchart LR
    P0[00 Generate<br/>worker key]
    P1[01 Resolve<br/>addresses]
    P2[02 Prepare<br/>Ollama]
    P3[03 Pull<br/>image]
    P4[04 Import<br/>key]
    P5[05 Generate<br/>ECDH]
    P6[06 Fund<br/>worker]
    P7[07 Register<br/>50k stake]
    P8[08 Run<br/>sidecar]

    P0 --> P1 --> P2 --> P3 --> P4 --> P5 --> P6 --> P7 --> P8

    P0 -.->|writes| S[(secrets.ps1)]
    P1 -.->|writes| R[(resolved.ps1)]
    P4 -.->|writes| K[~/lightchain-worker/keys/eth-keystore/]
    P5 -.->|writes| E[~/lightchain-worker/keys/worker-encryption.key]
    P7 -.->|on-chain| C[WorkerRegistry contract]
    P8 -.->|long-running| D[Docker container]
Loading
# Phase What changes Reversible? Time
00 Generate worker key New secp256k1 keypair, stored in secrets.ps1 Yes (delete the file, generate a fresh one) ~1 sec
01 Resolve addresses Reads 2 on-chain proxy addresses, persists locally Yes (just re-run) ~1 sec
02 Prepare Ollama Pulls llama3:8b if missing, creates llama3-8b alias Yes (ollama rm llama3-8b) 30s-5min
03 Pull image Downloads ~95 MB worker Docker image Yes (docker rmi) 30s-2min
04 Import key Writes encrypted keystore file to disk Yes (delete file, re-run) ~5 sec
05 Generate ECDH Writes worker-encryption.key to disk Yes BUT requires re-register if already registered ~5 sec
06 Fund worker On-chain tx: sends 50,005 LCAI funder → worker Yes (sweep back) ~10 sec
07 Register On-chain tx: stakes 50,000 LCAI Yes (deregister returns the stake minus any slashing) ~10 sec
08 Run sidecar Starts long-running container Yes (stop.ps1 removes it; registration + stake stay on-chain) ~3 sec

Costs and economics

Upfront, one-time (mainnet)

Item Amount
Stake (locked in WorkerRegistry) 50,000 LCAI
Funding tx gas < 0.01 LCAI
Registration tx gas < 0.05 LCAI
Gas buffer in worker wallet ~5 LCAI (recommended)
Total to fund ~50,005 LCAI

Per-job

Item Amount
Gas for ackJob < 0.0005 LCAI
Gas for completeJob < 0.0005 LCAI
Reward varies by AIConfig

Recoverable when you exit

Item Amount returned
Stake 50,000 LCAI (minus slashing)
Worker wallet balance at deregister Sweep with sweep-rewards

Testnet is identical in flow but free — claim LCAI from lightfaucet.ai instead of using real money.

Hardware requirements

Spec Minimum Recommended
CPU 4 cores x86_64 or Apple Silicon 8+ cores
RAM 16 GB 32 GB+
Storage 50 GB free 100 GB+ NVMe
GPU 8 GB VRAM (CUDA or Metal) 16-24 GB VRAM
Network 100 Mbps symmetric 1 Gbps

GPUs confirmed to work for llama3-8b (Q4 quantization, ~4.7 GB on disk, ~5-6 GB VRAM in use):

  • NVIDIA RTX 3060 / 3060 Ti / 3070 / 3080 / 3090, RTX 4060 Ti / 4070 / 4080 / 4090, RTX 5060 Ti, A4000 / A5000 / A6000 / L4 / A10 / A100.
  • Apple Silicon M1 Pro / M2 / M2 Pro / M3 / M3 Max / M4 / M4 Max (Metal acceleration is automatic).
  • AMD Radeon RX 7900 XT / XTX via ROCm (untested by us, reportedly works with Ollama 0.5+).

Cards with < 8 GB VRAM will OOM loading the model. CPU-only inference is too slow to be competitive.

Network reference

Resource Mainnet Testnet (verify on the run-node site)
Chain ID 9200 8200
Chain RPC https://rpc.mainnet.lightchain.ai https://rpc.testnet.lightchain.ai
Beacon API https://beacon.mainnet.lightchain.ai https://beacon.testnet.lightchain.ai
Worker Gateway https://worker-gateway.mainnet.lightchain.ai https://worker-gateway.testnet.lightchain.ai
Dispatcher https://dispatcher.mainnet.lightchain.ai -
Status page https://status.mainnet.lightchain.ai -
Worker image us-central1-docker.pkg.dev/lightchain/lightchain-mainnet-public-docker/worker:latest us-central1-docker.pkg.dev/lightchain/lightchain-testnet-public-docker/worker:latest
WorkerRegistry 0x0000000000000000000000000000000000001002 (genesis predeploy, same on both) same
AIConfig proxy 0x24D11533C354092ed6E18b964257819cE78Ce77D resolve via cast call $WORKER_REGISTRY_ADDRESS "aiConfig()(address)"
JobRegistry proxy 0xfB15F90298e4CcD7106E76fFB5e520315cC42B0b resolve via cast call $WORKER_REGISTRY_ADDRESS "jobRegistry()(address)"

AIConfig and JobRegistry are upgradeable proxies; the toolkit resolves them at runtime via Phase 01, so they auto-track any protocol upgrade.

Detailed guides

Guide When to read
docs/architecture.md Want to understand the 8 job-processing stages or the metrics endpoint.
docs/installation-windows.md Fresh Windows machine, need Docker + Ollama + Foundry.
docs/installation-linux.md Fresh Linux machine.
docs/installation-macos.md Fresh macOS machine (Apple Silicon or Intel).
docs/onboarding.md Want to know what each phase actually does and how to verify.
docs/operations.md You're past onboarding and want day-2 ops (monitor / sweep / deregister).
docs/troubleshooting.md Something is broken. Always check here first.
docs/security.md Want to understand the threat model + key management hardening.
docs/faq.md "How much can I earn?" / "Can I run this on a VPS?" / etc.

The gotchas this toolkit fixes for you

These are real failure modes we hit while running a mainnet worker. The toolkit defaults around them; the troubleshooting guide explains each in depth.

1. The model hash trap (stage 5)

The worker computes keccak256(SUPPORTED_MODELS) locally and uses that hash to look up incoming jobs. The gateway sends jobs keyed by keccak256("llama3-8b") = 0xf4a414fa.... If your SUPPORTED_MODELS is anything else ("llama3-8b:latest", "llama3:8b", "Llama3-8b"), the hash table miss causes every routed job to fail at stage 5 with:

ERROR job failed - stage 5 (resolve model): no local Ollama model configured for queued model ID "0xf4a414fa..."

The toolkit defaults SUPPORTED_MODELS=llama3-8b — the only string that matches what's registered on-chain. Do not change this unless you've also changed the on-chain registration via add-models.

2. The host.docker.internal IPv6 trap (Windows)

On Docker Desktop for Windows, host.docker.internal often resolves to an IPv6 address (fdc4:f303:9324::254). Some Go HTTP clients (including the worker's) stick with the first resolved address, and the IPv6 path can stall. The toolkit defaults OLLAMA_URL to the explicit IPv4 http://192.168.65.254:11434 on Windows for exactly this reason.

3. The benign WARN at startup

WARN ollama model verification failed (non-fatal) - missing models on Ollama server: [llama3-8b]

This fires every startup and does not block anything. The worker does a strict-string-equality check against Ollama's /api/tags, which always reports tagged names (llama3-8b:latest). The actual inference call at stage 6 uses the bare name and Ollama resolves it correctly. Ignore the WARN — troubleshooting.md covers this in depth.

4. The worker_ollama_up = 0 red herring

Even on a healthy, job-processing worker, this metric often stays at 0. It appears to be lazy/probe-updated rather than a continuous health signal. Don't panic — your worker is fine as long as websocket connected to gateway appears in the logs and you have no ERROR lines.

5. The undocumented Redis path

worker_heartbeat_last_emit_timestamp_seconds stays at 0 because the worker writes heartbeats to Redis, and the official docs never document a Redis URL. Best-effort interpretation: the gateway provides Redis credentials over the WS auth response if and when it needs them, and idle workers never get them. Doesn't block job processing.

6. Phase 06 doesn't need a persisted funder key

The toolkit's 06-fund-worker.{ps1,sh} reads $env:FUNDER_PRIVKEY from your shell session if set, otherwise prompts via Read-Host -AsSecureString / read -rs. Your funder key never needs to touch secrets.{ps1,env} on disk. This is much safer than the official docs' "set FUNDER_PRIVKEY=..." approach.

7. The friend's reminder: this is for workers, not chain nodes

If you see gsutil cp gs://lightchain-mainnet-backups-lightchain/... or AccessDeniedException 403, you've wandered into the chain-node install (Geth + Lighthouse). That requires private GCP access. Workers don't need any of it. This toolkit is the worker path — you're in the right place, just skip the chain-node detour.

See docs/troubleshooting.md for the full set of 16 named failure modes with symptoms and fixes.

Operations cheatsheet

# Day-to-day (Windows)
.\scripts\powershell\status.ps1                            # on-chain status
.\scripts\powershell\tail-jobs.ps1                         # watch jobs flow
docker logs -f lightchain-worker                            # all logs
.\scripts\powershell\stop.ps1                              # graceful stop
.\scripts\powershell\08-run-worker.ps1 -NoTail             # restart
.\scripts\powershell\sweep-rewards.ps1 -To 0xColdWallet    # move rewards out
.\scripts\powershell\deregister.ps1                        # reclaim 50k stake
# Day-to-day (Linux/macOS)
./scripts/bash/status.sh
./scripts/bash/tail-jobs.sh
docker logs -f lightchain-worker
./scripts/bash/stop.sh
./scripts/bash/08-run-worker.sh --no-tail
./scripts/bash/sweep-rewards.sh 0xColdWallet
./scripts/bash/deregister.sh

Full operations runbook in docs/operations.md.

Security model in one paragraph

The worker key (WORKER_PRIVKEY) lives in scripts/{powershell,bash}/secrets.{ps1,env} so it can be read by the container at startup. The toolkit ACL-restricts that file to your user account on first run and generates a strong random keystore password automatically. The much higher-value funder key (FUNDER_PRIVKEY) is never written to disk — Phase 06 reads it from a session env var or prompts for it interactively. Both the keystore on disk and the in-memory env are local-host-only; nothing is sent over the network. The 50,000 LCAI stake is locked in the on-chain WorkerRegistry contract; rewards land in the worker wallet's balance and you sweep them to a cold wallet on whatever cadence suits your risk tolerance. Treat the worker wallet as hot working capital, not savings. Full threat model and hardening recommendations in docs/security.md.

Contributing

PRs welcome — see CONTRIBUTING.md. The two highest-leverage contributions are (1) new entries in docs/troubleshooting.md for failure modes you hit and fixed, and (2) cross-platform compatibility improvements for OSes / distros we haven't tested.

Lint locally before pushing:

# Bash
shellcheck scripts/bash/*.sh

# PowerShell
Invoke-ScriptAnalyzer -Path scripts/powershell -Recurse -Severity Warning

# Markdown
npx markdownlint-cli2 "**/*.md"

CI runs the same checks on every PR via .github/workflows/lint.yml.

License

MIT. Use this however you like. No warranty.

Acknowledgements

  • The Lightchain team for building the protocol, the public worker image, and the runnable testnet.
  • Foundry (cast) for being a delight to script against.
  • Ollama for the cleanest "LLM-as-a-local-service" experience around.
  • Everyone in the Lightchain Discord who's shared logs and tracebacks — that collective body of knowledge is half this repo.

Not affiliated with or endorsed by Lightchain. This is an independent community toolkit. The official documentation is at workers-testnet.lightchain.ai/run-node.

About

Batteries-included PowerShell + Bash automation for running a Lightchain mainnet/testnet worker on your own hardware. 9 onboarding phases, 16 named failure modes solved, cross-platform from day one.

Topics

Resources

License

Contributing

Security policy

Stars

Watchers

Forks

Releases

No releases published

Packages

 
 
 

Contributors