# Core CLI Tools: Decision Guide The `core` CLI is your primary tool for cluster auth, node operations, Vault secrets management, IAM administration, and object storage. This doc covers **when** to reach for `core` vs `kubectl`/`helmfile`, the two separate auth domains that power different commands, and the complete command inventory. For exhaustive flag-level detail on each subcommand, see [~/workplace/core/USAGE.md](../../core/USAGE.md). --- ## The Two Auth Domains The `core` CLI maintains **two independent authentication systems** that gate different command families. Confusing them causes authentication failures. ### Domain 1: Node/Talos Operations (`core auth`) **Gates:** Node-level commands, Talos service management, cluster status. **Login mechanism:** `core auth login-oob` - Out-of-band device-code flow via Authentik - Token cached in `~/.core/token` (24h expiry) - Required before: `core nodes`, `core status `, `core services `, `core logs `, `core log-svc `, `core dmesg `, `core config`, `core upgrade`, `core shutdown`, `core reboot`, `core node`, `core pods clean` **Check auth state:** ```bash core auth status # Show token expiry core auth clear # Force re-auth on next command ``` **When to use:** - Troubleshooting node-level issues (crashes, disk space, network on a specific Talos node) - Checking Talos service health (etcd, kubelet, scheduler, etc.) - Upgrading cluster OS or managing node lifecycle - Reading kernel logs (dmesg) or kubelet logs on specific nodes ### Domain 2: Vault Secrets (`core secrets`) **Gates:** Secrets management (read/write), secret listing, secret export. **Login mechanism:** `core secrets login` - Interactive login to Vault (opens browser, approves auth) - Reads/writes to `~/.config/talos/secrets.toml` - Required before: `core get [--key KEY]`, `core put key=value`, `core secrets list`, `core secrets export`, `core secrets exec` **Check auth state:** ```bash core secrets status # Show Vault token / scopes core secrets clear # Force re-auth on next command ``` **When to use:** - Reading or writing cluster secrets (API keys, database passwords, OAuth client secrets) - Managing application credentials in Vault (centralized secret store) - Rotating secrets for services (e.g., OAuth2 client secrets) - Listing all secrets under a path - Bootstrapping `.env` files for helmfile deployment (via `vsource`) --- ## Auth Bug Fixes **Bug #1 (Fixed):** `core status ` is a **node-ops command**, not an auth verifier. It does NOT verify that you're authenticated to Vault. To verify auth state, use the correct domain-specific command: - For node access: `core auth status` - For Vault access: `core secrets status` **Bug #2 (Fixed):** `core secrets login` and `core auth login-oob` are **NOT interchangeable**. They gate completely different systems: - `core auth login-oob` gates node/cluster operations - `core secrets login` gates Vault secret read/write - You may be authenticated to one domain and not the other. Check state separately. --- ## When to Reach for `core` | Scenario | Tool | Why | |----------|------|-----| | Pod/deployment issue | `kubectl` | Pods, replicas, rollouts, events | | Package release management | `helmfile` | Install/upgrade Helm charts | | Node crashes, disk, kernel panic | `core auth` + node commands | Direct access to Talos node state | | Service unreachable on Talos node | `core status `, `core services ` | Talos service health | | Database password rotation | `core secrets` + `core put` | Vault secret write | | Need API key for app deployment | `core secrets` + `core get` | Fetch from Vault, inject via `vsource` | | Create OAuth2 app in Authentik | `core iam create-app` | Manage federated identity apps | | Add user to service (MinIO, Grafana, etc.) | `core iam add-member` | Group membership binding | | S3 object upload/download | `core bucket` | MinIO operations | --- ## Command Inventory Complete list of `core` subcommands, organized by domain. See [~/workplace/core/USAGE.md](../../core/USAGE.md) for usage flags and examples. ### Authentication ```bash # Node/Talos operations auth core auth login-oob # Authenticate with Authentik (device code flow) core auth status # Check token expiry / auth state core auth clear # Clear cached auth token # Vault secrets auth core secrets login # Authenticate to Vault (interactive) core secrets status # Check Vault token / scopes / expiry core secrets clear # Clear Vault auth token ``` ### Cluster & Node Operations ```bash # Node discovery and status core nodes # List all cluster nodes (IP, hostname, status) core status # Talos node overview (resources, uptime) core services # List Talos services (etcd, kubelet, etc.) # Logs core logs # Stream kubelet logs on node core log-svc # Logs for specific Talos service (etcd, scheduler, etc.) core dmesg # Kernel logs (ring buffer) from node # Node lifecycle core upgrade # Upgrade Talos OS on node core shutdown # Graceful shutdown core reboot # Reboot node # Kubernetes context core config kube-list # List available kubeconfig contexts core config kube-use # Switch to kubeconfig context (LAN vs WireGuard) # Pod cleanup core pods clean # Delete Failed/Evicted/Terminating pods core node # Get node details (includes pod stats) ``` ### Secrets Management (Vault) ```bash # Read secrets core get # Fetch all fields under path core get --key KEY_NAME # Fetch specific field # Write secrets core put key=value [key2=value2 ...] # Store secrets in Vault # List and export core secrets list # List all secret paths core secrets export # Export secrets as shell-sourceable format # Execute with secrets in environment core secrets exec -- # Run command with secrets loaded in env ``` **Convention:** Field name = variable name (SCREAMING_SNAKE_CASE). Never use `value=`. Example: ```bash # Write core put cluster/ANTHROPIC_API_KEY ANTHROPIC_API_KEY="sk-ant-..." # Read core get cluster/ANTHROPIC_API_KEY ``` ### IAM Management (Authentik) ```bash # Groups core iam list-groups # List all groups core iam create-group # Create new group # OAuth2 Applications core iam list-apps # List all OAuth2 apps core iam create-app --slug --redirect-uri # Create app core iam describe-app # Show client ID, secret, URIs, scope claims core iam rotate-secret # Rotate OAuth2 client secret # User management core iam add-member # Add user to group core iam bind-app # Grant group access to application # Cleanup core iam delete-app # Delete OAuth2 application ``` ### Object Storage (MinIO) ```bash # List and manage buckets core bucket list # List all buckets core bucket upload [] # Upload file to S3 core bucket download # Download file from S3 core bucket delete # Delete object from S3 ``` ### Utilities ```bash core help # Show command help core pf grafana # Port-forward to Grafana (localhost:3000) core pf prometheus # Port-forward to Prometheus (localhost:9090) core pf minio # Port-forward to MinIO console (localhost:9001) core pf iam # Port-forward to Authentik (localhost:7000) ``` --- ## Access Control Tiers The cluster uses a tiered access model based on authentication mechanism and network perimeter. ### Tier A: OIDC + RBAC (Authentik-enforced) Services with federated OIDC login and group-based role assignment. | Service | Auth Method | Group Claim | Role Binding | |---------|-------------|------------|--------------| | **Grafana** | Authentik OIDC | `groups` | Mapped to Admin / Viewer / Viewer | | **Argo CD** | Authentik OIDC | `groups` | RBAC role binding (policy.csv) | | **MinIO** | Authentik OIDC | `groups` / custom `policy` | Policy-based access (readwrite / readonly) | | **Forgejo** | Authentik OIDC | `email` (OAuth login only) | No group enforcement (open git repo) | | **kmsvc** | Vault JWT | `sub` / `aud` | Audience validation + service scope | **Provisioning:** ```bash # After core auth login-oob, bootstrap IAM apps: bash k8s/talos-iam/bootstrap-iam.sh ``` ### Tier B: Network-Perimeter Only (No Authentik Enforcement) Services with no OIDC support (product limitation). Access is restricted to LAN/WireGuard perimeter only. | Service | Network Access | Use Case | |---------|----------------|----------| | **Portainer** | LAN + WireGuard only | Container UI, workload browsing | | **Longhorn** | LAN + WireGuard only | Storage volume management | | **Temporal** | LAN + WireGuard only | Workflow execution (auth TBD) | All three are reachable **only** via WireGuard/LAN-only Ingress rules. Zero remote access risk, but also zero federated identity. If remote Temporal access is needed, upgrade the chart's auth configuration or replace with an OIDC-compatible workflow platform. **Accessing Tier B services:** ```bash # From off-LAN, use WireGuard context core config kube-use admin@homelab-cluster-1 core pf minio # connects via 10.6.0.1:9001 ``` --- ## Workflow: Rotate an OAuth2 Application Secret ```bash # 1. Rotate secret in Authentik SECRET=$(core iam rotate-secret grafana | jq -r '.client_secret') # 2. Update Helm values vi k8s/logging/grafana-values.yaml # Set: GRAFANA_OIDC_CLIENT_SECRET="$SECRET" # 3. Redeploy the app helmfile apply -l app=grafana # 4. Verify new secret is in use core iam describe-app grafana | grep client_secret ``` --- ## Workflow: Add User to Service ```bash # 1. Verify group exists (or create it) core iam list-groups | grep minio-admins # If not found: core iam create-group minio-admins # 2. Add user to group core iam add-member minio-admins alice # 3. Bind group to MinIO application core iam bind-app minio minio-admins # 4. User has access on next login # (OIDC login to MinIO → Authentik → group check → MinIO policy applied) ``` --- ## Workflow: Rotate a Database Password (Vault) ```bash # 1. Generate new password NEW_PASS=$(openssl rand -hex 32) # 2. Store in Vault core put cluster/POSTGRES_ADMIN_PASSWORD POSTGRES_ADMIN_PASSWORD="$NEW_PASS" # 3. Update database user kubectl exec -n ddb pod/ddb-cluster-0 -- psql -U postgres -c \ "ALTER USER postgres WITH PASSWORD '$NEW_PASS';" # 4. Update Helm values with new password reference # (Or if using helmfile hook: helmfile will re-run postInitApplicationSQL with new password) # 5. Restart pods to pick up new secret kubectl rollout restart -n deployment/ ``` --- ## Common Questions **Q: I'm getting "not authenticated" on `core nodes`. What do I do?** A: Run `core auth login-oob`. Node commands use a different auth domain than secrets. After login, `core nodes` should work. **Q: I have a valid Vault token but `core get` fails. Why?** A: Check that both auth domains are active: ```bash core auth status # Verify node auth is valid core secrets status # Verify Vault auth is valid ``` Both must succeed. If one is expired, re-auth that domain. **Q: Should I use `core bucket` or S3 CLI tools (aws-cli, s3cmd)?** A: Use `core bucket` for simplicity (no AWS credentials). Use s3cmd/aws-cli if you need advanced sync or bandwidth control. All three talk to the same MinIO backend. **Q: Can I add a user without creating a group first?** A: Groups are the unit of access control. Always create the group, then add users to it, then bind it to applications. Single-user bindings are not supported (by design). **Q: I rotated an OAuth2 secret but the app still fails to authenticate. What's next?** A: 1. Verify the new secret is stored: `core iam describe-app grafana` 2. Check the deployment has the new secret: `kubectl get secret -n logging grafana-oidc -o yaml | grep client_secret` 3. Restart the pod: `kubectl rollout restart -n logging deployment/grafana` 4. Check logs: `kubectl logs -n logging deployment/grafana | grep -i oauth` --- ## See Also - [~/workplace/core/USAGE.md](../../core/USAGE.md) — Exhaustive command reference with flags and examples - [CLAUDE.md](../CLAUDE.md) § Sign In (Device Code Flow) — Quick reference for `core auth login-oob` - [CLAUDE.md](../CLAUDE.md) § Quick Shortcuts — One-liners for common tasks - [CLAUDE.md](../CLAUDE.md) § Integration Checklist — New service onboarding