Standardized procedures for troubleshooting, developing, deploying, and operating the homelab platform. Each procedure explicitly calls out where the `core` CLI fits vs `kubectl`/`helmfile`/direct cluster access. See `core-cli-tools.md` for the auth/secrets domain split; see `infra-troubleshooting.md` for quick patterns and gotchas.
## Procedure A: Troubleshoot a Service or Cluster Issue
- Consult root `TROUBLESHOOTING.md` for the layer-before-tool SRE methodology (procedures 1–10).
- Use `infra-troubleshooting.md` § Quick Patterns for common diagnoses:
- CrashLoopBackOff: `kubectl logs -n <ns> <pod> --tail=50` + `kubectl describe pod -n <ns> <pod> | grep -A 10 Events`.
- Service 503: `kubectl get endpoints -n <ns> <svc>` (endpoints missing?) + `kubectl get pods -n <ns> -o wide` (pods not Ready?).
- Helm release stuck: `helmfile status | grep -E "FAILED|UNKNOWN|PENDING"` + `helm status <release> -n <ns> --show-resources`.
- If still unclear, escalate to `kubectl get all -n <ns>` and review resource events.
5.**For dashboards and live metrics:**
- Use `core pf grafana` (port-forward to localhost:3000) rather than raw `kubectl port-forward` — keeps forwarded ports consistent.
- If Prometheus unavailable, check: `kubectl get pods -n monitoring | grep prometheus`.
- If ServiceMonitor not scraping, verify: `kubectl get servicemonitor -A | grep <name>` and inspect `.spec.selector` matches the target pod's app label.
---
## Procedure B: Launch/Develop a New Service or POC
- Reference real example: root helmfile's `sqs` section.
5. **If the service needs secrets (DB password, API key, OAuth secret):**
- Generate value (e.g., `openssl rand -hex 32` for passwords).
- Store in Vault: `core put cluster/<SERVICE>_<KEY> <SERVICE>_<KEY>="value"`.
- **Critical gotcha:** field name MUST equal variable name (e.g., `FORGEJO_ADMIN_PASSWORD=` not `value=`) per `coding-standards.md` § Vault field=variable convention.
- Reference in values.yaml via `{{ env "VARIABLE_NAME" }}` (Helmfile Go template syntax, NOT shell `${VAR}`).
- Do NOT hardcode secrets in values.yaml or ConfigMaps.
6. **Verify Helm syntax before deploy.**
- Run `helmfile lint` (catches template errors, duplicate releases).
- Run `helmfile diff -l name=<service>` (show what will be deployed).
- Review diff for correctness (verify env var substitutions, resource limits, affinity rules).
7. **Deploy the service.**
- Run `helmfile apply -l name=<service>`.
- Monitor: `kubectl get pods -n <namespace> -w` (watch until Running).
- If pods stuck: `kubectl describe pod -n <namespace> <pod-name>` (check Events for SchedulingFailed, ImagePullBackOff, etc.).
8. **If the service exports `/metrics` (Prometheus format):**
- Endpoint: If publicly routed via Ingress, verify `/etc/hosts` entry (10.6.0.1 for WireGuard, 192.168.1.160 for LAN) and `curl https://my-service.riotpiao.com/health` (or equivalent health endpoint).
- Alternate isolated iterate path: `k8s/sqs/helmfile.yaml.gotmpl` (not recommended for production).
- Planned future: GitOps via `k8s/sqs/argocd/` (companion repo, not yet active).
- **Critical rule:** Temporal namespace registration is automatic via `queue-operator`; never manually `temporal operator namespace create` for any namespace referenced by a Queue's `temporal.io/namespace` label. See `~/workplace/kmsvc-manage/CLAUDE.md` ("Temporal Namespace Registration") for the full rule and why.
**Shared/reusable service repositories:** If a service's Helm chart and container image live in a separate repository, they must be:
- Published as a public GitHub repository under the `Riotpiaole` organization.
- Images pushed to GHCR (`ghcr.io/riotpiaole/...`) for public pullability.
- Consult `coding-standards.md` § Shared/Reusable Repos for the full publishing rule.
---
## Cross-References
- **core-cli-tools.md:** Auth/secrets domain split, command inventory, when to use `core` vs `kubectl`.