Move the ~22-service flat "AI Systems" group off the Main tab into a new four-tab layout (Main / AI / Infrastructure / Toolchain). The AI tab sorts the inference fleet by function into seven groups: AI - Inference gen, char-rp, char-rp-reasoning, Granite summarizer AI - Eval & Retrieval Selene, Skywork Reward, Qwen3 rerank/embed, image-bench AI - Gateways & Chat LiteLLM, Asset Engine, Gateway Chat, Open WebUI, ... AI - Speech (TTS) Chatterbox Fast, Kokoro, mOrpheus AI - Audio Tools Parakeet ASR, YT Voice Clipper AI - Image & Media ComfyUI, Arbo AI - Dormant stopped rollback seats + retired auditions Relabel each stack's homepage.group so canonical stacks/ matches the live containers on ana-ml2, ana-docker, and irv-ml1. Dormant stacks were refreshed with `docker compose up --no-start` so they carry the new label while staying stopped (compose-start rollback preserved). settings.yaml drives tab/order/ columns; services.yaml and README updated to the new scheme.
skaldsong
Wizard + reader surface for multi-agent storytelling. Single FastAPI
process serves both the SvelteKit-built SPA (static, baked into the
image) and the wizard backend. Talks to Worldtree as a Bifrost
consumer — Worldtree issues per-dispatch JWTs (post-v0.3) that
skaldsong's /bifrost endpoint verifies against the shared HS256
secret.
Server: ana-docker
URL: http://10.250.50.70:8300 (configurable via .env)
Upstream repo: vh/skaldsong
Image: gitea.phasefinal.com/vh/skaldsong:<sha> — built + pushed
by vh/skaldsong's CI on every push to main and on tag.
Path layout (on ana-docker)
| Host path | Container path | Purpose | Restic? |
|---|---|---|---|
/opt/docker/compose/skaldsong/ |
— | compose.yaml + .env | included (via /opt/docker) |
/opt/docker/conf/skaldsong/db/ |
/app/state/db |
SQLite (skaldsong-ui.db + WAL/SHM) — wizard state, story rows |
included |
/opt/docker/conf/skaldsong/runs/ |
/app/state/runs |
Per-story generation pipeline artifacts (spec, state, output, logs, manuscripts) | included |
Network model
Internal tooling, LAN-only. Container's :8000 published on host
:8300 (configurable via SKALDSONG_BIND / SKALDSONG_PORT); access
direct at http://10.250.50.70:8300. No Traefik, no TLS terminator,
no public hostname.
Skaldsong talks to two services on the LAN:
- Worldtree at
http://10.250.50.152:8080(corviduo-dev, LAN-direct from ana-docker — same subnet). - Kokoro TTS at
http://10.100.79.3:8193(irv-ml1, reached via the WireGuard tunnel on ana-wg — same path asset-engine uses).
Worldtree calls back to skaldsong's /bifrost endpoint at
http://10.250.50.70:8300 for tool-dispatch — that URL must be in
Worldtree's BIFROST_CLIENT_ALLOWED_HOSTS. Host:port changes
require a coordinated allowlist update on Worldtree-side (see
corviduo-dev README for
the docker-as-root edit pattern).
Deploy
Two paths — automated (preferred) and manual (escape hatch).
Automated (Gitea Actions, push-to-main)
vh/skaldsong ships .gitea/workflows/deploy.yaml. Push to main +
manual workflow_dispatch triggers:
- Build + push
gitea.phasefinal.com/vh/skaldsong:${{ github.sha }}and:latestto the gitea registry. - Checkout this management repo using
MGMT_REPO_TOKEN. - Run
scripts/elway ana-docker --playbook playbooks/deploy-skaldsong.yaml --var ref=${{ github.sha }}viaDEPLOY_SSH_KEY.
Three secrets required on vh/skaldsong's Actions settings:
DEPLOY_SSH_KEY— private key authorized on ana-docker for lkraven.MGMT_REPO_TOKEN— Gitea PAT withread:repositoryon this repo.REGISTRY_USER+REGISTRY_TOKEN— for the docker login step (token needswrite:packagescope).
Manual (elway from a workstation)
# Deploy a specific SHA (CI just pushed it):
scripts/elway ana-docker --playbook playbooks/deploy-skaldsong.yaml \
--var ref=<sha>
# Or pin to a release tag:
scripts/elway ana-docker --playbook playbooks/deploy-skaldsong.yaml \
--var ref=v0.1.0
Env-var contract
| Var | In compose? | In .env? |
Notes |
|---|---|---|---|
SKALDSONG_IMAGE |
✓ (image:) | ✓ | Full image URI; CI passes SHA-pin via elway --var ref=<sha> → playbook → this var. |
SKALDSONG_PORT |
✓ | ✓ | Host-side port (8300 default). Internal always 8000. |
SKALDSONG_BIND |
✓ | ✓ | Host bind address (0.0.0.0 default). |
SKALDSONG_DB_DIR |
✓ (mount) | ✓ | Host path for SQLite. |
SKALDSONG_RUNS_DIR_HOST |
✓ (mount) | ✓ | Host path for generation artifacts. |
SKALDSONG_BIFROST_JWT_KEY |
✓ (anchor) | ✓ | Shared HS256 secret w/ Worldtree's WORLDTREE_SKALDSONG_USER_KEY. Same value as WORLDTREE_TOKEN. |
SKALDSONG_HOST_BIFROST_ENDPOINT_URL |
✓ (anchor) | ✓ | URL Worldtree calls back to (must match allowlist). |
WORLDTREE_TOKEN |
✓ (anchor) | ✓ | Bearer for outbound HTTP to Worldtree. Same value as SKALDSONG_BIFROST_JWT_KEY. |
WORLDTREE_BASE_URL |
✓ (anchor) | ✓ | URL skaldsong calls Worldtree at. |
SKALDSONG_HOST_WIZARD_AGENT_ID |
✓ (anchor) | ✓ | Existing agent slot ID (skaldsong:wizard-v2). Blank burns a Heimdall quota slot on first boot. |
SKALDSONG_HOST_CORS_ORIGINS |
✓ (anchor) | ✓ | Comma-separated CORS origins. |
SKALDSONG_TTS_ENGINE |
✓ (anchor) | ✓ | kokoro (only engine in v1). |
SKALDSONG_TTS_BASE_URL |
✓ (anchor) | ✓ | Kokoro URL (WG-routed). |
&skaldsong-env anchor declares all SKALDSONG_* vars via ${VAR:-}
substitution. Same env-anchor pattern as Worldtree's &worldtree-env
(see Worldtree #175 heuristic);
new var additions must land in BOTH the .env AND the anchor.
Restart semantics
Per skaldsong's INV-006 (host CLAUDE.md): process restart marks any
running generation rows partial and never auto-resumes. Deploy
mid-run is safe — the SPA's reader treats partials like a power
outage. Cancellation of in-flight runs on deploy is acceptable for
v1.
docker compose up -d --force-recreate --pull always is the
playbook's apply step (or --pull never when called with a specific
--var ref=<sha> where the image was pre-pulled). Same kill-signal +
graceful-shutdown pattern as Worldtree.
Worldtree allowlist coordination
The SKALDSONG_HOST_BIFROST_ENDPOINT_URL value MUST be in Worldtree's
BIFROST_CLIENT_ALLOWED_HOSTS env var on corviduo-dev. As of
deploy-time the value is 10.250.50.70:8300.
If you change SKALDSONG_PORT or move skaldsong off ana-docker, the
allowlist needs a paired update on corviduo-dev. Reference: the
edit-via-docker-as-root pattern in
servers/corviduo-dev/README.md.