- Python 97.1%
- Shell 1.8%
- Dockerfile 1.1%
| Filename | Latest commit message | Latest commit date |
|---|---|---|
| .forgejo/workflows | ||
| docs | ||
| fabric | ||
| tests | ||
| .dockerignore | ||
| .gitignore | ||
| Dockerfile | ||
| README.md | ||
HomelabFabric
The AI Operations Fabric: a small, dependency-light toolkit for sending bounded, reviewable jobs to local worker hosts and tracking their results.
fabric/agent_runner.py: validates job specs against a worker host catalog and runs them through ashellorsshbackend, writing a run directory (job.json,status.json,notes.md, logs, declared outputs).fabric/ai_fabric.py: dashboard and API server. Indexes run artifacts into SQLite, tracks the worker registry, and serves the web UI.fabric/ai_fabric_dispatch.py: dashboard-triggered dispatch with worker-pool selection and per-group job authorization.fabric/ai_fabric_mcp.py: MCP server that lets coding agents list, validate, run and publish jobs.fabric/draft_job_spec.py: drafts new job specs with a local Ollama model.
Design notes live in docs/ai-ops-fabric.md and
docs/local-agent-runner-design.md.
Consumer contract
Fabric is generic. The jobs it runs and the hosts it runs them on belong to the consuming repository, which is expected to provide:
scripts/agents/agent_runner.py: the dispatcher, MCP server and job specs invoke the runner at this path inside the consumer's checkout.examples/agent-jobs/*.json: job specs.examples/agent-hosts/<name>.json: the worker host catalog.
The homelab repository is the
primary consumer. It vendors a tagged release of fabric/*.py into
scripts/agents/ with scripts/sync_fabric.sh, and its Ansible roles deploy
from that pinned copy.
Container image
The dashboard (ai_fabric.py serve) ships as a multi-arch (linux/amd64,
linux/arm64) image built by .forgejo/workflows/build.yml:
git.scruffydude.net/scruffydude/homelab-fabric
| Tag | Pushed on |
|---|---|
:<short-sha> |
every build |
:latest |
pushes to main |
:vX.Y.Z |
pushing a v* tag |
Pull requests run the tests only; images are built after the tests pass on a
push or manual workflow_dispatch. The workflow needs a REGISTRY_TOKEN repo
Actions secret (a scruffydude access token with write:package) and a
runner job image that has the docker buildx plugin.
Mounts
| Path | Mode | Contents |
|---|---|---|
/data |
rw | fabric.sqlite3, agent-runs/, and worker-registry.json. Seed the registry from the consumer's examples/agent-hosts/<name>.json before first start; the server exits if it is missing. |
/repo |
ro | Consumer checkout: scripts/agents/agent_runner.py, examples/agent-jobs/, examples/agent-hosts/. Dispatch runs /repo/scripts/agents/agent_runner.py with /repo as its working directory. |
/root/.ssh |
ro | Dispatch key (id_ed25519) and known_hosts for SSH workers. |
Environment
serve reads its defaults from these variables; explicit flags passed after
serve override them. The image sets them to the values below, so it runs with
no extra configuration given the mounts above. Outside the image the defaults
are the ones in ai_fabric.py serve --help.
| Variable | Flag | Image default |
|---|---|---|
AI_FABRIC_HOST |
--host |
0.0.0.0 |
AI_FABRIC_PORT |
--port |
8765 |
AI_FABRIC_DB |
--db |
/data/fabric.sqlite3 |
AI_FABRIC_ARTIFACT_ROOT |
--artifact-root |
/data/agent-runs |
AI_FABRIC_HOST_CONFIG |
--host-config |
/data/worker-registry.json |
AI_FABRIC_JOB_DIR |
--job-dir |
/repo/examples/agent-jobs |
AI_FABRIC_REPO_ROOT |
--repo-root |
/repo |
AI_FABRIC_IMPORT_BEFORE_SERVE |
--[no-]import-before-serve |
true |
AI_FABRIC_IMPORT_INTERVAL |
--import-interval |
15 |
AI_FABRIC_COST_PER_MILLION_TOKENS |
--cost-per-million-tokens |
10 |
The entrypoint is python3 /app/ai_fabric.py and the default command is
serve, so other subcommands work too, e.g.
docker run --rm -v ...:/data homelab-fabric summary.
The image exposes port 8765 and has a HEALTHCHECK that requests
/api/summary with Remote-Groups: admins. That endpoint is admin-only and
Authelia normally supplies the header.
docker run -d --init -p 8765:8765 \
-v /srv/ai-fabric/data:/data \
-v /srv/ai-fabric/workspace:/repo:ro \
-v /srv/ai-fabric/ssh:/root/.ssh:ro \
git.scruffydude.net/scruffydude/homelab-fabric:latest
tests/smoke_image.sh IMAGE starts an image against tests/fixtures and
checks that it reports healthy and serves /api/summary and /api/jobs.
Development
Python 3.10+ standard library only (tests use pytest).
pytest tests/ -v
Releasing
Releases are cut by pushing a v* tag: git tag -a vX.Y.Z, then
git push origin vX.Y.Z. The build workflow publishes
homelab-fabric:vX.Y.Z for that commit. Then in homelab run
scripts/sync_fabric.sh vX.Y.Z to update the vendored copy, point the
deployment at the new image tag, commit, and deploy.