🛡️ Security Model
LaraKube CLI is built so the credential most likely to leak — the one sitting in a CI secret or on a deploy runner — can do the least possible damage. Two ideas drive everything:
- Your admin credentials never leave your machine.
- Everything automated runs with the narrowest privilege that still works.
A leaked App A secret can deploy to app-a-prod and nothing else — not App B, not the shared Commons, not the node. Blast radius = one namespace.
1 · Admin stays local
The cluster-admin kubeconfig (from cloud:provision, or your provider's CLI for managed clusters) lives only in your ~/.kube/config. LaraKube CLI never uploads it to GitHub or any runner. It's the bootstrapping authority — used locally to mint the narrower credentials below — and it stays put.
Note: LaraKube CLI also aggressively masks secrets (like server passwords, DigitalOcean tokens, or raw AWS keys) in its diagnostic and runtime logs to prevent accidental exposure.
2 · Namespace-scoped deploys
Both larakube cloud:deploy (manual) and the generated GitHub Actions workflow deploy as a per-app, per-environment deployer ServiceAccount locked to its own {app}-{env} namespace by a namespaced Role. A namespaced Role can only grant namespaced resources, so the token is forbidden everywhere else — by construction, not by policy.
# yes — inside its own namespace
kubectl auth can-i create deployments -n myapp-production \
--as=system:serviceaccount:myapp-production:deployer # → yes
# no — another namespace, or anything cluster-scoped
kubectl auth can-i get secrets -n default \
--as=system:serviceaccount:myapp-production:deployer # → no
The manual path dogfoods the exact same credential locally (admin only bootstraps it, then the apply runs as deployer), so a missing permission surfaces on your machine — where you hold admin to fix it — rather than in CI. Full detail: Surgical Credentials.
3 · A hardened server
For self-managed VPS nodes, cloud:provision doesn't just install k3s — it locks the box down: a default-deny firewall, fail2ban, automatic security updates, key-only SSH, and (guarded) disabling of remote root login. cloud:harden re-applies it to an existing server. See Server Hardening.
(Managed clusters — DOKS/EKS/GKE/AKS — are hardened at the node level by your provider; LaraKube CLI targets them by kube-context and never SSHes in.)
4 · Multi-app isolation
Several apps can share one cluster (and even one set of backing services via Plex) while staying isolated:
- Namespaces — each app/env is its own namespace; the scoped
deployercan't cross them. - Plex tenants — on a shared Commons, each app gets its own database + login, Redis logical DB, and S3 bucket. A tenant credential reaches its own data and no one else's.
What isn't covered yet (honest)
Security is layered, and a few hardening knobs are deliberately deferred (tracked in the CLI's plans/active/server-hardening.md):
- The k3s API (6443) is open to the internet by default — restricting it to your operator IP is a recommended manual follow-up.
- The
larakubeadmin user keeps full sudo (it's the box's admin once root login is off) — OS-level deploy isolation, if ever wanted, would be a separate dedicated user. - Real SSO (OIDC) for human access is a longer-term path; today, Team Access issues per-person, revocable, scoped kubeconfigs (in-cluster credentials rather than federated identities).
LaraKube CLI's goal isn't to claim perfection — it's to make the secure path the default one, and to be honest about the edges.