Commit Graph
277 Commits
Author SHA1 Message Date
Frank 918fe4eaec Merge vllmScripts under llm/ (history-preserving import)
The vllmScripts repository (LLM inference fleet: serve scripts, systemd
units, env tunables, deployment runbook, research docs) is merged into
this repository. Its full history is grafted under llm/ with a
two-parent merge commit so no commit is lost.

A follow-up commit reorganizes llm/ into the repo layout:
llm/docs -> docs/LLM, llm/scripts -> scripts, llm/old -> old.
2026-08-22 15:03:03 -07:00
Frank 0746303c33 AGENTS.md: add mandatory Deletion & Trash Policy (mv to ~/.AGENTTRASH, never rm)
Explicit rule: stage deletions in a dated ~/.AGENTTRASH/YYYYMMDD-topic
directory, list sizes, and wait for user approval before purging. rm,
rm -rf, and git clean -f forbidden without explicit permission. Applies
to every host.
2026-08-22 14:38:26 -07:00
Frank c45f40a9b3 docs: reflect rollback to v3 on frank-default-large (Kairic experiment retired)
AGENTS.md topology table + runtime sections, docs/index.md deployment
diagram, docs/kairic-edge.md (retired experiment, perf summary), and
docs/ciru-activefpx-promptforge.md (active again) all restored to the
v3 reality. Remaining Kairic references are inside the retired reference
page itself.
2026-08-22 14:26:32 -07:00
Frank c60156f3c6 rollback frank-default-large to v3 CIRU ActiveFPX PromptForge (operator decision 2026-08-22)
Restores the script pair verbatim from 132e147. v3 settings: PromptForge
m2048_fused_tail1476 full-W8 views, Output-K8 draft proxy, BF16 mmproj
vision, TEMPERATURE 0.7 / TOP_P 0.95, batch 4096/4096, ctxcp 16, reasoning
on/deepseek, no-mmap. Runtime: build-promptforge llama-server + v3 model
files in /home/dank/models/CIRU-Qwen3.8-27B-ActiveFPX-v3. Kairic Edge
files remain on the machine for rollback (docs/kairic-edge.md).
2026-08-22 14:20:11 -07:00
Frank ddcd54e13f Make FASTGREEDY=1 compatible with non-greedy requests (argmax fastpath always off)
LLAMA_TARGET_GREEDY_ARGMAX_FASTPATH=0 unconditionally. FASTGREEDY=1 now
means: reasoning off, deterministic sampler defaults, compatible with
all non-greedy requests (temp != 0, penalties, reasoning budget). This
is the card's 'compatible mode' profile.
2026-08-22 13:45:57 -07:00
Frank c66273033b open-webui: reach the LLM via the host LAN IP, not the bridge gateway
The bridge gateway (10.89.3.1) lives in the rootless netns; llama-server
runs in the host netns, so the gateway refuses. 192.168.0.143:52625
reaches it through the rootless NAT (verified from the container).
Same LAN-IP pattern the doc already prescribes for the Dankserver
backend.
2026-08-22 13:44:48 -07:00
Frank 0951fc165c deploy.sh: restart caddy when the reload cannot be applied
A 'caddy reload' delivered over the admin API cannot apply a config
that disables the admin API -- the fix cannot ride the API it is meant
to enable (2026-08-22: admin off sat in the running config across
deploys). Track the reload result; on failure, restart the container
so it reads the rendered file on start.
2026-08-22 13:35:31 -07:00
Frank fe71f7516d Flip production to FASTGREEDY=1 (operator decision 2026-08-22)
Reasoning off, argmax fastpath on, deterministic sampler. The fast
greedy path rejects non-greedy requests with 400; chat clients must
send temperature 0.
2026-08-22 13:26:52 -07:00
Frank bb1ef9bfb3 caddy: keep admin on for hot reload; deploy.sh reloads after render
The Caddyfile had 'admin off', which disables Caddy's config file
watcher. Rendered Caddyfile changes never loaded until the container
was recreated, so the double-hash basicauth fix sat on disk unapplied
across deploys (2026-08-22). Admin binds to 127.0.0.1:2019 inside the
container and the port is unpublished, so nothing outside reaches it.

