Skip to main content

Self-Hosting L{CORE}

Run your own L{CORE} infrastructure with Docker Compose.

Why Self-Host?

BenefitDescription
No Lock-InDeploy on any EVM chain. Run on any infrastructure. Switch chains without rewriting your application.
No FeesZero protocol fees. Zero token requirements. You pay gas costs on your chosen chain—that's it.
Self-SovereignRun your own attestors. Own your infrastructure. No dependency on external networks or third-party uptime.

Infrastructure Requirements

ComponentMinimumRecommended
CPU2 cores4+ cores
RAM4 GB8+ GB
Storage20 GB SSD50+ GB SSD
Network100 Mbps1 Gbps

Supported Deployment Targets

TargetStatusNotes
Self-hosted (bare metal)✅ SupportedFull control, lowest cost
AWS EC2 / ECS✅ SupportedAny instance type
GCP Compute / GKE✅ SupportedAny machine type
Azure VMs / AKS✅ SupportedAny VM size
EigenCloud TEE✅ RecommendedFull 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:

VariableDescription
PRIVATE_KEYYour wallet private key (0x...)
LCORE_RPC_URLArbitrum Sepolia RPC endpoint
LCORE_DAPP_ADDRESSCartesi DApp address (see step 4)
LCORE_ADMIN_PUBLIC_KEYNaCl public key (from step 2)
LCORE_ADMIN_PRIVATE_KEYNaCl private key (from step 2)
PROOF_SIGNING_KEY32-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

  1. Check logs: docker-compose logs attestor
  2. Verify all required env vars are set
  3. Ensure wallet has funds for gas

Cartesi node not syncing

  1. Check logs: docker-compose logs cartesi
  2. Verify LCORE_DAPP_ADDRESS is correct
  3. Check RPC endpoint is accessible
  4. Ensure contract was deployed to correct network

Connection refused

  1. Check services are running: docker-compose ps
  2. Verify ports aren't in use: lsof -i :8001 and lsof -i :10000
  3. Check firewall rules

Out of gas

  1. Fund your wallet with more Arbitrum Sepolia ETH
  2. Get testnet ETH from: https://sepoliafaucet.com

Production Deployment

For production with TEE (Trusted Execution Environment), deploy to EigenCloud:

  1. 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 .
  2. Push to your registry

  3. 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