Veil Stack is a decentralized container orchestration platform governed by an FEVM smart contract. Node coordination runs over libp2p, cluster state is managed on-chain, and a planned FHE layer will enable confidential scheduling for regulated workloads.
The long-term vision is to link every scheduled workload to a paid Filecoin storage deal, turning container orchestration into a programmatic demand engine for Filecoin's storage market. V1 establishes the on-chain governance and cluster networking foundation; V2 adds the Filecoin deal pipeline.
Canteen.sol is deployed on Filecoin Calibration at 0x686d5d622298cfca880168Badf83ac3F71C4a33A.
| Component | Status |
|---|---|
| Canteen.sol on FEVM Calibration (membership, image registry, status reporting) | Deployed and working |
| On-chain feedback loop (scheduler reports container state to contract) | Working |
| Web dashboard with D3 force-directed graph | Live at /dashboard/ |
| MetaMask connection with Filecoin Calibration (chain 314159) | Working |
| Read-only and MetaMask-signed contract operations | Working |
| libp2p cluster networking (TCP, Noise, mDNS, GossipSub) | Working |
| Docker container runtime (pull, create, start, stop, remove) | Working |
| Container resource limits (512MB memory, 50% CPU, restart policy) | Working |
| IPFS pinning via Pinata (container metadata, image manifests) | Working |
| Event-driven scheduler (MemberJoin, MemberLeave, MemberImageUpdate) | Working |
| Health checks (container status reported on-chain via StatusReport) | Working |
REST API (/status, /containers, /cluster, /ipfs) |
Working |
CLI tool (veilstack — status, containers, nodes, add-image) |
Working |
| CI/CD (GitHub Actions: contract tests + Docker compose build) | Passing |
| npm audit in CI | Passing |
| Docker Compose (one-command local deployment) | Working |
| Windows compatibility (Docker named pipe, cross-platform socket detection) | Working |
| Structured logging (JSON, timestamps, component tags) | Working |
| Graceful shutdown (SIGTERM/SIGINT handlers, container cleanup) | Working |
| Health check endpoint (/health) | Working |
| Pre-commit hooks (husky + lint-staged) | Working |
| Lockfile (package-lock.json) | Committed |
| CONTRIBUTING.md | Present |
| SECURITY.md | Present |
| CHANGELOG.md | Present |
| Edge case documentation | Present |
| Performance benchmarks | Present |
| OpenAPI spec | Present |
| StorageDeal struct + deal proposal from addImage() | Planned (V2) |
| Deal monitoring (proposed → active → expired/slashed) | Planned (V2) |
| CID-verified image retrieval | Planned (V2) |
| Multi-provider deal fallback | Planned (V2) |
| FHE confidential scheduling | Research |
┌──────────────────────────┐
│ Operator / Dashboard │
│ (React + D3 + Web3) │
└────────────┬─────────────┘
│
┌────────────────────┼────────────────────┐
│ │ │
▼ ▼ ▼
┌──────────────┐ ┌──────────────┐ ┌──────────────┐
│ FEVM │ │ FEVM │ │ FEVM │
│ Contract │◄──►│ Contract │◄──►│ Contract │
│ (Canteen) │ │ (Canteen) │ │ (Canteen) │
└──────┬───────┘ └──────┬───────┘ └──────┬───────┘
│ StatusReport │ StatusReport │
▼ ▼ ▼
┌──────────────┐ ┌──────────────┐ ┌──────────────┐
│ Veil Node A │◄──►│ Veil Node B │◄──►│ Veil Node C │
│ (libp2p) │ │ (libp2p) │ │ (libp2p) │
│ + scheduler │ │ + scheduler │ │ + scheduler │
└──────┬───────┘ └──────┬───────┘ └──────┬───────┘
│ │ │
▼ ▼ ▼
┌──────────────┐ ┌──────────────┐ ┌──────────────┐
│ Docker Host │ │ Docker Host │ │ Docker Host │
└──────────────┘ └──────────────┘ └──────────────┘
│ │ │
└────────────────────┼────────────────────┘
│
▼
┌──────────────────┐
│ Filecoin Network │
│ (Calibration → │
│ Mainnet) │
└──────────────────┘
Components:
| Component | Description |
|---|---|
| Canteen.sol (FEVM) | Smart contract on Filecoin EVM: cluster membership, image registry, status reporting, replica rebalancing, port mapping |
| Dashboard | React + D3 frontend connected via Web3 to Canteen.sol; reads contract state, visualizes cluster topology |
| Veil Node (libp2p) | Peer-to-peer node with TCP transport, Noise encryption, mDNS/bootstrap discovery, GossipSub heartbeat gossip |
| Scheduler | Listens for FEVM events, manages Docker containers, reports container status back to contract (feedback loop) |
| REST API | Express endpoints: /status, /containers, /cluster, /ipfs for backend introspection |
CLI (veilstack) |
Command-line tool for cluster inspection: status, containers, nodes |
| IPFS Service | Pins deployment manifests to IPFS via Pinata for verifiable, tamper-evident storage |
| Filecoin Network | Target chain for FEVM contract and Filecoin deal origination (Calibration testnet now, mainnet planned) |
| Docker Socket Proxy | tecnativa/docker-socket-proxy sidecar; exposes a restricted Docker API over TCP |
| Document | Description |
|---|---|
| CONTRIBUTING.md | Development setup, code style, PR guidelines |
| SECURITY.md | Vulnerability reporting, threat model, known limitations |
| CHANGELOG.md | Version history and notable changes |
| docs/EDGE_CASES.md | Failure modes and recovery behavior at each layer |
| docs/BENCHMARKS.md | Performance measurements and scalability limits |
| docs/openapi.yaml | OpenAPI 3.0 spec for REST API |
Veil Stack implements a closed feedback loop between nodes and the on-chain contract:
- Scheduler starts → bootstraps by checking on-chain registration via
getMemberDetails() - Event poller → detects
MemberJoin,MemberLeave,MemberImageUpdate,StatusReportevents - Container lifecycle → scheduler pulls image, creates container with resource limits (512MB RAM, 50% CPU)
- Status reporting → after container start/stop, scheduler calls
reportStatus(host, image, state)on-chain - On-chain state → contract stores
{image, state, lastReported}per member, emitsStatusReportevent - Other nodes observe →
StatusReportevents are gossiped via GossipSub and logged by peer schedulers
This means cluster state is always verifiable on-chain — any observer can call getMemberStatus(host) to see what image a node is running and whether it's running, stopped, or crashed.
| Endpoint | Method | Description |
|---|---|---|
GET /health |
GET | Health check: status, uptime, version |
GET /status |
GET | Node status: host, container image/state, Docker availability, read-only mode |
GET /containers |
GET | List all Docker containers managed by this node (id, image, name, state, ports) |
GET /cluster |
GET | Cluster topology: host, peerId, peers, members, multiaddrs |
GET /ipfs |
GET | List pinned IPFS records (requires Pinata keys) |
POST /ipfs |
POST | Pin a JSON manifest to IPFS ({name, data}) |
DELETE /ipfs/:cid |
DELETE | Unpin a CID from IPFS |
Example — /status response:
{
"host": "veil-node-abc123",
"container": {
"image": "nginx:latest",
"state": "running",
"lastReported": 1700000000
},
"docker": true,
"readOnlyMode": true,
"registered": true
}| Feature | Description |
|---|---|
| Canteen.sol on FEVM Calibration | Member management, image registry, status reporting, rebalancing, port mapping |
| Dashboard integration | Read contract state, register nodes, add/remove images via MetaMask on Filecoin Calibration |
| Event-driven scheduler | Listens for on-chain events; schedules Docker containers accordingly |
| On-chain feedback loop | Scheduler reports container state back to contract; cluster state verifiable on-chain |
| IPFS pinning | Each deployment manifest pinned to IPFS via Pinata for verifiability |
| Feature | Description |
|---|---|
| StorageDeal struct | On-chain record: dealId, providerId, payloadCid, size, term |
| filecoin-service | Backend module integrating Lotus JSON-RPC for deal proposal and monitoring |
| Deal lifecycle | addImage() proposes a deal, monitors proposed → active → expired/slashed transitions |
| CID-verified retrieval | Before pulling an image, verify its CID matches the on-chain deal commitment |
| Multi-provider fallback | Re-propose to next available provider if one goes offline |
The live dashboard at https://veil-stack-canteen.vercel.app/dashboard/ provides:
- Cluster visualization — D3 force-directed graph of active Veil nodes with their assigned images
- Contract state — List of deployed images, member count, contract address, Web3 and cluster connectivity
- MetaMask integration — Connect with Filecoin Calibration to register nodes, add/remove images
- Live container status — On-chain
StatusReportdata shows node health
Note on D3 version: The dashboard uses D3 v4 (pinned) because the force-directed graph relies on
d3.eventfor drag interactions, which was removed in D3 v6. Upgrading D3 requires rewriting the drag handlers.
Environment (.env):
REACT_APP_FIL_CONTRACT_ADDRESS=0x686d5d622298cfca880168Badf83ac3F71C4a33A
REACT_APP_FIL_RPC_URL=https://api.calibration.node.glif.io/rpc/v1
REACT_APP_FIL_CHAIN_ID=314159
REACT_APP_CLUSTER_URL=http://localhost:5001/cluster
IPFS pinning (optional — requires Pinata keys):
PINATA_API_KEY=<your-api-key>
PINATA_SECRET_KEY=<your-secret-key>
Veil Stack includes a command-line tool for cluster inspection:
# Install globally
npm install -g ./canteen
# Or run directly
node canteen/veilstack.js <command>| Command | Description |
|---|---|
veilstack status |
Chain, contract, members, images, and backend status |
veilstack containers |
List running Docker containers managed by the scheduler |
veilstack nodes |
Cluster topology and libp2p peer info |
veilstack add-image <name> [replicas] |
Check image status on contract |
veilstack help |
Show help |
One-command local deployment:
cd canteen
docker compose up --buildThis starts the canteen node with Docker socket access, connected to Filecoin Calibration.
Veil Stack plans to support encrypted scheduling inputs using Zama's Universal FHE SDK for zero-trust and regulated environments:
- Encrypted telemetry: Nodes encrypt CPU, memory, and disk metrics before gossiping via libp2p heartbeats
- Ciphertext scheduling: Scheduling cost functions execute on encrypted inputs — no node sees another's raw metrics
- Toggle-able:
VEIL_FHE_MODE=enabled|disabled— plaintext scheduling is the default; FHE is ON for sensitive clusters
This is a planned feature for clusters that need confidentiality (healthcare, defense, cross-cloud ML). The core scheduling pipeline works without it.
Connect to the live deployment:
Open the dashboard at https://veil-stack-canteen.vercel.app/dashboard/ and connect MetaMask to Filecoin Calibration (chain ID 314159).
Run a local node:
# Clone the repository
git clone https://github.com/shivv23/Veil-Stack.git
cd Veil-Stack/canteen
# Install dependencies
npm install
# Configure
cp .env.example .env
# Edit .env with your settings
# Start a Veil node
npm startBuild the dashboard:
Node.js requirement: The dashboard uses react-scripts 3.x which requires Node 16 or the
--openssl-legacy-providerflag on Node 17+. Node 16 LTS is recommended for builds.
cd canteen/dashboard
npm install
NODE_OPTIONS=--openssl-legacy-provider npm run buildRun tests:
# Contract tests (requires Ganache)
npm run ganache &
sleep 3
npm run test:contracts
# Integration tests (requires running backend)
npm run test:integration
# Security audit
npm run audit| Priority | Feature | Status |
|---|---|---|
| P0 | Canteen.sol on FEVM Calibration | Done |
| P0 | Web dashboard with D3 visualization | Done |
| P0 | libp2p cluster networking | Done |
| P0 | Docker container management | Done |
| P0 | IPFS deployment pinning | Done |
| P0 | On-chain feedback loop (reportStatus) | Done |
| P0 | Container resource limits & health checks | Done |
| P0 | REST API (/status, /containers, /cluster) | Done |
| P0 | CLI tool (veilstack) | Done |
| P0 | CI/CD pipeline (GitHub Actions) | Done |
| P0 | Docker Compose deployment | Done |
| P0 | V2 contract with StorageDeal + DealAnchored | Planned |
| P0 | Filecoin deal proposal and monitoring | Planned |
| P0 | CID-verified image retrieval | Planned |
| P0 | Deal lifecycle dashboard visualization | Planned |
| P1 | Multi-provider deal fallback | Planned |
| P1 | Mainnet migration | Future |
| P2 | Zama FHE confidential scheduling | Research |
| P2 | 10-node cluster CI + federation model | Research |
| P3 | Security audit | Planned |
MIT