Deployment
Lantern splits into a control plane (scheduling, routing, dashboard) and a data plane (microVMs, execution, secrets). The data plane runs in your cloud — agent data never leaves your VPC.
Deployment options
Fully managed (Lantern Cloud)
Both planes hosted by Lantern. No infrastructure to manage. Sign up at lantern.run, create agents from the dashboard, everything runs on Lantern infrastructure.
Hybrid (recommended for production)
Control plane hosted by Lantern; data plane in your cloud. Agent data stays in your VPC.
- Deploy the data plane Helm chart into your cluster (see below).
- Register via
POST /v1/data-planesor Settings → Data Planes. This mints a one-time 32-byte bootstrap token — store it immediately. - The data plane dials out to
:50051(gRPC), sends the bootstrap token viaRegisterRPC, and receives a short-lived session JWT (1 h TTL, auto-rotated viaRefreshToken). - The data plane opens a persistent
RunStreambidi RPC. The control plane pushes run assignments; the agent reports status and completion back. Only run metadata crosses the boundary.
Tunnel RPCs
Defined in packages/proto/lantern/v1/dataplane.proto, served on the control plane's :50051 listener.
| RPC | Direction | Purpose |
|---|---|---|
Register | agent → CP | Exchange bootstrap token for session JWT |
Heartbeat | agent → CP | Liveness (every 30 s); learns drain orders |
ReportMetrics | agent → CP | CPU / memory / active-run pressure (every 60 s) |
RefreshToken | agent → CP | Rotate session JWT before 1 h expiry |
RunStream (bidi) | agent ↔ CP | CP pushes assignments; agent reports accepted / completed |
LANTERN_DP_MAX_STREAMS_PER_TENANT concurrent RunStream connections (default 10). Excess connections return gRPC RESOURCE_EXHAUSTED.Fully self-hosted
Both planes in your infrastructure. Full control, full responsibility.
Helm
helm repo add lantern https://charts.lantern.run && helm repo update
# Data plane only (hybrid mode)
helm install lantern-data-plane lantern/data-plane \
--namespace lantern --create-namespace \
--set controlPlane.endpoint=https://api.lantern.run \
--set controlPlane.token=$LANTERN_DATA_PLANE_TOKEN \
--set firecracker.enabled=true
# Full self-hosted stack
helm install lantern lantern/lantern \
--namespace lantern --create-namespace \
--values values.yaml# values.yaml
controlPlane:
replicas: 3
database:
host: your-postgres-host
name: lantern
user: lantern
passwordSecret: lantern-db-credentials
redis:
host: your-redis-host
dataPlane:
firecracker:
enabled: true
snapshotBucket: s3://your-bucket/snapshots
resources:
limits:
cpu: "4"
memory: "8Gi"
ingress:
enabled: true
host: lantern.yourcompany.com
tls:
enabled: trueTerraform
AWS
module "lantern" {
source = "lantern-ai/lantern/aws"
version = "~> 0.1"
cluster_name = "lantern-production"
vpc_id = module.vpc.vpc_id
subnet_ids = module.vpc.private_subnets
db_instance_class = "db.r6g.large"
node_instance_type = "m6i.xlarge"
node_count = 3
snapshot_bucket = "my-lantern-snapshots"
}GCP
module "lantern" {
source = "lantern-ai/lantern/gcp"
version = "~> 0.1"
project_id = "my-project"
region = "us-central1"
db_tier = "db-custom-4-16384"
node_machine_type = "e2-standard-4"
node_count = 3
}Azure
module "lantern" {
source = "lantern-ai/lantern/azure"
version = "~> 0.1"
resource_group = "lantern-production"
location = "eastus"
db_sku_name = "GP_Standard_D4s_v3"
node_vm_size = "Standard_D4s_v3"
node_count = 3
}Namespace isolation
Each tenant gets its own Kubernetes namespace: lantern-t-<tenant_id>. Provides network isolation, per-tenant resource quotas, and separate service accounts and secrets.
Monitoring
Every service emits OTel traces tagged with tenant_id, run_id, step_id, and agent_version. Compatible with Grafana + Tempo, Datadog, New Relic, Jaeger, and any OTel backend. Production alert rules, Grafana dashboards, and runbooks live in infra/monitoring/ and docs/runbooks/. See Observability for details.
Database migrations
The control plane manages its Postgres schema via golang-migrate. Migrations are embedded SQL shipped inside the binary.
- Fresh databases — migration
0001creates the full schema on first boot. - Existing databases —
0001is fullyIF NOT EXISTS; running it records version 1 inschema_migrationswith no DDL changes. - New changes — sequential pairs (
0002_*.up.sql/0002_*.down.sql). Down migrations required after the baseline.