Minimal full-stack authentication demo running in a k3d-managed K3s cluster:
browser -> k3d nginx serverlb -> Traefik Ingress -> frontend/backend -> MongoDB
The generated k3d nginx load balancer maps http://localhost:8080 to port 80 on the single K3s server. Traefik and Kubernetes Services route and balance application traffic across two frontend and two backend replicas.
- Docker
- k3d
- kubectl
- Node.js 24 and pnpm for local development
cp .env.example .env
# Change every secret value in .env.
./scripts/up.sh
./scripts/smoke.shDelete the environment with ./scripts/down.sh. The MongoDB volume belongs to the disposable k3d cluster and is removed with it.
The scripts generate and use .kube/k3d-k3s-test.yaml explicitly. They do not read or modify the host K3s kubeconfig at /etc/rancher/k3s/k3s.yaml.
Open MongoDB:
kubectl --kubeconfig .kube/k3d-k3s-test.yaml exec -it -n k3s-auth mongodb-0 -- sh -lc \
'mongosh --username "$MONGO_INITDB_ROOT_USERNAME" --password "$MONGO_INITDB_ROOT_PASSWORD" --authenticationDatabase admin k3s_auth'Make User Admin
db.users.updateOne(
{ username: "test" },
{ $set: { role: "admin", updatedAt: new Date() } },
);Hello Worldis public.Hello Userrequires a signed-in user.Hello Adminsrequires theadminrole./dashboardgives admins a live architecture view with pod CPU and memory usage, configured requests and limits, recent request flows, and pod deletion controls.- Sign-up creates normal users. The configured bootstrap account is created or promoted to admin whenever a backend pod starts.
- Access JWTs live for 15 minutes and remain in browser memory. Rotating refresh tokens live for seven days in an HttpOnly, SameSite cookie.
The dashboard reads pod usage from the K3s Metrics Server. Metrics may briefly show as unavailable while a new pod or the metrics pipeline becomes ready.