LanternDOCS

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.

Control PlaneLantern SaaS or self-hosted · Scheduling · Routing · Dashboard
⇅ outbound-only gRPC (mTLS) · :50051 · data plane dials OUT, no inbound ports needed
Data PlaneYour VPC (AWS / GCP / Azure) · microVMs · secrets · run payloads

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.

Best for: getting started and workloads without strict data residency requirements.

Hybrid (recommended for production)

Control plane hosted by Lantern; data plane in your cloud. Agent data stays in your VPC.

  1. Deploy the data plane Helm chart into your cluster (see below).
  2. Register via POST /v1/data-planes or Settings → Data Planes. This mints a one-time 32-byte bootstrap token — store it immediately.
  3. The data plane dials out to :50051 (gRPC), sends the bootstrap token via Register RPC, and receives a short-lived session JWT (1 h TTL, auto-rotated via RefreshToken).
  4. The data plane opens a persistent RunStream bidi 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.

RPCDirectionPurpose
Registeragent → CPExchange bootstrap token for session JWT
Heartbeatagent → CPLiveness (every 30 s); learns drain orders
ReportMetricsagent → CPCPU / memory / active-run pressure (every 60 s)
RefreshTokenagent → CPRotate session JWT before 1 h expiry
RunStream (bidi)agent ↔ CPCP pushes assignments; agent reports accepted / completed
Per-tenant cap: up to 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.

Operational overhead: you manage Postgres, Redis, and Kubernetes. Ensure your team has the capacity before choosing this path.

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: true

Terraform

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 0001 creates the full schema on first boot.
  • Existing databases0001 is fully IF NOT EXISTS; running it records version 1 in schema_migrations with no DDL changes.
  • New changes — sequential pairs (0002_*.up.sql / 0002_*.down.sql). Down migrations required after the baseline.
Only the control plane runs migrations. Other services read and write tables but never apply schema changes.