diff --git a/README.md b/README.md index 44c1660..ee42f54 100644 --- a/README.md +++ b/README.md @@ -1,77 +1,85 @@ -# Homelab Butler +# Homelab Butler 🤵 -Unified API proxy for the Pfannkuchen homelab. One token, one URL, all services. +Unified API proxy + infrastructure management for Homelab Pfannkuchen. -## Quick Start +**Base URL:** `http://10.4.1.116:8888` +**Auth:** `Authorization: Bearer ` -```bash -# Set your butler token -echo "BUTLER_TOKEN=$(openssl rand -hex 24)" > .env +## Service Proxy -# Deploy -docker compose up -d --build +Proxies requests to backend services with automatic authentication: + +| Service | Backend | Auth | +|---------|---------|------| +| `dockhand` | 10.4.1.116:3000 | Session | +| `sonarr` | 10.2.1.100:8989 | API Key | +| `radarr` | 10.2.1.100:7878 | API Key | +| `seerr` | 10.2.1.100:5055 | API Key | +| `outline` | 10.1.1.100:3000 | Bearer | +| `n8n` | 10.4.1.113:5678 | X-N8N-API-KEY | +| `proxmox` | 10.5.85.11:8006 | PVE Token | +| `homeassistant` | 10.10.1.20:8123 | Bearer | +| `grafana` | 10.1.1.111:3000 | Bearer | +| `uptime` | 159.69.245.190:3001 | Bearer | +| `waha` | 10.4.1.110:3500 | API Key | +| `forgejo` | 10.4.1.116:3001 | Bearer | +| `semaphore` | 10.4.1.116:8090 | Bearer | + +Usage: `GET/POST/PUT/DELETE /{service}/{path}` + +## VM Lifecycle + +| Endpoint | Method | Description | +|----------|--------|-------------| +| `/vm/list` | GET | All VMs across all 7 Proxmox nodes | +| `/vm/create` | POST | Full VM deployment (~10 min): ISO build, VM create, SSH wait, inventory, Ansible | +| `/vm/status/{vmid}` | GET | VM status (CPU, RAM, uptime) | +| `/vm/{vmid}` | DELETE | Destroy VM | + +### POST /vm/create +```json +{"node": 5, "ip": "10.5.1.115", "hostname": "lychee", "cores": 2, "memory": 4096, "disk": 32} +``` +Steps: iso-builder → Proxmox VM → wait SSH → add to pfannkuchen.ini → Ansible base setup (Docker, Borgmatic, Hawser) + +## Ansible / Inventory + +| Endpoint | Method | Description | +|----------|--------|-------------| +| `/inventory/host` | POST | Add host to pfannkuchen.ini (idempotent, with group) | +| `/ansible/run` | POST | Run Ansible playbook on host | + +### POST /inventory/host +```json +{"name": "lychee", "ip": "10.5.1.115", "group": "auto"} ``` -## Usage +## TTS / Speech -```bash -TOKEN="your-butler-token" -BUTLER="http://10.4.1.116:8888" +| Endpoint | Method | Description | +|----------|--------|-------------| +| `/tts/speak` | POST | Text-to-speech via Chatterbox | +| `/tts/voices` | GET | Available voices | +| `/tts/health` | GET | Speaker + Chatterbox status | -# List available services -curl -s -H "Authorization: Bearer $TOKEN" $BUTLER/ - -# Dockhand (session auth handled automatically) -curl -s -H "Authorization: Bearer $TOKEN" $BUTLER/dockhand/api/environments - -# Sonarr -curl -s -H "Authorization: Bearer $TOKEN" $BUTLER/sonarr/api/v3/series - -# Radarr -curl -s -H "Authorization: Bearer $TOKEN" $BUTLER/radarr/api/v3/movie - -# Seerr -curl -s -H "Authorization: Bearer $TOKEN" $BUTLER/seerr/api/v1/request - -# Proxmox -curl -s -H "Authorization: Bearer $TOKEN" $BUTLER/proxmox/api2/json/nodes - -# Home Assistant -curl -s -H "Authorization: Bearer $TOKEN" $BUTLER/homeassistant/api/states - -# Outline Wiki -curl -s -X POST -H "Authorization: Bearer $TOKEN" -H "Content-Type: application/json" \ - -d '{}' $BUTLER/outline/api/collections.list - -# n8n -curl -s -H "Authorization: Bearer $TOKEN" $BUTLER/n8n/api/v1/workflows - -# Grafana -curl -s -H "Authorization: Bearer $TOKEN" $BUTLER/grafana/api/dashboards/home - -# Uptime Kuma -curl -s -H "Authorization: Bearer $TOKEN" $BUTLER/uptime/api/status-page/pfannkuchen +### POST /tts/speak +```json +{"text": "Hallo!", "target": "speaker"} ``` - -## Services - -| Service | Backend | Auth handled | -|---------|---------|-------------| -| dockhand | 10.4.1.116:3000 | Session cookie (auto-login) | -| sonarr | 10.2.1.100:8989 | X-Api-Key | -| sonarr1080p | 10.2.1.100:8990 | X-Api-Key | -| radarr | 10.2.1.100:7878 | X-Api-Key | -| radarr1080p | 10.2.1.100:7879 | X-Api-Key | -| seerr | 10.2.1.100:5055 | X-Api-Key | -| outline | 10.1.1.100:3000 | Bearer token | -| n8n | 10.4.1.113:5678 | Bearer token | -| proxmox | 10.5.85.11:8006 | PVEAPIToken | -| homeassistant | 10.10.1.20:8123 | Bearer token | -| grafana | 10.1.1.111:3000 | Bearer token | -| uptime | 159.69.245.190:3001 | Bearer token | +- `"target": "speaker"` → plays on Pi5 speaker (10.10.1.166) +- `"target": "telegram"` → generates OGG on hermes, use `MEDIA:/tmp/trulla_voice.ogg` ## Credentials -API keys are read from `/app-config/kiro/api/` (mounted read-only). The butler token is set via `BUTLER_TOKEN` env var. +Reads from Vaultwarden cache (synced by host cron) with flat-file fallback (`/data/api/`). -For Dockhand: create `/app-config/kiro/api/dockhand` with the admin password. +## Stack + +``` +docker compose build && docker compose up -d +``` + +Requires: +- `.env` with `BUTLER_TOKEN` +- `/app-config/kiro/api/` flat-file credentials +- SSH key mount (`/home/sascha/.ssh:/root/.ssh:ro`) for VM operations