Licensing
Pilot operates in two modes:
- Monitoring mode (free) - cluster overview, health monitoring, activity scoring, consumer groups, Prometheus metrics, read-only API
- Management mode (licensed) - partition redistribution, broker maintenance, topic config updates, quota management, ACL management, reassignment execution
License Format
Licenses are offline JWT tokens signed with Ed25519. No internet connection is required for validation - only for automatic license fetching.
Claims used: sub (customer), lic (license ID), iat, nbf, exp, plus optional notes. Clock skew leeway is 300 seconds.
Configuration
| Variable | Default | Description |
|---|---|---|
LICENSE_STRING | "" | JWT license token |
LICENSE_FETCH_SUBSCRIPTION_ID | "" | Subscription ID for auto-fetch |
LICENSE_FETCH_TOKEN | "" | Per-customer fetch token |
LICENSE_FETCH_URL | https://license.calinora.io/api/license/fetch | License fetch endpoint |
LICENSE_FETCH_INTERVAL | 1h | Auto-fetch interval |
Automatic Fetching
When LICENSE_FETCH_SUBSCRIPTION_ID and LICENSE_FETCH_TOKEN are set, Pilot fetches a fresh license automatically at the configured interval. This is the recommended approach for subscription and enterprise customers.
Manual Configuration
Set LICENSE_STRING directly with the JWT token:
# docker-compose.yml
environment:
LICENSE_STRING: "${LICENSE_STRING:-}"Manual Fetch
For environments without outbound internet, fetch the license externally and provide it via LICENSE_STRING:
curl -X POST "https://license.calinora.io/api/license/fetch" \
-H "Authorization: Bearer <FETCH_TOKEN>" \
-H "Content-Type: application/json" \
-d '{"subscription_id":"sub_123"}'Network Requirements
If using automatic license fetching, outbound HTTPS (port 443) access to license.calinora.io is required.
API
Check License Status
GET /api/v1/licenseResponse:
{
"success": true,
"data": {
"state": "licensed",
"expires_at": "2026-01-15T00:00:00Z",
"lic": "abc123-def456",
"sub": "CustomerName"
}
}Possible state values: licensed, trial, expired, invalid.
Quick test:
curl -s http://localhost:8080/api/v1/license | jq '.'License Enforcement
Mutating endpoints are protected by license middleware:
- Licensed endpoints return
403 Forbiddenwith a structured JSON error when the license is invalid or expired - Free endpoints (GET requests, proposal generation, what-if simulation) remain accessible regardless of license state
On Expiry
An expired or missing license never affects the cluster. Pilot falls back to monitoring mode: dashboards, health checks, proposals, and Prometheus metrics keep running; self-healing loops skip with the reason license_invalid and apply nothing; reassignments already submitted to Kafka complete normally. With automatic fetching, a renewed license takes effect at the next fetch without a restart; with LICENSE_STRING, update the value and restart Pilot.
See Features for which operations require a license.
Prometheus Metrics
| Metric | Description |
|---|---|
pilot_license_valid | 1 if licensed, 0 if expired/invalid |
pilot_license_expiry_timestamp_seconds | Unix timestamp of license expiry |
pilot_license_fetch_total | Auto-fetch attempts by result |
Alert when license expires within 7 days:
pilot_license_expiry_timestamp_seconds - time() < 7 * 24 * 3600