Skip to content

Commit 681defa

Browse files
committed
Rewrite README for simplified runtime
1 parent 827d15a commit 681defa

1 file changed

Lines changed: 129 additions & 103 deletions

File tree

‎README.md‎

Lines changed: 129 additions & 103 deletions
Original file line numberDiff line numberDiff line change
@@ -1,20 +1,28 @@
11
# Foxhole
22

3-
Foxhole is a read-only-first homelab diagnostic agent for self-hosters. It collects compact evidence from the services you already run, explains what looks wrong, and keeps write actions behind explicit safety gates.
3+
Foxhole is an open-source, modular, read-only-first homelab diagnostic agent for self-hosters.
44

5-
The project is built around opt-in integrations: if you do not enable an integration, Foxhole does not register its tools or spend agent context on it.
5+
It collects compact evidence from the services you already run, explains what looks wrong, and keeps write actions behind explicit safety gates. Every service integration is opt-in: if you do not enable it, Foxhole does not register its tools or spend LLM context on it.
66

7-
## Current Status
7+
## Architecture And Status
88

9-
Foxhole is early software. The default runtime is a single FastAPI process that serves the dashboard, API, in-process scheduled diagnostics, authenticated browser session flow, and SQLite-backed history. Tagged releases publish a production image to `ghcr.io/jacobthree/foxhole`; contributors can still build the same image locally from this repository.
9+
Foxhole is early software. The default runtime is intentionally small: one FastAPI process serves the statically exported Next.js dashboard, REST API, authenticated browser session flow, in-process scheduled diagnostics, in-memory live events, and SQLite-backed history.
10+
11+
```text
12+
Browser -> FastAPI on :8000 -> dashboard, API, scheduler, events, SQLite history
13+
```
14+
15+
The Docker image serves the dashboard from `/app/ui/out`. Source-based LXC and systemd installs serve the same static export from `/opt/homelab-agent/ui/out` through `FOXHOLE_STATIC_UI_DIR`.
16+
17+
Redis, Celery, and Flower are not part of the default runtime. They remain available through a separate distributed Compose file for advanced installs that intentionally want separate API, worker, and beat processes.
1018

1119
## What Foxhole Can Inspect
1220

13-
| Area | Integrations |
21+
| Area | Supported Integrations |
1422
| --- | --- |
15-
| Containers | Docker through a socket proxy, Portainer |
1623
| Virtualization and storage | Proxmox VE, Proxmox backup job visibility |
17-
| Media | Plex, Sonarr, Radarr, Tautulli, Overseerr |
24+
| Containers | Docker through a read-only socket proxy, Portainer |
25+
| Media automation | Plex, Sonarr, Radarr, Tautulli, Overseerr |
1826
| Monitoring | Uptime Kuma |
1927
| DNS and network | Pi-hole, Unbound, allowed-subnet LAN discovery |
2028
| Reverse proxy | Caddy route and upstream diagnostics |
@@ -26,155 +34,154 @@ Foxhole is early software. The default runtime is a single FastAPI process that
2634
| --- | --- | --- |
2735
| Stage 1 | Read-only default | Inspects logs, queues, containers, DNS, storage, and monitor state. Write-class tools are denied. |
2836
| Stage 2 | Confirmed writes | Narrow write tools require an explicit confirmation token before execution. |
29-
| Stage 3 | Policy-gated automation | Disabled by default. Intended for narrow remediation rules only. |
30-
31-
The default path is Stage 1. Worker diagnostics are read-only and should never perform mutations.
37+
| Stage 3 | Policy-gated automation | Disabled by default. Reserved for narrow remediation loops only. |
3238

33-
## Quick Start: Self-Hosted Stack
39+
The default path is Stage 1. Diagnostics should never mutate homelab state.
3440

35-
The included Compose stack runs the default single-process Foxhole app from the GHCR image:
41+
## Quick Start: Docker Compose
3642

37-
- Static dashboard and FastAPI backend on `127.0.0.1:8000`
38-
- In-process scheduled diagnostics
39-
- In-memory live events
40-
- SQLite durable history
41-
- Optional internal read-only Docker socket proxy
43+
The standard Compose stack pulls the production image from GHCR:
4244

43-
Redis, Celery worker, Celery beat, and Flower are not part of the default stack. They remain available only through the separate distributed Compose file for advanced installs.
45+
```text
46+
ghcr.io/jacobthree/foxhole:latest
47+
```
4448

45-
Durable history is written to `iac/compose/data/foxhole.db` on the host. Settings changed through the dashboard or API are written to `iac/compose/config/foxhole.env`. Back up both files if you care about event history, audits, incidents, check results, and integration settings.
49+
### 1. Initialize Paths And Environment
4650

