feat: add tailscale, vault, k8s tool guides; onboarding + machines docs; fill out claude.md; sync README, llm.txt, manifest
This commit is contained in:
@@ -0,0 +1,144 @@
|
||||
# Kubernetes (k8s) Guide
|
||||
|
||||
A local Kubernetes cluster runs on Tabitha under the `silma-ai` namespace. This is Silma's local data and infrastructure plane — databases, vector stores, message queues, secrets, observability, and workflow orchestration.
|
||||
|
||||
---
|
||||
|
||||
## Cluster
|
||||
|
||||
| Field | Value |
|
||||
|-------|-------|
|
||||
| **Context** | `docker-desktop` |
|
||||
| **Namespace** | `silma-ai` |
|
||||
| **Manifests** | `/Users/Tabitha/.openclaw/k8s/silma-ai/` |
|
||||
|
||||
---
|
||||
|
||||
## Starting the Stack
|
||||
|
||||
```bash
|
||||
# Apply all manifests (idempotent)
|
||||
bash /Users/Tabitha/.openclaw/k8s/silma-ai/scripts/apply.sh
|
||||
|
||||
# Or via npm from the OCPlatform root
|
||||
cd /Users/Tabitha/.openclaw && npm run k8s:silma-ai:ensure
|
||||
|
||||
# Port-forward all services to localhost (run in a separate terminal, stays in foreground)
|
||||
bash /Users/Tabitha/.openclaw/k8s/silma-ai/scripts/port-forward.sh
|
||||
```
|
||||
|
||||
---
|
||||
|
||||
## Service Map
|
||||
|
||||
All services below are accessible at `localhost:<port>` **only when the port-forward script is running.**
|
||||
|
||||
| Service | Port(s) | Auth | Notes |
|
||||
|---------|---------|------|-------|
|
||||
| **PostgreSQL + pgvector** | `5432` | secret: `postgres-credentials` | DB: `silma` — primary relational + vector store |
|
||||
| **Redis** | `6379` | none | In-memory cache, pub/sub |
|
||||
| **Elasticsearch** | `9200` | none | Full-text search |
|
||||
| **Kafka** | `9092` | none | Event streaming (Zookeeper internal on 2181) |
|
||||
| **Qdrant** | `6333` (HTTP), `6334` (gRPC) | none | Vector DB for Silma's semantic memory |
|
||||
| **MinIO** | `9000` (API), `9001` (console) | secret: `minio-credentials` | S3-compatible object storage |
|
||||
| **Vault** | `18200` | token: `devroot` | Secrets management — see `tools/vault.llm.md` |
|
||||
| **Prometheus** | `9090` | none | Metrics scraper |
|
||||
| **Grafana** | `3000` | secret: `grafana-admin` | Dashboards and observability UI |
|
||||
| **Temporal** | `7233` (gRPC) | none | Workflow orchestration engine |
|
||||
| **Temporal UI** | `8233` | none | Web UI for Temporal workflows |
|
||||
|
||||
---
|
||||
|
||||
## LLM Inference (Host — NOT in k8s)
|
||||
|
||||
LLM inference runs natively on Tabitha's host (not in Docker) to get Metal/GPU acceleration:
|
||||
|
||||
```bash
|
||||
cd /Users/Tabitha/.openclaw && npm run api:llm
|
||||
|
||||
# Endpoints (OpenAI-compatible):
|
||||
# Gemma-4-E4B: http://localhost:8080
|
||||
# Gemma-4-26B: http://localhost:8081
|
||||
```
|
||||
|
||||
---
|
||||
|
||||
## Common kubectl Commands
|
||||
|
||||
```bash
|
||||
# Check all pods
|
||||
kubectl get pods -n silma-ai
|
||||
|
||||
# Check a specific pod's logs
|
||||
kubectl logs -n silma-ai <pod-name> --tail=50
|
||||
kubectl logs -n silma-ai <pod-name> -f # follow
|
||||
|
||||
# Describe a pod (for debugging CrashLoopBackOff etc.)
|
||||
kubectl describe pod -n silma-ai <pod-name>
|
||||
|
||||
# Get secrets (base64-encoded)
|
||||
kubectl get secret -n silma-ai postgres-credentials -o jsonpath='{.data.password}' | base64 -d
|
||||
|
||||
# Restart a deployment
|
||||
kubectl rollout restart deployment -n silma-ai <deployment-name>
|
||||
|
||||
# Get all resources in namespace
|
||||
kubectl get all -n silma-ai
|
||||
|
||||
# Check PVCs (persistent storage)
|
||||
kubectl get pvc -n silma-ai
|
||||
```
|
||||
|
||||
---
|
||||
|
||||
## Connecting to Services
|
||||
|
||||
### PostgreSQL
|
||||
```bash
|
||||
# After port-forward is active:
|
||||
psql -h localhost -p 5432 -U silma -d silma
|
||||
# Password: from kubectl get secret postgres-credentials
|
||||
```
|
||||
|
||||
### Qdrant (Silma's vector memory)
|
||||
```python
|
||||
from qdrant_client import QdrantClient
|
||||
client = QdrantClient(host="localhost", port=6333)
|
||||
client.get_collections()
|
||||
```
|
||||
|
||||
### MinIO
|
||||
```python
|
||||
import boto3
|
||||
s3 = boto3.client('s3',
|
||||
endpoint_url='http://localhost:9000',
|
||||
aws_access_key_id='minioadmin',
|
||||
aws_secret_access_key='minioadmin')
|
||||
s3.list_buckets()
|
||||
```
|
||||
|
||||
### Redis
|
||||
```bash
|
||||
redis-cli -h localhost -p 6379 ping
|
||||
```
|
||||
|
||||
---
|
||||
|
||||
## Storage
|
||||
|
||||
PVC data is persisted on Hagia (`/Volumes/Hagia/k8s/volumes/`). If Hagia is not mounted, PVCs will be unavailable and pods will fail to start.
|
||||
|
||||
```bash
|
||||
# Verify Hagia is mounted before starting k8s services
|
||||
ls /Volumes/Hagia/k8s/volumes/
|
||||
```
|
||||
|
||||
---
|
||||
|
||||
## Notes for AI Agents
|
||||
|
||||
- **Always run the port-forward script first** before trying to connect to any k8s service
|
||||
- Tabitha must have Docker Desktop running with the `docker-desktop` context active
|
||||
- If pods are in `CrashLoopBackOff`, check if Hagia is mounted — most PVCs depend on it
|
||||
- Vault (`localhost:18200`) requires the port-forward — see `tools/vault.llm.md` for secret access patterns
|
||||
- LLM inference is on the host, not in k8s — don't look for it with `kubectl`
|
||||
@@ -0,0 +1,101 @@
|
||||
# Tailscale Network Guide
|
||||
|
||||
All machines in Jacob Mathison's environment are connected via Tailscale. This is the backbone of cross-machine access — SSH, kittens WebSocket bridges, Gitea, and local services all route over it.
|
||||
|
||||
---
|
||||
|
||||
## Tailscale Account
|
||||
|
||||
- **Account:** `silmaai2000@` (silmaai Tailscale account)
|
||||
- **Network name:** silmaai2000's tailnet
|
||||
|
||||
---
|
||||
|
||||
## Machine Inventory
|
||||
|
||||
| Hostname | Tailscale IP | OS | Role | Status |
|
||||
|----------|-------------|-----|------|--------|
|
||||
| `macbook-pro-3` (Tabitha) | `100.76.192.116` | macOS arm64 | Silma AI primary — OCPlatform, k8s | ✅ Online |
|
||||
| `orson` | `100.79.253.19` | macOS arm64 | Gitea host, CI runner (act_runner), Hagia attached | ✅ Online |
|
||||
| `orson-macbook-pro` | `100.108.57.113` | macOS arm64 | Orson second interface | ✅ Online |
|
||||
| `tabitha-macbook-pro` | `100.120.22.37` | macOS arm64 | Tabitha second interface | — |
|
||||
| `ozymandiass-macbook-pro` (Ozymandias) | `100.115.222.5` | macOS x86_64 | Travel laptop / coding box | — Offline |
|
||||
| `hunter-wsl2` | `100.118.15.20` | Linux (WSL2) | Hunter Albert's dev machine | — Offline |
|
||||
| `joseph-bro-windows` | `100.123.22.58` | Windows | Aaron Pressey's machine (GoatLord) | — Offline |
|
||||
| `mimir-mme3l` (Mimir) | `100.100.117.5` | Linux | Mimir server (Hunter's AI bridge box) | — Offline |
|
||||
|
||||
---
|
||||
|
||||
## Verify Connectivity
|
||||
|
||||
```bash
|
||||
# Check your own Tailscale IP and status
|
||||
tailscale ip
|
||||
tailscale status
|
||||
|
||||
# Ping a machine
|
||||
ping 100.79.253.19 # Orson/Hagia/Gitea host
|
||||
ping 100.76.192.116 # Tabitha (Silma primary)
|
||||
```
|
||||
|
||||
---
|
||||
|
||||
## Connecting to Machines
|
||||
|
||||
### Via kittens WebSocket bridge (preferred for remote exec)
|
||||
|
||||
All machines run `silma-kittens` — a WebSocket server that allows remote command execution without needing SSH keys.
|
||||
|
||||
```python
|
||||
import asyncio, json, websockets
|
||||
|
||||
async def remote(ip, cmd, token='silma-kittens-2026', timeout=20):
|
||||
url = f'ws://{ip}:8765/?token={token}'
|
||||
async with websockets.connect(url, open_timeout=5) as ws:
|
||||
await ws.recv()
|
||||
await ws.send(json.dumps({'type': 'exec', 'id': '1', 'cmd': cmd}))
|
||||
r = json.loads(await asyncio.wait_for(ws.recv(), timeout=timeout))
|
||||
return r.get('stdout', ''), r.get('stderr', '')
|
||||
|
||||
# Orson
|
||||
out, err = asyncio.run(remote('192.168.12.138', 'hostname'))
|
||||
|
||||
# Or via Tailscale IP
|
||||
out, err = asyncio.run(remote('100.79.253.19', 'whoami'))
|
||||
```
|
||||
|
||||
**Kittens token:** `silma-kittens-2026` (same on all machines)
|
||||
**Port:** `8765`
|
||||
|
||||
### Creon (Hunter's static ngrok tunnel)
|
||||
Hunter's machine uses a permanent ngrok domain:
|
||||
- **URL:** `wss://creon.ngrok.app/?token=3ClCIkJOCu1Gd5RO2PA4JHRD1ji_soHXcU4c3vMCbvEBFsKi`
|
||||
- Requires `ngrok-skip-browser-warning: true` header
|
||||
|
||||
---
|
||||
|
||||
## Key Service Endpoints (via Tailscale)
|
||||
|
||||
| Service | Address | Notes |
|
||||
|---------|---------|-------|
|
||||
| Gitea | `http://100.79.253.19:3000` | Self-hosted git on Orson/Hagia |
|
||||
| Tabitha k8s services | `localhost:*` when port-forwarded | See `tools/k8s.llm.md` |
|
||||
|
||||
---
|
||||
|
||||
## /etc/hosts Entries (Tabitha)
|
||||
|
||||
```
|
||||
100.79.253.19 Theodora Orson Hagia
|
||||
```
|
||||
|
||||
These aliases are set on Tabitha — `Orson`, `Hagia`, `Theodora` all resolve to `100.79.253.19`.
|
||||
|
||||
---
|
||||
|
||||
## Notes for AI Agents
|
||||
|
||||
- If Tailscale is not connected, cross-machine operations will fail silently — verify with `tailscale status` first
|
||||
- Gitea and kittens are both reachable via LAN IP (`192.168.12.x`) or Tailscale IP (`100.x.x.x`) when on the same network
|
||||
- Offline machines have kittens installed but the tunnel won't be up — check `tailscale status` before trying
|
||||
- GoatLord (`joseph-bro-windows`) also has a static ngrok URL: `exsufflicate-ineradicable-cortez.ngrok-free.app` (port 8765)
|
||||
@@ -0,0 +1,107 @@
|
||||
# Vault Secrets Guide
|
||||
|
||||
HashiCorp Vault runs in the `silma-ai` k8s namespace on Tabitha. It is the authoritative store for all credentials and API keys in this environment.
|
||||
|
||||
---
|
||||
|
||||
## Access
|
||||
|
||||
| Field | Value |
|
||||
|-------|-------|
|
||||
| **Host port** | `18200` (port-forwarded from k8s cluster port 8200) |
|
||||
| **URL** | `http://localhost:18200` |
|
||||
| **Root token** | `devroot` |
|
||||
| **KV engine** | `silma/` (KV v2) |
|
||||
| **UI** | `http://localhost:18200/ui` |
|
||||
|
||||
⚠️ **Requires k8s port-forward to be active.** Run first:
|
||||
```bash
|
||||
bash /Users/Tabitha/.openclaw/k8s/silma-ai/scripts/port-forward.sh
|
||||
```
|
||||
|
||||
---
|
||||
|
||||
## Quick Access via Helper Script
|
||||
|
||||
```bash
|
||||
cd /Users/Tabitha/.openclaw/workspace
|
||||
bash scripts/vault.sh read <path>
|
||||
```
|
||||
|
||||
---
|
||||
|
||||
## Available Secrets
|
||||
|
||||
| Path | Contents |
|
||||
|------|---------|
|
||||
| `discord` | `bot_token`, `client_id` |
|
||||
| `telegram` | `bot_token` |
|
||||
| `github/silma` | `username`, `pat`, `password` |
|
||||
| `github/hunter` | `pat` |
|
||||
| `twitter/silma` | `password` |
|
||||
| `twitter/blb` | `email`, `password` |
|
||||
| `buffer` | `email`, `password` |
|
||||
| `spotify` | `username`, `password`, `client_id`, `client_secret`, `redirect_uri` |
|
||||
| `google` | `password` |
|
||||
| `gmail` | `imap_app_password` |
|
||||
| `zoho` | `mail_password` |
|
||||
| `aws` | `account_id`, `iam_username`, `iam_password`, `signin_url` |
|
||||
| `reddit/silma-paws` | `username`, `email`, `password` |
|
||||
| `reddit/silma-claws` | `username`, `email`, `password` |
|
||||
| `hackerone` | `email`, `password` |
|
||||
| `openclaw` | `gateway_token` |
|
||||
| `patreon/blb` | `email`, `password` |
|
||||
| `hunter/ngrok` | `creon_secret` |
|
||||
| `api-keys/gemini` | `api_key` |
|
||||
| `api-keys/nvidia` | `api_key`, `base_url` |
|
||||
| `api-keys/runware` | `api_key` |
|
||||
| `api-keys/eia` | `api_key` |
|
||||
| `api-keys/airnow` | `api_key` |
|
||||
| `api-keys/census` | `api_key` |
|
||||
| `api-keys/noaa` | `token` |
|
||||
| `api-keys/ticketmaster` | `api_key`, `secret` |
|
||||
| `api-keys/banner-pyre` | `gemini_api_key`, `gcp_project` |
|
||||
|
||||
---
|
||||
|
||||
## Reading Secrets (curl)
|
||||
|
||||
```bash
|
||||
VAULT_TOKEN=devroot
|
||||
VAULT_ADDR=http://localhost:18200
|
||||
|
||||
# Read a secret
|
||||
curl -s -H "X-Vault-Token: $VAULT_TOKEN" \
|
||||
"$VAULT_ADDR/v1/silma/data/discord" | python3 -m json.tool
|
||||
|
||||
# Extract a specific field
|
||||
curl -s -H "X-Vault-Token: $VAULT_TOKEN" \
|
||||
"$VAULT_ADDR/v1/silma/data/discord" \
|
||||
| python3 -c "import sys,json; d=json.load(sys.stdin); print(d['data']['data']['bot_token'])"
|
||||
|
||||
# List all secret paths
|
||||
curl -s -H "X-Vault-Token: $VAULT_TOKEN" \
|
||||
-X LIST "$VAULT_ADDR/v1/silma/metadata/" \
|
||||
| python3 -c "import sys,json; d=json.load(sys.stdin); [print(k) for k in d['data']['keys']]"
|
||||
```
|
||||
|
||||
---
|
||||
|
||||
## Writing Secrets
|
||||
|
||||
```bash
|
||||
# Write / update a secret
|
||||
curl -s -H "X-Vault-Token: $VAULT_TOKEN" \
|
||||
-X POST "$VAULT_ADDR/v1/silma/data/my-secret" \
|
||||
-H "Content-Type: application/json" \
|
||||
-d '{"data": {"key": "value"}}'
|
||||
```
|
||||
|
||||
---
|
||||
|
||||
## Notes for AI Agents
|
||||
|
||||
- Vault is **only reachable on Tabitha** after the k8s port-forward is active
|
||||
- The root token `devroot` is intentional for this local dev instance — do not rotate it without updating all scripts
|
||||
- Prefer Vault over `credentials/secrets.env` for any new secrets — `secrets.env` is a fallback for when Vault isn't running
|
||||
- Do not print or log full secret values — extract only the field you need
|
||||
Reference in New Issue
Block a user