Skip to main content
InfraGap.com Logo
Home
Getting Started
Core Concept What is a CDE? How It Works Benefits CDE Assessment Getting Started Guide Inner Loop vs Outer Loop Environment Drift Local vs Cloud CDEs for Startups
AI & Automation
AI Coding Assistants Agentic AI AI-Native IDEs Agentic Engineering AI Agent Orchestration AI Governance AI-Assisted Architecture Shift-Left AI LLMOps Autonomous Development AI/ML Workloads CDEs for Data Science GPU Computing
Agent Infrastructure
Agent Experience (AX) Agent Egress Control Computer Use Agents Agent Evals Agent Runbooks Agent Client Protocol AGENTS.md MCP Servers Git Worktrees Kubernetes Agent Sandbox Agent Fleets Agent Identity Prompt Injection Defense Agent Observability Context Engineering AI Code Review Bottleneck Headless Agents in CI Spec-Driven Development Agent Readiness Code Provenance
Implementation
Architecture Patterns DevContainers Advanced DevContainers Language Quickstarts IDE Integration CI/CD Integration Platform Engineering Developer Portals Container Registry Multi-CDE Strategies Remote Dev Protocols Nix Environments Hermetic Builds OpenTofu for CDEs Kubernetes Development
Operations
Performance Optimization High Availability & DR Disaster Recovery Monitoring Capacity Planning Multi-Cluster Development Troubleshooting Runbooks Ephemeral Environments Sandbox Environments Workspace Snapshots Database Branching
Security
Security Deep Dive Zero Trust Architecture Secrets Management Vulnerability Management Network Security IAM Guide Supply Chain Security Air-Gapped Environments AI Agent Security MicroVM Isolation Compliance Guide EU AI Act Cyber Resilience Act Data Residency Governance
Planning
Pilot Program Design Stakeholder Communication Risk Management Migration Guide Cost Analysis FinOps GreenOps Vendor Evaluation Training Resources Developer Onboarding Team Structure Platform Maturity Model Open Source CDEs AI Productivity Paradox Build vs Buy DevEx Metrics Productivity Engineering Industry Guides CDEs for Healthcare CDEs for Financial Services CDEs for Government Edge Development WebAssembly in CDEs
Resources
Tools Comparison State of CDEs 2026 Isolation Decision Tool Template Library
Learning Paths
All Paths Platform Engineer Security and Compliance Engineering Manager
Vendor Reviews
GitHub Codespaces Coder Ona Google Workstations Microsoft Dev Box Okteto Eclipse Che DevPod Daytona E2B
Head to Head
Coder vs Codespaces Coder vs Ona Ona vs Codespaces Coder vs Okteto Self-Hosted vs Managed E2B vs Daytona CDE Market Guide CDE vs Alternatives Case Studies Lessons Learned Glossary FAQ Sources & Citations

CDE Template Library

The artifacts from across this site collected in one place - environment definitions, agent policy, decision records, and the runbook you want written before you need it

Every template links back to the page that explains it. Each one states what it is for and what it deliberately leaves out.

How to Use These

These are starting points, not finished configurations. Each is short enough to read in full before you commit it, which is the property that matters most: a template you paste without reading is a template you cannot defend in a review. Placeholders sit in angle brackets so an unedited one fails loudly rather than quietly doing something plausible.

The agent identity scheme and the egress policy are security controls. Treat them as sketches of a shape, not as hardened policy - the pages they come from carry the failure modes, which is why every template links back to one.

Environment Definitions

Baseline devcontainer.json

For: the annotated reference that shows every field you are likely to need, so you can delete down to what you actually use.

Not for: production images. It has no pinned digests, no non-root hardening, and no build cache strategy. From DevContainers.

.devcontainer/devcontainer.json
{
  "name": "My Dev Container",
  "image": "mcr.microsoft.com/devcontainers/typescript-node:1-20-bullseye",

  // Or build from Dockerfile
  "build": {
    "dockerfile": "Dockerfile",
    "context": ".."
  },

  // Features - modular add-ons
  "features": {
    "ghcr.io/devcontainers/features/git:1": {},
    "ghcr.io/devcontainers/features/docker-in-docker:2": {}
  },

  // Lifecycle scripts
  "postCreateCommand": "npm install",
  "postStartCommand": "npm run dev",

  "customizations": {
    "vscode": {
      "extensions": [
        "dbaeumer.vscode-eslint",
        "esbenp.prettier-vscode"
      ],
      "settings": {
        "editor.formatOnSave": true
      }
    }
  },

  "forwardPorts": [3000, 5432],

  "containerEnv": {
    "NODE_ENV": "development"
  }
}

Python and Go recipes

For: two concrete single-language stacks with the test and lint wiring already in place.

