kube-applier: a Pod that applies your Git repository to the cluster
kube-applier enables automated deployment and declarative configuration for your Kubernetes cluster.
At a glance
- What is it?
- kube-applier is a Go service that runs inside a Kubernetes cluster, watches a Git repository, and issues kubectl apply for the JSON and YAML files it finds, with a full run on an interval and a quick run when a commit lands. It suits a team that wants a simple push model from Git to cluster, and it asks for cluster-wide write permissions and a pinned kubectl.
- Who is it for?
- Adopt kube-applier if you want a small, understandable service that applies files from a Git repository into your cluster and you can accept a pull-apply model with one replica and cluster-wide write permissions. Do not adopt it if you need drift detection, rollout status, or a controller that reconciles continuously, because kube-applier applies on a schedule and on commits rather than watching the cluster.
- Can I use it commercially?
- Yes. Apache-2.0 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 last received commits 163 days ago.
- What is it written in?
- Mainly Go, according to GitHub's language statistics.
Answers come from the project's GitHub data, last synced on October 20, 2026, and from our analysis. They are not legal advice.
Editorial analysis
A controller pod that turns commits into cluster objects
kube-applier is a service that enables continuous deployment of Kubernetes objects by applying declarative configuration files from a Git repository to a Kubernetes cluster. The mechanism is deliberately simple and that simplicity is the design.
The service runs as a Pod inside the cluster it manages. It watches the Git repository, and it ensures that the cluster objects stay up to date with their associated spec files, which are JSON or YAML. The repository is mounted into the pod, so the applier reads the files from disk and applies them with kubectl.
Two run modes make up the whole system. At a specified interval, kube-applier performs a full run, issuing kubectl apply commands for all JSON and YAML files within the repo. When a new commit to the repo occurs, it performs a quick run, issuing apply commands only for the files that changed since the last run.
The README is explicit that quick runs and full runs are handled separately and concurrently. That concurrency is the interesting part of the design. A full run is a periodic reconciliation of everything, and a quick run is an event-driven response to a change. Handling them separately means a burst of commits does not queue behind a full pass, and a full pass does not delay a commit that is waiting to be applied.
The service also serves a status page and provides metrics for monitoring, so it is not a black box that mutates the cluster silently. The Go source is laid out in packages that map onto those concerns: applylist/ for the list of things to apply, git/ for the repository watching, kube/ for the cluster interaction, run/ for the run logic, metrics/ for the Prometheus output, webserver/ and static/ for the status page, and templates/, sysutil/ and vendor/ for the rest.
The project comes from Box, the licence is Apache-2.0, and the description is short: automated deployment and declarative configuration for your Kubernetes cluster.
The environment variables that decide what gets applied
The configuration surface is a set of environment variables, and two of them are mandatory.
REPO_PATH is the absolute path to the directory containing the configuration files to be applied. It must be a Git repository, or a path within one. Every .json and .yaml file within that directory and its subdirectories will be applied, unless it is listed on the blacklist or excluded from the whitelist. LISTEN_PORT is the port for the container, and it should match the port in the container spec.
The rest is optional and worth reading in order of how often you will touch it.
BLACKLIST_PATH points to a file listing files that should not be applied. The path must be absolute, and the README suggests you may want to check the blacklist file into the repo. The file is plaintext with a file path on each line, and each path is relative to REPO_PATH, so with REPO_PATH set to /git/repo, a blacklisted file at /git/repo/apps/app1.json is listed as apps/app1.json. WHITELIST_PATH works the same way but restricts the applier to a subset. An empty or unset whitelist means everything in the repo is eligible, and if a file appears in both lists the file is not applied. Both files support line comments, where a line whose first non-blank character is # is ignored.
DIRECTORY_MODE is a boolean string that makes the applier apply directory paths rather than individual files, with two caveats: it cannot ignore any files at the top level directly under REPO_PATH, and the paths in the blacklist file must themselves be directories for the ignore to work.
The timing knobs are POLL_INTERVAL_SECONDS, the wait between checks for new commits, defaulting to 5 and settable to 0 to disable the wait, and FULL_RUN_INTERVAL_SECONDS, the interval between automatic full runs, defaulting to 300, five minutes, and also settable to 0. Setting the full run to 0 is how you turn off periodic reconciliation and keep only commit-driven applies.
Two smaller ones round it out. SERVER names the Kubernetes API server address, and the README notes that by default discovery of the API server is handled by kube-proxy, with this variable only needed if kube-proxy is not set up, in which case the address is written into a kubeconfig file on the backend. Authentication to the API server is handled by service account tokens. DIFF_URL_FORMAT lets the status page link to the source diff for a specific commit, by giving a URL for a hosted remote repo with %s in place of the commit hash. LOG_LEVEL sets the -v flag on the kubectl commands that are run, which is the first thing to reach for when an apply is not doing what you expect.
Building the image and running it as a Deployment
The setup instructions are from an era of Go development, and they still work if you follow them literally.
$ go get github.com/box/kube-applier
$ cd $GOPATH/src/github.com/box/kube-applier
$ make containerAfter that you need to push the image to a registry in order to reference it in a Kubernetes container spec. The make target builds with a tag defined in the Makefile, and the underlying build sets the target platform explicitly and disables cgo:
container:
docker build -t kube-applier:$(TAG) .The Makefile also has deps, which runs go mod tidy, a build target that cleans, tidies, formats and compiles the binary, a clean target, an fmt target that runs gofmt over the source while skipping the vendor directory, and a test-unit target that runs the tests with the race detector.
On the runtime side, the Dockerfile shows something you should know before you build: the base builder image is golang:1.7, the runtime image is ubuntu with git installed, and the kubectl binary is downloaded from the Kubernetes release bucket and made executable. The exact kubectl it fetches is version 1.9.4, which is the version constraint discussed below.
For running it, the README suggests a Deployment, with example YAML files in the demo/ directory, including a deployment.yaml and a service.yaml. Two warnings come with that suggestion and both matter operationally.
The first is that only one replica is supported at this point, so there may be a gap in application if the node serving the replica goes hard down until it is rescheduled onto another node. The second is marked IMPORTANT: the Pod containing the kube-applier container must be spawned in a namespace that has write permissions on all namespaces in the API Server, with kube-system given as the example.
That second requirement is the real operational cost of this design. The applier needs to be able to write anywhere, because it applies whatever is in the repository, and a repository is easy to fill with files that touch namespaces the pod was not originally scoped to.
The kubectl version rule and the known apply problems
The requirements section is where this project shows its age, and it is also where the sharpest constraint lives.
The listed requirements are Go 1.7 or newer, Docker 17.05 or newer and a Kubernetes cluster. The README says kube-applier generally supports any Kubernetes server release, assuming that you are installing a compatible kubectl client in your Dockerfile. That assumption is the whole of the compatibility story: the tool has no server-side version detection, it just runs whatever kubectl you gave it.
The rule is precise. The kubectl version specified in the Dockerfile must be either the same minor release as the cluster API server, or one release behind the server. A client 1.3 with a server 1.4 is fine, but a client 1.4 with a server 1.3 is not. Since the Dockerfile downloads kubectl 1.9.4, an image built from the repository as it stands is pinned to a Kubernetes 1.9-era cluster, and using it against a modern cluster means rebuilding the image with a different kubectl download URL.
The README then lists known problems with kubectl apply itself that may affect your use of kube-applier. Releases prior to 1.6.0 are subject to many known issues with applying ThirdPartyResource objects, with three upstream issue links given. And 1.5 and 1.6 releases before 1.5.8 and 1.6.3 are not supported due to an issue with namespaces, with the upstream issue and the fix pull request linked.
None of this is kube-applier's own bug, and it is stated clearly rather than hidden. But it does mean the tool inherits every quirk of kubectl apply, including the ones that were never fixed in the client, and that the project itself is a thin wrapper around a command whose behaviour you have to track separately from the wrapper.
The Go module file adds one more data point about where the project stands. The module is github.com/box/kube-applier and it declares go 1.23.0, with direct dependencies on the Prometheus client library, testify and go.uber.org/mock. So the runtime behaviour is anchored to an old kubectl while the build toolchain has been updated to a current Go release, which is the shape of a project that gets dependency bumps but not feature work.
The push model, and the pull model it is not
It is worth being explicit about the model, because it is the single decision that determines whether kube-applier is the right tool for you.
kube-applier pushes. It watches a repository, and on a commit or on a timer it issues kubectl apply for the files. The cluster is not consulted to work out what has drifted, because the applier does not read the state of the cluster and compare it with the desired state. It applies, and kubectl apply itself does a three-way merge using the last applied configuration annotation, which is where the drift handling actually comes from.
The alternative approach, the one this project is not, is pull-based reconciliation by a controller that continuously compares the desired state in Git with the observed state of the cluster and acts on the difference. That model gives you drift detection, a view of what is pending, and per-object sync status as a first class concept, and it is the model that most of the current GitOps tooling is built around.
The push model has its own virtues. There is no controller to operate, no state to store, and the behaviour of the system is easy to reason about from the repository. A commit leads to an apply, and a timer leads to an apply. For a team that wants a Git to cluster pipeline with a status page and metrics and nothing else running, that is a reasonable trade.
The README does not include a comparison with other tools, and this article does not assert facts about projects it has not read. What can be said from the documentation in front of us is what kube-applier does and does not do: it applies files, it serves a status page, it exports metrics, it does not describe itself as a continuous reconciler, and it explicitly runs a periodic full run precisely because it is not watching the cluster.
The status page and the DIFF_URL_FORMAT option are the two features that make the push model more pleasant, since they let you see what was applied and jump to the diff that caused it.
Where kube-applier is the wrong tool
The first case is drift. If somebody changes a Deployment by hand, or a controller mutates a resource, kube-applier will not notice and will not correct it, because correction only happens when it applies the file again, and the apply is driven by commits and by the timer. The five-minute default full run does eventually put the file back, but the system is not tracking cluster state and it does not report a diff between what is running and what should be.
The second is availability. Only one replica is supported, and the README warns that there may be a gap in application if the node serving the replica goes hard down until it is rescheduled. For a cluster where the applier is responsible for keeping critical workloads present, that gap is a real availability property of the design, not an edge case.
The third is the permission model. The pod needs write permissions on all namespaces in the API server. That is a wide grant for a component whose job is to apply a directory of files, and it is the kind of requirement that a security review will question. The README's own advice about checking the blacklist into the repository is an acknowledgement that the repository contents determine how far that permission is used.
The fourth is anything needing multi-cluster or multi-environment promotion. The configuration is one repository path, one blacklist, one whitelist and one target cluster, and the README describes no mechanism for promoting the same files through a staging and then a production environment, which is the workflow most teams actually want from a Git to cluster pipeline.
The fifth is the age of the pieces. The base builder image is golang:1.7, the kubectl in the Dockerfile is 1.9.4, and the compatibility notes are about Kubernetes 1.5 and 1.6. The Go module has been brought up to date, but the runtime assumptions have not. Adopting it means accepting that you are assembling the modern parts yourself, and that the compatibility guidance in the README is historical.
The last point is the release cadence. The tagged versions are v0.2.3 in September 2024, v0.2.4 in December 2024 and v0.2.5 in September 2025, and the last push to the repository was on 2026-05-13. The project is not archived, and the version number in the Makefile is still v0.2.0, which tells you the tag in the image name is not kept in step with the released versions.
Editorial conclusion
Adopt kube-applier if you want a small, understandable service that applies files from a Git repository into your cluster and you can accept a pull-apply model with one replica and cluster-wide write permissions. Do not adopt it if you need drift detection, rollout status, or a controller that reconciles continuously, because kube-applier applies on a schedule and on commits rather than watching the cluster. Verify first that the kubectl you bake into the image matches your API server minor version, that the blacklist and whitelist files cover the paths you expect, and that your namespace grants the write access the pod needs, since the licence is Apache-2.0, the newest release is v0.2.5 from 2025-09-08, and the last push was on 2026-05-13.
Frequently asked questions
What does kube-applier do in a Kubernetes cluster?
It runs as a Pod, watches a mounted Git repository, and issues kubectl apply for the JSON and YAML files it finds. It performs a full run at a configured interval for all files in the repo, and a quick run when a new commit lands for the files that changed, and the two are handled separately and concurrently.
Which environment variables are required to run kube-applier?
REPO_PATH, the absolute path to the directory of configuration files to apply, and LISTEN_PORT, the port for the container, are required. Optional variables include DIRECTORY_MODE, SERVER, BLACKLIST_PATH, WHITELIST_PATH, POLL_INTERVAL_SECONDS, FULL_RUN_INTERVAL_SECONDS, DIFF_URL_FORMAT and LOG_LEVEL.
How do I build the kube-applier container image?
The README gives go get github.com/box/kube-applier, cd $GOPATH/src/github.com/box/kube-applier and make container, after which you push the image to a registry so it can be referenced in a container spec. The image is built with a Go builder stage and an Ubuntu runtime stage that downloads kubectl.
What kubectl version does kube-applier need?
The kubectl specified in the Dockerfile must be the same minor release as the cluster API server or one release behind it, so a client 1.3 with a server 1.4 is fine but a client 1.4 with a server 1.3 is not. The Dockerfile as shipped downloads kubectl 1.9.4.
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/box-kube-applier)Was this useful?