deploy.sh now issues an explicit 'caddy reload' (retry loop) after
'up -d', with the file watcher as backstop.
2026-08-22 13:22:01 -07:00
Frank da68b5ce1a fix: basicauth double-prefix render; open-webui off slirp4netns
basicauth (2026-08-22 incident):
- the Caddyfile template carried its own $2a$14$ prefix and deploy.sh
  substituted the full hash (prefix included), rendering an invalid
  double-prefixed hash. Every basicauth vhost rejected every password
  with 401 and Caddy logged nothing.
- template is now a bare REPLACE_WITH_HASH token; tests pin the render
  contract (no prefix in template; rendered line is exactly 'dank <hash>').

open-webui (2026-08-22 incident):
- its slirp4netns helper process died, leaving the container running
  with only 'lo' in its netns: port 3005 accepted TCP and reset every
  request, so chat served empty responses for ~2 days, unlogged.
- move to a pinned bridge network (systemd-open-webui, 10.89.3.0/24,
  gw 10.89.3.1) — no per-container helper to die.
- LLM endpoint reached via the gateway (host.containers.internal is
  slirp-only): OPENAI_API_BASE_URL=http://10.89.3.1:52625.
- add a quadlet healthcheck: /health (app) + non-loopback interface
  (network liveness; the dead-tap state leaves only 'lo').
- deploy script now copies the .network file too.
- docs updated (OpenWebUI History section, Caddy basic-auth contract).
2026-08-22 13:07:43 -07:00
Frank 7f617b9ee6 Add bench-fast-greedy.sh for A/B fast-greedy vs production testing 2026-08-22 13:03:21 -07:00
Frank f347d5336f Set FASTGREEDY=0 default in env; add deployment notes 2026-08-22 12:54:28 -07:00
Frank e0329caef8 Add FASTGREEDY mode to serve script: reasoning off + argmax fastpath on for fast-greedy bench
FASTGREEDY=1 flips the serve script to the card's default profile:
- reasoning off (no logit budget overhead)
- LLAMA_TARGET_GREEDY_ARGMAX_FASTPATH=1 (exact-Q8 GPU argmax)
- deterministic sampler (temp 0, top_p 1, top_k 0, min_p 0)

This mirrors the card's 'fast greedy (default)' benchmark config.
Production (FASTGREEDY=0) unchanged.
2026-08-22 12:54:03 -07:00
Frank 5c9ade4e7a deploy.sh: fix quoting of the cfhash label template 2026-08-22 04:16:18 -07:00
Frank e0a25415a1 deploy.sh: rebuild local images when their Containerfile hash changes
buildah can serve a stale COPY --from layer (cache keyed on stage
name), so a Containerfile edit silently produced an unchanged image.
The image now carries a cfhash label; a mismatch forces a --no-cache
rebuild.
2026-08-22 04:14:43 -07:00
Frank 7d6a285371 copy /bin/busybox.static (the -static package does not overwrite /bin/busybox) 2026-08-22 04:13:55 -07:00
Frank 824d39a29e busybox-static for healthchecks; alloy: rely on the default UI listener
- alpine's /bin/busybox is musl-dynamic and cannot execute in the
  distroless loki image (missing loader); busybox-static links in
- alloy 1.x refuses to configure the ui service from a config block;
  the default UI already listens on 127.0.0.1:12345 where the
  healthcheck probes
2026-08-22 04:09:04 -07:00
Frank dc421efea4 deploy.sh: escape the image-build loop vars for the remote string 2026-08-22 04:04:24 -07:00
Frank 1f4766f233 observability: fix alloy ui component, busybox healthchecks for loki/alloy
- alloy 1.x renamed the server component to ui; the old block failed the
  initial load and the container crash-looped
- grafana/loki is distroless and grafana/alloy lacks wget, so their
  healthchecks could never run; local images add a static busybox from
  alpine for that one command
