the control plane is the network coordinator. it is itself an attested agent that verifies nodes, routes traffic, and maintains the ledger.
| endpoint | description |
|---|---|
GET /health |
service health |
GET /v1/tunnel |
websocket for agents |
GET /v1/resolve/{app} |
proxy routing (public) |
POST /v1/proxy/{app} |
forward over ws tunnel |
GET /v1/apps |
admin list (auth required) |
GET /v1/apps/{app} |
admin detail |
POST /v1/credits/purchase - mint usd credits for a userPOST /v1/credits/transfer - transfer credits between accountsGET /v1/balances/{account} - account balancePOST /v1/usage/report - report usage for a periodPOST /v1/settlements/{period}/finalize - settle a periodPOST /v1/abuse/reports - file abuse report (launcher)POST /v1/abuse/reports/{id}/authorize - authorize abuse (owner)POST /v1/nodes/register - register node capacity, pricing, stakeGET /v1/nodes/{node} - admin node detailagent registers:
{
"type": "register",
"repo": "org/repo",
"release_tag": "v0.1.3",
"app_name": "myapp",
"network": "forge-1",
"agent_id": "uuid"
}
control plane challenges:
{
"type": "attest_request",
"nonce": "<hex>",
"deadline_s": 30,
"reason": "register"
}
agent responds:
{
"type": "attest_response",
"nonce": "<hex>",
"quote": "<base64>",
"report_data": "<hex>",
"measurements": {}
}
health heartbeat:
{"type": "health", "status": "pass"}
| network | policy | use case |
|---|---|---|
forge-1 |
sealed only | production |
sandbox-1 |
unsealed ok | development |
# server bind
EE_CONTROL_BIND=0.0.0.0
EE_CONTROL_PORT=8088
# attestation
EE_ALLOWLIST_ASSET=agent-attestation-allowlist.json
EE_PCCS_URL=https://pccs.example.com
EE_ATTEST_INTERVAL_SEC=3600
EE_ATTEST_DEADLINE_SEC=30
# registration
EE_REGISTRATION_TTL_DAYS=30
EE_REGISTRATION_WARN_DAYS=3
# auth
EE_ADMIN_TOKEN=secret
EE_GITHUB_TOKEN=ghp_xxx
EE_LAUNCHER_TOKEN=launcher_secret
EE_UPTIME_TOKEN=uptime_secret
# proxy
EE_PROXY_BIND=0.0.0.0
EE_PROXY_PORT=9090
# ledger
EE_DB_PATH=control_plane/data/control-plane.db
EE_HEALTH_TIMEOUT_SEC=120
python -m venv .venv
source .venv/bin/activate
pip install -r control_plane/requirements.txt
python control_plane/server.py
with docker:
docker compose -f control_plane/docker-compose.yml up --build
optional: update cloudflare dns via api (a/aaaa for control, control-direct, *.app):
export CLOUDFLARE_API_TOKEN=...
export CLOUDFLARE_ZONE=easyenclave.com
python control_plane/scripts/cloudflare_dns.py --ip 1.2.3.4 --proxied --dry-run
or enable auto-update on startup:
EE_DNS_UPDATE_ON_START=true
EE_DNS_AUTO_IP=true
EE_DNS_PROXIED=true
CLOUDFLARE_API_TOKEN=...
CLOUDFLARE_ZONE=easyenclave.com
the resolve endpoint returns backend status for your proxy:
curl https://control.easyenclave.com/v1/resolve/myapp
{
"app_name": "myapp",
"status": "active",
"endpoint": "wss://...",
"sealed": true,
"last_attest": "2024-01-15T10:30:00Z"
}
use nginx or another proxy to route based on this response.
if you proxy through cloudflare, use ssl/tls “full (strict)” so it connects to your origin over https. websockets are supported.
for wildcard tls on *.app, caddy uses cloudflare dns challenge and requires
CLOUDFLARE_API_TOKEN (dns edit) in the control plane env.
agents connect outbound (no inbound ports needed):
EE_CONTROL_WS=wss://control-direct.easyenclave.com:8088/v1/tunnel \
EE_REPO=owner/repo \
EE_RELEASE_TAG=v0.1.3 \
EE_APP_NAME=myapp \
EE_NETWORK=forge-1 \
EE_BACKEND_URL=http://127.0.0.1:8080 \
python agent/agent.py