# Minimal single-tenant SandboxTemplate for DeepSeek Harness Web. # # This is the "just one DSH Web" quick-start template. For the full # multi-tenant platform (warm pool, per-user claims, gateway, idle-suspend), # see examples/dsh-agents-as-a-service/. # # Prerequisites (create these first, or apply 00-prereqs.yaml from the # examples directory): # - Namespace dsh-demo. # - Secret dsh-provider-keys in dsh-demo with key DEEPSEEK_API_KEY # (injected via envFrom; the pod starts without it, only model calls fail). # The agent-sandbox controller (v1.0.7, API v1beta1) must be installed. apiVersion: extensions.agents.x-k8s.io/v1beta1 kind: SandboxTemplate metadata: name: dsh-web-template namespace: dsh-demo spec: service: true # headless Service per Sandbox -> stable DNS (status.serviceFQDN) podTemplate: spec: securityContext: runAsNonRoot: true runAsUser: 1000 # Matches the UID of the 'node' user runAsGroup: 1000 fsGroup: 1000 # DSH's credentials plugin refuses to start when .credentials.yaml has # any group/other permission bit (it creates the file 0600). The # default kubelet fsGroup policy ("Always") recursively ORs 0660 into # every file each time the pod starts, so a recreated/resumed sandbox # comes back with 0660 and crash-loops. OnRootMismatch skips that walk # once the volume root already has the fsGroup ownership/mode from the # first mount. Keep in sync with # examples/dsh-agents-as-a-service/10-sandboxtemplate.yaml. fsGroupChangePolicy: OnRootMismatch containers: - name: dsh-web image: ghcr.io/sredevopsorg/deepseek-kubernetes-sandbox:dsh-v0.2.1-rc.2 imagePullPolicy: IfNotPresent ports: - name: web containerPort: 3080 envFrom: - secretRef: name: dsh-provider-keys # Secret with key DEEPSEEK_API_KEY env: # Empty => DSH derives links from the request Host. Keep it empty # when fronting the sandbox with a proxy/gateway. - name: DSH_PUBLIC_URL value: "" # DSH Host/Origin-fences /api. Empty trusts only localhost, which # is right for `kubectl port-forward`. Set this to the public host # (e.g. dsh.example.com) if you expose DSH behind an Ingress, so # requests forwarded with the browser's Host are accepted. - name: DSH_TRUSTED_HOSTS value: "" volumeMounts: - name: dsh-home mountPath: /home/node/.dsh # DSH_HOME # / is behind DSH's launch-token cookie (401 without it); use an # unauthenticated path for probes. The startup probe gives a cold # start (plugin activation on a small node, or the first resume of a # suspended sandbox) up to 120s before liveness can restart it. startupProbe: httpGet: path: /favicon.svg port: 3080 periodSeconds: 5 failureThreshold: 24 readinessProbe: httpGet: path: /favicon.svg port: 3080 initialDelaySeconds: 5 periodSeconds: 5 livenessProbe: httpGet: path: /favicon.svg port: 3080 initialDelaySeconds: 15 periodSeconds: 15 securityContext: allowPrivilegeEscalation: false capabilities: drop: ["ALL"] seccompProfile: type: RuntimeDefault volumeClaimTemplates: - metadata: name: dsh-home spec: accessModes: ["ReadWriteOnce"] resources: requests: storage: 5Gi # storageClassName omitted => cluster default