mirror of
https://github.com/sredevopsorg/deepseek-kubernetes-sandbox.git
synced 2026-11-03 09:23:25 +00:00
Remove obsolete layout/migration prose and legacy gateway-alias references, reconcile the required-check policy, fix version-label/RBAC/workspace/channel drift, and de-duplicate the example and gateway docs. Rename the minimal manifest to 10-sandboxtemplate.yaml and mount the dsh-home PVC's workspace subPath at /workspace so the documented persistence is real. Enforce numbered top-level manifests in check-examples.sh. Verified with make check, yamllint, shellcheck, a Markdown link/anchor scan, and git diff --check. Co-authored-by: SREDevOpsAgents <agents@sredevops.org>
214 lines
11 KiB
Markdown
214 lines
11 KiB
Markdown
# deepseek-kubernetes-sandbox
|
|
|
|
**DeepSeek Harness Web, packaged as a container.** This repository's primary
|
|
artifact is a slim, non-root, multi-arch image of
|
|
[DeepSeek Harness](https://github.com/deepseek-ai/deepseek-harness) Web
|
|
(`dsh web`), ready for Docker and Kubernetes. Everything else exists to support
|
|
that image or to demonstrate an implementation on top of it.
|
|
|
|
The flagship implementation is
|
|
[`examples/dsh-agents-as-a-service/`](examples/dsh-agents-as-a-service/): the
|
|
"agents-as-a-service" platform pattern with one DSH Web instance per user,
|
|
provisioned from a warm pool on
|
|
[kubernetes-sigs/agent-sandbox](https://github.com/kubernetes-sigs/agent-sandbox),
|
|
suspended when idle, and fronted by a small browser-usable gateway.
|
|
|
|
## Quick start
|
|
|
|
```bash
|
|
docker run -d --name dsh-web \
|
|
-p 3080:3080 \
|
|
-v dsh-home:/home/node/.dsh \
|
|
-e DEEPSEEK_API_KEY \
|
|
ghcr.io/sredevopsorg/deepseek-kubernetes-sandbox:dsh-v0.2.1-rc.5
|
|
```
|
|
|
|
DSH Web is **not usable at a bare `/`**. Without its launch-token cookie it
|
|
answers `401`, and the token is printed only in the startup logs:
|
|
|
|
```bash
|
|
docker logs dsh-web 2>&1 | grep -m1 '?token='
|
|
# dsh web: http://localhost:3080/?token=...
|
|
```
|
|
|
|
Open the printed `?token=...` URL once: DSH sets its auth cookie and the UI loads
|
|
normally afterwards. Hitting `/` directly (or after the cookie expires) returns
|
|
`401` by design.
|
|
|
|
### Host port and public URL
|
|
|
|
If `3080` is taken locally, map another port and set the public URL so the quoted
|
|
token URL matches:
|
|
|
|
```bash
|
|
docker run -d --name dsh-web -p 18081:3080 \
|
|
-e DSH_PUBLIC_URL=http://localhost:18081 \
|
|
-v dsh-home:/home/node/.dsh \
|
|
-e DEEPSEEK_API_KEY \
|
|
ghcr.io/sredevopsorg/deepseek-kubernetes-sandbox:dsh-v0.2.1-rc.5
|
|
# then open http://localhost:18081/?token=...
|
|
```
|
|
|
|
### Hosts, probes and the 401
|
|
|
|
- **Probes must not hit `/`.** It returns `401` without the launch token, so a
|
|
readiness/liveness probe on `/` crash-loops the pod. Probe `/favicon.svg`
|
|
instead: it is unauthenticated. The shipped manifests use it.
|
|
- **Host allow-listing.** DSH rejects unknown `Host` headers. `localhost` and
|
|
`127.0.0.1` are always trusted; add any other public hostname to
|
|
`DSH_TRUSTED_HOSTS` (comma or space separated). A gateway or Ingress that
|
|
forwards the browser's `Host` needs its hostname listed there.
|
|
- **State lives in `/home/node/.dsh`.** Mount a volume (Docker) or PVC
|
|
(Kubernetes) to keep conversations, sessions and config across restarts.
|
|
|
|
### Runtime environment
|
|
|
|
| Variable | Default | Purpose |
|
|
| --- | --- | --- |
|
|
| `DEEPSEEK_API_KEY` | empty | Provider credential consumed by DSH. Inject it; never bake it into the image or commit it. |
|
|
| `DSH_PORT` | `3080` | Port DSH Web listens on inside the container. |
|
|
| `DSH_HOST` | auto-detected pod/container IP | Bind address. Leave empty in Kubernetes. |
|
|
| `DSH_PUBLIC_URL` | `http://localhost:${DSH_PORT}` | Public base URL used in generated links and the launch-token URL in the logs. |
|
|
| `DSH_TRUSTED_HOSTS` | empty | Extra trusted `Host`/`Origin` entries, comma/space separated. |
|
|
| `DSH_HOME` | `/home/node/.dsh` | DSH state directory (mount a volume here). |
|
|
|
|
DSH also resolves the standard per-provider environment names —
|
|
`OPENROUTER_API_KEY`, `GEMINI_API_KEY`, `NVIDIA_API_KEY`, `OPENAI_API_KEY`,
|
|
`ANTHROPIC_API_KEY`, `GROQ_API_KEY`, `XAI_API_KEY`, `HF_TOKEN`, and others —
|
|
through its packaged provider catalog. Inject them the same way; a key saved in
|
|
DSH's credential store wins over the environment. See
|
|
[provider credentials](docs/main-image.md#provider-credentials).
|
|
|
|
Full contract, build args, probes, volumes and signals:
|
|
[docs/main-image.md](docs/main-image.md).
|
|
|
|
## Published images
|
|
|
|
Published to GitHub Container Registry. The main image is the repository image;
|
|
example components are nested packages below it:
|
|
|
|
```
|
|
ghcr.io/sredevopsorg/deepseek-kubernetes-sandbox # DSH Web (main image)
|
|
ghcr.io/sredevopsorg/deepseek-kubernetes-sandbox/dsh-agents-as-a-service/gateway # example gateway
|
|
```
|
|
|
|
| Tag | Contents | Meaning |
|
|
| --- | --- | --- |
|
|
| `dsh-v0.2.1-rc.5` | DSH Web, port `3080` | **Current release identity.** Immutable: once published it never moves. |
|
|
| `latest` | DSH Web | Most recent release; same digest as the current identity. |
|
|
| `main` | DSH Web | Development channel rebuilt when image-definition files change on `main`. Not a release; not for production. |
|
|
|
|
The example gateway is published under its nested path with the same release
|
|
identity, e.g.
|
|
`ghcr.io/sredevopsorg/deepseek-kubernetes-sandbox/dsh-agents-as-a-service/gateway:dsh-v0.2.1-rc.5`.
|
|
|
|
Release identities, channels and rollback rules are explained in
|
|
[docs/versioning.md](docs/versioning.md). Production deployments should pin a
|
|
digest:
|
|
|
|
```bash
|
|
docker buildx imagetools inspect ghcr.io/sredevopsorg/deepseek-kubernetes-sandbox:dsh-v0.2.1-rc.5
|
|
# image: ghcr.io/sredevopsorg/deepseek-kubernetes-sandbox@sha256:<digest>
|
|
```
|
|
|
|
## Build from source
|
|
|
|
```bash
|
|
make image # build the main DSH Web image (clones and builds upstream DSH)
|
|
make run # build it, then run it interactively (needs DEEPSEEK_API_KEY)
|
|
```
|
|
|
|
The pins (`DSH_VERSION`, `RELEASE_REVISION`, `PNPM_VERSION`) come from
|
|
[versions.env](versions.env) — never hard-code them
|
|
(`make check` verifies). [`build.sh`](build.sh) is a deprecated shim that
|
|
forwards to `make`; use the Makefile targets.
|
|
|
|
## Examples
|
|
|
|
Self-contained implementations that consume the image. Index and contract:
|
|
[`examples/README.md`](examples/README.md) and
|
|
[docs/examples.md](docs/examples.md).
|
|
|
|
| Example | What it demonstrates |
|
|
| --- | --- |
|
|
| [`examples/dsh-agents-as-a-service/`](examples/dsh-agents-as-a-service/) | Full multi-tenant platform: SandboxTemplate with per-user PVCs, warm pool, one claim per user, suspend-when-idle, wake-on-return, browser gateway with signup + `HttpOnly` sessions + HTTP/WebSocket proxy, Ingress or Gateway API + GitHub SSO exposure, and opt-in gVisor/NetworkPolicy/provider-key hardening and failed-Pod recovery. Start with the [walkthrough](examples/dsh-agents-as-a-service/README.md) and the [architecture](examples/dsh-agents-as-a-service/docs/architecture.md). |
|
|
| [`examples/minimal-single-tenant/`](examples/minimal-single-tenant/) | The smallest useful setup: one `SandboxTemplate` and one `SandboxClaim`, reached through `kubectl port-forward` + the launch-token URL. Manifest: [`manifests/10-sandboxtemplate.yaml`](examples/minimal-single-tenant/manifests/10-sandboxtemplate.yaml). |
|
|
|
|
The gateway is a component of the multi-tenant example and has its own
|
|
[README](examples/dsh-agents-as-a-service/gateway/README.md) (API, configuration,
|
|
auth/SSO, limitations). The example also documents opt-in gVisor,
|
|
`nodeSelector`, NetworkPolicy and extra provider-key hardening in
|
|
[optional hardening](examples/dsh-agents-as-a-service/docs/optional-hardening.md).
|
|
|
|
## Agent skills
|
|
|
|
DSH discovers project skills from `.dsh/skills/<name>/SKILL.md`. The repository
|
|
ships [`dsh-agent-sandbox-platform`](.dsh/skills/dsh-agent-sandbox-platform/SKILL.md),
|
|
which covers operating and extending the platform, the optional
|
|
[agent-sandbox MCP server](https://github.com/kubernetes-sigs/agent-sandbox/blob/main/clients/integrations/mcp-server/README.md),
|
|
and a read-only cluster preflight. Runbooks, the MCP reference, the extension
|
|
guide and troubleshooting notes live beside `SKILL.md`.
|
|
|
|
## Repository layout
|
|
|
|
| Path | Purpose |
|
|
| --- | --- |
|
|
| [`Dockerfile`](Dockerfile) | Primary artifact: the multi-stage DSH Web image (port `3080`). |
|
|
| [`versions.env`](versions.env) | Single source of truth for the DSH ref, repository revision, pnpm/control-plane versions and image names. |
|
|
| [`Makefile`](Makefile), [`build.sh`](build.sh) | Canonical local entrypoint; `build.sh` is a deprecated shim. |
|
|
| [`docs/`](docs/README.md) | Repository docs: image contract, example contract, gitflow, versioning. |
|
|
| [`examples/`](examples/README.md) | One self-contained implementation per directory. |
|
|
| [`examples/dsh-agents-as-a-service/`](examples/dsh-agents-as-a-service/) | Multi-tenant platform example: `manifests/`, `gateway/`, `docs/`, `scripts/`. |
|
|
| [`examples/minimal-single-tenant/`](examples/minimal-single-tenant/) | Single-sandbox quickstart. |
|
|
| [`scripts/`](scripts/) | Repository checks: versions, example layout, manifest YAML, version bump. |
|
|
| [`.dsh/skills/`](.dsh/skills/) | Project-local DSH skills, auto-discovered from the git root. |
|
|
| [`.github/`](.github/) | CI, release automation, dependency updates, PR/issue templates. |
|
|
| [`.env.sample`](.env.sample) | Reference environment names for local runs; nothing reads it automatically. Never commit a real key. |
|
|
|
|
## Development
|
|
|
|
The Makefile is the canonical entrypoint. No cluster is needed for `check`,
|
|
`test`, `lint`, `gateway` or `image`:
|
|
|
|
| Target | What it does |
|
|
| --- | --- |
|
|
| `make check` | Version pins, example layout and manifest YAML checks. Run before every commit. |
|
|
| `make test` | Gateway unit tests (`pytest`). |
|
|
| `make lint` | `ruff` + `shellcheck` (+ `yamllint`/`actionlint` when installed). |
|
|
| `make image` | Build the main DSH Web image. |
|
|
| `make gateway` | Build the example gateway image locally (`dsh-aaas-gateway:dev`). |
|
|
| `make e2e` | Full kind walkthrough of the multi-tenant example (needs a cluster with agent-sandbox). |
|
|
| `make changelog` | Regenerate `CHANGELOG.md` with git-cliff (release only). |
|
|
| `make set-version` | Bump pins in `versions.env`; e.g. `make set-version DSH_VERSION=<ref> RELEASE_REVISION=rN`. |
|
|
|
|
Local setup and the PR workflow: [CONTRIBUTING.md](CONTRIBUTING.md); branches,
|
|
required checks and releases: [docs/gitflow.md](docs/gitflow.md).
|
|
|
|
## Versioning and releases
|
|
|
|
The release identity is the upstream DSH ref plus an optional repository
|
|
revision: `DSH_VERSION` and `RELEASE_REVISION` in [versions.env](versions.env).
|
|
The current identity is **`dsh-v0.2.1-rc.5`** — the first release at this
|
|
upstream DSH ref, so it carries no repository revision. Tags are immutable; a
|
|
broken release is fixed by publishing `-r(N+1)`, never by re-tagging.
|
|
|
|
`CHANGELOG.md` is generated by [git-cliff](https://git-cliff.org) from
|
|
Conventional Commits and is never edited by hand. See
|
|
[`CHANGELOG.md`](CHANGELOG.md), [docs/versioning.md](docs/versioning.md) and
|
|
[cliff.toml](cliff.toml).
|
|
|
|
## Contributing
|
|
|
|
- [CONTRIBUTING.md](CONTRIBUTING.md) — local setup, PR workflow, what a change needs.
|
|
- [AGENTS.md](AGENTS.md) — repository conventions for AI coding agents (and humans) and the CI commands.
|
|
- [SECURITY.md](SECURITY.md) — private vulnerability reporting and project threat notes.
|
|
- [CODE_OF_CONDUCT.md](CODE_OF_CONDUCT.md) — community standards.
|
|
- [docs/gitflow.md](docs/gitflow.md) — branches, protected `main`, required checks, release process.
|
|
|
|
Do not commit secrets; secret-shaped YAML lives in `*.yaml.example` files, and
|
|
version pins change only through `versions.env` / `make set-version`.
|
|
|
|
## License
|
|
|
|
[MIT](LICENSE) © Nicolás Georger.
|