8 open-source tools you can combine so that git push deploys your entire stack.
You’ve probably heard the buzzwords: GitOps, NoOps, immutable infrastructure.
Today I’d like to walk you—step by step—through why these concepts exist
and how a small constellation of tools (Git, NixOS,
Docker,
Terraform,
Kubernetes,
ArgoCD, DSPy, and
OPA) fit together to create a platform that deploys itself every time you
hit merge.
In the old world, a server was a pet: lovingly hand-fed config files, patched on Sundays, and inevitably different from every other server. The result?
Instead of pets, we want cattle - identical, replaceable, and defined in
text files that live in Git.
If Git is the single source of truth, the rest of the stack becomes a
conveyor belt that turns that truth into running software.
| Tool | One-Sentence Job | Why It Matters |
|---|---|---|
| Git | The single source-of-truth for every line of code and config. | Immutable history + pull-requests = collaboration without chaos. |
| NixOS | An entire Linux distro expressed in one declarative file. |
Reinstalls laptop or 1 000-server fleet with
nixos-rebuild.
|
| Terraform | Describe cloud resources (VPCs, disks, IAM) in HCL. | Re-creates an entire region from scratch in 15 min after a coffee spill. |
| Docker | Bundle the app and its libraries into an immutable image. | Same artifact runs on your Mac, in CI, and in prod. |
| Argo CD | A robot that watches Git and makes Kubernetes match it. |
Manual kubectl apply is now a pull-request review.
|
| Kubernetes | The planet-scale scheduler that keeps those containers healthy. | Auto-heals, scales, and rolls out with zero downtime. |
| DSPy | Prompt-engineering as typed, testable code. | Turns LLM prompts into reproducible pipelines. |
| OPA / Kyverno | Policy-as-code gatekeepers for every API call. |
Blocks :latest images or unencrypted buckets before
they deploy.
|
💡 Press Ctrl + + / -, or pinch-zoom on
mobile to enlarge the diagram. Right Click to Open Image in New Tab.
Declarative GitOps workflow
Let’s add a new feature: “Show real-time in-game leaderboards”.
nix develop gives the exact
same tools as prod.
# Reproducible Stack in 5 Steps
| Step | Tech | One-liner Purpose |
|------|-------------|------------------------------------------|
| 1 | NixOS | Immutable host OS |
| 2 | Terraform | Provision K8s cluster |
| 3 | Docker | Local dev parity |
| 4 | Argo CD | GitOps continuous delivery |
| 5 | OPA Gatekeeper | Policy guardrails |
## Quickstart
1. `nix develop` – drops you into a shell with Terraform, kubectl, Argo CD CLI.
2. `terraform init && terraform apply` – spins up managed K8s.
3. `kubectl apply -f argocd-app.yaml` – bootstraps Argo CD.
4. `kubectl apply -f constraint-template.yaml` – sample “no latest tag” policy.
{
description = "Reproducible Dev Shell";
inputs.nixpkgs.url = "github:NixOS/nixpkgs/nixos-unstable";
inputs.flake-utils.url = "github:numtide/flake-utils";
outputs = { self, nixpkgs, flake-utils }:
flake-utils.lib.eachDefaultSystem (system:
let pkgs = nixpkgs.legacyPackages.${system};
in {
devShells.default = pkgs.mkShell {
packages = with pkgs; [
terraform
kubectl
argocd
docker
];
};
});
}
provider "kubernetes" {
config_path = "~/.kube/config"
}
resource "kubernetes_namespace" "example" {
metadata {
name = "example-namespace"
}
}
version: '3.8'
services:
web:
image: nginx:latest
ports:
- "80:80"
volumes:
- ./html:/usr/share/nginx/html
depends_on:
- redis
redis:
image: redis:latest
ports:
- "6379:6379"
volumes:
- redis_data:/data
volumes:
redis_data:
apiVersion: argoproj.io/v1alpha1
kind: Application
metadata:
name: example-app
namespace: argocd
spec:
destination:
namespace: default
server: https://kubernetes.default.svc
source:
repoURL: https://github.com/example/repo.git
path: manifests
project: default
syncPolicy:
automated: {}
apiVersion: v2
name: nginx-chart
description: A Helm chart for Kubernetes
version: 0.1.0
appVersion: "1.20"
apiVersion: templates.gatekeeper.sh/v1beta1
kind: ConstraintTemplate
metadata:
name: k8sallowedrepos
spec:
crd:
spec:
names:
kind: K8sAllowedRepos
targets:
- target: admission.k8s.gatekeeper.sh
rego: |
package k8sallowedrepos
violation[{"msg": msg}] {
input.review.object.spec.containers[_].image != "allowed/repo"
msg := "Image repository is not allowed"
}
Declarative, Git-driven stacks aren’t tools; they’re a culture.
When everything is code, knowledge lives in the repo, not in someone’s
head.
That means faster onboarding, fearless refactors, and - best of all -
Friday deploys that don’t ruin weekends.
Welcome to the Declared World: where the robots do the toil, and we get back to building great games.