- deploy.sh builds all three local images if missing
- tests: 3 new seams
2026-08-22 03:59:14 -07:00
Frank 816986139f observability: run as container root 0:0, not 1000:1000
Measured the rootless mapping: container root IS the invoking user
(dank, owner of the /opt data dirs); the images' default users (loki
10001, prometheus nobody, grafana 472) map to subuids that own nothing.
1000:1000 was the wrong direction.
2026-08-22 03:45:06 -07:00
Frank 8b3cd2ff79 large: batch profile flipped to the runner's qualified 2048/512 (fastest measured prefill, no decode change) 2026-08-22 03:30:58 -07:00
Frank 11a713e05d observability: run prometheus/loki/grafana as 1000:1000 (rootless uid mapping)
Container root maps to a subuid that owns nothing under /opt, so the
data-dir writes fail. Container uid 1000 is the invoking user in
rootless podman. Fixes the awk service-block seam to use regex match.
2026-08-22 03:22:50 -07:00
Frank 3c3f90e4c5 observability: run prometheus/loki/grafana as 1000:1000 (rootless uid mapping)
Container root maps to a subuid that owns nothing under /opt, so the
data-dir writes fail. Container uid 1000 is the invoking user in
rootless podman.
2026-08-22 03:19:18 -07:00
Frank 3eb29de6ca bench: add prod2048 config (runner batch sizes on chat profile); docs: ubatch 4096 results 2026-08-22 03:17:41 -07:00
Frank 765fd2902a searxng limiter: fix stale .local name in comment 2026-08-22 03:05:25 -07:00
Frank 37f05a5f9e observability configs: loki delete_request_store, prometheus targets, grafana root URL
- loki: recent releases require compactor.delete_request_store when
  retention is enabled (was crash-looping on start)
- prometheus: scrape targets carried legacy dankclaw.local names with
  URL schemes (invalid); point at published LAN ports and the gitea
  quadlet's published port instead
- grafana: GF_SERVER_ROOT_URL to the canonical HTTPS name
- tests: 3 new seams for the deployed observability configs
2026-08-22 03:04:36 -07:00
Frank bd9d75af3f large: ubatch 4096 (match v3), add --no-mmap; sync bench harness prod config 2026-08-22 03:02:16 -07:00
Frank 0f2bb636d7 bench: add Kairic A/B config harness; make v3 spec-stack harness self-contained (survives the Kairic env swap) 2026-08-22 02:53:32 -07:00
Frank 4360551938 docs: Kairic Edge reference page (build runbook, config.h gap, byte-identical rebuild, perf data); mark v3 doc retired; update topology 2026-08-22 02:51:39 -07:00
Frank d5e9c63802 deploy.sh: drop --pull=missing (podman-compose rejects it) 2026-08-22 02:51:36 -07:00
Frank 5caa2178c3 deploy.sh: extract CADDY_BASICAUTH_HASH via grep/cut, not by sourcing .env
Sourcing the .env in a set -u shell dies on the bcrypt hash's $2
expansion. grep/cut pulls the value without any shell interpretation.
2026-08-22 02:51:13 -07:00
Frank 4572a7739d Caddy: keep plex.franksdank.casa HTTP-only (not in the Porkbun account) 2026-08-22 02:44:06 -07:00
Frank 7f4ce06927 Caddy phase 2: TLS via Porkbun DNS-01 wildcard certs
- Caddyfile: drop http:// site prefixes, global acme_dns porkbun block,
  HTTPS redirects on the bare-IP and legacy vhosts
- new dankclaw/caddy/Containerfile: xcaddy build with caddy-dns/porkbun
- compose: caddy uses franksdank/caddy-porkbun:latest + Porkbun env vars
- deploy.sh: build the image on first deploy if missing
- .env.example: rename PORKBUN_API_SECRET -> PORKBUN_API_SECRET_KEY
  (the name the caddy-dns/porkbun module expects)