4751
```bash
4852
mkdir -p iac/compose/data iac/compose/config
4953
cp iac/compose/.env.example iac/compose/config/foxhole.env
50-
$EDITOR iac/compose/config/foxhole.env
51-
docker compose -f iac/compose/docker-compose.yml up -d
5254
```
5355

54-
Open `http://127.0.0.1:8000` for the dashboard.
56+
### 2. Configure Minimum Settings
5557

56-
Enable Docker diagnostics only when you want Foxhole to inspect local containers:
58+
Edit `iac/compose/config/foxhole.env`:
5759

58-
```bash
59-
docker compose -f iac/compose/docker-compose.yml --profile docker up -d
60+
```env
61+
FOXHOLE_API_BEARER_TOKEN=change-me
62+
FOXHOLE_RUNTIME_MODE=single
63+
FOXHOLE_SCHEDULER_ENABLED=true
64+
FOXHOLE_SESSION_COOKIE_SECURE=false
6065
```
6166

62-
Then set these values in `iac/compose/config/foxhole.env` or through Settings > Integrations:
67+
Keep `FOXHOLE_SESSION_COOKIE_SECURE=false` for the default local HTTP URL. Set it to `true` when serving Foxhole behind HTTPS.
6368

64-
```env
65-
FOXHOLE_DOCKER_ENABLED=true
66-
FOXHOLE_DOCKER_SOCKET_PROXY_URL=tcp://docker-socket-proxy:2375
69+
### 3. Start Foxhole
70+
71+
```bash
72+
docker compose -f iac/compose/docker-compose.yml up -d
6773
```
6874

69-
Use the distributed Compose file only when you intentionally want separate Redis/Celery worker processes:
75+
Open the dashboard:
7076

71-
```bash
72-
docker compose -f iac/compose/docker-compose.distributed.yml up -d
77+
```text
78+
http://127.0.0.1:8000
7379
```
7480

75-
Start Flower only when debugging distributed-mode Celery:
81+
Health checks:
7682

7783
```bash
78-
docker compose -f iac/compose/docker-compose.distributed.yml --profile debug up flower
84+
curl http://127.0.0.1:8000/healthz
85+
curl -H "Authorization: Bearer $FOXHOLE_API_BEARER_TOKEN" \
86+
http://127.0.0.1:8000/readyz
7987
```
8088

81-
For contributor builds, build a local image and point Compose at it:
89+
## Optional Profiles And Configuration
90+
91+
### Docker Diagnostics
92+
93+
Docker diagnostics require the optional internal socket proxy. Start Compose with the `docker` profile:
8294

8395
```bash
84-
docker build -t foxhole:local .
85-
FOXHOLE_IMAGE=foxhole FOXHOLE_IMAGE_TAG=local docker compose -f iac/compose/docker-compose.yml up -d
96+
docker compose -f iac/compose/docker-compose.yml --profile docker up -d
8697
```
8798

88-
Minimum required setting:
99+
Then set these values in `iac/compose/config/foxhole.env` or through Settings > Integrations:
89100

90101
```env
91-
FOXHOLE_API_BEARER_TOKEN=change-me
92-
FOXHOLE_RUNTIME_MODE=single
93-
FOXHOLE_SCHEDULER_ENABLED=true
94-
FOXHOLE_SESSION_COOKIE_SECURE=false
102+
FOXHOLE_DOCKER_ENABLED=true
103+
FOXHOLE_DOCKER_SOCKET_PROXY_URL=tcp://docker-socket-proxy:2375
95104
```
96105

97-
Keep `FOXHOLE_SESSION_COOKIE_SECURE=false` for the default local HTTP URL. Set it to `true` when serving Foxhole behind HTTPS.
106+
The app has no default socket proxy URL. Docker remains incomplete until both the profile is running and the proxy URL is configured.
98107

99-
Optional chat/model settings:
108+
### LLM Configuration
100109

101110
```env
102111
FOXHOLE_LLM_PRIMARY_MODEL=agent-primary
103112
FOXHOLE_LLM_PRIMARY_API_KEY=
104113
FOXHOLE_LLM_PRIMARY_API_BASE=
114+
105115
FOXHOLE_LLM_LOCAL_MODEL=agent-local
106116
FOXHOLE_LLM_LOCAL_API_BASE=http://host.docker.internal:11434
107117
```
108118

109-
Health checks:
119+
### Distributed Mode
120+
121+
Use distributed mode only when you intentionally want Redis/Celery processes instead of the lightweight single-process runtime:
110122

111123
```bash
112-
curl http://127.0.0.1:8000/healthz
113-
curl -H "Authorization: Bearer $FOXHOLE_API_BEARER_TOKEN" \
114-
http://127.0.0.1:8000/readyz
124+
docker compose -f iac/compose/docker-compose.distributed.yml up -d
115125
```
116126

117-
Detailed Compose notes live in [docs/deployment/docker-compose.md](docs/deployment/docker-compose.md).
118-
119-
Back up `iac/compose/data/` and `iac/compose/config/` for Compose installs. For LXC or systemd installs, back up `/opt/homelab-agent/data/` and `/etc/homelab-agent/foxhole.env`. The deployment docs include stop-copy-restore commands for each path.
120-
121-
To serve Foxhole behind HTTPS, proxy only the unified app port, for example Caddy `reverse_proxy 127.0.0.1:8000`, and set `FOXHOLE_SESSION_COOKIE_SECURE=true`. Do not expose the Docker socket proxy, Redis, Celery, or Flower services.
122-
123-
## Architecture
124-
125-
Production Foxhole is intentionally small:
127+
Start Flower only when debugging distributed-mode Celery:
126128

127-
```text
128-
Browser -> FastAPI on :8000 -> static dashboard, API, scheduler, SQLite history
129+
```bash
130+
docker compose -f iac/compose/docker-compose.distributed.yml --profile debug up flower
129131
```
130132