Not for: dependency resolution. Both call a package manager at create time, which means a slow first start and a build that can drift. Full versions, including debugger configuration, are on Quickstarts.

python/devcontainer.json
{
  "name": "Python 3.13",
  "image": "mcr.microsoft.com/devcontainers/python:3.13",

  "features": {
    "ghcr.io/devcontainers/features/python:1": {
      "version": "3.13",
      "installJupyterlab": true
    },
    "ghcr.io/devcontainers/features/git:1": {}
  },

  "customizations": {
    "vscode": {
      "extensions": ["ms-python.python", "charliermarsh.ruff"],
      "settings": { "python.testing.pytestEnabled": true }
    }
  },

  "forwardPorts": [8000, 8888, 5000],
  "postCreateCommand": "pip3 install --user -r requirements.txt",
  "remoteUser": "vscode"
}
go/devcontainer.json
{
  "name": "Go 1.23",
  "image": "mcr.microsoft.com/devcontainers/go:1.23",

  "features": {
    "ghcr.io/devcontainers/features/go:1": {
      "version": "1.23"
    },
    "ghcr.io/devcontainers/features/git:1": {}
  },

  "customizations": {
    "vscode": {
      "extensions": ["golang.go"],
      "settings": {
        "go.lintTool": "golangci-lint",
        "go.testFlags": ["-v", "-race"]
      }
    }
  },

  "forwardPorts": [8080, 9000],
  "postCreateCommand": "go mod download && go install -v golang.org/x/tools/gopls@latest",
  "remoteUser": "vscode"
}

Polyglot workspace, composed from features

For: a repository that needs several runtimes plus cluster tooling, built by composition rather than by a bespoke image.

Not for: fast starts. Every feature is an install step at build time, and docker-in-docker widens the isolation boundary. From Advanced DevContainers.

polyglot/devcontainer.json
{
  "image": "mcr.microsoft.com/devcontainers/base:ubuntu",
  "features": {
    "ghcr.io/devcontainers/features/node:1": {
      "version": "20"
    },
    "ghcr.io/devcontainers/features/python:1": {
      "version": "3.12"
    },
    "ghcr.io/devcontainers/features/docker-in-docker:2": {},
    "ghcr.io/devcontainers/features/kubectl-helm-minikube:1": {}
  }
}

Multi-container stack

For: the smallest correct wiring of an application container to a database and a cache.

Not for: anything durable. There is no named volume for Postgres, no health check ordering, and the password is literally the word dev. From DevContainers.

docker-compose.yml
services:
  app:
    build: .
    volumes:
      - .:/workspace

  postgres:
    image: postgres:15
    environment:
      POSTGRES_PASSWORD: dev

  redis:
    image: redis:7-alpine

Agent Instructions, Identity, and Egress

AGENTS.md starter

For: telling an agent the things it would otherwise get wrong by guessing - which test command gates a merge, which paths are generated, what a pull request is expected to look like.

Not for: enforcement. This file is advisory context competing for attention in a context window; a line reading "do not touch" is a request, not a permission boundary. From AGENTS.md.

AGENTS.md
# AGENTS.md

## Project

Payments API. Go 1.24 service behind an internal gateway. Card
authorization only; settlement is a separate repository.

## Setup

Use `make bootstrap`, not `go mod download` - it also generates
the protobuf stubs the build needs.

## Build and test

- `make test` is fast, but it does NOT gate merges.
- `make test-integration` is what CI gates on. It needs Postgres,
  which `make bootstrap` starts in a container.
- Run `make lint` first. CI rejects lint failures.

## Conventions

- Wrap errors with `fmt.Errorf("...: %w", err)`. Never return a
  bare error from an exported function.
- Use `internal/clock`, not `time.Now()`, so tests control time.

## Do not touch

- `internal/gen/**` is generated. Edit the `.proto` files and
  rerun `make bootstrap`.
- `deploy/prod/**` requires a platform team review.

## Pull requests

Title: `[payments] short imperative summary`. Keep changes under
roughly 400 lines; split larger work into several PRs.

Agent identity and a least-privilege, short-lived credential

For: naming a single agent run so authorization and audit can both address it, then minting a credential scoped to one repository that expires with the task. The registration issues an identity only against attested selectors, so no bootstrap secret exists to steal.

Not for: copying as an API contract. The token request models the shape of a scoped installation token; its delegation and correlation fields are a local convention, not a published schema. From Agent Identity, which draws on Microsoft Security's "Least privilege for AI agents" (July 16, 2026).

spiffe-ids.txt
# One trust domain per environment - never one per team
spiffe://dev.example.internal

# The agent workload itself
spiffe://dev.example.internal/ns/agents/sa/coding-agent

# A single execution of it. Authorization and audit
# both address this.
spiffe://dev.example.internal/ns/agents/sa/coding-agent/run/7f3c9a12