- tests: 7 new caddyfile/compose seams for the TLS config
2026-08-22 02:39:41 -07:00
Frank 40d50fed06 large: Kairic chat profile — reasoning on/deepseek, batch 4096/2048, preserve_thinking
Local overrides to the pinned runner for production chat:
  - --reasoning on --reasoning-format deepseek (thinking to
    message.reasoning_content, matching the retired v3 service so the
    fleet's reasoning clients work)
  - --reasoning-budget -1 (unrestricted thinking)
  - --chat-template-kwargs '{"preserve_thinking":"true"}' (preserve
    thinking tokens in the conversation history across turns)
  - batch 4096 / ubatch 2048 (larger than the runner's 2048/512; unified
    memory has headroom)

The Kairic IU4 lane (--kairic-edge) and the MTP draft fast path are
unaffected.
2026-08-22 01:03:08 -07:00
Frank 7aee1df7c3 large: disable target greedy argmax fast path for chat (Kairic)
The pinned runner sets LLAMA_TARGET_GREEDY_ARGMAX_FASTPATH=1, but the
exact-Q8 argmax fast path fails closed on any non-greedy request. The
model card's own chat instructions override sampling per request with
Qwen live values (temp 0.7, top-p 0.8, top-k 20, min-p 0,
presence_penalty 1.5), which the fast path rejects (400). Production
chat forces the fast path to 0; the Kairic IU4 lane (--kairic-edge) and
the MTP draft fast path are unaffected.
2026-08-22 00:28:01 -07:00
Frank 4c438390dd large: swap to Kairic Edge IU4 runtime (pinned tag kairic-edge-qwen38-27b-v1)
Serves jcbtc/Qwen3.8-27B-IU4-Kairic-Edge (four-artifact payload) with
the qualified pinned-runner profile: 262K ctx, 1 slot, b2048/ub512,
t16/tb32, f16 KV, 32 ctx checkpoints, 8 GiB prompt cache with idle-slot
persistence, native MTP4, deterministic sampler, reasoning off.

The serve script replicates the release pinned runner verbatim; the only
differences are safe bind vars (no bare HOST env var; HIP collision rule)
and this machine's split 7.15 SDK LD_LIBRARY_PATH layout.

Rollback: revert this commit and redeploy; v3 model files and the v3
binary are untouched.
2026-08-22 00:21:34 -07:00
Frank e9277fa8af deploy.sh: declare the per-target arrays (COMPOSE_UP, COPY_SHARED) 2026-08-21 23:17:04 -07:00
Frank 724f186414 Caddyfile: transport is a reverse_proxy subdirective (jellyfin h2c) 2026-08-21 21:50:03 -07:00
Frank 6ea490d64c deploy: sed delimiter '|' for the Caddyfile hash render (bcrypt contains '/')
Plus a regression seam that reproduces the render with a slash-bearing
hash.
2026-08-21 21:48:15 -07:00
Frank 4a679fce80 Caddy consolidation: single Caddy on dankclaw fronts both hosts
Per user direction, Caddy runs only on dankclaw. It fronts every
service on both hosts: local services by container name, quadlet
services by published LAN port, dankserver services by published LAN
port (192.168.0.235:PORT).

- dankclaw/Caddyfile: merged vhost list (was: two Caddyfiles, one per
  host). gitea's single vhost moves in from the retired gitea-caddy
  quadlet (option B). Upstreams fixed to live reality: gitea :3000,
  search :8081 (gluetun), chat :3005 (open-webui quadlet), media
  services via 192.168.0.235. Retired: llms (open-webui on dankserver
  is removed; chat is its successor), the dankserver homepage (302 to
  the shared one).
- dankserver/Caddyfile, dankclaw/gitea/Caddyfile: deleted (git rm).
- dnsmasq addn-hosts: every name -> 192.168.0.143 (the one Caddy
  host); no .235 records, no llms.
- compose.yaml: removed the openwebui/postgres/gitea services (they
  are quadlets now); caddy service mounts the rendered Caddyfile from
  /home/dank/Containers/caddy, healthcheck probes the bare-IP
  catch-all (302).
- deploy.sh: per-target logic (dankserver = pull-only, health via the
  shared Caddy at 192.168.0.143); renders CADDY_BASICAUTH_HASH from
  the host .env into the mounted Caddyfile.
- .env.example: CADDY_BASICAUTH_HASH on dankclaw; Porkbun block
  dropped from dankserver (its Caddy is gone); SEARXNG_BASE_URL to
  the flat name; stale OPENAI_* block dropped (quadlet is
  self-contained).
- tests: caddyfile.bats now asserts the single-Caddyfile invariant;
  dnsmasq.bats cross-checks vhosts -> .143 and the retired names.
2026-08-21 21:44:18 -07:00
Frank 3b9379bb5b docs: benchmark ngram-mod stacking under MTP on v3 stack (8k/16k/64k); doc CLI order does not matter 2026-08-21 20:43:47 -07:00
Frank f1074ade61 fix bench harness: derive PromptForge sidecar paths and set PROMPTFORGE_MODE; correct env sourcing 2026-08-21 20:25:49 -07:00
Frank fb49202e59 bench: add spec-stack comparison harness (MTP vs MTP+ngram-mod) for v3 CIRU stack 2026-08-21 20:25:00 -07:00
Frank 8652116cec docs: document frank-default-large v3 upgrade (Output-K8 runtime, full-W8 views, BF16 vision); update AGENTS/deploy payload sizes 2026-08-21 20:18:57 -07:00
Frank 132e1478cf frank-default-large: upgrade to CIRU ActiveFPX PromptForge v3 (Output-K8 runtime, full-W8 views, BF16 vision) 2026-08-21 20:00:31 -07:00
Frank 9c8298df05 dnsmasq: add foreground CMD to the image
The image had no command, so the container exited immediately (0).
dnsmasq also daemonizes by default; -k keeps it as PID 1.
2026-08-21 19:38:08 -07:00
Frank 577003bed1 docs: 2026-08-21 incident (distro upgrade dropped CUDA 12 runtime) + Dankserver now Ubuntu 26.04 2026-08-21 19:31:05 -07:00
Frank 1dee2b737e dnsmasq: serve config from /home/dank/Containers/dnsmasq (rootless-correct)
/opt is root-owned; the established data-location pattern (see
docs/Architecture/Storage Policy.md, open-webui quadlet) is
/home/dank/Containers/<service>.
2026-08-21 16:41:49 -07:00
Frank 55d062ea7b DNS names: flat franksdank.cloud scheme + dnsmasq LAN DNS on dankclaw
Phase 1 of the local-DNS-name work. Users type a name, not a port.

- dnsmasq quadlet on dankclaw (rootless, slirp4netns, port 53 published):
  serves the flat name scheme from addn-hosts, upstream 1.1.1.1/1.0.0.1.
  Image built from the in-repo Containerfile (localhost/dnsmasq:latest).
- Caddyfiles (both hosts): all *.dankclaw.local / *.dankserver.local vhosts
  renamed to flat <service>.franksdank.cloud. Explicit http:// site
  addresses for now; TLS (wildcard LE via DNS-01/Porkbun) lands in phase 2.
- Drift reconciliation (live /etc/caddy/Caddyfile on dankserver differs
  from the repo): added the live-only llms.franksdank.cloud vhost
  (OpenWebUI on :3000). Dropped the legacy search vhost from dankserver
  (the name belongs to dankclaw's gluetun-routed SearXNG; the legacy
  instance stays reachable at 192.168.0.235:8081).
- Homepage service links updated to the new names.
- New test seams (TDD): tests/dnsmasq.bats (quadlet boot-persistence,
  port 53, conf/record validity, Caddyfile<->addn-hosts cross-check on
  the right host IPs); caddyfile.bats naming-convention tests updated.

LAN clients get this DNS from the SURFboard G36 (DNS Relay -> statically
configured -> 192.168.0.143); the router change is a pending user step.
2026-08-21 16:31:42 -07:00
Frank 833f2365f1 env: add Porkbun API token placeholders (DNS-01 cert issuance)
Real tokens live only in the host .env files (git-ignored):
- /home/dank/serverAppConfigs/dankclaw/.env
- /home/dank/serverAppConfigs/dankserver/.env

Token is scoped to the franksdank.cloud zone (DNS read/write).
2026-08-21 16:00:16 -07:00