Skip to content

Releases: coder/coder-k8s

v0.1.5

Choose a tag to compare

@ThomasK33 ThomasK33 released this 14 Oct 23:41
57ee69a

This release turns on two kinds: CoderAIGatewayKey and CoderMCPServer. The operator now creates, rotates and deletes Coder AI Gateway keys, and it manages MCP server configs that Coder chats use. It also cleans up better. A CoderControlPlane now waits for the keys, AI providers and MCP servers that use it while you delete them, so their deletes reach Coder. A cleanup record is a ConfigMap that the operator writes before each AI provider or key create. It lets the operator delete what a namespace deletion left in Coder, when a control plane on the same Coder database comes back. Read the upgrade notes before you upgrade. The first step needs an action from you.

Upgrade notes

  1. Apply the CRDs and RBAC before or together with the new image (#346, #374, #381). This release adds the CoderAIGatewayKey and CoderMCPServer CRDs, new ClusterRole rules, and two new objects in coder-system: the Role manager-role and the RoleBinding coder-k8s-cleanup-records. From a clone of v0.1.5, run:

    kubectl apply -f config/crd/bases/ -f config/rbac/

    Or apply dist/install.yaml from v0.1.5. The operator watches every kind that it reconciles, so the manager does not start without the two new CRDs. Without the Role and the RoleBinding, the operator cannot write cleanup records. Then it creates no AI provider and no key, and existing CoderAIProvider objects stop syncing. Check both objects:

    kubectl -n coder-system get role manager-role
    kubectl -n coder-system get rolebinding coder-k8s-cleanup-records

    If you run the operator in another namespace, change the namespace of both objects.

  2. Delete the AI providers that v0.1.4 left in Coder by hand (#374, #375). In v0.1.4, a namespace deletion or a provider deleted after its control plane left the provider in Coder in some cases. v0.1.4 wrote no cleanup records, so this release cannot find those providers. Search the v0.1.4 operator logs for Releasing the finalizer without a delete in Coder: the provider can stay in the Coder database, which names the provider ID. Then open AI settings > Providers (/ai/settings/providers) as an owner, and delete each provider that no CoderAIProvider object uses. A CoderAIProvider that still exists gets its record at its first reconcile that reaches Coder.

  3. Do not give other users write access to ConfigMaps in coder-system (#374). A cleanup record names the Coder provider ID or the key name prefix that a sweep deletes. A user who can write these ConfigMaps can point a sweep at other Coder resources. Find the records with kubectl -n coder-system get configmaps -l coder.com/cleanup-record.

  4. Expect slower control plane deletes (#362, #384). A CoderControlPlane delete can now take up to about 15 minutes while its keys, providers and MCP servers delete. Before, it went at once. See "Changed behavior".

  5. Delete keys, providers and MCP servers before their namespace. This advice does not change. A namespace deletion removes Coder's pods at once, so the operator cannot delete these objects in Coder at that time.

New

  • CoderAIGatewayKey (#341, #346, #370). This is the first release that runs this kind. One object keeps one Coder AI Gateway key in a Secret that the object owns. The operator creates the key, rotates it (every 30 days by default), deletes replaced keys after a grace period (1 hour by default), and deletes every key of the object when you delete the object. The control plane must opt in with spec.aiGateway.allowKeys: true. Without it, the object stalls with NotAllowed. An object that never created a key makes no Coder call. You need a Coder Premium license with the AI Gateway enabled, and the operator user must be a site owner. A gateway key is a full-trust credential. Grant write access to coderaigatewaykeys, and read access to the output Secrets, only to principals that can hold that power. The guide is Manage AI Gateway keys.
    • Key names. The operator names its keys ck8s-<UID>-<serial>, where <UID> is the object's metadata.uid without dashes. The operator and the sweep delete keys with this prefix. Do not give your own keys names that start this way.
    • Only Coder's own 404 proves that a key is gone. A 404 from a proxy makes the operator retry (#341).
  • CoderMCPServer (#330, #356, #360, #363, #366, #368, #381). This is the first release that runs this kind. One object manages one MCP server config in a Coder organization (AI settings > MCP servers). Coder chats then offer its tools to the model. The control plane must list the organizations in spec.mcpServers.organizations. Without it, the object stalls with MCPServersNotAllowed. You need Coder v2.37.2 or later, and the operator user must be a site owner. The guide is Manage MCP servers.
    • Kill switches. The operator disables the server in Coder when the credential Secret withdraws consent, or when the control plane withdraws its opt-in. A disable in the dashboard stalls the object with DisabledExternally. A spec edit enables the server again.
    • Access. spec.access lists groups. When a listed group does not exist in Coder, the operator removes the access of unlisted groups and of users, and adds no group.
    • Deletion. Deleting the object deletes the config in Coder.
  • Opt-in status admission policy for CoderMCPServer (#377). config/admission/status-operator-only.yaml holds a ValidatingAdmissionPolicy and its binding. Only the operator ServiceAccount can then write codermcpservers/status, and cluster admins are denied too. The install bundle does not apply it. Apply it with kubectl apply -f config/admission/. It needs Kubernetes v1.30 or later, where ValidatingAdmissionPolicy is GA. It hard-codes the user system:serviceaccount:coder-system:coder-k8s. If the operator runs as another ServiceAccount or in another namespace, edit the expression first, or the operator cannot write status.
  • GitOps health rules for CoderMCPServer (#383). config/gitops/argocd-health-codermcpserver.lua is for Argo CD. config/gitops/flux-healthcheck-codermcpserver.yaml is for a Flux v2.5+ Kustomization with spec.wait: true.
  • Cleanup records and the sweep (#374, #375, #385, #386). Before each AI provider or key create, the operator writes a ConfigMap ck8s-cleanup-<object UID> in its own namespace (coder-system). The label coder.com/cleanup-record holds the kind (CoderAIProvider or CoderAIGatewayKey). The record holds no secret. It names the object, the Coder deployment ID from /api/v2/buildinfo, and the provider ID or the key name prefix. If the operator cannot write the record, it sends no create.
    • When an object goes without a delete in Coder, for example in a namespace deletion, the record stays. The leftovers stay valid in Coder until the sweep deletes them.
    • The sweep runs when a ready CoderControlPlane in the same namespace reaches the same Coder deployment again, which means the same Coder database. It matches by deployment ID, never by URL or name. The operator user of that control plane must be a site owner.
    • A new Coder database behind the same URL is never swept. A control plane in another namespace never sweeps a record either.
    • The counter coder_k8s_cleanup_records_swept_total{kind} counts swept records. When no ready control plane reaches a record's deployment, the gauge coder_k8s_cleanup_records_unmatched{kind} counts the record. The operator also writes a NoMatchingDeployment Warning Event on the ConfigMap every 10 minutes.
  • New metric coder_k8s_cleanup_released_without_delete_total{kind} (#362). It counts each CoderAIGatewayKey or CoderAIProvider finalizer that went without a delete in Coder.

Changed behavior

  • A deleted CoderControlPlane waits for the objects that use it (#362, #384, #385). This applies while CoderAIGatewayKey, CoderAIProvider or CoderMCPServer objects that reference the control plane are being deleted.
    • The control plane keeps its finalizer for up to 10 minutes, so Coder keeps running. The objects delete in Coder as usual, with retries.
    • After the 10 minutes, the remaining objects get at most 5 more minutes for one last delete attempt. So a control plane delete can take up to about 15 minutes. Before, it went at once.
    • A key or MCP server delete attempt that runs during the wait stops at the end of the wait.
    • T...
Read more

v0.1.4

Choose a tag to compare

@ThomasK33 ThomasK33 released this 14 Oct 11:12
3372652

This release turns on the CoderAIProvider kind. The operator now creates, syncs, disables and deletes AI providers in Coder from Kubernetes objects. It also hardens how the operator handles credentials. The operator no longer follows redirects to another origin with the operator token. It refuses more Secrets as credentials, and it uses the operator token Secret only when the control plane owns it. Aggregated API errors no longer show the Coder URL. CoderTemplateTest no longer gets stuck after two no-effect create answers, and no longer gives up too early on an uncertain create. Read the upgrade notes before you upgrade. Several items need an action from you.

Security

  • No cross-origin redirects with the operator token (#230, #293, #297, #306). The bootstrap client, the license and entitlements client and the aggregated API server's Coder client now follow a redirect only to the same scheme, host and port. A redirect to another origin fails the call, so the operator never sends Coder-Session-Token there. This also covers the websocket that streams workspace build logs (coderworkspaces/log?follow=true). Same-origin redirects still work. The log line says refusing redirect to a different origin than the coder URL, or refusing request to a different origin than the coder URL for a refused websocket request.
  • More Secrets are refused as credentials (#258, #271, #282). CoderWorkspaceProxy, CoderProvisioner and CoderAIProvider now refuse every Secret that the spec of a CoderControlPlane in the same namespace references. This covers spec.licenseSecretRef, spec.database.connectionSecretRef, spec.extraEnv secretKeyRefs, spec.envFrom secretRefs, spec.imagePullSecrets, spec.tls.secretNames, spec.expose.ingress.tls, spec.certs.secrets and the Secret sources of spec.volumes. Before, of a control plane's Secrets, the operator refused only its operator token Secret.
  • The operator token Secret must be owned (#238). A CoderControlPlane now uses its operator token Secret only when the control plane is the Secret's controller owner. It no longer takes over an existing Secret with that name.
  • Aggregated API errors hide Coder details (#281, #291). Error messages no longer show the Coder URL, the request path, Coder's IP address or Coder's internal error text. This covers 403, 409, 5xx, unexpected statuses and network errors. Status codes do not change. The full Coder error stays in the server log (coder-errors logger).
  • Provider IDs are checked before every Coder call (#325). The CoderAIProvider controller sends no request when status.providerID is not a canonical, lowercase, non-nil UUID. It logs an assertion failed: error instead.

Upgrade notes

  1. Apply the CRDs and RBAC before or together with the new image (#315). This release adds the CoderAIProvider CRD, new RBAC rules and new CoderControlPlane fields. Apply config/crd/bases/ and config/rbac/ from v0.1.4, or apply dist/install.yaml from v0.1.4. The operator watches every kind it reconciles, so the manager fails to start if the CoderAIProvider CRD is missing.
  2. Check your operator token Secrets before you upgrade (#238). A control plane whose operator token Secret (spec.operatorAccess.generatedTokenSecretName, default <name>-operator-token) has another owner, or no owner, stops using operator access. Provisioners, template tests, CoderAIProvider objects and the aggregated API server then stop working for that control plane. The condition OperatorTokenSecretOwned=False with the reason TokenSecretNotOwned reports it. Secrets that an earlier version used already have the right owner. The usual cause is a control plane that was deleted with --cascade=orphan and created again. Operator token Secret has a command that lists unowned Secrets. To fix one, delete the leftover Secret so the controller creates a new one, or set generatedTokenSecretName to a free name.
  3. Move proxy and provisioner credentials out of control plane Secrets (#258, #271). A CoderWorkspaceProxy or CoderProvisioner that references a Secret that a control plane spec also references now reports CredentialsReady=False with the reason CredentialRefused. It keeps its last applied Deployment, but the operator does not apply its spec changes. Store the credential in its own labeled and annotated Opaque Secret, and point the reference at that Secret. Configure credential Secrets has a command that lists the affected resources.
  4. Turn off CODER_REDIRECT_TO_ACCESS_URL on control planes (#293). With CODER_REDIRECT_TO_ACCESS_URL=true (or --redirect-to-access-url) on a CoderControlPlane, every operator call to Coder fails with refusing redirect to a different origin than the coder URL: the license, provisioner key, aggregated API, CoderTemplateTest and CoderAIProvider calls. These calls also failed before, because the redirect drops the API path. To send browsers from HTTP to HTTPS, set the redirect in your Ingress, Gateway or load balancer instead. With spec.bootstrap on a proxy, spec.bootstrap.coderURL must be the final origin that answers without a redirect (#230).
  5. Expect plain HTTP inside the cluster when built-in TLS is on (#273). With spec.tls.secretNames, the provisioner key calls and the aggregated API server now call the control plane Service at http://<control plane>.<namespace>.svc.cluster.local:<port>, not at status.url. The control-plane controller and CoderTemplateTest already did this. The operator token crosses the cluster network without TLS. Use a service mesh if you need encryption inside the cluster. Use a NetworkPolicy to limit which pods can reach the control plane Service. Allow the operator and aggregated API server pods to reach the control plane Service HTTP port. Provisioner pods still connect to status.url.
  6. Remove unsupported list options from codertemplates requests (#234). A codertemplates LIST now applies label and field selectors. A codertemplates LIST now returns 400 for continue, for resourceVersionMatch, and for a field selector on any field other than metadata.name and metadata.namespace. Templates have no labels, so a label selector that requires a label returns no templates. Before, the server ignored them and returned every template. limit is still ignored, and any resourceVersion is accepted. A kubectl apply --prune -l ... over codertemplates now sees only the matching templates.
  7. Check provisioner key cleanup (#248). When you delete a CoderProvisioner, the operator now deletes only the Coder key recorded in status.organizationID and status.provisionerKeyID. When the status has no key, the operator removes the finalizer without a call to Coder. If the status lost its key IDs, delete the key in Coder by hand (coder provisioner keys list --org <organization>).
  8. Grant write access to CoderAIProvider only to Coder owners (#315). The operator calls Coder as a site owner. Give create, update, patch and delete on coderaiproviders only to principals that can act as a Coder owner for AI providers in the whole deployment. Such a principal can use any opted-in credential Secret in the namespace, toward the origins that the Secret lists. A delete deletes the provider in Coder for every user.
  9. Check your Coder version (#315, #345). CoderAIProvider needs Coder v2.37.2 or later. The CI E2E tests of coder-k8s v0.1.4 run against Coder v2.37.2. coder-k8s still uses the Coder SDK v2.37.3.

Added

  • CoderAIProvider (#235, #245, #253, #265, #276, #283, #298, #302, #303, #310, #312, #315). This new coder.com/v1alpha1 kind manages one AI provider in Coder. The object name is the Coder provider name, and it cannot be a UUID. spec.type (openai, anthropic, azure, google, openai-compat, openrouter or vercel) and spec.controlPlaneRef cannot change. The operator creates the provider and keeps its settings and API key equal to the spec. It reads the key from spec.apiKeySecretRef, a credential Secret that lists the origin o...
Read more

v0.1.3

Choose a tag to compare

@ThomasK33 ThomasK33 released this 13 Oct 10:09
8805e14

This release adds template versions, workspace build logs, workspace start and stop, template promotion and rollback, and the new CoderTemplateTest kind. It also adds credential consent checks for CoderWorkspaceProxy and CoderProvisioner, and kube-apiserver now verifies the certificate of the aggregated API server. Read the upgrade notes before you upgrade. Several items need an action from you.

Security

  • Credential consent checks for CoderWorkspaceProxy and CoderProvisioner (GHSA-v37g-f2wp-qqg4, #225). The operator now uses a Kubernetes Secret only when the Secret is marked as a credential for the destination that receives it:

    • The Secret has the label coder.com/credential: "true".
    • Its annotation coder.com/credential-destinations lists the origin (scheme://host[:port]) that receives the value.
    • It has type Opaque. The value is not empty, is at most 8 KiB, and has no leading or trailing whitespace.

    The operator refuses Secrets that it generates itself, and it reads and updates a generated proxy token Secret or provisioner key Secret only when the resource owns it. It refuses extraEnv and extraArgs entries that set the URL or token that it sets itself. Proxy pods no longer get a Kubernetes service account token. The new condition CredentialsReady reports the result. When a check fails, the operator sends nothing to Coder and keeps the last applied Deployment.

  • Go 1.26.9 and golang.org/x/net v0.60.0 (#222). This fixes 12 Go advisories that govulncheck reported as called by coder-k8s code. They are in the HTTP/1 and HTTP/2 code, crypto/tls, html/template and MIME header parsing.

  • Server-side dry-run is rejected (#171). Coder has no dry-run mode. codertemplates and coderworkspaces now answer every dryRun=All write (create, update, patch, server-side apply, delete) with 400 BadRequest, before any request goes to Coder.

  • Verified serving certificate (#140, #141). kube-apiserver now verifies the aggregated API server's certificate through the APIService caBundle. The APIService manifest no longer sets insecureSkipTLSVerify: true.

  • Least-privilege standalone ServiceAccount (#146, #147). A standalone aggregated API server now runs as coder-k8s-apiserver, without manager-role.

Upgrade notes

  1. Label and annotate the Secrets that proxies and provisioners use (#225). Before you upgrade, follow Configure credential Secrets for proxies and provisioners (docs/how-to/workspace-proxy-credentials.md). The page has jq and shell checks that list every Secret and setting that needs a change. In short:

    • Label and annotate every referenced Secret. This covers spec.proxySessionTokenSecretRef, spec.bootstrap.credentialsSecretRef and spec.extraEnv[].valueFrom.secretKeyRef on CoderWorkspaceProxy, and spec.extraEnv[].valueFrom.secretKeyRef on CoderProvisioner:

      kubectl -n <ns> label secret <name> coder.com/credential=true
      kubectl -n <ns> annotate secret <name> coder.com/credential-destinations=https://coder.example.com
    • A proxy that uses the operator token Secret as spec.bootstrap.credentialsSecretRef needs a dedicated Coder token in its own Secret.

    • With spec.bootstrap, the bootstrap credentials Secret must exist on every reconcile. Recreate it if you deleted it after the first registration.

    • A generated proxy token Secret (default <proxy>-proxy-token) or provisioner key Secret (default <provisioner>-provisioner-key) must not exist yet, or the resource must own it. Otherwise delete it, or set a new name. For a provisioner, the operator then creates a new provisioner key. A Secret that an earlier version already adopted has the resource as its owner and stays in use.

    • Remove extraEnv and extraArgs entries that the operator sets itself. For CoderWorkspaceProxy these are CODER_PRIMARY_ACCESS_URL, CODER_PROXY_SESSION_TOKEN, --primary-access-url and --proxy-session-token. For CoderProvisioner these are CODER_URL, CODER_PROVISIONER_DAEMON_KEY, --url and --key.

    • Proxy pods no longer get a service account token. A custom proxy image that reads the Kubernetes API needs a change. Each proxy that passes the checks rolls out one time after the upgrade.

    • After the upgrade, check that every proxy and provisioner reports CredentialsReady=True. A resource that fails a check keeps running with its last applied Deployment, but the operator does not apply its spec changes until you fix the cause. CredentialsReady=False uses one of these reasons: CredentialSecretNotFound, CredentialKeyMissing, CredentialNotOptedIn, CredentialDestinationNotAllowed, CredentialRefused, CredentialMalformed, TokenSecretNotOwned, KeySecretNotOwned and ReservedSettingOverride. The messages name Secrets, keys, fields and origins, and never contain values.

  2. Grant write access to CoderWorkspaceProxy, CoderProvisioner and CoderControlPlane only to admins (#225). Give create, update and patch on coderworkspaceproxies, coderprovisioners and codercontrolplanes only to principals that can already read Secrets and create Pods in that namespace. A custom spec.image runs with everything the pod receives, including the proxy token or provisioner key and every extraEnv value. The checks in this release do not restrict the image.

  3. Apply the CRDs and RBAC before or together with the new image (#210, #213). This release adds the CoderTemplateTest CRD and new CoderControlPlane fields (spec.templateTests). Apply config/crd/bases/ and config/rbac/ from v0.1.3, or apply dist/install.yaml from v0.1.3. The operator watches every kind it reconciles, so the manager does not start if the CoderTemplateTest CRD is missing.

  4. Move the aggregated API server to the managed serving CA (#140, #141, #146). In a Pod, the server now serves a certificate signed by its own CA. It keeps the CA in the Secret coder-system/coder-k8s-apiserver-tls and puts the CA into the APIService caBundle. Apply the changes in this order:

    1. kubectl apply -f config/rbac/. This includes config/rbac/apiservice-cabundle-role.yaml, which lets the server patch its own APIService.
    2. Deploy the new image. It sets caBundle and turns insecureSkipTLSVerify off in one step.
    3. kubectl apply -f deploy/apiserver-apiservice.yaml. The file no longer sets insecureSkipTLSVerify.

    If you apply step 3 before the new image runs, requests through kube-apiserver fail with 503 until the new image starts. Do not apply an old copy of deploy/apiserver-apiservice.yaml after that. If cert-manager or a GitOps tool owns caBundle, annotate the APIService with coder.com/manage-ca-bundle=false first. Anyone who can read the coder-k8s-apiserver-tls Secret can issue certificates that this CA vouches for. See Deploy the aggregated API server for rollback and CA replacement.

  5. Move a standalone aggregated API server to its own ServiceAccount (#146, #147). This applies only to --app=aggregated-apiserver. --app=all and dist/install.yaml do not change. Apply the RBAC and the empty placeholder Secret, then switch the Deployment to coder-k8s-apiserver:

    kubectl apply -f config/apiserver-standalone/ -f config/rbac/apiservice-cabundle-role.yaml
    kubectl -n coder-system patch deployment coder-k8s --type=json \
      -p '[{"op": "replace", "path": "/spec/template/spec/serviceAccountName", "value": "coder-k8s-apiserver"}]'

    The new ServiceAccount cannot create Secrets, so the placeholder must exist before the pod starts. The server fills the placeholder. When you apply it over an existing Secret, the Secret keeps its CA.

  6. Stop using server-side dry-run on codertemplates and coderworkspaces (#171). kubectl diff, kubectl apply --dry-run=server, kubectl delete --dry-run=server and the opt-in server-side diff of Argo CD now get 400 BadRequest for these resources. The default Argo CD diff and sync send no server-side dry-run. The new start, stop and promote subresources support ?dryRun=All as a read-only preview.

  7. Check your Coder version (#163). coder-k8s now uses the Coder SDK v2.37.3. Coder v2.37 is a release on Coder's mainline channel, not the stable channel. The CI E2E tests of coder-k8s v0.1.3 run against Coder v2.37.2.

  8. Grant the new permissions to the users who need them (#178, #179, #185, #187). Each new resource and subresource has its own grant. Access to codertemplates does not include codertemplateversions. No verb on coderworkspaces or codertemplates grants the subresources, and no default role ...

Read more

v0.1.2

Choose a tag to compare

@ThomasK33 ThomasK33 released this 25 Sep 08:27
c9ffd94

This release contains the security fix from v0.1.1 plus a packaging repair. The v0.1.1 release build failed before publishing, so v0.1.1 has no binaries or images; use this release.

Security

  • Authentication for the aggregated API server and the MCP HTTP server (GHSA-c3vp-pjh2-7gv4, #136). In v0.1.0, both servers accepted unauthenticated requests and acted with the operator's authority, and the default --app=all ran both. The aggregated API server now authenticates and authorizes every request through Kubernetes (front-proxy certificates, TokenReview, SubjectAccessReview); anonymous callers reach only /healthz, /livez and /readyz. The MCP server no longer runs in --app=all; --app=mcp-http listens on 127.0.0.1:8090 and requires a bearer token from --mcp-token-file.
  • Dependency updates for published advisories (#92, #101, #104, #118), and code and image security scanning in CI (#88).

Upgrade notes

  1. The aggregated API server needs config/rbac/auth-delegator-binding.yaml and config/rbac/authentication-reader-binding.yaml for the operator ServiceAccount (both are applied by kubectl apply -f config/rbac/). Without read access to kube-system/extension-apiserver-authentication it does not start; without permission to create SubjectAccessReviews it denies requests.
  2. Clients that called port 6443 directly must send a Kubernetes bearer token with RBAC on aggregation.coder.com, or go through kube-apiserver (kubectl).
  3. RBAC on codertemplates and coderworkspaces is owner-equivalent inside Coder: the server calls Coder with the control plane's operator token. Grant it only to subjects you would trust as Coder owners.
  4. --app=all no longer runs MCP and deploy/mcp-service.yaml is removed; delete the old Service. To use MCP, run --app=mcp-http --mcp-token-file=<file> and connect through kubectl port-forward.
  5. Outside a cluster, the aggregated API server needs KUBECONFIG (exactly one file) or ~/.kube/config.

Added

  • dist/install.yaml, a generated one-file install bundle for the operator in controller mode, kept fresh by CI (#89).
  • CoderControlPlane can reference an external PostgreSQL connection Secret (#122).
  • Kind E2E coverage for the CoderWorkspace lifecycle (#114).

Fixed

  • CoderTemplate Update applies metadata only after the new source is active, and returns 409 Conflict if the template changed during the import (#129).
  • spec.files template Create waits for the import before creating the template (#116).
  • Canonical organization, owner, template and workspace names are enforced so repeated kubectl apply converges (#106, #111).
  • Aggregated API delete preconditions are honored, and workspace resourceVersion reflects the returned representation (#110, #115).
  • kubectl rollout restart works on operator-managed Deployments (#121).
  • Release and :main image builds are unified and repaired, and tag releases no longer fail on an unset GORELEASER_CHANNEL (#86, #87, #99, #131, #138).

Documentation

  • Rewritten README and docs (#123); corrected deploy steps (#124, #126); the standalone session token is kept in a Secret (#135); the 34-second write budget for template imports is documented (#128).

v0.1.1

Choose a tag to compare

@ThomasK33 ThomasK33 released this 25 Sep 08:00
78a2eca

Warning

The release build for this tag failed before publishing, so v0.1.1 has no binaries, archives or container images. Use v0.1.2, which contains the same fix plus the packaging repair (#138). The v0.1.1 source and Go module already include the security fix (#136).

Security

  • Authentication for the aggregated API server and the MCP HTTP server (GHSA-c3vp-pjh2-7gv4, #136). In v0.1.0, both servers accepted unauthenticated requests and acted with the operator's authority, and the default --app=all ran both. The aggregated API server now authenticates and authorizes every request through Kubernetes (front-proxy certificates, TokenReview, SubjectAccessReview); anonymous callers reach only /healthz, /livez and /readyz. The MCP server no longer runs in --app=all; --app=mcp-http listens on 127.0.0.1:8090 and requires a bearer token from --mcp-token-file.
  • Dependency updates for published advisories (#92, #101, #104, #118), and code and image security scanning in CI (#88).

Upgrade notes

  1. The aggregated API server needs config/rbac/auth-delegator-binding.yaml and config/rbac/authentication-reader-binding.yaml for the operator ServiceAccount (both are applied by kubectl apply -f config/rbac/). Without read access to kube-system/extension-apiserver-authentication it does not start; without permission to create SubjectAccessReviews it denies requests.
  2. Clients that called port 6443 directly must send a Kubernetes bearer token with RBAC on aggregation.coder.com, or go through kube-apiserver (kubectl).
  3. RBAC on codertemplates and coderworkspaces is owner-equivalent inside Coder: the server calls Coder with the control plane's operator token. Grant it only to subjects you would trust as Coder owners.
  4. --app=all no longer runs MCP and deploy/mcp-service.yaml is removed; delete the old Service. To use MCP, run --app=mcp-http --mcp-token-file=<file> and connect through kubectl port-forward.
  5. Outside a cluster, the aggregated API server needs KUBECONFIG (exactly one file) or ~/.kube/config.

Added

  • dist/install.yaml, a generated one-file install bundle for the operator in controller mode, kept fresh by CI (#89).
  • CoderControlPlane can reference an external PostgreSQL connection Secret (#122).
  • Kind E2E coverage for the CoderWorkspace lifecycle (#114).

Fixed

  • CoderTemplate Update applies metadata only after the new source is active, and returns 409 Conflict if the template changed during the import (#129).
  • spec.files template Create waits for the import before creating the template (#116).
  • Canonical organization, owner, template and workspace names are enforced so repeated kubectl apply converges (#106, #111).
  • Aggregated API delete preconditions are honored, and workspace resourceVersion reflects the returned representation (#110, #115).
  • kubectl rollout restart works on operator-managed Deployments (#121).
  • Release and :main image builds are unified and repaired (#86, #87, #99, #131).

Documentation

  • Rewritten README and docs (#123); corrected deploy steps (#124, #126); the standalone session token is kept in a Secret (#135); the 34-second write budget for template imports is documented (#128).

v0.1.0: Hello, coder-k8s

Choose a tag to compare

@ThomasK33 ThomasK33 released this 13 Feb 23:10
e7fe0e0

Added

  • Initial release of coder-k8s, a Kubernetes operator and aggregated API server for managing Coder with native Kubernetes APIs.
  • CoderControlPlane CRD and reconciler that deploys and manages a Coder control plane, including readiness, leader election, license reconciliation from a Secret, entitlements reporting, and bootstrap of an operator API user/token (#2, #23, #41, #49, #66, #67, #77).
  • CoderProvisioner CRD and controller for external provisioner daemons, with rate-limit-aware backoff and entitlement gating (#43, #65, #73, #79).
  • CoderWorkspaceProxy CRD and controller (renamed from WorkspaceProxy) for declarative workspace proxy management (#23, #61).
  • Aggregated API server (aggregation.coder.com/v1alpha1) exposing CoderWorkspace and CoderTemplate backed by the Coder SDK, with all-namespaces LIST across multiple control planes, WATCH support, OpenAPI/SSA integration, template source files via spec.files, and build-promotion gating (#11, #50, #69, #70, #72, #85).
  • MCP HTTP server with control-plane and aggregated MCP operations for AI/operational tooling (#35, #48).
  • Single-binary coder-k8s with --app=all|controller|aggregated-apiserver|mcp-http modes; all is the default (#11, #53).
  • Deployable manifests under deploy/, generated CRDs/RBAC, an Argo CD ApplicationSet example, and a CloudNativePG-backed CoderControlPlane example (#38, #75, #80).
  • Documentation site published to GitHub Pages with tutorials, how-tos, and an auto-generated API reference (#19, #24, #71, #78).
  • Apache-2.0 license and OCI image labels on the published :main image (#3, #57).

Fixed

  • Best-effort SSA create-on-update fallback and GVK-mapped OpenAPI schemas so server-side apply works against the aggregated API (#82, #83, #84).
  • Reduced noisy reconcile errors and corrected the CloudNativePG access URL (#44).
  • Prevent MCP schema panic in the control-plane status tool (#58).
  • Removed duplicate server arg passed to the Coder control plane (#40).
  • Stop generating aggregation CRDs in manifests (the aggregated API server owns those types) (#68).
  • Generated RBAC is now the single source of truth (#60).