de1d9e1d93
Replaces initial Nomad/Consul/Terraform skeleton with current Docker-based infrastructure across all three nodes (hf-pdocker-01, hf-pdocker-02, bart). Key changes: - CLAUDE.md: updated service distribution reflecting hf-pdocker-01 restored - docs/plans/2026-03-08-hf-pdocker-01-rebuild.md: new rebuild plan doc - compose/bart/: ai-agents, guacamole, matrix, media, openvas, smarthome, watchtower - compose/hf-pdocker-02/: traefik, monitoring, adguard, gitea, semaphore, wikijs, unifi, vaultwarden, actual-budget, mcpo, netclaw, trivy, watchtower, n8n - compose/hf-pdocker-01/: frigate, frigate-notify, farm-agent - stacks/: all Swarm stack definitions (monitoring, traefik, smarthome, matrix, guacamole, media, ai-agents, frigate, gitea, semaphore, wikijs, unifi, etc.) - .gitignore: exclude .env credential files and acme.json certs - .env.example: placeholder credential files for all services - .claude/agents/: gitea-backup and other infrastructure agent configs - scripts/: frigate media cleanup and NAS sync scripts Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
183 lines
5.9 KiB
Markdown
183 lines
5.9 KiB
Markdown
# Farm Manager — Design Document
|
|
|
|
**Date**: 2026-03-05
|
|
**Status**: Approved
|
|
|
|
## Overview
|
|
|
|
A web-based dashboard for managing Docker services across the 3-node homelab cluster. Provides full control (start/stop/restart/logs/pull) with service grouping for bulk operations.
|
|
|
|
## Architecture
|
|
|
|
Three components:
|
|
|
|
1. **Dashboard** — Static HTML/CSS/JS served by the API server. Dark theme, single page with service cards, group management, and slide-out log viewer.
|
|
2. **API Server** — Python FastAPI on hf-pdocker-01:8888. Serves frontend, proxies Docker commands to node agents, manages group definitions in JSON.
|
|
3. **Node Agent** — Python FastAPI on each node:8889. Mounts Docker socket, exposes REST API for container operations. Auto-detects Swarm vs Compose containers.
|
|
|
|
```
|
|
Browser → Dashboard (hf-pdocker-01:8888)
|
|
↓
|
|
API Server
|
|
↙ ↓ ↘
|
|
Agent Agent Agent
|
|
(01:8889) (02:8889) (bart:8889)
|
|
↓ ↓ ↓
|
|
Docker Docker Docker
|
|
Socket Socket Socket
|
|
```
|
|
|
|
## API Endpoints
|
|
|
|
### API Server (hf-pdocker-01:8888)
|
|
|
|
| Method | Path | Description |
|
|
|--------|------|-------------|
|
|
| GET | `/api/nodes` | List all nodes with health status |
|
|
| GET | `/api/services` | All containers across all nodes |
|
|
| POST | `/api/services/{node}/{container}/start` | Start container |
|
|
| POST | `/api/services/{node}/{container}/stop` | Stop container |
|
|
| POST | `/api/services/{node}/{container}/restart` | Restart container |
|
|
| GET | `/api/services/{node}/{container}/logs?tail=100` | Stream logs |
|
|
| POST | `/api/services/{node}/{container}/pull` | Pull latest image |
|
|
| GET | `/api/groups` | List all groups |
|
|
| POST | `/api/groups` | Create group |
|
|
| PUT | `/api/groups/{id}` | Edit group |
|
|
| DELETE | `/api/groups/{id}` | Delete group |
|
|
| POST | `/api/groups/{id}/start` | Start all services in group |
|
|
| POST | `/api/groups/{id}/stop` | Stop all services in group |
|
|
| POST | `/api/groups/{id}/restart` | Restart all services in group |
|
|
|
|
### Node Agent (each node:8889)
|
|
|
|
| Method | Path | Description |
|
|
|--------|------|-------------|
|
|
| GET | `/containers` | List all containers with status |
|
|
| POST | `/containers/{id}/start` | Start |
|
|
| POST | `/containers/{id}/stop` | Stop |
|
|
| POST | `/containers/{id}/restart` | Restart |
|
|
| GET | `/containers/{id}/logs?tail=100` | Get logs |
|
|
| POST | `/containers/{id}/pull` | Pull latest image |
|
|
| GET | `/health` | Agent health check |
|
|
|
|
## Frontend UI
|
|
|
|
- **Sidebar**: Node list with health dots, group list with expand/collapse, "All Services" view, group management button
|
|
- **Main area**: Grid of service cards (name, status badge, node, image, uptime, action buttons)
|
|
- **Log viewer**: Slide-out right panel, last 200 lines, auto-scroll
|
|
- **Group actions**: Toolbar with Start All / Stop All / Restart All, confirmation modal for destructive actions
|
|
- **Group editor**: Modal with name field and checkbox service list
|
|
- **Styling**: Dark theme, custom CSS variables, no framework
|
|
|
|
## Data Storage
|
|
|
|
### Groups (`/mnt/docker-data/configs/farm-manager/groups.json`)
|
|
|
|
```json
|
|
{
|
|
"groups": [
|
|
{
|
|
"id": "ai-agents",
|
|
"name": "AI Agents",
|
|
"services": [
|
|
{"node": "hf-pdocker-01", "container": "ai-agents_margaret"},
|
|
{"node": "hf-pdocker-01", "container": "ai-agents_spirit"},
|
|
{"node": "hf-pdocker-01", "container": "ai-agents_bob"},
|
|
{"node": "hf-pdocker-01", "container": "ai-agents_clippy"}
|
|
]
|
|
}
|
|
]
|
|
}
|
|
```
|
|
|
|
### Node config (`config.json`)
|
|
|
|
```json
|
|
{
|
|
"nodes": [
|
|
{"name": "hf-pdocker-01", "host": "192.168.86.192", "agent_port": 8889},
|
|
{"name": "hf-pdocker-02", "host": "192.168.86.100", "agent_port": 8889},
|
|
{"name": "bart", "host": "192.168.86.167", "agent_port": 8889}
|
|
]
|
|
}
|
|
```
|
|
|
|
### Default Groups
|
|
|
|
| Group | Services |
|
|
|-------|----------|
|
|
| AI Agents | margaret, spirit, bob, clippy |
|
|
| Smart Home | homeassistant, esphome, mosquitto |
|
|
| Monitoring | grafana, prometheus, alertmanager, influxdb, blackbox-exporter |
|
|
| Media | jellyfin, sonarr, radarr, sabnzbd, nzbhydra2, jellyseerr |
|
|
| Matrix | synapse, synapse-db, wellknown |
|
|
| Guacamole | guacamole, guacd, guacamole-db |
|
|
| Dev Tools | gitea, gitea-db, semaphore, semaphore-db, wikijs, wikijs-db |
|
|
| Security | vaultwarden, trivy, openvas |
|
|
| Network | traefik, adguard, unifi, unifi-db |
|
|
| Frigate | frigate, frigate-notify |
|
|
|
|
## Deployment
|
|
|
|
### Node Agent (all 3 nodes)
|
|
|
|
- Path: `/mnt/docker-data/compose/{node}/farm-agent/docker-compose.yml`
|
|
- Image: built once, pushed to registry at 127.0.0.1:5050
|
|
- Mounts: `/var/run/docker.sock`
|
|
- Port: 8889
|
|
- mem_limit: 128M
|
|
|
|
### API Server + Dashboard (hf-pdocker-01)
|
|
|
|
- Path: `/mnt/docker-data/compose/hf-pdocker-01/farm-manager/docker-compose.yml`
|
|
- Port: 8888
|
|
- Config: `/mnt/docker-data/configs/farm-manager/`
|
|
- mem_limit: 256M
|
|
|
|
### Swarm Handling
|
|
|
|
Node agent auto-detects Swarm-managed containers and uses `docker service` API for Swarm services, `docker` API for Compose containers.
|
|
|
|
## Repo
|
|
|
|
- Gitea: `jeremy/farm-manager` (git.hobbs.farm)
|
|
- Structure:
|
|
|
|
```
|
|
farm-manager/
|
|
├── agent/
|
|
│ ├── main.py
|
|
│ ├── docker_ops.py
|
|
│ ├── requirements.txt
|
|
│ └── Dockerfile
|
|
├── server/
|
|
│ ├── main.py
|
|
│ ├── routes/
|
|
│ ├── static/
|
|
│ │ ├── index.html
|
|
│ │ ├── style.css
|
|
│ │ └── app.js
|
|
│ ├── requirements.txt
|
|
│ └── Dockerfile
|
|
├── tests/
|
|
│ ├── test_agent.py
|
|
│ ├── test_server.py
|
|
│ └── conftest.py
|
|
├── config.json
|
|
├── groups.json
|
|
└── README.md
|
|
```
|
|
|
|
## Testing
|
|
|
|
| Layer | Scope | Tool |
|
|
|-------|-------|------|
|
|
| Unit | Agent Docker operations, group CRUD, API proxy logic | pytest + pytest-asyncio |
|
|
| Integration | API server ↔ mock agent, group persistence | pytest + httpx TestClient |
|
|
| Contract | Agent response schemas match dashboard expectations | pydantic models |
|
|
|
|
## Monitoring
|
|
|
|
- Prometheus blackbox probes: `:8888/health` and `:8889/health` on each node
|
|
- No auth (internal LAN only)
|