131-
The Docker image copies the exported Next.js dashboard into `/app/ui/out` and FastAPI serves it directly. LXC and systemd installs serve the same export from `/opt/homelab-agent/ui/out` through `FOXHOLE_STATIC_UI_DIR`. In the default `single` runtime, scheduled checks run inside the app process and live events use an in-memory bus. Redis is only checked in `distributed` mode.
132-
133-
## Dashboard UI
133+
### Local Image Builds
134134

135-
The production dashboard is statically exported into the backend image and served by FastAPI. Run the Next.js UI separately only during frontend development:
135+
Contributors can build the same production image locally and point Compose at it:
136136

137137
```bash
138-
cd ui
139-
pnpm install
140-
NEXT_PUBLIC_API_URL=http://localhost:8000 pnpm dev
138+
docker build -t foxhole:local .
139+
FOXHOLE_IMAGE=foxhole FOXHOLE_IMAGE_TAG=local docker compose -f iac/compose/docker-compose.yml up -d
141140
```
142141

143-
Open `http://localhost:3000`. `NEXT_PUBLIC_API_URL` points the dev UI at the backend. Without it, the UI uses same-origin API paths for production. Use the Settings page to log in with the bearer token, then configure integrations under Settings > Integrations.
142+
## Data Persistence And Backups
143+
144+
> Critical state lives in the database path and the editable settings file. Back up both before recreating, moving, or upgrading an install.
145+
146+
| Install Type | Database And History | Settings And Secrets |
147+
| --- | --- | --- |
148+
| Docker Compose | `iac/compose/data/foxhole.db` | `iac/compose/config/foxhole.env` |
149+
| LXC or systemd | `/opt/homelab-agent/data/` | `/etc/homelab-agent/foxhole.env` |
144150

145-
The integrations page shows:
151+
The database stores events, audits, generated incidents, scheduled check results, and history. The env file stores bearer tokens, integration credentials, cookie settings, and dashboard/API-edited settings.
146152

147-
- configured, incomplete, and disabled integrations
148-
- stable capability IDs such as `containers.list` and `reverse_proxy.routes.diagnose`
149-
- read-only vs confirmation-gated tool behavior
150-
- generated integration manifest metadata and resource URIs
153+
Stop-copy-restore commands are documented in:
151154

152-
## Architecture And Security
155+
- [Docker Compose deployment](docs/deployment/docker-compose.md)
156+
- [Debian and Ubuntu deployment](docs/deployment/debian-ubuntu.md)
157+
- [Proxmox LXC deployment](docs/deployment/proxmox-lxc.md)
153158

154-
- **Default runtime:** One FastAPI process serves the dashboard, API, scheduler, event stream, and SQLite history.
155-
- **Docker socket:** Foxhole uses `tecnativa/docker-socket-proxy` only when Docker diagnostics are enabled. Stage 1 exposes read-only Docker API groups and keeps `POST=0`.
156-
- **Secrets:** API keys and tokens are represented as Pydantic secrets and redacted from readiness/config summaries.
157-
- **LLM context:** Tools return compact structured evidence by default. Raw logs require explicit bounded output modes.
158-
- **Integrations:** Tools are registered only when their integration is configured, which keeps agent context and permissions scoped to your environment.
159-
- **Manifests:** Built-in integrations expose metadata through `/integration-manifests` for future plugin and MCP adapter work.
159+
## Security Architecture
160160

