Docs · how to

Self-host the control plane

Run your own denv control plane, on a laptop with SQLite or in your AWS account with the CDK stacks.

The managed service at api.denv.ai is the same code. Labs that need the control plane inside their own network run it themselves: one container, one database, nothing else.

On one machine, with SQLite

git clone https://github.com/opencrew-ai/denv-backend && cd denv-backend
make build
DENV_BOOTSTRAP_KEY=dak_local ./bin/denv-cp -addr :8080 -db ./denv.db -public-url http://<this host>:8080

The bootstrap key is the first team's API key. Sidecars on other machines reach the control plane at -public-url, so it must be an address they can open; nothing on the control plane dials out to them.

To run it as a container:

make image
docker run -d --name denv-cp -p 8080:8080 -v denv:/data -e DENV_DB=/data/denv.db -e DENV_PUBLIC_URL=http://<this host>:8080 -e DENV_BOOTSTRAP_KEY=dak_local denv-cp

In your AWS account, with the CDK stacks

The repository's infra/ directory holds four stacks: a VPC, a DynamoDB table, the Fargate service behind an HTTPS load balancer with its Route 53 zone and certificate, and CloudFront distributions for the install script and the site.

cd infra && npm install
AWS_PROFILE=<profile> npx cdk bootstrap --qualifier denv --toolkit-stack-name CDKToolkit-denv
AWS_PROFILE=<profile> npx cdk deploy DenvNetwork DenvData DenvControlPlane --require-approval never

The control-plane stack creates a public hosted zone for the domain and waits for certificate validation. Point the domain's nameservers at the zone's NameServers output at your registrar; once they resolve, validation completes and the stack finishes. Then deploy DenvEdge the same way and publish the sidecar binaries with make release.

To use a hosted zone that already exists: npx cdk deploy -c hostedZoneId=<id> ….

Configuration

Variable Meaning
DENV_DB path.db for SQLite, or dynamodb://<table>?region=<region>
DENV_PUBLIC_URL the URL sidecars and cloud-init use to reach the control plane
DENV_CONSOLE_URL the console's origin; enables CORS and sets the device-flow verification page
DENV_GITHUB_CLIENT_ID, DENV_GITHUB_CLIENT_SECRET GitHub OAuth app for sign-in; callback <public url>/auth/github/callback
DENV_GITHUB_APP_ID, DENV_GITHUB_APP_PRIVATE_KEY, DENV_GITHUB_WEBHOOK_SECRET GitHub App for push-to-deploy; webhook <public url>/webhooks/github
DENV_DEV_LOGIN 1 enables POST /auth/dev-login for local use without GitHub
DENV_BOOTSTRAP_KEY the first team's API key, used once on an empty database
DENV_RELEASES_DIR directory the control plane serves denvd binaries from

The full list is in the control plane configuration reference.

What runs where

Only the control plane runs in your account from these stacks. Environments run on the targets you connect; the control plane holds teams, projects, versions, deployments and verdicts, never environment data. One task is enough for the control plane today; the sidecar hub is in-process, so run a single task until commands are routed through the database.