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
11 changes: 10 additions & 1 deletion .github/workflows/ci.yml
Original file line number Diff line number Diff line change
Expand Up @@ -96,7 +96,9 @@ jobs:
with:
version: v4.2.2
- name: Shell lint
run: shellcheck scripts/*.sh workspace/*.sh workspace/devbox-shell
run: shellcheck scripts/*.sh workspace/*.sh workspace/devbox-shell workspace/tests/*.sh
- name: Terminal compatibility unit tests
run: workspace/tests/test-devbox-shell.sh
- name: Release version consistency
run: scripts/check-version.sh
- name: Secret scan
Expand Down Expand Up @@ -140,6 +142,9 @@ jobs:
- uses: actions/checkout@9c091bb21b7c1c1d1991bb908d89e4e9dddfe3e0 # v7.0.0
- name: Build image
run: docker build --tag "devboxes-${{ matrix.component }}:ci" "${{ matrix.component }}"
- name: Exercise terminal compatibility inside workspace image
if: matrix.component == 'workspace'
run: workspace/tests/test-image-terminal.sh devboxes-workspace:ci

kind:
name: Clean-cluster install
Expand All @@ -154,4 +159,8 @@ jobs:
go install sigs.k8s.io/kind@v0.31.0
echo "$(go env GOPATH)/bin" >> "$GITHUB_PATH"
- name: Run full lifecycle E2E
env:
# GitHub-hosted runners cannot retain an SSH PTY through Kind's port-forward.
# The workspace image job above exercises the same shell with a real TTY.
DEVBOXES_E2E_INTERACTIVE_SSH: "0"
run: scripts/kind-e2e.sh
22 changes: 21 additions & 1 deletion CHANGELOG.md
Original file line number Diff line number Diff line change
Expand Up @@ -4,6 +4,25 @@ All notable changes to Devboxes are documented here. The project follows [Keep a

## [Unreleased]

## [0.2.0] - 2026-07-13

### Added

- Added native CLI browser authorization with an external system browser, numeric loopback callback, high-entropy state, PKCE S256, CSRF-protected approval and denial, automatic code exchange, and `--no-open` support.
- Added versioned, scoped, expiring CLI bearer tokens with strict claim validation, an optional dedicated signing key, and a domain-separated key derived from the existing access token by default.
- Added a pinned Ghostty `xterm-ghostty` terminfo source with upstream MIT attribution, broad ncurses terminfo packages, and image-level tmux regression coverage.

### Changed

- Changed interactive `devbox login` to eliminate terminal token prompting while preserving explicit `--token` and `DEVBOX_TOKEN` compatibility for automation and headless use.
- Changed `devbox-shell` to validate and preserve installed terminal capabilities, retain `DEVBOX_ORIGINAL_TERM` and `COLORTERM`, and fall back deterministically for unknown or untrusted terminal names.
- Configured tmux to use the installed `tmux-256color` entry internally and advertise truecolor only for known capable terminal families.

### Security

- Authorization codes are opaque, hash-only at rest, bounded, automatically pruned, bound to the exact client, redirect, PKCE challenge, subject, and expiry, and atomically consumed once.
- CLI authorization and token responses use no-store and referrer protections; login return targets and loopback redirects reject open redirects, non-numeric hosts, unexpected paths, and unsupported PKCE methods.

## [0.1.2] - 2026-07-13

### Fixed
Expand Down Expand Up @@ -41,7 +60,8 @@ All notable changes to Devboxes are documented here. The project follows [Keep a
- Portable Helm chart with values schema, namespace-scoped RBAC, configurable storage, ingress, LoadBalancer or NodePort SSH, ServiceMonitor, and disruption budget.
- macOS and Linux CLI releases, SHA-256 verification installer, GHCR images, OCI chart publishing, image provenance attestations, and clean Kind install CI.

[Unreleased]: https://github.com/vicotrbb/devboxes/compare/v0.1.2...HEAD
[Unreleased]: https://github.com/vicotrbb/devboxes/compare/v0.2.0...HEAD
[0.2.0]: https://github.com/vicotrbb/devboxes/compare/v0.1.2...v0.2.0
[0.1.2]: https://github.com/vicotrbb/devboxes/compare/v0.1.1...v0.1.2
[0.1.1]: https://github.com/vicotrbb/devboxes/compare/v0.1.0...v0.1.1
[0.1.0]: https://github.com/vicotrbb/devboxes/releases/tag/v0.1.0
4 changes: 3 additions & 1 deletion Makefile
Original file line number Diff line number Diff line change
Expand Up @@ -9,7 +9,8 @@ lint:
npm run lint
cd controller && uv run ruff format --check . && uv run ruff check . && uv run mypy
cd cli && cargo fmt --check && cargo clippy --all-targets --all-features --locked -- -D warnings
shellcheck scripts/*.sh workspace/*.sh workspace/devbox-shell
shellcheck scripts/*.sh workspace/*.sh workspace/devbox-shell workspace/tests/*.sh
workspace/tests/test-devbox-shell.sh
./scripts/check-version.sh

test:
Expand All @@ -24,6 +25,7 @@ helm:
images:
docker build --tag devboxes-controller:local controller
docker build --tag devboxes-workspace:local workspace
workspace/tests/test-image-terminal.sh devboxes-workspace:local

clean:
rm -rf node_modules controller/.venv controller/.mypy_cache controller/.pytest_cache controller/.ruff_cache controller/.coverage controller/htmlcov cli/target
4 changes: 4 additions & 0 deletions NOTICE
Original file line number Diff line number Diff line change
Expand Up @@ -2,3 +2,7 @@ Devboxes
Copyright 2026 Victor Bona

This product includes software developed by Devboxes contributors.

The workspace image includes a generated Ghostty terminfo entry derived from Ghostty,
Copyright (c) 2024 Mitchell Hashimoto and Ghostty contributors, licensed under the MIT
License. The pinned source provenance and license are under workspace/terminfo.
18 changes: 17 additions & 1 deletion README.md
Original file line number Diff line number Diff line change
Expand Up @@ -84,7 +84,7 @@ kubectl -n devboxes create secret generic devboxes-workspace \
--from-file=SSH_AUTHORIZED_KEYS="$HOME/.ssh/id_ed25519.pub"

helm install devboxes oci://ghcr.io/vicotrbb/charts/devboxes \
--version 0.1.2 \
--version 0.2.0 \
--namespace devboxes
```

Expand Down Expand Up @@ -155,6 +155,18 @@ devbox login --url https://devboxes.example.com
devbox create atlas --preset medium --ttl 24 --repo owner/project --ssh
```

Login opens the system browser, asks the current Devboxes browser session to approve the
CLI, exchanges a one-time PKCE authorization code, verifies the resulting scoped token,
and stores it without displaying it. If the browser is not already signed in, the existing
operator login page appears first. This removes token pasting from the terminal; it does
not add SSO or unauthenticated LAN trust.

For a machine where the CLI cannot open a browser, print the URL and open it manually:

```bash
devbox login --url https://devboxes.example.com --no-open
```

For a port-forwarded controller, localhost HTTP is deliberately allowed:

```bash
Expand All @@ -181,6 +193,10 @@ devbox ssh atlas -- -L 3000:127.0.0.1:3000

The CLI stores its configuration at the platform config directory under `devbox/config.toml` with mode `0600` on Unix. `DEVBOX_URL`, `DEVBOX_TOKEN`, and `DEVBOX_CONFIG` support non-interactive and multi-profile workflows.

Existing automation can continue to use the master token through `DEVBOX_TOKEN` or an
explicit `--token`. Browser login receives an expiring CLI token instead of the master
credential.

## Credentials and prepared accounts

Only `SSH_AUTHORIZED_KEYS` is required. Add optional values to the `devboxes-workspace` Secret to prepare GitHub, Git, Codex, or Claude Code. Public GitHub repositories clone without `GH_TOKEN`.
Expand Down
7 changes: 6 additions & 1 deletion SECURITY.md
Original file line number Diff line number Diff line change
Expand Up @@ -32,7 +32,12 @@ Recommended deployment controls:
- keep Kubernetes, ingress, CSI, images, chart, and CLI releases current;
- verify release checksums and image provenance attestations.

The CLI refuses plaintext HTTP except exact loopback hosts. It has no skip-TLS-verification option. Workspace SSH disables password, keyboard-interactive, and root login and uses persistent Ed25519 host keys.
The CLI refuses plaintext controller URLs except exact loopback hosts. Browser login uses an
external browser, a `127.0.0.1` ephemeral callback, state validation, PKCE S256, one-time
authorization codes, and expiring scoped tokens. It has no skip-TLS-verification option.
Workspace SSH disables password, keyboard-interactive, and root login and uses persistent
Ed25519 host keys. Incoming terminal names are validated against installed terminfo before
tmux starts.

## Dependency and supply-chain policy

Expand Down
4 changes: 2 additions & 2 deletions charts/devboxes/Chart.yaml
Original file line number Diff line number Diff line change
Expand Up @@ -2,8 +2,8 @@ apiVersion: v2
name: devboxes
description: Self-hosted, ephemeral development environments on Kubernetes
type: application
version: 0.1.2
appVersion: "0.1.2"
version: 0.2.0
appVersion: "0.2.0"
kubeVersion: ">=1.29.0-0"
home: https://github.com/vicotrbb/devboxes
icon: https://raw.githubusercontent.com/vicotrbb/devboxes/main/docs/assets/devboxes-mark.svg
Expand Down
13 changes: 13 additions & 0 deletions charts/devboxes/templates/deployment.yaml
Original file line number Diff line number Diff line change
Expand Up @@ -77,6 +77,19 @@ spec:
value: {{ .Values.controller.cleanupIntervalSeconds | quote }}
- name: DEVBOXES_SESSION_TTL_SECONDS
value: {{ .Values.controller.sessionTtlSeconds | quote }}
- name: DEVBOXES_AUTHORIZATION_CODE_TTL_SECONDS
value: {{ int .Values.controller.authorizationCodeTtlSeconds | quote }}
- name: DEVBOXES_AUTHORIZATION_CODE_STORE_SIZE
value: {{ int .Values.controller.authorizationCodeStoreSize | quote }}
- name: DEVBOXES_CLI_TOKEN_TTL_SECONDS
value: {{ int .Values.controller.cliTokenTtlSeconds | quote }}
{{- if .Values.controller.cliSigningKeyKey }}
- name: DEVBOXES_CLI_SIGNING_KEY
valueFrom:
secretKeyRef:
name: {{ .Values.controller.existingSecret }}
key: {{ .Values.controller.cliSigningKeyKey }}
{{- end }}
- name: DEVBOXES_LOG_LEVEL
value: {{ .Values.controller.logLevel | quote }}
- name: DEVBOXES_WORKSPACE_IMAGE
Expand Down
4 changes: 4 additions & 0 deletions charts/devboxes/values.schema.json
Original file line number Diff line number Diff line change
Expand Up @@ -23,6 +23,10 @@
"maxTtlHours": {"type": "integer", "minimum": 1, "maximum": 168},
"cleanupIntervalSeconds": {"type": "integer", "minimum": 1},
"sessionTtlSeconds": {"type": "integer", "minimum": 60},
"authorizationCodeTtlSeconds": {"type": "integer", "minimum": 30, "maximum": 600},
"authorizationCodeStoreSize": {"type": "integer", "minimum": 16, "maximum": 10000},
"cliTokenTtlSeconds": {"type": "integer", "minimum": 300, "maximum": 31536000},
"cliSigningKeyKey": {"type": "string"},
"logLevel": {"type": "string", "enum": ["DEBUG", "INFO", "WARNING", "ERROR", "CRITICAL"]},
"resources": {"type": "object"},
"podAnnotations": {"type": "object", "additionalProperties": {"type": "string"}},
Expand Down
6 changes: 6 additions & 0 deletions charts/devboxes/values.yaml
Original file line number Diff line number Diff line change
Expand Up @@ -18,6 +18,12 @@ controller:
maxTtlHours: 168
cleanupIntervalSeconds: 60
sessionTtlSeconds: 43200
authorizationCodeTtlSeconds: 120
authorizationCodeStoreSize: 1024
cliTokenTtlSeconds: 2592000
# Optional key in controller.existingSecret. Empty derives a domain-separated
# signing key from accessTokenKey so no new mandatory credential is required.
cliSigningKeyKey: ""
logLevel: INFO
resources:
requests:
Expand Down
Loading
Loading