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
2 changes: 2 additions & 0 deletions .github/workflows/ci.yml
Original file line number Diff line number Diff line change
Expand Up @@ -107,6 +107,8 @@ jobs:
"$(go env GOPATH)/bin/gitleaks" detect --source . --no-git --redact --no-banner
- name: Helm Insights contracts
run: scripts/test-helm-insights.sh
- name: Helm custom image contracts
run: scripts/test-helm-images.sh
- name: Render LoadBalancer installation
run: helm template devboxes charts/devboxes --namespace devboxes > /tmp/devboxes.yaml
- name: Validate Kubernetes resources
Expand Down
13 changes: 13 additions & 0 deletions CHANGELOG.md
Original file line number Diff line number Diff line change
Expand Up @@ -4,6 +4,19 @@ All notable changes to Devboxes are documented here. The project follows [Keep a

## [Unreleased]

### Added

- Added opt-in custom image profiles across Helm, the API, CLI, dashboard, authenticated documentation, and public documentation. Profiles support isolated pod-local service sidecars and explicitly vetted Devboxes-compatible workspace derivatives.
- Added `devbox image profiles` and `devbox create --image PROFILE_OR_IMAGE`, resolved image allocation reporting, bounded sidecar resources and ports, strict chart/controller validation, and Helm contract tests.

### Changed

- Persist the fully resolved custom image profile on each workspace so stop, start, TTL expiry, and Insights template reconciliation cannot silently change an existing image contract after Helm configuration changes.

### Security

- Restrict custom image selection to an operator-approved catalog. Sidecars receive no Devboxes Secret, persistent-home mount, Kubernetes API token, public Service, extra capability, command override, or scheduling injection surface.

## [0.4.0] - 2026-07-20

### Added
Expand Down
1 change: 1 addition & 0 deletions Makefile
Original file line number Diff line number Diff line change
Expand Up @@ -21,6 +21,7 @@ test:
helm:
scripts/test-helm-insights.sh
scripts/test-helm-gpu.sh
scripts/test-helm-images.sh
helm template devboxes charts/devboxes --namespace devboxes --set workspace.sshService.type=NodePort --set workspace.sshService.host=192.0.2.10 >/dev/null

images:
Expand Down
33 changes: 32 additions & 1 deletion README.md
Original file line number Diff line number Diff line change
Expand Up @@ -20,10 +20,11 @@ Each workspace includes Rust, Node.js, Python, `uv`, GitHub CLI, Codex CLI, Clau

## What ships

- A Rust `devbox` CLI for create, list, inspect, SSH, start, stop, delete, and opt-in Insights workflows.
- A Rust `devbox` CLI for create, list, inspect, SSH, start, stop, delete, custom-image profiles, and opt-in Insights workflows.
- A FastAPI controller with an authenticated API, accessible browser workbench, Insights dashboard, documentation, metrics, health checks, and TTL cleanup.
- A versioned Helm chart with values schema validation and namespace-scoped RBAC.
- Optional operator-approved GPU profiles for NVIDIA, AMD, Intel, partitioned, or shared accelerators.
- Optional operator-approved custom image profiles for pod-local services or vetted workspace derivatives.
- Multi-architecture controller and workspace images for `linux/amd64` and `linux/arm64`.
- Persistent SSH host identity, shell state, tool installs, account state, and source under `/home/dev`.
- GitHub Releases with macOS and Linux CLI binaries and SHA-256 checksums.
Expand Down Expand Up @@ -169,6 +170,35 @@ devbox create training --gpu-profile nvidia-l4 --preset large --ssh

The dashboard exposes the same profiles in its create form. Devboxes sets the resource in both container requests and limits, preserves the resolved allocation across stop and start, and surfaces scheduler reasons when capacity is unavailable. Read [GPU acceleration](docs/gpu.md) for driver prerequisites, NVIDIA and AMD examples, image contracts, sharing, security, upgrades, and troubleshooting.

### Enable approved custom images

Devboxes does not accept an unrestricted container image from a client. Instead, an operator publishes a reviewed catalog. Service profiles run an unprivileged image such as NGINX as a credential-free sidecar beside the prepared SSH workspace; workspace profiles are only for compatible Devboxes-derived images.

```yaml
workspace:
customImages:
enabled: true
profiles:
- name: nginx
displayName: NGINX preview
description: Serve a local static-site preview
image: docker.io/nginxinc/nginx-unprivileged:1.27.5-alpine
mode: sidecar
ports:
- name: http
containerPort: 8080
```

Users discover and select the same catalog in the terminal or dashboard:

```bash
devbox image profiles
devbox create docs-preview --image nginx --ssh
devbox ssh docs-preview -- -L 8080:127.0.0.1:8080
```

Read [custom image profiles](docs/images.md) for the image contract, resource bounds, security boundary, upgrade behavior, and workspace-mode requirements.

### Enable Insights

Insights is disabled by default. Enable it to collect privacy-bounded local AI metrics and aggregate Git activity into a persistent controller database:
Expand Down Expand Up @@ -313,6 +343,7 @@ Read [CONTRIBUTING.md](CONTRIBUTING.md) before proposing a change. Security repo
- [Golden path](docs/golden-path.md) for a performance-oriented installation and daily workflow.
- [CLI reference](docs/cli.md) and [API reference](docs/api.md) for client contracts.
- [GPU acceleration](docs/gpu.md) for accelerator profiles, images, scheduling, and operations.
- [Custom image profiles](docs/images.md) for approved sidecars, compatible workspace derivatives, and their security boundary.
- [Insights](docs/insights.md) for telemetry semantics, privacy, storage, backup, and purge.
- [Configuration](docs/configuration.md) and [credentials](docs/credentials.md) for installation details.
- [Operations](docs/operations.md) and [troubleshooting](docs/troubleshooting.md) for production ownership.
Expand Down
25 changes: 25 additions & 0 deletions charts/devboxes/templates/deployment.yaml
Original file line number Diff line number Diff line change
Expand Up @@ -24,6 +24,27 @@
{{- if and .Values.gpu.enabled (not .Values.gpu.defaultProfile) }}
{{- fail "gpu.defaultProfile is required when gpu.enabled=true" }}
{{- end }}
{{- $customImageNames := dict }}
{{- $customImageReferences := dict }}
{{- range .Values.workspace.customImages.profiles }}
{{- if hasKey $customImageNames .name }}
{{- fail (printf "workspace.customImages contains duplicate name %q" .name) }}
{{- end }}
{{- if hasKey $customImageReferences .image }}
{{- fail (printf "workspace.customImages contains duplicate image %q" .image) }}
{{- end }}
{{- if not (trim .displayName) }}
{{- fail (printf "custom image profile %q displayName must not be blank" .name) }}
{{- end }}
{{- if contains "://" .image }}
{{- fail (printf "custom image profile %q image must not contain a URL scheme" .name) }}
{{- end }}
{{- $_ := set $customImageNames .name true }}
{{- $_ := set $customImageReferences .image true }}
{{- end }}
{{- if and .Values.workspace.customImages.enabled (eq (len .Values.workspace.customImages.profiles) 0) }}
{{- fail "workspace.customImages.profiles is required when workspace.customImages.enabled=true" }}
{{- end }}
apiVersion: apps/v1
kind: Deployment
metadata:
Expand Down Expand Up @@ -161,6 +182,10 @@ spec:
{{- end }}
- name: DEVBOXES_WORKSPACE_IMAGE
value: {{ include "devboxes.workspaceImage" . | quote }}
- name: DEVBOXES_CUSTOM_IMAGES_ENABLED
value: {{ .Values.workspace.customImages.enabled | quote }}
- name: DEVBOXES_CUSTOM_IMAGES
value: {{ .Values.workspace.customImages.profiles | toJson | quote }}
- name: DEVBOXES_WORKSPACE_SECRET_NAME
value: {{ .Values.workspace.existingSecret | quote }}
- name: DEVBOXES_WORKSPACE_SERVICE_ACCOUNT_NAME
Expand Down
77 changes: 77 additions & 0 deletions charts/devboxes/values.schema.json
Original file line number Diff line number Diff line change
Expand Up @@ -42,6 +42,25 @@
"required": ["image", "existingSecret", "serviceAccount", "sshService"],
"properties": {
"image": {"$ref": "#/definitions/imageWithoutPullPolicy"},
"customImages": {
"type": "object",
"additionalProperties": false,
"required": ["enabled", "profiles"],
"properties": {
"enabled": {"type": "boolean"},
"profiles": {
"type": "array",
"maxItems": 32,
"items": {"$ref": "#/definitions/customImageProfile"}
}
},
"allOf": [
{
"if": {"properties": {"enabled": {"const": true}}},
"then": {"properties": {"profiles": {"minItems": 1}}}
}
]
},
"existingSecret": {"type": "string", "minLength": 1},
"imagePullSecret": {"type": "string"},
"storageClass": {"type": "string"},
Expand Down Expand Up @@ -274,6 +293,64 @@
"tag": {"type": "string"}
}
},
"customImageProfile": {
"type": "object",
"additionalProperties": false,
"required": ["name", "displayName", "image"],
"properties": {
"name": {
"type": "string",
"minLength": 1,
"maxLength": 40,
"pattern": "^[a-z0-9](?:[a-z0-9-]{0,38}[a-z0-9])?$"
},
"displayName": {"type": "string", "minLength": 1, "maxLength": 80},
"description": {"type": "string", "maxLength": 160},
"image": {"type": "string", "minLength": 1, "maxLength": 512},
"mode": {"type": "string", "enum": ["sidecar", "workspace"]},
"pullPolicy": {"type": "string", "enum": ["Always", "IfNotPresent", "Never"]},
"resources": {"$ref": "#/definitions/customImageResources"},
"ports": {
"type": "array",
"maxItems": 8,
"items": {"$ref": "#/definitions/customImagePort"}
}
},
"allOf": [
{
"if": {
"properties": {"mode": {"const": "workspace"}},
"required": ["mode"]
},
"then": {"not": {"required": ["resources"]}}
}
]
},
"customImageResources": {
"type": "object",
"additionalProperties": false,
"properties": {
"cpuRequest": {"type": "string", "minLength": 1, "maxLength": 32},
"memoryRequest": {"type": "string", "minLength": 1, "maxLength": 32},
"cpuLimit": {"type": "string", "minLength": 1, "maxLength": 32},
"memoryLimit": {"type": "string", "minLength": 1, "maxLength": 32}
}
},
"customImagePort": {
"type": "object",
"additionalProperties": false,
"required": ["name", "containerPort"],
"properties": {
"name": {
"type": "string",
"minLength": 1,
"maxLength": 63,
"pattern": "^[a-z0-9](?:[-a-z0-9]{0,61}[a-z0-9])?$"
},
"containerPort": {"type": "integer", "minimum": 1024, "maximum": 65535},
"protocol": {"type": "string", "enum": ["TCP", "UDP", "SCTP"]}
}
},
"gpuToleration": {
"type": "object",
"additionalProperties": false,
Expand Down
22 changes: 22 additions & 0 deletions charts/devboxes/values.yaml
Original file line number Diff line number Diff line change
Expand Up @@ -41,6 +41,28 @@ workspace:
image:
repository: ghcr.io/vicotrbb/devboxes-workspace
tag: ""
# Custom images are opt-in and operator-owned. A sidecar profile runs a
# compatible non-root application image beside the prepared Devboxes workspace.
# A workspace profile replaces it and must preserve the complete SSH contract.
customImages:
enabled: false
# Example profile fields:
# - name: nginx
# displayName: NGINX preview
# description: Serve a local static-site preview over the pod network
# image: docker.io/nginxinc/nginx-unprivileged:1.27.5-alpine
# mode: sidecar
# pullPolicy: IfNotPresent
# resources:
# cpuRequest: 25m
# memoryRequest: 32Mi
# cpuLimit: 500m
# memoryLimit: 512Mi
# ports:
# - name: http
# containerPort: 8080
# protocol: TCP
profiles: []
existingSecret: devboxes-workspace
imagePullSecret: ""
storageClass: ""
Expand Down
4 changes: 3 additions & 1 deletion cli/README.md
Original file line number Diff line number Diff line change
Expand Up @@ -8,6 +8,8 @@ devbox login --url https://devboxes.example.com
devbox create atlas --repo owner/project --ssh
devbox gpu profiles
devbox create inference --gpu --ssh
devbox image profiles
devbox create docs-preview --image nginx --ssh
```

See the [CLI reference](../docs/cli.md) for every command, option, environment variable, output contract, and SSH workflow. [GPU acceleration](../docs/gpu.md) covers operator-approved accelerator profiles. The [golden path](../docs/golden-path.md) covers the recommended installation and performance setup.
See the [CLI reference](../docs/cli.md) for every command, option, environment variable, output contract, and SSH workflow. [GPU acceleration](../docs/gpu.md) covers operator-approved accelerator profiles, and [custom image profiles](../docs/images.md) covers approved service and workspace images. The [golden path](../docs/golden-path.md) covers the recommended installation and performance setup.
Loading