# The supervising CI runner is a DIFFERENT principal
spiffe://dev.example.internal/ns/ci/sa/pipeline-runner

# Issued only to a workload attesting to these selectors
spire-server entry create \
  -spiffeID spiffe://dev.example.internal/ns/agents/sa/coding-agent \
  -parentID spiffe://dev.example.internal/spire/agent/k8s_psat/dev/node-17 \
  -selector k8s:ns:agents \
  -selector k8s:sa:coding-agent \
  -x509SVIDTTL 900
scoped-token-request.json
{
  "agent_identity":
    "spiffe://dev.example.internal/ns/agents/sa/coding-agent",
  "run_id": "7f3c9a12",
  "on_behalf_of": "user:[email protected]",
  "repositories": ["example-org/billing-service"],
  "permissions": {
    "contents": "read",
    "pull_requests": "write",
    "issues": "none",
    "actions": "none",
    "secrets": "none",
    "administration": "none",
    "packages": "none"
  },
  "expires_in_seconds": 900
}

Egress allowlist starter

For: a default-deny egress posture in two layers - a proxy policy that separates reading from writing at the same hostname and injects credentials the workspace never sees, and the Kubernetes policy that forces all traffic through it.

Not for: deployment as written. The proxy policy is an illustrative shape rather than any vendor's schema, and method and path rules are not expressible without terminating TLS - a proxy that does so becomes the highest-value target you operate. The default-deny policy also blocks DNS, which is why port 53 is allowed back explicitly. From Agent Egress Control.

egress-policy.yaml
default: deny   # anything unmatched is refused and logged

