- [The problem](#orgbb75f94) - [The build](#orgfbe04a5) - [bee-stack](#org2a0b6ad) - [Ollama](#org1c426c5) - [Qdrant](#orgdc1f624) - [Postgres](#orge7fbc62) - [Gitea](#org7a818c2) - [bee-tools](#org208cd35) - [Emacs integration](#org52a039b) - [Bug bounty workflow](#orgc55ddfb) - [What actually makes this interesting](#org1316116) - [Code](#org0be0fe8) # The problem No broadband. Rural NC. One Android phone tethered over USB. # The build A Raspberry Pi 4 runs hostapd and dnsmasq, WiFi AP, DHCP, and NAT for the cluster. A TP-Link managed switch connects three nodes. All internet exits through the phone. ```shell Three nodes run Talos Linux (v1.12.6, Kubernetes v1.35.2): [ WAN / Internet ] │ (USB Tethering via Android / Mullvad) ┌──────▼────────────────────────────────────────┐ │ LoqArch Workstation (Arch Linux + Doom Emacs) │ └──────┬────────────────────────────────────────┘ │ (wlp8s0 / 10.10.10.243) ┌──────▼────────────────────────────────────────┐ │ Raspberry Pi 4 (AP + NAT + dnsmasq) │ └──────┬────────────────────────────────────────┘ │ (eth0 / 10.10.10.1) [ TP-Link Managed Switch ] │ ├─► talos-cp (10.10.10.10) ── k8s Control Plane │ ├─► talos-w1 (10.10.10.11) ── Ollama (mirror), Qdrant, Storage │ └─► talos-w2 (10.10.10.12) ── Ollama (primary), Gitea, Postgres, bee-tools ``` Everything uses local-path RWO PVCs. No cloud. No NFS. No CNI drama. Just pure pain and suffering. # bee-stack The “beeattack” namespace is the whole point. All services are internal; NodePorts forward through the control-plane IP. ## Ollama Two instances sharing model storage via PVCs. Primary on w2, mirror on w1. Custom model `bee-raw` — derived from a fine-tuned triage base, system-prompted for direct security research with no disclaimers, temperature 0.2, 8k context. Built inside the pod with a Modelfile. Also runs `gemma4` and `nomic-embed-text` for embeddings. ## Qdrant Three collections: `docs` (reference material, 768-dim cosine), `notes` (org-denote vault + research notes), `code` (gitea repo contents). All ingested via a Python chunker that calls the nomic embedding model through Ollama’s API. Gotchas worth noting: Qdrant 1.17+ changed the upsert format. The old `points` key breaks silently on some operations. WAL corruption happens if you patch the deployment before the pod finishes terminating — wait for full pod termination before reapplying. ## Postgres Structured side of the research store: findings, targets, LLM sessions, research notes, doc full-text with a `tsvector` index, and a tool call log. Postgres FTS complements the Qdrant semantic search — exact-match queries go to Postgres, fuzzy conceptual queries go to Qdrant. Port-forwarded on 15432 locally. NodePort is technically open but firewalled by Talos. ## Gitea Self-hosted git. Registration disabled. Push webhook fires on every commit → bee-tools re-ingests changed files into `qdrant/code`. Token stored at `~/.config/bee-tools-token`. ## bee-tools FastAPI bridge. The connective tissue. Endpoints cover: RAG search (single collection and merged multi-collection), git file read/write/search, Postgres note and query operations, session save/load, doc ingest and FTS, bug bounty findings CRUD, targets, tool call logging, and a browser UI. Source lives in `~/Homelab/bee-stack/bee-tools.py`. Deployed via configmap — edit file, recreate configmap, rollout restart. One rule: all route definitions must appear before the `if __name__` block. FastAPI silently drops anything after it. # Emacs integration The workstation (LoqArch, Arch Linux) runs Doom Emacs. All of the above surfaces through `gptel` via a custom config at `~/.config/doom/custom/llm-gptel.el`. Keybinds live under `SPC l`: | Key | Action | |--------- |------------------------------------------ | | `SPC l l` | Open gptel chat buffer | | `SPC l B` | Switch to bug bounty mode | | `SPC l T` | Start recon on target domain | | `SPC l R` | Toggle RAG auto-inject | | `SPC l q` | Manual RAG search → `*bee-rag*` buffer | | `SPC l Q` | Postgres FTS → `*bee-docs*` buffer | | `SPC l w` | Web search → `*bee-web*` buffer | | `SPC l A` | Security analysis of current buffer/region | | `SPC l e` | Run shell command on LoqArch | | `SPC l F` | Save finding to Postgres | | `SPC l L` | List findings → `*bee-findings*` buffer | RAG auto-inject runs before every prompt: pulls the top-scoring chunks from Qdrant across all three collections, filters below a 0.72 score threshold, injects up to 5 chunks into the system context. The model sees relevant docs without being asked. gptel tools (callable by the model during a session): `rag_search`, `doc_search`, `web_search`, `url_fetch`, `shell_exec`, `file_read`, `file_write`, `git_read`, `git_write`, `git_search`, `db_note`, `db_query`, `vuln_finding`. # Bug bounty workflow The whole stack exists to support this: ``` SPC l B → bug bounty mode (no-disclaimer system prompt) SPC l T → enter target → LLM recon analysis auto-starts SPC l w → search target intel SPC l W → fetch JS, pages, endpoints SPC l e → run local tools (curl, ffuf, nmap) SPC l A → analyze interesting code or responses SPC l F → confirmed finding → save to Postgres SPC l L → review all findings SPC X v → org-capture detailed report ``` Findings track: target, title, severity, description, PoC, impact, CVSS, status, and bounty paid. Status flow: `new → triaged → accepted → resolved` (or `duplicate` / `wontfix`). # What actually makes this interesting Most homelab LLM setups front-end a single Ollama instance. This one is built around a research loop: 1. Docs and notes are embedded and searchable semantically and via FTS. 2. Every LLM session has access to the full tool set — search, shell, git, DB — without any manual copy-paste. 3. Findings feed back into the knowledge base. A resolved vuln becomes a note, gets embedded, and shows up in future sessions on similar targets. 4. The whole thing runs on a tethered phone connection. Nothing about the stack assumes reliable or fast internet. The constraint shaped the design. Local-first wasn’t a preference — it was the only option. # Code [bee-stack](https://gitea.bee.local/yopi/bee-stack) (self-hosted, not public) ```bash ~/Homelab/bee-stack/ ├── bee-tools.py # FastAPI service ├── bee-stack.sh # deploy postgres + bee-tools ├── bee-tools-bb.sh # deploy findings/targets schema + elisp └── fix-bee-tools.sh # clean rebuild + redeploy ```