The server, the kuben CLI and the cluster agent are rewritten in Go. It is not a performance rewrite: it brings the maintained Kubernetes libraries (client-go, controller-runtime, envtest), builds in seconds and code more people can read.
Same contracts as 1.2: the REST API is generated from the same OpenAPI document, and an oracle test compares its answers with the released 1.2.0 binary; the CRD manifest, the database schema, the configuration keys, the existing Helm values and the AgentLink protocol are unchanged. 2.0.0 adds no migration, so going back to 1.2.x is a change of binary or image.
CLI parity: every kuben command and flag of 1.2, with the same output of --version and exit status 2 for a command line that does not parse.
A new console on shadcn/ui: a home dashboard, tables with filters and pages, the Doctor with its evidence graph, and settings for single sign-on and CI trust, in English and Persian, light and dark, under the same strict content security policy.
Release files keep their 1.x names and signatures: install.sh and the Helm chart work unchanged. Pre-releases are never latest: name the version (install.sh --version v2.0.0-alpha.1, helm --version 2.0.0-alpha.1), run kuben upgrade-check --major first; with Helm, upgrade with --set backup.upgradeCheckMajor=true.
The Helm chart can now turn on single sign-on (sso.*), GitHub Actions CI trust (ci.githubActions.*) and Git sources with builds (git.github.*, build.*); secrets come from Secrets you name and are mounted as files.
The console approves or rejects deployments that wait for approval (Deployments tab) and lists the builds of Git-sourced apps with their outcome, scan result and SBOM (Builds tab).
Not in yet: scale-to-zero (the activator role is ignored with a warning), terminals, and build logs. [runtime] settings are accepted and have no effect. 1.2.x remains the stable line.
Scan reports parse again, and idle mode defaults to off under Helm
The image scan wrote a control character where the Trivy database date belongs, so no report parsed and every scan was recorded as unavailable: the scan gate never saw a finding. Reports parse again, with the date.
The CRD manifest quotes off: kubectl and Helm read a plain off as the boolean false, so apps installed through the Helm chart got false as the default idle mode instead of off.
Breaking: Kuben keeps its data in PostgreSQL. SQLite is gone and 1.x data is not imported; without a database URL the server stops with a message that shows how to run a local PostgreSQL.
Deploy an image to an app and expose it over HTTPS; the cluster agent connects to Kuben over mutual TLS (AgentLink).
Git sources through a GitHub App, built in isolated in-cluster BuildKit Jobs.
Organizations with roles, kuben backup and restore, managed secrets, single sign-on, CI trust for GitHub Actions, and image scans with a gate on deploys.
Preview environments, custom domains with claims and DNS-01 certificates (kuben dns01-issuer), and status pages.
Ready within seconds on a cluster that has just started
One failing watch no longer restarts every informer: each kind retries on its own, so the errors of a freshly installed k3s (a CRD not there yet) cost seconds, not minutes of an unready server.
Informers that have not listed within 45 seconds start over and log which kinds they were waiting for; a subsystem that ran for a minute before it failed restarts at the shortest delay again.
/livez and /readyz are no longer logged on every poll, so the service log shows what matters; kuben setup prints the service’s latest warnings when it is not ready yet.
When port 3000 is taken (the Dokploy console, for one), kuben setup names who holds it and asks which port to use, with the next free one filled in; without a terminal it takes that port. --port now also moves the port of an existing install.
The config is written after the port is settled, so a run that stopped on a busy port no longer keeps failing.
A warning when another web server holds ports 80 and 443, which apps need for public addresses.
An orange KUBEN wordmark to open the install, orange spinners and prompts, ✔ for every step that is in place, and the time long steps took.
curl -fsSL https://kuben.teamtem.com/install.sh | sh on a fresh Linux server installs k3s if needed, the service user, the configuration, kuben.service and the firewall, and prints the link to the setup page; the same command upgrades (kuben setup, status, uninstall).
The first admin account is created from the console on a setup page, guarded by a token from the installer; nothing is seeded and nothing is logged.
The session cookie is Secure exactly when the console has an https public URL (cookie_secure = auto), so signing in over http://<ip>:3000 works on day one.
Installer output in the style of modern CLIs: one line per step, with a spinner while it runs.
The smoke test runs the one-liner as root on fresh runners after every release and every day: setup page, an app, an upgrade in place, uninstall.
Charts 1.0.0 to 1.0.3 rendered KubenConfig.spec as null without platform settings, and the API server rejected the documented helm install; the chart now renders an empty spec.
CI validates the chart against a real API server before merge, and smoke-test failures report the failing command’s output.
The binary keeps its database in ~/.local/state/kuben or systemd’s state directory, so kuben doctor and kuben serve work without root; an existing /data is still used.
A generated admin password is never logged: the binary prints it to its terminal, or writes an owner-only file under systemd.
kuben doctor reports an unreadable kubeconfig, and doctor and serve warn when the Secure cookie meets plain HTTP.
The chart keeps the KubenConfig on uninstall, so apps keep their routes; the uninstall guide lists what stays behind.
A smoke test installs the published binary, chart and image anonymously on k3s after every release and every day.