tsuru/tsuru: a self-hosted PaaS that runs on Kubernetes and talks to your CLI
Open source and extensible Platform as a Service (PaaS).
At a glance
- What is it?
- tsuru is a Go-based Platform as a Service that schedules application deployments onto a Kubernetes cluster through a pool model. Here is how its local development flow works, what the documentation covers, and where it stops being the right tool.
- Who is it for?
- Adopt tsuru/tsuru if you already run Kubernetes and want a self-hosted deployment layer where developers interact with a tsuru CLI rather than raw manifests, and you accept MongoDB plus a registry as part of the stack. Do not adopt it if you have no cluster to point it at.
- Can I use it commercially?
- Yes. BSD-3-Clause is a permissive licence: you can use, modify and sell software built on it, as long as you keep its copyright and licence notices.
- Is it still maintained?
- Yes. The repository received new commits within the last day.
- What is it written in?
- Mainly Go, according to GitHub's language statistics.
Answers come from the project's GitHub data, last synced on September 29, 2026, and from our analysis. They are not legal advice.
Editorial analysis
The problem tsuru/tsuru solves, and who it is written for
tsuru/tsuru is an open source Platform as a Service. The README frames the audience directly: "With tsuru, you don't need to think about servers at all." That sentence describes the product boundary. The application developer writes code in one of the supported languages and pushes it; the platform handles the servers underneath. The README lists Python, Nodejs, GO, Ruby, PHP, Perl, Lua and Java as popular platforms, each of which lives in the separate tsuru/platforms repository rather than in this one.
The second audience is the operator. This repository is the API server, not the client. The Go module is github.com/tsuru/tsuru, the main binary is built from ./cmd/tsurud, and the Dockerfile exposes port 8080 with ENTRYPOINT ["/usr/local/bin/tsurud"] and CMD ["api"]. Day-to-day work happens through the tsuru command-line tool, which is distributed from the separate tsuru-client repository. If you are looking for a tool a single developer installs on a laptop to deploy a side project, this is a different shape of software: it wants a cluster, a database and an image registry before it does anything useful.
Where it fits is the middle ground between raw Kubernetes manifests and a fully managed platform. The README's supported install guides are Minikube and GKE, so the intended deployment target is a Kubernetes cluster you control.
How tsuru/tsuru schedules apps: pools, clusters and the provision layer
The mechanism is visible in the repository layout. There is a provision/ directory, a pool concept in the CLI, and a cluster concept in the API. The README's local walkthrough makes the relationship concrete: you create a team, create a pool, then label a Kubernetes node so that the pool has somewhere to land.
The flow is: an application is assigned to a pool, the pool is backed by a cluster, and the provisioner translates the app into workloads on that cluster. The README shows the node label as tsuru.io/pool=my-pool, which is how a Kubernetes node is attached to a tsuru pool. Without that label, the pool exists but has no capacity, and a deploy has nowhere to go.
State lives outside the API process. The docker-compose.yml in the repository runs mongo with image mongo:6 on port 27017, a registry with image registry:2 on port 5000, a deploy-agent on port 8000 pointing at buildkit over tcp://buildkit:8001, and buildkit itself with privileged: true. The tsuru-api service is behind a compose profile named tsurud-api, so it does not start with the default set. That separation is deliberate: the dependencies can run without the API, and the API can be built separately from the Dockerfile.
The build path is not a plain docker build of application code. The deploy-agent talks to BuildKit, and the Dockerfile for the API itself runs make tsurud in a golang:1.26.6-alpine3.23 builder stage. The Go module declares go 1.26.6, so the toolchain version is pinned in two places and they should be kept aligned.
Installing the tsuru client and running a first local deploy
There are two installs to keep straight. The API server is this repository; the CLI is a separate download. The README points at https://github.com/tsuru/tsuru-client/releases/ and gives an example for release 1.1.1 on OS X:
curl -sSL https://github.com/tsuru/tsuru-client/releases/download/1.1.1/tsuru-1.1.1-darwin_amd64.tar.gz | tar xzThat unpacks a tsuru binary into the current directory. The README does not say where to put it on your PATH.
For the API itself, the README's local development section lists the prerequisites: docker or podman, minikube, go, and yq. It also states you need the Tsuru Client already installed. The first command prepares configuration files and dependencies:
make local.setupThe README notes you do not need to run this again unless you want to reset the environment. Then start the API and its dependencies:
make local.runWith the API up, point the CLI at the local target. The README compares targets to kubectl config contexts:
tsuru target-set local-dev
tsuru login [email protected] # password: admin@123
tsuru cluster listIf the setup worked, the README says you should see your local Minikube cluster listed as the default provisioner. To deploy something you need a team, a pool, and a labelled node:
tsuru team create my-team
tsuru pool add my-pool
kubectl label nodes minikube tsuru.io/pool=my-poolWhen you are finished, make local.stop stops the dependencies and make local.cleanup removes all associated resources. The README warns that cleanup is for when you no longer need the API and its dependencies on the machine.
Where tsuru/tsuru gets in your way
The dependency weight is the first real constraint. A working tsuru installation needs MongoDB, an image registry, BuildKit, the deploy-agent, and a Kubernetes cluster. The docker-compose.yml runs buildkit with privileged: true, which is not a container you can drop into every shared or locked-down environment. If your platform team cannot grant a privileged container, the local stack as documented will not come up.
The second constraint is that the README's local path is a development path, not a production one. The API service in docker-compose.yml sits behind the tsurud-api profile and is built from the repository rather than pulled as a pinned image tag. The README's install guides for Minikube and GKE are the production-shaped paths, and they are hosted on the documentation site rather than reproduced in the README. Anyone evaluating this repository alone will find the API configuration surface (etc/tsuru.conf, mounted read-only at /etc/tsuru/tsuru.conf) largely undocumented here.
The third is that the platform list is not in this repository. The README links out to tsuru/platforms for each language, so the quality of a Python or Ruby deploy depends on a repository you have not looked at yet. If your stack is not on that list, tsuru is the wrong tool until someone writes the platform.
Finally, the integration test path has a sharp edge that the README states outright: the kubectl config file "must not be" $HOME/.kube/config and must point only at the Minikube cluster. That is a guard against tests touching a real cluster, and it means you cannot run the integration suite against whatever kubeconfig happens to be active.
tsuru/tsuru compared with running plain Kubernetes
The honest alternative is Kubernetes itself, with kubectl and a set of manifests or a Helm chart. The difference in approach is the abstraction boundary. With plain Kubernetes, the unit you hand a developer is a Deployment, Service and Ingress, and the developer is expected to understand pods, images and resource requests. With tsuru, the unit is an application attached to a pool, and the developer uses tsuru app list, tsuru team create and tsuru pool add instead of kubectl apply.
That trade cuts both ways. tsuru gives you an opinionated deploy path and a CLI that hides the cluster, which shortens the distance between writing code and having it running. It also inserts a layer you must operate: MongoDB for state, a registry for images, BuildKit for builds, and the API in front of all of it. Plain Kubernetes has no such layer, but then every team owns its own manifests, and nothing enforces a shared deploy convention.
A second alternative is a managed platform that runs on someone else's infrastructure. tsuru's install guides are Minikube and GKE, so it is designed to run on a cluster you own or rent, and the operational responsibility stays with you either way. The choice is less about features than about whether you want a deployment convention imposed centrally.
Maintenance, releases and what the BSD-3-Clause licence means for you
The repository is not archived, and the last push was on 2026-09-17, five days before this writing. Recent releases are v1.32.0 on 2026-09-03, 1.31.2 on 2026-09-03, and 1.31.1 on 2026-08-20. That is a steady release cadence over the last month, and the repository shows the machinery to match: a Makefile with test, lint, race and yamlfmt targets, a .golangci.yml, a staticcheck.conf, and a GitHub Actions CI badge in the README.
Upgrade cost is concentrated in two places. The Go toolchain is pinned at go 1.26.6 in go.mod, and the Dockerfile repeats golang_version=1.26.6 alongside alpine_version=3.23. Those two must move together when you rebuild. The dependency list in go.mod is long and includes Kubernetes-adjacent libraries such as github.com/kedacore/keda/v2 v2.20.0 and github.com/containerd/containerd/v2 v2.3.3, so a Go minor-version bump is a real rebuild, not a formality.
On licensing: the repository is BSD-3-Clause, and the Makefile header states the same ("Use of this source code is governed by a BSD-style license that can be found in the LICENSE file"). BSD-3-Clause is a permissive licence, but the deploy-agent and BuildKit images referenced in docker-compose.yml are separate artifacts with their own terms, and the language platforms live in another repository. Check those separately before you ship. This is a description of what the files say, not legal advice.
Editorial conclusion
Adopt tsuru/tsuru if you already run Kubernetes and want a self-hosted deployment layer where developers interact with a tsuru CLI rather than raw manifests, and you accept MongoDB plus a registry as part of the stack. Do not adopt it if you have no cluster to point it at. Verify first that the tsuru-client release for your platform exists, that your Kubernetes nodes can be labelled with tsuru.io/pool, and that the etc/tsuru.conf and docker-compose.yml service set matches what your environment can run.
Frequently asked questions
How do I install tsuru?
The client is a separate download from the tsuru-client releases page; the README shows a curl command that unpacks a tsuru binary for a given release and platform. The API server itself is this repository, and the README's local development section starts with make local.setup followed by make local.run.
What is tsuru?
tsuru is an extensible, open source Platform as a Service written in Go. The README describes it as making application deployments faster and easier, with developers writing apps in the language of their choice, backing them with add-on resources, and managing them through the tsuru command-line tool.
What does the tsuru CLI target-set command do?
The README says targets work similarly to Kubernetes kubectl config contexts, letting you switch between environments. In the local walkthrough, tsuru target-set local-dev points the CLI at the local Tsuru API instance rather than a remote server.
Which databases and services does tsuru need to run?
The repository's docker-compose.yml defines mongo on mongo:6, a registry on registry:2, a deploy-agent on port 8000 pointed at buildkit, and buildkit itself, with the tsuru-api service behind a profile named tsurud-api. MongoDB holds state and the registry holds images.
How do I stop or reset a local tsuru environment?
The README gives make local.stop to stop the dependencies and free system resources, and make local.cleanup to remove all associated resources when you no longer need the API and its dependencies locally.
Official sources
Add this badge to your README
If you maintain this project, the badge below links readers to this analysis and shows its maintenance status from the daily GitHub snapshot. Paste the markdown into your README; add ?metric=license or ?metric=stars to the image URL for a different field.
[](https://hysenlabs.com/projects/tsuru-tsuru)