161-
## Useful Endpoints
161+
- **Single exposed app:** Proxy only the unified Foxhole app port, for example Caddy `reverse_proxy 127.0.0.1:8000`.
162+
- **Docker socket boundary:** Compose uses `tecnativa/docker-socket-proxy` only when Docker diagnostics are enabled. Stage 1 exposes read-only Docker API groups and keeps `POST=0`.
163+
- **Secret redaction:** API keys and tokens are Pydantic secrets and are redacted from readiness/config summaries.
164+
- **Scoped tools:** Integrations register tools only after their required configuration is present.
165+
- **LLM context control:** Tools return compact structured evidence by default. Raw logs require explicit bounded output modes.
166+
- **Capability metadata:** Built-in integrations expose manifests through `/integration-manifests` for capability views and future MCP adapter work.
162167

163-
| Endpoint | Purpose |
164-
| --- | --- |
165-
| `GET /healthz` | Public process health |
166-
| `GET /readyz` | Authenticated readiness and redacted settings summary |
167-
| `POST /auth/login` | Validates bearer token and sets an HTTP-only browser session cookie |
168-
| `POST /chat` | Evidence-backed agent chat |
169-
| `GET /events` | Recent events |
170-
| `GET /dashboard/summary` | Dashboard control-plane summary |
171-
| `GET /capabilities` | Integration capability view |
172-
| `GET /integration-manifests` | Built-in integration manifests |
173-
| `GET /widgets/homepage` | Optional Homepage/Homarr-compatible status widget |
168+
Do not expose the Docker socket proxy, Redis, Celery, or Flower services through a reverse proxy.
174169

175-
## Homepage/Homarr Widget
170+
## API And Widget Reference
176171

177-
The widget endpoint is disabled by default and can be protected with a separate token:
172+
| Endpoint | Method | Purpose |
173+
| --- | --- | --- |
174+
| `/healthz` | `GET` | Public process/container health |
175+
| `/readyz` | `GET` | Authenticated readiness and redacted settings summary |
176+
| `/auth/login` | `POST` | Validates bearer token and sets an HTTP-only session cookie |
177+
| `/chat` | `POST` | Evidence-backed agent chat |
178+
| `/events` | `GET` | Recent events |
179+
| `/dashboard/summary` | `GET` | Dashboard control-plane summary |
180+
| `/capabilities` | `GET` | Integration capability view |
181+
| `/integration-manifests` | `GET` | Built-in integration manifests |
182+
| `/widgets/homepage` | `GET` | Optional Homepage/Homarr-compatible status widget |
183+
184+
### Homepage/Homarr Widget
178185

179186
```env
180187
FOXHOLE_WIDGET_ENABLED=true
@@ -189,17 +196,24 @@ GET /widgets/homepage?token=change-me
189196

190197
See [docs/integrations/homepage-homarr.md](docs/integrations/homepage-homarr.md).
191198

192-
## Documentation
199+
## Dashboard Development
193200

194-
- [Architecture](docs/architecture.md)
195-
- [Docker Compose deployment](docs/deployment/docker-compose.md)
196-
- [Debian and Ubuntu deployment](docs/deployment/debian-ubuntu.md)
197-
- [Proxmox LXC deployment](docs/deployment/proxmox-lxc.md)
198-
- [Proxmox permissions](docs/deployment/proxmox-permissions.md)
199-
- [Caddy integration](docs/integrations/caddy.md)
200-
- [Docker integration](docs/integrations/docker.md)
201-
- [Plex integration](docs/integrations/plex.md)
202-
- [Sonarr/Radarr integration](docs/integrations/sonarr-radarr.md)
201+
Production serves the statically exported dashboard from FastAPI. Run Next.js separately only while working on frontend code:
202+
203+
```bash
204+
cd ui
205+
pnpm install
206+
NEXT_PUBLIC_API_URL=http://localhost:8000 pnpm dev
207+
```
208+
209+
Open `http://localhost:3000`. Without `NEXT_PUBLIC_API_URL`, the UI uses same-origin API paths for the production static export.
210+
211+
Build the production static export:
212+
213+
```bash
214+
cd ui
215+
pnpm build
216+
```
203217

204218
## Development
205219

@@ -218,6 +232,18 @@ pnpm lint
218232
pnpm build
219233
```
220234

235+
## Documentation
236+
237+
- [Architecture](docs/architecture.md)
238+
- [Docker Compose deployment](docs/deployment/docker-compose.md)
239+
- [Debian and Ubuntu deployment](docs/deployment/debian-ubuntu.md)
240+
- [Proxmox LXC deployment](docs/deployment/proxmox-lxc.md)
241+
- [Proxmox permissions](docs/deployment/proxmox-permissions.md)
242+
- [Caddy integration](docs/integrations/caddy.md)
243+
- [Docker integration](docs/integrations/docker.md)
244+
- [Plex integration](docs/integrations/plex.md)
245+
- [Sonarr/Radarr integration](docs/integrations/sonarr-radarr.md)
246+
221247
## Non-Goals Right Now
222248

223249
- No broad autonomous remediation.

0 commit comments

Comments
 (0)