asset-engine: scaffold deploy stack on ana-docker
Mirrors task-board's build-on-host pattern: elway playbook clones vh/asset-engine into /opt/docker/build/, docker build, install compose + seed .env, up -d, verify /health. No registry. Internal-only tool — LAN port 8200 (bind 0.0.0.0) is primary; Traefik labels additionally route asset-engine.phasefinal.com with TLS via the anaprod cert resolver. DB and outputs are separate bind-mounts under /opt/docker/conf/asset-engine/ so outputs/ can move volumes later without touching DB state. INFERENCE_HOST defaults to 10.100.79.3 (irv-ml1 over WG). OIDC env seam is pre-allocated empty for v2.
This commit is contained in:
@@ -0,0 +1,85 @@
|
||||
# asset-engine
|
||||
|
||||
Control plane over the PFI inference fleet — FastAPI + HTMX/Shoelace
|
||||
UI that exposes the catalog at [`docs/asset-engine/services.yaml`](../../docs/asset-engine/services.yaml)
|
||||
as a web app, routes generation requests to inference hosts (irv-ml1
|
||||
over WG by default), and persists generated assets to a local SQLite
|
||||
DB + content-addressed blob store.
|
||||
|
||||
**Server:** ana-docker
|
||||
**Hostname (TLS):** `asset-engine.phasefinal.com` (TLS via Traefik / `anaprod` cert resolver)
|
||||
**LAN port:** `10.250.50.70:8200` (configurable via `.env`)
|
||||
**Upstream repo:** [vh/asset-engine](https://gitea.phasefinal.com/vh/asset-engine)
|
||||
**Image:** `asset-engine:local` — built on the host from the git repo by
|
||||
the deploy playbook. Not pulled from a registry.
|
||||
|
||||
## Deploy
|
||||
|
||||
Two paths — automated (preferred) and manual (escape hatch / first-time).
|
||||
|
||||
### Automated (Gitea Actions, push-to-main)
|
||||
|
||||
The asset-engine repo ships `.gitea/workflows/{ci,deploy}.yaml`. CI runs
|
||||
on PRs (uv sync, pytest, catalog drift check against this repo's
|
||||
`docs/asset-engine/services.yaml`); the deploy workflow runs on push to
|
||||
main and just calls the elway playbook below pinned to the triggering
|
||||
commit SHA. Drift check is a BLOCKING gate — a PR that vendors a
|
||||
services.yaml mismatched against this repo fails CI and can't merge.
|
||||
|
||||
A reference copy of the deploy workflow lives next to this README at
|
||||
[`gitea-workflow-deploy.yaml.example`](gitea-workflow-deploy.yaml.example);
|
||||
the canonical source is in the asset-engine repo. The example header
|
||||
lists the two repo secrets required (`DEPLOY_SSH_KEY`, `MGMT_REPO_TOKEN`).
|
||||
|
||||
### Manual (elway from a workstation)
|
||||
|
||||
The playbook owns the full flow: clone/update the source repo,
|
||||
`docker build`, install compose + seed .env, bring up, verify health.
|
||||
|
||||
```bash
|
||||
# First deploy (or update to latest main)
|
||||
scripts/elway ana-docker --playbook playbooks/deploy-asset-engine.yaml
|
||||
|
||||
# Pin to a specific ref (tag, branch, or commit SHA)
|
||||
scripts/elway ana-docker --playbook playbooks/deploy-asset-engine.yaml --var ref=v0.1.0
|
||||
```
|
||||
|
||||
## Path layout (on ana-docker)
|
||||
|
||||
| Host path | Container path | Purpose | Restic? |
|
||||
|---|---|---|---|
|
||||
| `/opt/docker/build/asset-engine/` | — | git checkout used as docker build context | excluded |
|
||||
| `/opt/docker/compose/asset-engine/` | — | compose.yaml + .env | included (via `/opt/docker`) |
|
||||
| `/opt/docker/conf/asset-engine/db/` | `/app/runtime/db` | SQLite (`asset_engine.db` + WAL) | **included** |
|
||||
| `/opt/docker/conf/asset-engine/outputs/` | `/app/runtime/outputs` | content-addressed blob store | **included** |
|
||||
|
||||
## Network model
|
||||
|
||||
Internal-only tool, two entry points:
|
||||
|
||||
- **LAN**, default: `http://10.250.50.70:8200` — container port 8000
|
||||
published on the host, bound to 0.0.0.0 (configurable via
|
||||
`ASSET_ENGINE_BIND` / `ASSET_ENGINE_PORT`).
|
||||
- **TLS hostname**: `https://asset-engine.phasefinal.com` — Traefik on
|
||||
ana-docker terminates TLS and forwards to the container over the
|
||||
`traefik-net` docker network on port 8000.
|
||||
|
||||
`INFERENCE_HOST` defaults to `10.100.79.3` (irv-ml1 over WG). Override
|
||||
in `.env` if the fleet's inference topology moves.
|
||||
|
||||
## Catalog drift
|
||||
|
||||
`docs/asset-engine/services.yaml` in this repo is the canonical
|
||||
catalog. The asset-engine repo vendors a copy at `data/services.yaml`
|
||||
and re-vendors via `uv run scripts/sync_catalog.py` after upstream
|
||||
changes; CI fails any PR where the vendored copy diverges from this
|
||||
one. Pattern is: edit catalog here → asset-engine re-vendors → both
|
||||
sides commit on the same merge window.
|
||||
|
||||
## Outputs directory growth
|
||||
|
||||
`outputs/` grows unbounded in v1 — `Asset.retention` exists in the
|
||||
schema but the GC sweep isn't wired yet. The plan: Beszel alert when
|
||||
`du -sh /opt/docker/conf/asset-engine/outputs` crosses ~50 GB,
|
||||
revisit the threshold once we have real growth data. Tracking issue
|
||||
in the asset-engine repo.
|
||||
Reference in New Issue
Block a user