routes:
  - name: read-github-api
    match:
      domain: api.github.com
      method: [GET, HEAD]
    inject:
      header: Authorization
      secret_ref: vault://agents/repo-read
    log: full

  - name: publish-release
    match:
      domain: api.github.com
      method: [POST]
      path: /repos/example-org/*/releases
    approval: human   # held until an operator approves
    inject:
      header: Authorization
      secret_ref: vault://agents/release-write
    log: full
networkpolicy.yaml
apiVersion: networking.k8s.io/v1
kind: NetworkPolicy
metadata:
  name: default-deny-egress
spec:
  podSelector: {}
  policyTypes:
  - Egress
---
apiVersion: networking.k8s.io/v1
kind: NetworkPolicy
metadata:
  name: allow-dns-and-egress-proxy
spec:
  podSelector:
    matchLabels:
      role: agent-workspace
  policyTypes:
  - Egress
  egress:
  - to:
    - namespaceSelector:
        matchLabels:
          kubernetes.io/metadata.name: kube-system
    ports:
    - protocol: UDP
      port: 53
    - protocol: TCP
      port: 53
  - to:
    - ipBlock:
        cidr: 10.0.0.0/24
    ports:
    - protocol: TCP
      port: 5978

Decisions and Adoption

Architecture decision record

For: recording why a platform choice was made while the reasons are still fresh, so the next team does not relitigate it from scratch. Follows the format Michael Nygard described in "Documenting Architecture Decisions" (2011).

Not for: design documentation. An ADR captures one decision and its cost. It does not describe how the system works, and it is never edited after acceptance - it is superseded by a later record instead. Written for this library rather than lifted from an existing page.

docs/adr/0007-example.md
# ADR-0007: <the decision, stated as a completed action>

Date: <YYYY-MM-DD>
Status: proposed | accepted | superseded by ADR-<nnnn>
Deciders: <the rota or role that owns this, not a person>

## Context

What forces a decision now. Constraints, deadlines, and the
things that are NOT negotiable. No recommendation here.

## Decision

We will <the choice>, because <the reason that survives review>.
A commitment, not a preference.

## Options considered

1. <option> - rejected because <the specific disqualifier>
2. <option> - CHOSEN

## Consequences

- What gets easier, and what gets harder.
- What we now have to operate that we did not before.
- The signal that would tell us this decision was wrong.

## Revisit when

<a concrete trigger, such as "workspace count passes 500" -
never "in six months">

CDE pilot plan

For: agreeing who is in the pilot and what counts as success before anyone provisions a workspace, so the decision at the end is a reading rather than an argument.

Not for: use with the numbers as given. Every target below is a starting figure to be replaced with your own baseline; a pilot measured against someone else's benchmark proves nothing about your organization. From Pilot Program.

cde-pilot-plan.yaml
# Replace every target with your own measured baseline first.

team:
  size: "5 to 15 developers"
  lead: "a manager who will champion it and absorb the friction"
  stack: "containers and standard tooling, not a legacy monolith"
  roadmap: "no critical deadline, no major refactor in flight"
  avoid:
    - "teams under deadline pressure"
    - "specialized hardware: GPU, embedded, iOS builds"
    - "regions far from the cloud region you will serve"

success_criteria:
  productivity:
    onboarding_time: "under 4 hours"
    workspace_startup: "under 5 minutes"
    environment_issues_per_week: "under 2"
  experience:
    developer_nps: "above +30"
    would_recommend: "above 70 percent"
  reliability:
    platform_uptime: "above 99.5 percent"
    support_tickets_per_week: "under 5"
  adoption:
    daily_active_users: "above 80 percent"
    returned_to_local: "under 5 percent"
  ai_agents:
    task_success_rate: "above 75 percent"
    sandbox_escapes: 0
  cost:
    llm_cost_attribution: "100 percent"
    idle_workspace_waste: "under 10 percent"

decision_gate:
  go: "criteria met and the team wants to keep it"
  conditional: "named gaps, named owners, one more window"
  no_go: "write down why, before anyone re-proposes it"

Vendor RFP scorecard

For: forcing the weighting conversation before the demos, when it is still an honest one. Five categories, weights summing to 100, each criterion scored 1 to 5. Paste it into a spreadsheet as CSV.

Not for: deciding for you. The weights encode one set of priorities and yours will differ - a regulated team pushes data residency up, a small team pushes support down. Change them first and record why. From Vendor Evaluation; the interactive version is on the readiness assessment.

vendor-scorecard.csv
Category,Criterion,Weight,Score,Weighted,Notes
Security and Compliance,Data residency control,10,,,
Security and Compliance,Authentication and SSO,8,,,
Security and Compliance,Audit logging and SIEM export,8,,,
Security and Compliance,Secrets management,5,,,
Security and Compliance,Network isolation,4,,,
Developer Experience,IDE support,8,,,
Developer Experience,Workspace startup time,6,,,
Developer Experience,DevContainer support,6,,,
Developer Experience,Port forwarding and previews,5,,,
Infrastructure and Operations,Multi-cloud support,6,,,
Infrastructure and Operations,Resource management,5,,,
Infrastructure and Operations,High availability,5,,,
Infrastructure and Operations,Template and IaC system,4,,,
Cost and Licensing,Pricing model,5,,,
Cost and Licensing,Auto-stop and idle management,5,,,
Support and Ecosystem,Documentation and community,4,,,
Support and Ecosystem,Enterprise support,3,,,
Support and Ecosystem,Roadmap and innovation,3,,,
TOTAL,,100,,,

When an Agent Goes Wrong

Rogue-agent incident runbook skeleton

For: one file per incident class, written before the incident, with the containment step first and evidence preservation second. The order matters: a workspace reaped by an idle timer takes the transcript with it.

Not for: its timings. Every interval is an example value to be tuned against your own observed distributions, and the commands are placeholders rather than any product's real syntax. From Agent Runbooks; the general operational form is on Runbooks.

agent-runbook-template.yaml
# Timings are EXAMPLE values. Tune to your own distributions.
name: "<short imperative title of the incident class>"
severity: "sev2"            # raise for suspected compromise
owner: "platform-oncall"    # a rota, never a named individual

trigger:
  alert: "<alert or saved query that fires this runbook>"
  condition: "<the threshold, as a rule not a feeling>"

immediate_actions:          # EXAMPLE: first action within 5 min
  - contain: "smallest kill switch covering the blast radius"
  - preserve: "mark the workspace no-reap BEFORE anything else"
  - declare: "open the channel, name an incident lead"
  - revoke: "revoke the run credential; cancel is not enough"

investigation:              # EXAMPLE: classified within 60 min
  collect:
    - "conversation and tool-call transcript for the run id"
    - "egress allow/deny log for the run id"
    - "token spend from the gateway, not from billing"
    - "image digest, model version, granted permissions"
  questions:
    - "did it read untrusted content before diverging"
    - "was every action inside its granted permissions"

recovery:
  - "enumerate secondary credentials the run could reach"
  - "revert merged changes by run id, every repository"
  - "check tickets, comments, and cloud resources too"
  - "restart path: <how it returns, and who approves>"

follow_up:                  # EXAMPLE: review within 5 days
  primary_cause: "injection | model | tooling | permissions"
  actions:
    - "add the eval that would have caught this"
    - "narrow the tool contract or the permission"
  retention: "quarantine expires <date>, owner <name>"

What This Library Is Not

Not a compliance artifact

Nothing here maps to a control in a published framework. For audit evidence, start from compliance and work back to configuration, not the other way round.

Not vendor-neutral by accident

Where a template names a product, that product documents the field. Anything invented for illustration is labeled as such, both here and on the source page.

Not a substitute for reading

The source pages carry the caveats that make a template safe to use; the summaries here are an index, not the argument. Every figure quoted on this site is listed at sources.