- ArgoCD migrated to argocd namespace - Cert-manager issuers/certs created - 20 namespaces imported with pod-security labels - S3 backend temporarily offline (MinIO), using local backup - Pending: Remove metadata drift from helm releases, re-apply
343 lines
12 KiB
Markdown
343 lines
12 KiB
Markdown
# 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 <ip>`, `core services <ip>`, `core logs <ip>`, `core log-svc <ip> <svc>`, `core dmesg <ip>`, `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 <path> [--key KEY]`, `core put <path> 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 <NODE>` 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 <ip>`, `core services <ip>` | 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 <ip> # Talos node overview (resources, uptime)
|
|
core services <ip> # List Talos services (etcd, kubelet, etc.)
|
|
|
|
# Logs
|
|
core logs <ip> # Stream kubelet logs on node
|
|
core log-svc <ip> <svc> # Logs for specific Talos service (etcd, scheduler, etc.)
|
|
core dmesg <ip> # Kernel logs (ring buffer) from node
|
|
|
|
# Node lifecycle
|
|
core upgrade <ip> # Upgrade Talos OS on node
|
|
core shutdown <ip> # Graceful shutdown
|
|
core reboot <ip> # Reboot node
|
|
|
|
# Kubernetes context
|
|
core config kube-list # List available kubeconfig contexts
|
|
core config kube-use <ctx> # Switch to kubeconfig context (LAN vs WireGuard)
|
|
|
|
# Pod cleanup
|
|
core pods clean # Delete Failed/Evicted/Terminating pods
|
|
core node <node-name> # Get node details (includes pod stats)
|
|
```
|
|
|
|
### Secrets Management (Vault)
|
|
|
|
```bash
|
|
# Read secrets
|
|
core get <path> # Fetch all fields under path
|
|
core get <path> --key KEY_NAME # Fetch specific field
|
|
|
|
# Write secrets
|
|
core put <path> key=value [key2=value2 ...] # Store secrets in Vault
|
|
|
|
# List and export
|
|
core secrets list # List all secret paths
|
|
core secrets export <path> # Export secrets as shell-sourceable format
|
|
|
|
# Execute with secrets in environment
|
|
core secrets exec -- <command> # 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 <name> # Create new group
|
|
|
|
# OAuth2 Applications
|
|
core iam list-apps # List all OAuth2 apps
|
|
core iam create-app <name> --slug <slug> --redirect-uri <uri> # Create app
|
|
core iam describe-app <app> # Show client ID, secret, URIs, scope claims
|
|
core iam rotate-secret <app> # Rotate OAuth2 client secret
|
|
|
|
# User management
|
|
core iam add-member <group> <username> # Add user to group
|
|
core iam bind-app <app> <group> # Grant group access to application
|
|
|
|
# Cleanup
|
|
core iam delete-app <app> # Delete OAuth2 application
|
|
```
|
|
|
|
### Object Storage (MinIO)
|
|
|
|
```bash
|
|
# List and manage buckets
|
|
core bucket list # List all buckets
|
|
core bucket upload <bucket> <file> [<remote-path>] # Upload file to S3
|
|
core bucket download <bucket> <remote-path> <file> # Download file from S3
|
|
core bucket delete <bucket> <remote-path> # 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 <ns> deployment/<app>
|
|
```
|
|
|
|
---
|
|
|
|
## 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
|