---
title: BACK lab
tagline: An internal developer platform you can run on a laptop and change.
status: wip
highlight: 1
tags: [kubernetes, argo-cd, crossplane, kyverno]
links:
repo: https://github.com/hvpaiva/back
github: hvpaiva/back
---
## The problem
Platform engineering is easy to read about and hard to practice. Changing
a platform means having one, and wiring Backstage, Argo CD, Crossplane and
Kyverno together until they agree with each other is the part nobody hands
you.
## Constraints
One laptop. One kind node. No cloud account, so an emulator stands in for
AWS. GitHub is the only outside service, because Argo CD has to read what
to deploy from somewhere real. And the lab has to say where it is lying: a
laboratory that hides its own stage set teaches the wrong thing.
## What I built
A cluster that comes up with `just up`, and two identities to see it
through: `dev`, a developer in `team-a`, and `platform-admin`.
From the developer's side there is one service, `hello`, whose repository
holds its code and a short declaration of what it needs from the platform:
name, team, port, size, whether it is public, and a bucket. A push to
`staging` builds an image and deploys it. A pull request from `staging` to
`main` promotes that same image to production once the platform's rules
have checked it. The developer never writes a Kubernetes manifest, never
writes a Dockerfile, and never creates the bucket.
From the platform's side, Argo CD installs and upgrades everything from
Git, itself included. One chart turns what a service declares into
Deployments, Services and routes, with the platform's defaults for probes,
resources and security context. Crossplane serves the platform's own APIs,
so a request for a bucket, a queue, a table or a cache becomes that thing
in the lab's cloud account.
Changing the platform has its own loop, which is the point of the lab.
`just render <api>` prints what a request would create, in a second and
without a cluster, checked against the schemas. `just diff <app>` shows
what applying a folder would change. `just local` hands one Argo CD
Application to your working copy, and `just gitops` hands it back.
The file I care most about is `docs/decisions.md`, which names every place
the lab trades realism for running on one machine and says what a company
would do instead. One node hides high availability, and hides that Argo CD
should deploy from outside the cluster it manages. One emulator with one
dummy key stands where a company would give each stage its own account,
with credentials the teams never see. Traefik replaced ingress-nginx
because ingress-nginx reached end of life in March 2026; the AWS emulator
changed for the same reason, and its replacement is pinned by digest
because it has a single maintainer and was created the day after its
predecessor's sunset. `setup.sh` offers to add you to the `docker` group
and tells you, before you answer, that membership there is equivalent to
root on the machine.
Backstage is the B and is not in yet. Kyverno is installed with no policy
of its own.
git clone github.com/hvpaiva/back