Deploy Kwirth in your Kubernetes cluster in under 5 minutes. No external dependencies, no complex configuration.
| Requirement | Minimum version | Notes |
|---|---|---|
| Kubernetes | 1.24+ | Any distribution: EKS, GKE, AKS, k3s, Kind, Docker Desktop |
| Helm | 3.x | Required for Helm install method |
| kubectl | 1.24+ | For manual install or port-forwarding |
| ClusterRole | — | Kwirth needs read access to cluster resources. If you write your own role instead of using the supplied manifests, include the batch API group, or jobs will not appear in the resource selector |
Those are the prerequisites for running Kwirth on Kubernetes. Deploying on AWS ECS or with Docker Compose has its own, listed with that option — and running there without a cluster to observe is a supported configuration in its own right.
helm repo add kwirth https://kwirthmagnify.github.io/kwirth/helm-charts helm repo update
helm install kwirth kwirth/kwirth \ --namespace kwirth \ --create-namespace
kubectl port-forward -n kwirth svc/kwirth 3883:3883 # Open http://localhost:3883
Three manifests, and they differ in one thing: how much of the cluster Kwirth is allowed to touch. Each is a single file, each is applied the same way. Pick one.
| Manifest | What the cluster lets it do | Node metrics | Config lives in |
|---|---|---|---|
| kwirth.yaml | verbs: ['*'] on 15 API groups | yes | Secrets and ConfigMaps |
| kwirth-full-ro.yaml | get, list, watch. Nothing else, anywhere | yes | a PersistentVolumeClaim |
| kwirth-zero.yaml | nothing at all — not one RBAC object in the file | no | a PersistentVolumeClaim |
kwirth.yaml — everything works. The express setup: up in two minutes with every feature available. It is a broad grant, and deliberately so — verbs: ['*'] is create and delete on every Secret in the cluster and exec into any pod, which is what makes the ops and fileman plugins, and the Magnify commands, work at all.
kubectl apply -f \ https://raw.githubusercontent.com/kwirthmagnify/kwirth/master/deploy/kubernetes/manifests/kwirth.yaml kubectl get pods -n kwirth --watch
kwirth-full-ro.yaml — not one write. The same deployment with every verb that changes the cluster removed: one rule, three verbs. And it loses no observability for it, metrics included — Kwirth reads the ServiceAccount token Kubernetes already projects into every pod and that the kubelet rotates, so reaching each node's kubelet costs no permission at all. That needs Kwirth 0.6.65 or later; on an older image it starts fine and says There is no SA Token, no metrics will be available.
kubectl apply -f \ https://raw.githubusercontent.com/kwirthmagnify/kwirth/master/deploy/kubernetes/manifests/kwirth-full-ro.yaml
What it gives up are the actions: the Magnify commands — restart, scale, cordon, drain, evict, apply, delete — and the ops and fileman plugins. The button stays in the UI and the API server answers 403, so if you do not want buttons that cannot work, do not install those two plugins. Its configuration also moves to a PersistentVolumeClaim instead of Secrets, and that is what removes the write permission rather than a detail of persistence: MASTERKEY becomes the key that configuration is encrypted with: leave it unset and kwirth generates a random one on the first boot and keeps it on the volume, so each installation gets its own instead of a shared default — it must then never change. For at-rest encryption that also resists someone reading the volume, set it from a Secret kept outside the volume.
kwirth-zero.yaml — it does not know it is in a cluster. No ClusterRole, no binding, no ServiceAccount of its own, and the token the kubelet projects into every pod turned off, so there is no credential in the container either. Use it where the cluster is not yours to read: a shared platform, a tenant namespace, a policy that does not hand out ClusterRoles. It is the ECS deployment below, in a pod — it serves the front end, installs and runs extensions, keeps its configuration on the volume, uses the database, and federates against other Kwirths that do have access. What it loses is everything that reads the cluster it lives in.
kubectl apply -f \ https://raw.githubusercontent.com/kwirthmagnify/kwirth/master/deploy/kubernetes/manifests/kwirth-zero.yaml
That one carries FORCE=container, and the line is not optional: the kubelet injects KUBERNETES_SERVICE_HOST into every pod, so taking the permissions away does not stop Kwirth being identified as a Kubernetes workload — and inside a cluster the API is deliberately not optional, because a failure there is an error and not a degradation. Note that container does not mean "no cluster": it means the platform is not one Kwirth recognises. Mount a kubeconfig and the same deployment reads that cluster, which is what the ECS task definition below does.
The Helm chart offers the same three as kwirth.mode: normal, readonly and zero.
Kwirth runs as an ECS task with the same image, on either launch type. There is no ECS-specific build, and nothing to declare for the environment to be detected: the ECS agent injects its own metadata variable in both launch types and Kwirth reads it.
What changes is not the image, it is what the platform stops giving you. Kubernetes hands Kwirth a namespace to keep its state in and an identity; ECS hands neither, so both become configuration.
| Requirement | Notes |
|---|---|
| ECS cluster | Existing. The template does not create one |
| VPC with private subnets | One per AZ you use. The EFS mount targets live here too |
| Application Load Balancer | Existing. The template creates the target group; you attach it to a listener |
| EFS | Created by the template. Without a volume nothing survives a task recycle |
| IAM permissions | For the identity that deploys — see iam-deploy-policy.json |
Attach iam-deploy-policy.json to the user or role you deploy with. The one people forget is iam:PassRole: creating the service means handing ECS the roles the task will assume, and without it the error talks about the service rather than the missing permission.
EFS with its access point, security groups, target group, IAM roles, log group and the generated MASTERKEY secret.
aws cloudformation deploy \ --template-file deploy/ecs/cloudformation.yaml \ --stack-name kwirth \ --capabilities CAPABILITY_IAM \ --parameter-overrides \ VpcId=vpc-xxxx \ SubnetIds=subnet-aaaa,subnet-bbbb \ ClusterName=my-cluster \ LoadBalancerSecurityGroupId=sg-xxxx
The stack outputs TargetGroupArn. Kwirth answers /healthz in every environment, and the target group already checks that path — point it elsewhere and the task is recycled forever without saying why.
aws elbv2 create-rule \ --listener-arn <YOUR_LISTENER_ARN> \ --priority 10 \ --conditions Field=path-pattern,Values='/*' \ --actions Type=forward,TargetGroupArn=<TargetGroupArn>
It is the first diagnostic for a deployment you cannot look inside. It states what Kwirth found and why.
Execution environment: 'ecs' Kubernetes API: no (no usable kubeconfig) Store: encrypted files at '/data/kwirth' (KWIRTH_STORE)
Prefer not to use CloudFormation? Register task-definition-fargate.json directly and create the service by hand — the template is then just the specification of what to create around it.
MASTERKEY derives the encryption key for secrets at rest. Changing it later makes everything already written unreadable — there is no migration. Decide it once, before the first run, and pass it through secrets[], never environment[], which is visible in the console and in describe-task-definition.SQL persistence is optional and separate — some extensions keep their data in PostgreSQL, which on ECS means RDS or Aurora. The connection is lazy, so Kwirth starts fine without it. Details, including why the database user needs CREATEDB, in the deploy/ecs/ folder.
Kwirth on your own machine or a VM, without Kubernetes: persistent, with its secrets encrypted, and optionally with PostgreSQL. One script does everything — it writes the configuration, generates the master key, starts the containers, waits until Kwirth is healthy and tells you where to log in.
| Requirement | Notes |
|---|---|
| Docker | Docker Engine or Docker Desktop, with Compose v2 (docker compose) |
The deploy/compose/ folder | From the repository: the compose files and the two install scripts |
From deploy/compose/. install.sh on Linux, macOS and WSL; install.ps1 on Windows.
./install.sh up # Linux, macOS, WSL .\install.ps1 up # Windows PowerShell Kwirth is up: http://127.0.0.1:3883 First login: admin / password (change it right away)
Run up again with options at any time; they are remembered in .env.
./install.sh up --sql # + PostgreSQL ./install.sh up --kubeconfig ~/.kube/k3d # observe a cluster ./install.sh up --watchtower # update itself when the tag moves ./install.sh up --tag 0.6.57 --port 8080 # pin a version, another port
./install.sh update # pull the new image of the tag and recreate ./install.sh down # stop; the data stays in its volumes ./install.sh destroy # remove everything, data included (asks first)
up writes a MASTERKEY into deploy/compose/.env, and that key is the only way to read Kwirth's encrypted store. Keep a copy of .env — lose it and the data in the volume cannot be read again. It is never overwritten by later runs.127.0.0.1 only: nothing outside the machine reaches Kwirth until you pass --bind 0.0.0.0. "Restart Kwirth" restarts the container with the image it already has — to get a new one, use update or --watchtower. Everything else is in the deploy/compose/ folder.On first boot, Kwirth creates a default admin user with password password. You will be prompted to change the password on first login.
Kwirth can monitor any number of Kubernetes clusters. The cluster where Kwirth runs is auto-connected. To add a remote cluster:
Use the resource selector just below the top bar. You need to specify what is your cluster and your target 'view' (the whole cluster, one or more namespaces, one or more controller, one or more pods or even a set of containers belonging to different pods). Then choose a channel type, for example:
Click the ADD button and you will get a new tab added. On the tab settinigs just select START and the magic begins.
Kwirth Magnify is available as a standalone desktop application in two distributions. Both connect to any Kwirth instance and support local kubeconfig clusters out of the box — no cluster-side Kwirth installation required for basic use.
The original desktop build, based on Electron. Available for Windows (.exe) and Linux (.AppImage).
⬇ Download Electron build from GitHub Releases
A lighter, faster build powered by Tauri. Smaller binary, lower memory footprint. Available for Windows (.msi) and Linux (.AppImage).
⬇ Download Tauri build from GitHub Releases