Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
16 changes: 16 additions & 0 deletions coder/ai.coder.com.tf
Original file line number Diff line number Diff line change
Expand Up @@ -250,6 +250,22 @@ module "ai-coder-com-demo" {
manual_trigger = var.manual_trigger
exclude_from_archive = local.exclude_from_archive
}
"universal-sandbox" = {
path = "${path.module}/../deployments/ai.coder.com/demo/universal-sandbox"
description = "General-purpose development workspace. Use this when no language- or repo-specific template fits.
"
display_name = "Universal Sandbox (Generic Dev Environment)"
icon = "/icon/personalize.svg"
default_ttl = 1
failure_ttl = 24
time_til_dormant = 1
time_til_dormant_autodelete = 4
manual_trigger = var.manual_trigger
exclude_from_archive = local.exclude_from_archive
vars = {
namespace = "coder-ws-demo"
}
}
"ec2-win-vm" = {
path = "${path.module}/../deployments/ai.coder.com/demo/ec2-win-vm"
description = "Work on a Windows VM on AWS EC2!"
Expand Down
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
# Generic Dev Template
# Universal Sandbox Template

A general-purpose, Kubernetes-based Coder workspace template designed as the default environment for Coder Agents. This template provides a batteries-included development environment with AI coding agents, IDEs, and a broad set of pre-installed programming languages and tools suitable for most development workflows.
A general-purpose, Kubernetes-based Coder workspace template designed as the default environment for Coder Agents. This template provides a batteries-included development environment with AI coding agents, IDEs, cloud/infrastructure tooling, and a broad set of pre-installed programming languages and tools suitable for most development workflows.

**This is the default template.** Unless the user explicitly requests a different template or this template does not suit their specific use-case, this is the one that should be spun up.

Expand All @@ -10,7 +10,7 @@ The workspace uses a persistent volume mounted at `/home/coder`. Any executables

## Pre-installed Programming Languages and Tools

The default container image (`public.ecr.aws/f7a1d7a4/coder-aidev:1.1.5`) is based on **Ubuntu Noble (24.04)** and comes with the following pre-installed:
The container image is built from `public.ecr.aws/f7a1d7a4/coder-aienv:1.1.6` (based on **Ubuntu Noble 24.04**) with additional tooling layered on top. The full image is defined in `images/aws/dev/Dockerfile.noble`.

### Programming Languages

Expand Down Expand Up @@ -57,6 +57,55 @@ cursor-agent --version
goose session start
```

### Cloud and Infrastructure Tools

| Tool | Description |
|------|-------------|
| **AWS CLI** | Amazon Web Services command-line interface |
| **Terraform** | Infrastructure as Code provisioning tool (HashiCorp) |
| **Terragrunt** | Thin wrapper for Terraform providing DRY configurations |
| **AWS CDK** | AWS Cloud Development Kit (via npm) |
| **kubectl** | Kubernetes cluster CLI (v1.35) |
| **Helm** | Kubernetes package manager |
| **K9s** | Terminal-based Kubernetes UI (v0.50.18) |
| **Docker (Podman)** | Container runtime via Podman with Docker CLI symlink |

```bash
# AWS
aws sts get-caller-identity
aws s3 ls

# Terraform / Terragrunt
terraform version
terraform init && terraform plan
terragrunt run-all plan

# CDK
cdk --version
cdk synth

# Kubernetes
kubectl get pods
helm list
k9s

# Docker (backed by Podman)
docker ps
docker build -t myimage .
podman-compose up
```

### Database Tools

| Tool | Description |
|------|-------------|
| **PostgreSQL Client** | `psql` CLI and related utilities |

```bash
psql -h hostname -U user -d database
pg_dump -h hostname -U user database > backup.sql
```

### Developer Tools

| Tool | Description |
Expand Down Expand Up @@ -170,9 +219,9 @@ npx @wonderwhy-er/desktop-commander
|-----------|-------------|---------|
| `Github URL` | Repository URL to clone (optional) | Empty |
| `Container Image` | Docker image for the workspace | `public.ecr.aws/f7a1d7a4/coder-aidev:1.1.5` |
| `vCPU Count` | Number of vCPUs to allocate | `2` |
| `Memory` | Amount of memory in Gi to allocate | `2` |
| `Storage` | Persistent volume size in Gi (immutable after creation) | `50` |
| `vCPU Count` | Number of vCPUs to allocate (min: 2, max: 4) | `2` |
| `Memory` | Amount of memory in Gi to allocate (min: 2, max: 8) | `2` |
| `Storage` | Persistent volume size in Gi (immutable after creation, min: 10, max: 100) | `50` |
| `Preview Port` | Port for web app preview (must be > 1023, max 65535) | `4200` |

## Infrastructure
Expand Down Expand Up @@ -207,10 +256,10 @@ The agent displays real-time metrics:
## Files

```
generic/
universal-sandbox/
├── main.tf # IDEs, apps, and git-clone configuration
├── workspace.tf # Kubernetes deployment, agent, and PVC setup
├── variables.tf # User-configurable parameters
├── providers.tf # Terraform provider configuration
└── tmp.auto.tfvars.json # Namespace variable (auto-loaded)
└── README.md # This file
```
Original file line number Diff line number Diff line change
Expand Up @@ -22,6 +22,11 @@ data "coder_parameter" "cpus" {
default = 2
type = "number"
order = 4

validation {
min = 2
max = 4
}
}

data "coder_parameter" "memory" {
Expand All @@ -32,6 +37,11 @@ data "coder_parameter" "memory" {
default = 2
type = "number"
order = 4

validation {
min = 2
max = 8
}
}

data "coder_parameter" "storage" {
Expand All @@ -42,6 +52,11 @@ data "coder_parameter" "storage" {
default = 50
type = "number"
order = 4

validation {
min = 10
max = 100
}
}

data "coder_parameter" "container_image" {
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -9,6 +9,11 @@ locals {
"com.coder.user.id" = data.coder_workspace_owner.me.id
"com.coder.user.username" = data.coder_workspace_owner.me.name
}
coder_org_map = tomap({
"coder-ws-experiment" = "experiment"
"coder-ws" = "coder"
"coder-ws-demo" = "demo"
})
}

resource "coder_metadata" "pod_info" {
Expand Down Expand Up @@ -139,15 +144,25 @@ resource "kubernetes_deployment_v1" "this" {
}

resources {
limits = {
cpu = "${data.coder_parameter.cpus.value}"
memory = "${data.coder_parameter.memory.value}Gi"
}

requests = {
cpu = "500m"
memory = "1Gi"
}
limits = merge(
{
cpu = "${data.coder_parameter.cpus.value}"
memory = "${data.coder_parameter.memory.value}Gi"
},
local.coder_org_map[nonsensitive(var.namespace)] != "coder" ? {
ephemeral-storage = "${data.coder_parameter.storage.value}Gi"
} : {}
)

requests = merge(
{
cpu = "500m"
memory = "1Gi"
},
local.coder_org_map[nonsensitive(var.namespace)] != "coder" ? {
ephemeral-storage = "25Gi"
} : {}
)
}

volume_mount {
Expand All @@ -168,9 +183,16 @@ resource "kubernetes_deployment_v1" "this" {

volume {
name = "home"
persistent_volume_claim {
claim_name = kubernetes_persistent_volume_claim_v1.home.metadata.0.name
read_only = false
dynamic "persistent_volume_claim" {
for_each = local.coder_org_map[nonsensitive(var.namespace)] != "coder" ? [1] : []
content {
claim_name = kubernetes_persistent_volume_claim_v1.home[0].metadata.0.name
read_only = false
}
}
dynamic "empty_dir" {
for_each = local.coder_org_map[nonsensitive(var.namespace)] == "coder" ? [1] : []
content {}
}
}

Expand All @@ -180,6 +202,7 @@ resource "kubernetes_deployment_v1" "this" {
}

resource "kubernetes_persistent_volume_claim_v1" "home" {
count = local.coder_org_map[nonsensitive(var.namespace)] != "coder" ? 1 : 0
metadata {
name = data.coder_workspace.me.id
namespace = var.namespace
Expand Down