Self-Hosting L{CORE}
Run your own L{CORE} infrastructure with Docker Compose.
Why Self-Host?
| Benefit | Description |
|---|---|
| No Lock-In | Deploy on any EVM chain. Run on any infrastructure. Switch chains without rewriting your application. |
| No Fees | Zero protocol fees. Zero token requirements. You pay gas costs on your chosen chain—that's it. |
| Self-Sovereign | Run your own attestors. Own your infrastructure. No dependency on external networks or third-party uptime. |
Infrastructure Requirements
| Component | Minimum | Recommended |
|---|---|---|
| CPU | 2 cores | 4+ cores |
| RAM | 4 GB | 8+ GB |
| Storage | 20 GB SSD | 50+ GB SSD |
| Network | 100 Mbps | 1 Gbps |
Supported Deployment Targets
| Target | Status | Notes |
|---|---|---|
| Self-hosted (bare metal) | ✅ Supported | Full control, lowest cost |
| AWS EC2 / ECS | ✅ Supported | Any instance type |
| GCP Compute / GKE | ✅ Supported | Any machine type |
| Azure VMs / AKS | ✅ Supported | Any VM size |
| EigenCloud TEE | ✅ Recommended | Full security guarantees |
Prerequisites
- Docker and Docker Compose installed
- Funded wallet on your target EVM chain (for gas fees)
- RPC endpoint from Alchemy, Infura, QuickNode, or similar
Quick Start
1. Clone the Repository
git clone https://github.com/Modern-Society-Labs/lcore-sdk.git
cd lcore-sdk
2. Generate Keys
Generate the required cryptographic keys:
# Generate NaCl keypair for L\{CORE\} encryption
node -e "
const nacl = require('tweetnacl');
const kp = nacl.box.keyPair();
console.log('LCORE_ADMIN_PUBLIC_KEY=' + Buffer.from(kp.publicKey).toString('base64'));
console.log('LCORE_ADMIN_PRIVATE_KEY=' + Buffer.from(kp.secretKey).toString('base64'));
"
# Generate proof signing key
node -e "console.log('PROOF_SIGNING_KEY=' + require('crypto').randomBytes(32).toString('hex'))"
3. Configure Environment
# Copy the template
cp .env.example .env
# Edit with your values
nano .env # or your preferred editor
Required values:
| Variable | Description |
|---|---|
PRIVATE_KEY | Your wallet private key (0x...) |
LCORE_RPC_URL | Arbitrum Sepolia RPC endpoint |
LCORE_DAPP_ADDRESS | Cartesi DApp address (see step 4) |
LCORE_ADMIN_PUBLIC_KEY | NaCl public key (from step 2) |
LCORE_ADMIN_PRIVATE_KEY | NaCl private key (from step 2) |
PROOF_SIGNING_KEY | 32-byte hex string (from step 2) |
4. Deploy Cartesi Application (First Time Only)
If you need your own Cartesi DApp:
# Install Cartesi CLI
npm install -g @cartesi/cli
# Build the RISC-V image
cd cartesi
cartesi build
# Deploy to Arbitrum Sepolia
export CARTESI_PRIVATE_KEY=0x... # Your private key
cartesi deploy --network arbitrum-sepolia
# Note the Application Address from output
# Update LCORE_DAPP_ADDRESS in your .env
Or use our shared testnet deployment:
LCORE_DAPP_ADDRESS=0xAE0863401D5B953b89cad8a5E7c98f5136E9C26d
5. Start Services
docker-compose up -d
6. Verify
# Check attestor health
curl http://localhost:8001/healthcheck
# Expected response:
# {"status":"ok","version":"5.0.0","lcore_enabled":true}
# Check Cartesi node
curl "http://localhost:10000/inspect/$(python3 -c "import urllib.parse; print(urllib.parse.quote('{\"type\":\"health\"}'))")"
Architecture
L{CORE} Self-Hosting Architecture
YOUR SERVER
Attestor
:8001
- REST API
- zkTLS
- Validation
Cartesi Node
:10000
- SQLite storage
- Privacy buckets
- Inspect queries
Arbitrum Sepolia
RPC
InputBox
Contract
Common Operations
View Logs
# All services
docker-compose logs -f
# Just attestor
docker-compose logs -f attestor
# Just Cartesi
docker-compose logs -f cartesi
Restart Services
docker-compose restart
Stop Services
docker-compose down
Update to Latest Version
docker-compose pull
docker-compose up -d
Reset Data
docker-compose down -v # Removes volumes
docker-compose up -d
Troubleshooting
Attestor won't start
- Check logs:
docker-compose logs attestor - Verify all required env vars are set
- Ensure wallet has funds for gas
Cartesi node not syncing
- Check logs:
docker-compose logs cartesi - Verify
LCORE_DAPP_ADDRESSis correct - Check RPC endpoint is accessible
- Ensure contract was deployed to correct network
Connection refused
- Check services are running:
docker-compose ps - Verify ports aren't in use:
lsof -i :8001andlsof -i :10000 - Check firewall rules
Out of gas
- Fund your wallet with more Arbitrum Sepolia ETH
- Get testnet ETH from: https://sepoliafaucet.com
Production Deployment
For production with TEE (Trusted Execution Environment), deploy to EigenCloud:
-
Build images for EigenCloud:
docker build -f attestor.dockerfile -t your-registry/lcore-attestor:eigencloud .
docker build -f cartesi-node.dockerfile -t your-registry/lcore-cartesi:eigencloud . -
Push to your registry
-
Deploy on EigenCloud dashboard
See EigenCloud Deployment for detailed instructions.
Running Attestor Locally (Development)
For local development without Docker:
1. Clone and Install
git clone https://github.com/Modern-Society-Labs/lcore-sdk.git
cd lcore-sdk/attestor
npm install
2. Configure Environment
cp .env.sample .env
# Edit .env with your values
3. Run
npm run start:tsc
Server starts on port 8001 by default.
Enabling TOPRF
TOPRF (Thresholded OPRF) obscures sensitive data consistently:
# Generate keys
npm run generate:toprf-keys
# Add to .env:
# TOPRF_PUBLIC_KEY=...
# TOPRF_SHARE_PUBLIC_KEY=...
# TOPRF_SHARE_PRIVATE_KEY=...
Enabling Authentication
For private attestors:
# Add to .env:
AUTHENTICATION_PUBLIC_KEY=0x123456789...
All unauthenticated connections will be rejected.
Next Steps
- SDK Usage Guide - Using the TypeScript SDK
- Configuration Reference - All environment variables
- IoT Patterns - Integrating IoT devices