Commit Graph

366 Commits

Author SHA1 Message Date
vh 8f6c364f47 cosyvoice: warn that \instruct\ is Chinese-only; XML tags for EN
Verified empirically (gitea #7): the neosun wrapper's \`instruct\`
field routes through CosyVoice's inference_instruct2 which expects
a Chinese template. English directives produce Chinese-phonemed
speech of the directive itself — the model is stuck in Chinese
context regardless of the directive language.

XML inline tags (<angry>, <sad>, etc.) bypass that path entirely
and work cleanly for English emotion control.

README updated:
  - Added Gotcha section entry explaining the instruct trap with
    the specific failure mode and the byte-identical-response
    evidence
  - Smoke-test recipes (steps 4 + 5) reworked to use <angry>...</angry>
    in the input instead of an English instruct value
  - "Emotion / style control" table now marks instruct as Chinese-
    only with ⚠️ and XML tags as 
2026-04-24 16:45:19 -07:00
vh 9c20e42215 task-board: add stack + elway deploy playbook
stacks/task-board/compose.yaml + .env.example describe the runtime —
image tag is task-board:local (built on the host), 7878 on host maps
to 7878 in container, SQLite lives at /opt/docker/conf/task-board/data/
(bind mount, uid 1000 friendly), homepage auto-card labels under
Toolchain group, on traefik-net like the rest of the fleet.

playbooks/deploy-task-board.yaml is the first real elway playbook —
exercises everything we built tier-1 + tier-2 idempotency for:

  - `creates:` on mkdir + first-time clone + compose dir + data dir
  - `when:` to chown /opt/docker/build only if it came up root-owned
  - `when:` to seed .env only if one doesn't already exist (never
    clobbers user edits on rerun)
  - `changed_when:` on the `git reset --hard` step so repeat runs
    against the same ref report `ok` instead of `changed`
  - `changed_when: "false"` on every verify step (they attest, not
    change)
  - `upload:` with mode for compose.yaml + .env

Post-up the playbook polls /api/health for 30s before handing off to
the verify phase, so verification doesn't race the healthcheck's
start_period. Verify covers: /api/health 200, /api/tasks shape, /mcp
reachable, container on traefik-net.

Prereqs documented in the playbook header: Docker + compose plugin,
traefik-net network, git SSH access to gitea from the target host.
2026-04-24 14:26:42 -07:00
vh 04884742e2 cosyvoice: rewrite README smoke test + document gotchas
The original smoke-test curl used voice="default" which doesn't
exist — the neosun wrapper ships zero preset voices, and the
built-in SFT speakers (中文男/女 etc.) are not surfaced. Calling
/v1/audio/speech with any unregistered voice returns a 400 whose
JSON body curl happily writes into the .wav (124-byte phantom).

Replaced the smoke test with the full clone → synthesize flow and
added a gotchas section covering:
  - No default voice; /v1/voices/create is mandatory
  - Reference audio ≤30s (frontend asserts; longer clips 500 at
    synthesis time, not at upload)
  - Providing an explicit transcript beats the auto-ASR fallback
  - voice_id is the handle, not name
  - Both cosyvoice-v3 and cosyvoice-v2 ship in the image

