GitOps in 10 Minutes: Infrastructure as a Git Repo
GitOps means your infrastructure is defined in Git and automatically deployed from it. This guide explains what GitOps is, why it matters for solo devs and small teams, and how to start β from versioning config files to full ArgoCD automation.
You know how to git push your code. But what about your infrastructure?
Your Nginx config, your firewall rules, your database credentials, your Kubernetes manifests β where do they live? If the answer involves SSH, a shared Wiki page, or "ask Jean-Michel, he set it up" β you have a problem.
GitOps means treating infrastructure the same way you treat code: versioned, reviewed, auditable, and automatically deployed from a Git repo. No more SSH. No more "works on my machine." No more mystery configs.
GitOps is a core principle of open-source API management β and one of the reasons STOA was designed GitOps-first from day one.
The Problem: Configuration Driftβ
Here's a scenario every developer has lived:
- You deploy your app to production. It works.
- Three months later, someone SSHs into the server to "fix a thing."
- Another person tweaks an Nginx config directly.
- A third changes an environment variable through the cloud console.
- Six months later, nobody knows what the production config actually is.
This is configuration drift β the gap between what you think is deployed and what actually runs. It's the silent killer of reliability.
What you think is deployed: What's actually running:
βββββββββββββββββββββββ βββββββββββββββββββββββ
β nginx.conf (v3) β β nginx.conf (v3.1?) β β manual SSH edit
β API_KEY=abc123 β β API_KEY=xyz789 β β cloud console change
β replicas: 2 β β replicas: 3 β β kubectl scale
β TLS: Let's Encrypt β β TLS: expired! β β cert not renewed
βββββββββββββββββββββββ βββββββββββββββββββββββ
Your git repo The actual server
What GitOps Actually Isβ
GitOps is a simple idea: Git is the single source of truth for your infrastructure.
Developer β git push β Git Repo β (auto-sync) β Infrastructure
β β
"What should "What actually
be running" is running"
β
Constantly reconciled
Three core principles:
- Declarative β You describe the desired state ("I want 2 replicas, TLS enabled, rate limit 100/min"), not the steps to get there.
- Versioned β Every change goes through Git: commit, review, merge. Full audit trail.
- Automated β A tool (ArgoCD, Flux, etc.) continuously compares Git with reality and fixes any drift.
The Old Way vs. GitOpsβ
| The Old Way | GitOps | |
|---|---|---|
| Deploy | SSH + manual commands | git push β auto-deploy |
| Rollback | "Does anyone remember what we changed?" | git revert β auto-rollback |
| Audit | Check server logs (if they exist) | git log β who, when, what, why |
| Reproduce | Impossible β config lives on the server | Clone the repo, apply β identical environment |
| Review | "Hey, I'm changing the firewall rules" (Slack message) | Pull request with diff, review, approve |
| Disaster recovery | Rebuild from memory + documentation (if current) | git clone + apply β back in minutes |
A Concrete Exampleβ
Let's say you have a simple API deployed on Kubernetes. Here's what a GitOps repo looks like:
infra/
βββ base/
β βββ deployment.yaml # Your API: image, replicas, health checks
β βββ service.yaml # How traffic reaches your API
β βββ ingress.yaml # Domain name + TLS
β βββ configmap.yaml # Non-secret configuration
βββ overlays/
β βββ staging/
β β βββ kustomization.yaml # staging overrides (1 replica, debug logging)
β βββ production/
β βββ kustomization.yaml # production overrides (3 replicas, minimal logging)
βββ secrets/
βββ sealed-secret.yaml # Encrypted secrets (safe to commit)
Deploy a changeβ
Want to scale production to 5 replicas? No SSH. No kubectl. Just a pull request:
# overlays/production/kustomization.yaml
# Change replicas: 3 β replicas: 5
patches:
- target:
kind: Deployment
name: my-api
patch: |
- op: replace
path: /spec/replicas
value: 5
git add overlays/production/kustomization.yaml
git commit -m "scale(prod): increase API replicas to 5 for launch traffic"
git push origin main
ArgoCD detects the change, applies it to the cluster. Done. Full audit trail in git.
Rollback a bad deployβ
Something broke? No panic:
git revert HEAD
git push origin main
# ArgoCD automatically rolls back to previous state
Compare this to the old way: "Quick, SSH into prod and change the thing back. What was the old value? Let me check Slack..."
Why Freelancers and Small Teams Need GitOpsβ
You might think GitOps is only for big companies with dedicated DevOps teams. Wrong. It's actually more valuable for small teams and solo developers because:
1. You Can't Rely on Memoryβ
When you're juggling 3-5 client projects, you won't remember what you configured 6 months ago. Git remembers.
2. Client Handoffs Become Trivialβ
"Here's the repo. Everything that runs in production is in this folder. git log shows every change." No knowledge transfer meetings. No runbooks that are already outdated.
3. Disaster Recovery Is Freeβ
Server dies? Hard drive corrupted? Cloud provider outage? With GitOps: clone the repo, point to a new cluster, apply. Everything's back in minutes.
4. You Can Prove What You Didβ
Client asks "when did you change the SSL config?" You don't guess β you show them the commit:
commit 8a3f2c1 (2026-01-15)
Author: You <you@example.com>
Date: Wed Jan 15 14:30:00 2026
fix(tls): renew SSL cert and switch to Let's Encrypt auto-renewal
- Old: manual cert from GoDaddy, expired Dec 30
- New: Let's Encrypt with auto-renewal via cert-manager
- Tested in staging first (commit 7b2e1d0)
Getting Started: No Kubernetes Requiredβ
You don't need Kubernetes to use GitOps. You can start with any infrastructure:
Level 1: Version Your Config Filesβ
Put your Nginx configs, Docker Compose files, and environment variable templates (not values!) in Git:
mkdir infra && cd infra
git init
# Add your configs
cp /etc/nginx/nginx.conf ./nginx/
cp ~/docker-compose.yml ./
cp .env.example ./ # Template only β never the actual .env!
git add . && git commit -m "chore: initial infrastructure config"
From now on, every config change goes through Git first: edit, commit, then apply.
Level 2: Automate the Applyβ
Use a simple CI/CD pipeline to apply changes when you push:
# .github/workflows/deploy.yml
name: Deploy
on:
push:
branches: [main]
paths: ['infra/**']
jobs:
deploy:
runs-on: ubuntu-latest
steps:
- uses: actions/checkout@v4
- name: Copy configs to server
run: |
scp -r infra/nginx/ server:/etc/nginx/
ssh server "nginx -t && systemctl reload nginx"
Not fancy. But now you have versioned configs + automated deployment + audit trail. That's GitOps.
Level 3: Full GitOps with ArgoCDβ
When you're ready for Kubernetes (or already there):
# Install ArgoCD (one-time)
kubectl create namespace argocd
kubectl apply -n argocd -f https://raw.githubusercontent.com/argoproj/argo-cd/stable/manifests/install.yaml
# Point ArgoCD at your Git repo
argocd app create my-api \
--repo https://github.com/you/infra.git \
--path overlays/production \
--dest-server https://kubernetes.default.svc \
--dest-namespace default \
--sync-policy automated
Now ArgoCD watches your repo and automatically applies any change you push. Push a commit β cluster updates. Revert a commit β cluster rolls back.
How STOA Embraces GitOpsβ
STOA Platform was designed GitOps-first from day one (see ADR-007):
- Every config is declarative β API contracts, policies, routing rules are YAML/JSON in Git
- ArgoCD-native β STOA ships with ArgoCD manifests and Helm charts, auto-sync enabled
- No manual kubectl β Changes flow from
git pushthrough CI to the cluster automatically - Drift detection β If someone manually changes something on the cluster, ArgoCD detects it and reverts to the Git state
- Sealed secrets β Credentials are encrypted in Git using sealed-secrets, decrypted only inside the cluster
The result: your entire API gateway configuration β routes, policies, TLS certs, rate limits, access control β lives in Git. Auditable. Reviewable. Reproducible.
Even the free tier works this way. No "GitOps is a premium feature" gatekeeping.
The Mindset Shiftβ
GitOps isn't really about tools. It's about a mindset:
If it's not in Git, it doesn't exist.
- Server config modified via SSH? It will be overwritten by the next sync.
- Environment variable changed in the console? It will drift back to Git state.
- Database migration run manually? It should have been a versioned script.
This feels restrictive at first. Then it becomes liberating. Because when everything is in Git:
- You never lose configuration
- You always know what's deployed
- You can reproduce any environment
- You can prove every change
Stop SSHing into servers. Start git push-ing your infrastructure.
FAQβ
Do I need Kubernetes for GitOps?β
No. GitOps is a pattern, not a Kubernetes feature. You can version Nginx configs, Docker Compose files, or even shell scripts in Git and auto-apply them with CI/CD. Kubernetes + ArgoCD is the most popular GitOps stack, but Level 1 and Level 2 in this guide work without Kubernetes.
What's the difference between GitOps and Infrastructure as Code (IaC)?β
IaC (Terraform, Pulumi) describes infrastructure declaratively. GitOps adds the reconciliation loop: a tool continuously ensures the live state matches the Git state. IaC is "define and apply." GitOps is "define, apply, and keep in sync forever."
How does STOA use GitOps?β
STOA stores API contracts, routing policies, and access rules as declarative YAML. ArgoCD watches the Git repo and applies changes automatically β see ADR-007 for the full architecture. Even secret management follows GitOps patterns via sealed-secrets.
Is GitOps secure? What about secrets in Git?β
Never store plaintext secrets in Git. Use encrypted secrets (sealed-secrets, SOPS) or external secret managers (Vault, Infisical). The encryption key lives outside Git; the encrypted blob is safe to commit. See our API security checklist for more.
Related: Open Source API Gateway Guide | API Security Checklist | Quick Start
Want to manage your APIs with GitOps? STOA Quick Start gets you running in 5 minutes. Join the community on Discord.
