People who work with code are used to a simple idea: the Git repository holds the official version, every change goes through review and the history tells who changed what. GitOps extends the same idea to infrastructure and releases: what runs in production must always match what is written in a repository.
The principles
GitOps rests on four principles, often stated like this:
- Declarative: the desired state of the system is described in files, not in sequences of commands.
- Versioned and immutable: those files live in Git, with the full history of every change.
- Applied automatically: an agent reads the repository and brings the system to the described state.
- Continuously reconciled: the agent constantly checks that the real system does not drift from the declared one and, if it does, corrects or reports it.
The practical consequence is that no changes are made directly on systems. To release a new version you change a file in the repository, open a review request and, once it is approved and merged, the agent applies the change.
Push and pull
Traditional pipelines follow a push model: once the tests finish, the pipeline connects to the cluster or server and applies the changes. To do so it must hold production access credentials.
GitOps usually uses a pull model: an agent running inside the cluster watches the repository and pulls in the changes. The difference has important consequences.
| Aspect | Push model | Pull model |
|---|---|---|
| Who applies changes | The CI pipeline | An agent in the cluster |
| Production credentials | In the pipeline | Only in the cluster |
| Detection of manual changes | None | Continuous |
| Network access required | From CI to the cluster | From the cluster to Git |
With the pull model the cluster doesn't need to accept connections from outside to receive releases, and the CI service holds no production keys. If the pipeline is compromised, the attacker does not directly gain access to the cluster.
How the work is organized
A common structure involves two kinds of repository.
- The application repository contains the code. Its pipeline runs the tests, builds the container image and publishes it with a unique tag.
- The configuration repository contains the manifests describing what must run in each environment: which image, how many replicas, which parameters.
At the end of the build, the application pipeline automatically opens a change to the configuration repository, updating the image tag for the staging environment. The production release is another change to the same repository, approved by whoever is responsible for it.
Keeping the two repositories separate prevents every code change from triggering unwanted releases and allows different permissions for those who develop and those who approve production releases.
The tools
The most widespread GitOps tools are designed for Kubernetes:
- Argo CD offers a graphical interface showing the state of each application, the differences between repository and cluster and the history of synchronizations;
- Flux is more minimal, configured entirely through files and integrated with Kubernetes package management tools.
Both read manifests written directly or generated with tools such as Helm and Kustomize. The principle can also be applied outside Kubernetes, for example with infrastructure as code applied automatically when a change is merged, but that is where it has found its most mature form.
The secrets problem
If everything must live in Git, where do passwords go? Not in plain text, obviously. There are two main solutions:
- encrypted secrets in the repository, with tools such as Sealed Secrets or SOPS: the file is encrypted and only the cluster holds the key to decrypt it;
- references to an external secret manager: the repository contains only the secret's name, and a component in the cluster fetches the value from the dedicated service.
The second solution is usually preferable for the most sensitive secrets, because rotation and revocation happen in a single place.
Rollback and auditing
One of the most concrete benefits of GitOps is rollback: going back to the previous version means reverting a commit. Git history also becomes a log of interventions: who released what, when and with whose approval. In environments with audit or certification requirements, this log comes without additional tools.
When it pays off
GitOps is at its best with many services, several environments and several people releasing. For a single server with one application, a reconciliation agent is often unnecessary complexity: a pipeline that applies changes after the tests delivers most of the benefits. In my work I propose it when releases are frequent and you need to know with certainty, at any moment, what is running in production.
In short
- GitOps makes a Git repository the single source of truth for what runs in each environment.
- Changes go only through reviewed commits; an agent applies them and corrects drift.
- The pull model keeps production credentials inside the cluster and out of the pipeline.
- Argo CD and Flux are the most widespread tools; secrets should be encrypted or read from a secret manager.
- Rollback becomes a simple return to an earlier commit, but for small projects the approach can be overkill.