Also documented streaming: available via /api/tts with stream=true
(~150ms TTFB), NOT on /v1/audio/speech. Clarified field-name
differences between the OpenAI-compat and native endpoints in a
table. No WebSocket / SSE in this wrapper despite upstream support.
2026-04-24 00:28:15 -07:00
vh 01c5380059 parakeet: rewrite on sherpa-onnx; own the wrapper end-to-end
The Shadowfita FastAPI wrapper hit two unfixed upstream bugs on the
first real /transcribe call — chunker return-shape mismatch (open
issue #16) and a `torchaudio.tensor` that doesn't exist (open #10).
Rather than babysit someone else's half-tested code, switched to
sherpa-onnx with the prebuilt int8 Parakeet-TDT tarball from k2-fsa,
and wrote our own ~60-line FastAPI wrapper.

Moving parts now owned in-tree:
  Dockerfile      CUDA 12.8 + cuDNN 9 runtime base, installs
                  sherpa-onnx==1.12.39+cuda12.cudnn9 + fastapi +
                  soundfile + libasound2 (sherpa-onnx links to ALSA
                  at load time even when we never touch a mic).
  app.py          OfflineRecognizer.from_transducer() once at startup;
                  /transcribe and /v1/audio/transcriptions both accept
                  multipart uploads and return {"text": ...}.
  entrypoint.sh   Idempotent model download to /models on first run
                  (~400 MB int8 tarball), then exec uvicorn.

Smoke test: 0.wav (bundled in the tarball, The House of the Seven
Gables excerpt) transcribes cleanly in ~1.2s on GPU.

PARAKEET_MODEL_URL in .env lets you swap to the v3 (25-language)
tarball without touching any other files. Wipe *.onnx + tokens.txt
from the models dir and the entrypoint re-downloads.
2026-04-24 00:18:45 -07:00
vh 1a67370138 parakeet + cosyvoice: add stacks + deploy to irv-ml1
Two new speech stacks on irv-ml1, both on the /worktank/<stack>/
pattern, no tnet (irv-ml1 is local-endpoints-only for now).

parakeet — ASR via Shadowfita/parakeet-tdt-0.6b-v2-fastapi:
  - docker buildx git context pinned to SHA 31c5652; no source
    vendored. Rebuild on SHA bump.
  - GPU-capable FastAPI + Silero VAD + WS streaming.
  - API: POST /transcribe, WS /ws/transcribe, GET /healthz. Not the
    literal OpenAI `/v1/audio/transcriptions` path — note in README.
  - HF cache at /worktank/parakeet/models/ (excluded from restic).
  - Build ~158s first time; steady-state start ~40s.

cosyvoice — TTS via neosun/cosyvoice:v1.3.2 shipping
Fun-CosyVoice3-0.5B-2512 (CosyVoice 3, chosen over v2 for the
expanded 5,000-hour instruction-following data covering emotions,
speed, tones, dialects, accents, role-playing; ~150ms streaming
TTFB matches v2). API: /v1/audio/speech (OpenAI drop-in),
/v1/voices/create (cloning), /health.
  - Host port 8190 (container 8188; host 8188 already taken by comfyui).
  - /worktank/cosyvoice/{voices,input,output}/; voices include in
    restic (precious — reproducing a clone needs the original ref
    audio), input+output excluded (scratch).
  - Model weights (~2-3 GB) live inside image layer; re-download on
    tag bump, persist across `compose up -d`.

Both healthy on first deploy.
2026-04-23 23:40:36 -07:00
vh 06476745f1 comfyui: add stack + deploy to irv-ml1
New stack mirroring PFI convention (stacks/comfyui/) using
mmartial/comfyui-nvidia-docker:ubuntu24_cuda12.8-20260312. Both GPUs
exposed, pinned to CUDA 12.8 to match the host's 570.x driver and the
native cuda-toolkit already in place.

Layout — single tree under /worktank/comfyui/ (462G dedicated, 1%
used pre-deploy):
  - basedir/  → /basedir   user state (models, workflows, custom_nodes,
                           input, output); owned 1000:1000 so external
                           tools can edit workflow JSON directly.
  - run/      → /comfy/mnt  ComfyUI source + venv + pip cache (~7.8G
                           after bootstrap). Bind mount instead of
                           named volume — the image refuses to chown
                           mounted paths at startup, so keeping this
                           lkraven-owned avoids the sudo dance.

servers/irv-ml1/README.md refreshed: Docker upgraded to 29.4.1 with
traefik-net in place; dockge + beszel-agent + dozzle-agent already
present; /storetank dropped 92% → 64%; restic coverage to
rest-server-nh3 is operational (not "currently none" as prior text).
2026-04-23 22:56:21 -07:00
vh 58f2a22966 llama-swap: pin qwen3.5-9b + qwen3.6-35-a3b as a coexistence group
Adds a new `pinned` group with swap: false (models coexist in VRAM),
exclusive: false (group shares with other groups), persistent: true
(never unload). Each member also gets ttl: 0 so the per-model
idle-timeout can't drop them either — belt + suspenders.

Pair is currently qwen3.5-9b (~6 GB Q4) + qwen3.6-35-a3b (~29 GB Q6).
Plus the 128K KV caches, roughly 50-60 GB VRAM resident. Appropriate
for an A6000/H100-class card; verify fit after deploy.

Committed as a canonical change; push + restart still needed on
ana-ml2.
2026-04-22 09:05:19 -07:00
vh f5cc60bcfc docs: document rest-server-ana data layout + repo-recreate flow
rest-server-ana README now describes the /mnt/backup/restic/repo/
top-level NFS mount and its three per-site subdirs:

  ana/ — live data served by this rest-server (per-host repos +
         .htpasswd) — what DATA_DIR points at
  esh/ — mirror destination for ESH-site backups (pending)
  nh3/ — mirror destination for NH3 Synology's tree (pending)

ana-ml2 README gains a proper "Recreating the repo" section with the
correct /mnt/backup/restic/repo/ana/ana-ml2/ path for wiping the old
repo after a lost passphrase, and two paths for regenerating keys:

  - interactive: type a user-generated passphrase at restic's init
    prompt, then install it into /etc/restic/password via `cat > file`
    + Ctrl-D (no shell history or transcript exposure)
  - scripted: openssl rand -base64 48, passphrase prints once and must
    be captured into the password manager immediately

Cross-site replication snippet in rest-server-ana README updated to
use the unified /mnt/backup/restic/repo/{esh,nh3}/ destinations
instead of the earlier restic-mirror-*/ staging paths.
2026-04-20 23:26:17 -07:00
vh dc8faaacc0 homepage: polish pass (C)
services.yaml:
- ANA-Firewall: href + siteMonitor both point at the IP now (was href
  to FQDN but siteMonitor to IP — inconsistent)
- PFI-VM-Docker, NH3-SW1, NH3-VM-Docker, ESH-VM-Docker: upgrade from
  `ping:` to `siteMonitor:` against the href URL so the up/down dot
  reflects whether the web UI actually responds, not just ICMP

dockge canonical:
- icon sh-dockge.png (was si-portainer — wrong project). Applies to all
  five fleet Dockge instances once their compose files are redeployed.

Per-group colors investigated but not supported by homepage (only site-
wide `color:` exists); skipped.
2026-04-20 22:55:51 -07:00
vh 879bea25e4 calibre-web-automated: fix healthcheck (curl, not wget)
CWA image ships curl and busybox nc but no wget, so the initial
healthcheck wedged the container in unhealthy state. Swap to curl -fsS
hitting the login page; compose-time substitution of CWA_PORT keeps
custom port overrides working.
2026-04-20 22:28:30 -07:00
vh dfdabd1d02 calibre: replace with Calibre-Web-Automated on esh-docker-vm
Retire the linuxserver.io calibre + calibre-web pair. CWA
(crocodilestick/calibre-web-automated) is an all-in-one: combined web UI
with Calibre backend, auto-ingest via drop folder, scheduled metadata
maintenance — single container on :8083.

- Reuses the existing library at /mnt/books/calibre/calibre_library
  (NFS) and the existing calibre-web config at /opt/docker/conf/calibre-web,
  so user accounts and the book catalogue carry over.
- Requires NETWORK_SHARE_MODE=true (library is on NFS; SQLite WAL would
  corrupt otherwise).
- New drop-zone at /mnt/books/calibre/ingest; files placed there are
  ingested into the library and then removed.
- Loses the LSIO desktop Calibre GUI (ports 8082/8181/8281) — run
  Calibre locally if you need the desktop UI.

Old compose dirs (/opt/docker/compose/{calibre,calibre-web}) removed on
esh-docker-vm; old images can be pruned at leisure.
2026-04-20 22:14:38 -07:00
vh 8d6921cb75 llama-swap: add Qwen3.6 35B-A3B stock + swap abliterated, 128K ctx
- New: qwen3.6-35-a3b using -hf unsloth/Qwen3.6-35B-A3B-GGUF:UD-Q6_K_XL
  (~29 GB weights, thinking on, KB Qwen sampler defaults).
- Swap: qwen3.6-35-a3b-abliterated from IIEleven11 Heretic Q8_0 to
  mradermacher/Qwen3.6-35B-A3B-abliterated-i1-GGUF:i1-Q6_K (already in
  the /hfcache on ana-ml2; ~27 GB).
- Context: bumped both Qwen 3.6 entries 32768 -> 131072.
2026-04-20 22:14:26 -07:00
vh 0be8de8ab0 fleet: register vm-esh-nas as 5th Docker host + canonical dockge stack
vm-esh-nas (10.0.50.154) is a NAS-adjacent Docker VM on the esh-pve-nas
hypervisor. Runs filezilla (port 5800), dockge, beszel-agent, dozzle-agent
with /mnt/{share,music,books,media} NFS-mounted from 10.0.50.50.
Use this host when a stack needs direct NFS mounts to the ESH NAS shares.

Canonicalize dockge as stacks/dockge/ — single compose used on all five
Docker hosts with per-host DOCKGE_HOST_LABEL/DOCKGE_HOST_IP in .env so
each card on the homepage points at its own instance. Labeled
homepage.group=Service Networking.

Beszel + Dozzle agent dirs also renamed to beszel-agent-<site> /
dozzle-agent-<site> pattern across the fleet for consistency.
2026-04-20 22:14:13 -07:00
vh 2be296ffa0 homepage: function-first layout + fleet label sweep
Reorganize the gethomepage dashboard from site-based (PFI-ANA, ESH, NH3)
to function-first grouping (Monitoring, AI Systems, Apps, Media, Games,
Infra-<site>, Service Networking). Canonical config now tracked in
configs/homepage/ with Plex/Jellyfin widget keys moved to env
substitution.

Label sweep across fleet compose files:
  - beszel, dozzle, backrest -> Monitoring
  - rest-server-ana -> Service Networking

Healthcheck fixes (previous wget/curl paths broke on distroless +
--private-repos 401):
  - beszel hub:    /beszel health --url ...
  - beszel agent:  /agent health (newly added)
  - rest-server:   nc -z localhost 8000 (TCP probe)

Group name originally "Wiring / Plumbing" collapsed to single-word group
on homepage's parser; renamed to "Service Networking" everywhere.
2026-04-20 22:14:00 -07:00
vh f6b0e2b22f Correct Ana-side NAS identity: Debian 12, not TrueNAS
Network probes (no web admin, Debian SSH banner, only file-server ports
open) show 10.250.50.50 is vanilla Debian 12 with hand-configured NFS/SMB,
reprovisioned from the original TrueNAS SCALE install. Update stack
comments, README storage notes, Backrest description, proxmox-vms.md
entry for VM 100, and the restic configs intro to match.

Cross-site sync plan simplifies to plain rsync over SSH on both sides —
no appliance-specific tooling needed.
2026-04-20 14:36:07 -07:00
vh e376d0aec9 Initial commit: PFI fleet inventory, stacks, tooling, and backup pipeline
Captures the full workspace state built up to this point:

  - CLAUDE.md + README.md describing conventions and the four-host fleet
    (ana-ml2, ana-docker, nh3-docker, esh-docker-vm).
  - Per-host notes under servers/<host>/ with ssh-target fallback files
    and latest system-details snapshots (two in-compose credential leaks
    scrubbed; the upstream compose files still need to move those to .env).
  - scripts/: server_inspect.sh (read-only remote diagnostic),
    refresh-server-info.sh (dir-driven discovery + snapshot capture with
    validation warnings), add-host.sh, sync-stacks.sh (pull
    compose/conf trees), deploy-stack.sh (push with per-file diff + prompt).
  - stacks/: canonical compose for backrest, beszel, dozzle, llama-swap,
    rest-server-ana, rest-server-nh3, vllm-qwen3, plus the retired
    infinity reference. All use the .env-driven + traefik-net + homepage
    label pattern.
  - configs/restic/ana-docker/: first resticprofile config + pre-backup
    hook (Synapse pg_dump, Seafile mysqldump, Vaultwarden SQLite); templates
    for the other three hosts to come.
  - docs/pfi/: general infrastructure reference carried over.
  - .gitignore excludes .env, stacks-mirror/, and assorted secret/state
    filenames to prevent re-leaks on later commits.
2026-04-20 14:29:48 -07:00