Commit Graph
27 Commits
Author SHA1 Message Date
Frank 49e8dfff66 docs: the vault and AGENTS.md describe two Dankclaw endpoints
halogen-flash-server is ACTIVE again with its 2026-09-16 measured ledger (budget
33.5 GiB against a need of 27.2 — no clamp — and 14.7 GiB left for everything
else), ik_llama.cpp is retired with its measurements kept as the record of why,
and the new frank-small runbook covers the -mtp file, the 64 KiB/token KV
arithmetic, the MTP contract, and the reasoning_effort trap that cost me every
subagent on the endpoint.

AGENTS.md: topology, Active Services, runbook index, and three new llama.cpp
lessons (MTP is a property of the file; --jinja is what `tools` needs; a model's
template can reject the harness's thinking level). Three pre-existing defects
found while editing it: a truncated sentence mid-file, a harness path that does
not exist on either server, and the benchmarking stop/mask recipe still calling
frank-large a root unit.

Truthfulness notes worth keeping: the co-tenant stall NOTE prints again, so the
claim that it "no longer prints" is gone and the three observed block counts are
recorded instead of a guessed threshold; and the Observability page says out
loud why frank-large has no scrape job rather than leaving a silent absence.
2026-09-16 14:52:51 -07:00
Frank f134cc8876 docs+units: fix every claim my own changes made false
Retiring dankclaw/compose.yaml and adding alert rules invalidated claims across
the repo, including in the rule file agents read first. Clean cutover includes
the prose.

**Tests that had gone hollow.** Four assertions grepped dankclaw/compose.yaml
for a service name. With the file gone they passed by *absence* — a gate that
can no longer fail. Each now asserts the real invariant ("no dankclaw compose
file competes with the quadlet units") and keeps a live check for a re-added
entry, so it still fails when one appears: verified by recreating a compose file
with a comfyui service and watching three tests go red, then removing it.

**AGENTS.md, which was wrong about ComfyUI.** It said ComfyUI runs CPU-only
("no ROCm wheels for gfx1151, CUDA images wrong"). That was true in the
compose era and is false now: the restored unit runs with /dev/kfd + /dev/dri and
must NOT pass --cpu. An agent trusting the rule file would have re-broken it.
Also corrected: the observability paragraph ("RUNNING BUT UNCONFIGURED, no
datasource, no rules" — all three have been configured since 2026-09-16), the
Active runbook row that still named halogen for frank-large, halogen's absence
from the Retired table, the benchmark policy naming halogen's harness, and the
seam list.

**Unit and page claims.** prometheus.container said "no alerting rules anywhere
in this stack"; node-exporter.container said Dankserver runs from its compose
stack; Prometheus.md documented three jobs as working (they scrape HTML: they
can never report up) and said no dashboard existed; index.md and the three
authentik service pages pointed at the retired file; Authentik.md's upgrade
instruction told you to bump an image tag in it.

One bad edit of my own on the way (a stale line number clobbered a See Also
entry in Prometheus.md) — caught by reading back, fixed, and the vault link
checker now proves the cross-references hold.
2026-09-16 07:46:23 -07:00
Frank 80a070d71b homepage: three cards could never be green, and one of them was lying
The board showed mariadb, valkey and Postgres as "down". None of them is down:
the checker runs on Dankclaw and can reach that host's loopback, its container
names, and published LAN addresses — while all three cards probe
container-internal database ports (192.168.0.235:3306, 127.0.0.1:6379/:5432).
They were red by construction, which is how a status board stops being read.
Publishing a database port on the LAN to make a badge green is not a trade this
fleet makes, so they are wip with the reason in their description, and the apps
that front them carry the status. Gluetun (WireGuard, UDP) was the pre-existing
example of the same call.

The rule is now written down in the Homepage doc: a card must be probeable from
the monitor's host or be wip. That is the same lesson as the Prometheus jobs
that scrape HTML pages and can never report up — an always-red signal teaches
the operator to ignore the surface it lives on.
2026-09-16 07:36:11 -07:00
Frank 06d3502a2b docs: ComfyUI is a unit now, and three scrape jobs can never be green
ComfyUI's page described a compose service and a systemd unit that shelled out
to `podman compose up`. It now documents the Quadlet, the keep-groups + udev
mechanism (verified inside the running container: torch sees Radeon 8060S), the
9,146-restart incident that forced the move, and the trap that caused it — a
stale container outlives the compose edit that should have replaced it.

The observability page gains the audit result: four jobs read "down" and three
of them always will, because they scrape HTML pages or a /metrics that does not
exist. The page names each error, says plainly that none is an outage, and
refuses the tempting fix (deleting the job makes an absent scrape look like a
healthy one) in favour of the remedy it already recommended: a blackbox exporter
in probe mode, and Gitea's metrics enabled or the job repointed.
2026-09-16 07:17:59 -07:00
Frank d8835e69c6 docs: six observability units across two hosts, and what the reboot cost
The page said "all five are rootless Quadlet units on Dankclaw", which stopped
being true when Dankserver's node-exporter was restored to a unit. It now names
both hosts and both deployments, records why the second one happened (the same
compose-only reboot argument, a day and a half of missing host metrics, and a
wildcard bind), and states the exposure rule for a two-listener fleet with the
`ss` evidence that the wildcard is gone.
2026-09-16 07:09:55 -07:00
Frank 823814920b docs: record the alerting rules and what they still cannot do
Both pages claimed there was no alerting; there are six rules now, so they say
which rules exist, that promtool and /api/v1/rules both confirm them, and — in
the same breath — that no rule reaches a person, because this stack has no
Alertmanager and no contact point. The dashboard's ALERTS panel is named as the
only place an alert becomes visible without opening Prometheus.
2026-09-16 06:51:23 -07:00
Frank c272407e6e docs: observability state after the Grafana provisioning
The page said Grafana has zero datasources and zero dashboards; that is now
false, so it says what exists (Prometheus datasource, LLM fleet dashboard), how
it was verified (the API — a provisioned dashboard does not show up in the
legacy dashboard table on this Grafana version, which is a trap worth recording)
and what is still missing (nothing alerted on, Loki unread, correlation manual).
The section heading drops "UNCONFIGURED" because it no longer is, entirely.
2026-09-16 06:42:24 -07:00
Frank 3037240f4f docs: point the frank-medium runbook and observability page at the new scrape
The capacity work in this runbook was done with ad-hoc probes; the same signals
now have history in Prometheus, so the page says which series to watch and
admits the honest gap — this stack has no alerting, so a saturated pool shows up
on a graph after the fact rather than paging anyone.
2026-09-16 06:37:39 -07:00
Frank 701ab14f60 docs(observability): record the quadlet cutover, the exposure posture, and the unconfigured state
Rewrites the [[Observability]] umbrella page and the five component pages for
what is actually deployed: rootless Quadlet units instead of compose services,
the loopback-only publish posture (node-exporter's LAN binding explained), the
loki healthcheck living in its image because the image has no shell, and the
Home=/root trap that killed the first grafana start.

Adds the note that matters most to a reader: the stack is installed, healthy
and UNCONFIGURED. Grafana reports zero datasources and zero dashboards with an
empty provisioning directory; Prometheus has no rule files and no Alertmanager;
Loki is configured but has no reader; node-exporter runs its default
collectors. Alloy is the only configured piece. Metrics and logs are collected
and retained, and nothing is visualized or alerted on.

AGENTS.md's boot-persistence gap note is replaced by the resolution.
2026-09-11 16:10:27 -07:00
Frank 8212d4451a docs: rename frank-default-large/small/sightsound to frank-large/small/npu across vault
Mechanical identity rename across the knowledge base, AGENTS.md, README, the
hermes config example, and homepage services.json. No behavior change; served
aliases on the LLM endpoints change with the deploy of commit 69f87c8.
2026-09-03 16:17:14 -07:00
Frank 1e491fa69f docs(hermes,dns): document the new internal-only exposure surface
Post-change doc reconciliation for the hermes vhosts + DNS deletion batch:

- Hermes-Dashboard.md: access is now the hermesadmin.franksdank.cloud vhost
  (direct Caddy proxy to 192.168.0.143:9119, no guard chain — exempt because the
  dashboard enforces its own basic-auth login), plus the raw LAN port. The old
  text claimed an Authentik-guarded public vhost, which was decommissioned.
- Hermes-WebUI.md: description updated — the webui is now also reachable via the
  unguarded hermes.franksdank.cloud vhost (its own password auth is the gate).
- LAN-DNS.md: "add a name in two places" corrected to a two-or-three-step
  decision; internal-only names (prometheus/loki/grafana/seerr) deliberately get
  no public A record and resolve on the LAN only, and DNS-01 issuance is
  unaffected because the challenge is a TXT record in the same zone.
- Seerr.md: DNS row corrected — addn-hosts only since 2026-09-02; NXDOMAIN on WAN.
- hermes-dashboard.container: unit comment no longer claims Authentik termination.

No behavior change in this commit; tests 233/233 green (docs-completeness seam included).
2026-09-02 18:57:38 -07:00
Frank 54239294b7 authentik: require flows + application on proxy providers; harden SSO e2e
The loki/grafana/seerr proxy providers were script-provisioned with no
flows and no Application: null flows made the embedded outpost's Rust
deserializer reject the whole config (all guarded vhosts down after any
outpost reload), and the missing apps bounced post-login to authentik's
user UI instead of the app. Backfilled both live; documented the two
provisioning rules and updated the provider inventory. SSO e2e now
asserts the app landing (pathname leaves /if/, no IdP markers in body)
instead of only the hostname.
2026-09-01 18:55:44 -07:00
Frank ffae9b5e21 qBittorrent pinned to 4.6.7; all five download clients live-verified
- qB 5.x's 204 login breaks Readarr's retired client at runtime; 4.6.7 answers
  legacy 200+Ok. Pin recorded in the unit and documented.
- Prowlarr download client created via schema template; all five clients test
  200 through the podman gateway.
- PBKDF2 gotcha: qB 5.x conf rewrite left a hash 4.6.7 rejects; fresh rewrite
  of the same line restored login.
- E2E: torrent through the Panama tunnel at ~17 MB/s, completed into Finished
  Torrents, deleted with data.
2026-09-01 18:10:32 -07:00
Frank ea0bba3023 docs(authentik): outpost claim-cache gotcha (proxysession) + Containers data paths 2026-09-01 17:43:15 -07:00
Frank 00b7eb75d4 docs: Anubis v1.27.0 — domain-wide cookie, persistent key, new gotchas
- Facts table: image pin, COOKIE_DOMAIN, persistent ED25519 key via host
  env file; restarts no longer invalidate solved challenges.
- Gotcha 8: X-Real-Ip mandatory at v1.27+ (500 without; chain sets it).
- Gotcha 9: DENY renders error-styled page at HTTP 200 — probe bodies,
  not statuses.
- Verify live: probe www (apex 308s), version-marker grep, body-based
  deny check. All commands executed live before commit.
2026-09-01 17:13:51 -07:00
Frank 94d9d249a1 docs: FrankBook-Pro active-tunnel reality (PA-12, 6881 retirement, qB wiring + save-path convention) 2026-09-01 16:32:16 -07:00
Frank 3094ffa746 docs: identify WG endpoint as ProtonVPN Seattle; Mac gate is a second dashboard WG config 2026-09-01 15:58:22 -07:00
Frank 2d06be876f docs: correct Jellyfin admin-password claim (archive OCR corruption); prepare Mac WG peer 2026-09-01 15:53:13 -07:00
Frank 6a67a9067f docs: Jellyfin LDAP-Auth integration (outpost + plugin) and authentik LDAP rules 2026-09-01 15:43:04 -07:00
Frank b6be6d3da6 docs: FrankBook-Pro page + 2026-09-01 log
Document the Mac *arr/qBittorrent stack (VM placement, gluetun credential
gate, socat LaunchAgents, PBKDF2 qB seed) and log the day: dankserver
recovery + full quadlet cutover of the six media services, the frankbook
skip-propagation/PBKDF2 handler fix, the 7-service frankbook deploy, and
the jellyfin GPU-parity finding.
2026-09-01 14:32:57 -07:00
Frank 9d678122d7 docs: grafana OAuth2-RP contract + authentik fork quirks (live-verified 2026-08-31)
Token exchange chain verified end-to-end in-process on the live provider
(pk 9): authorize -> ORM-minted code -> form-encoded token exchange with
Basic client auth -> userinfo. Key findings documented:
- Application row + grant_types must exist before authorize can complete
- token endpoint consumes form-encoded bodies only (JSON body => no
  grant_type parsed -> unsupported_grant_type); client auth is Basic-only
- PropertyMappingEvaluator.evaluate(*args,**kwargs) forwards kwargs to
  BaseEvaluator.evaluate(expression_source), so context kwargs become the
  expression source and every evaluation raises a swallowed exception;
  userinfo therefore answers sub-only claims for every provider in this
  fork. Scope granting filter (provider= M2M descriptor) is always empty.
- Grafana identity = sub hash until the evaluator bug is fixed upstream.
2026-08-31 06:06:57 -07:00
Frank ee1e038f30 docs: authentik/anubis/network corrected to live-verified outpost behavior
Meta-header routing and forward_auth removed from the described design — both
disproved live. Documents: Host-based provider routing with per-guarded-host
proxy providers (lockstep rule), the null-flows wedge that starves the
embedded outpost config fetch, the Anubis /outpost.goauthentik.io/* transport
exemption, the single-file bind-mount stale-policy inode gotcha, Invalid next
URL as a dead design, and the public-DNS record requirement per guarded host.
2026-08-29 23:55:48 -07:00
Frank eb7448815b docs(caddy): record the h2c-transport gotcha behind the jellyfin vhost 502
Kestrel rejects the h2c upgrade preface; Caddy surfaced that as a 502 per
request while the backend answered 200 on plain HTTP/1.1 from Caddy's network.
Contrast recorded: Plex PMS needs the TLS transport, Jellyfin needs none.
2026-08-29 04:26:37 -07:00
Frank e006ad1f0f docs(anubis): record the challenge-flow contract and the JS-canary gotcha
The policy must ALLOW Anubis's own endpoints before the challenge-all rule
or the challenge challenges itself: browsers POST-solve via make-challenge
then GET-navigate pass-challenge, and a challenged answer renders as the
browser's own fetch-failure error page. Non-JS clients never reach the
verify step, which is why every curl probe looked green while every human
hit a wall. Also records that v1.13.0's valid action verbs are
ALLOW/CHALLENGE/DENY (ACCEPT crash-looped the unit on first deploy).
2026-08-29 01:57:39 -07:00
Frank ef07e7d01a fix(caddy,authentik): auth guarded vhosts by proxying the whole request through authentik
The forward_auth target /outpost.goauthentik.io/auth/caddy does not exist
in authentik 2026.8 (verified live: 404 for every header combination; the
URL tree has no outpost auth prefix at all — the outpost worker dials back
to core over ws/outpost/<uuid>/ instead). Unauthenticated subrequests got
404, Caddy treated >=400 as 'not authenticated' and redirected browsers to
the dead path — users saw authentik's own Not-Found page.

Fix: guarded vhosts now proxy the whole request through authentik-server:9000
with X-authentik-meta-outpost/-provider/-app headers (the exact header set
this build's Traefik controller emits, adapted for Caddy). Unauthenticated
clients get the login flow served in place; once a session exists,
authentik proxies on to the provider's internal_host — now
http://caddy:8017, a new post-auth internal listener that routes straight to
the app. The chain terminates; nothing dials back into authentik.

Live DB changes applied alongside (postgres is the source of truth):
provider pk=1 authentication_flow=default-authentication-flow (was NULL —
the actual cause of the 404s) and internal_host=http://caddy:8017 (was
self-referential http://authentik-server:9000).
2026-08-28 22:28:32 -07:00
Frank 21fa38e6a8 anubis: fix image ref typo in deploy pull, health probe exec form, unit alias tag
Three compounding deploy-handler bugs found by live deployment:
- podman image exists/pull used a mixed-case ghcr.io ref that podman's
  reference parser rejects before any network I/O (repository name must be
  lowercase); all refs now lowercase — ghcr resolves case-insensitively.
- the unit runs the image under a localhost/ alias tag: this host's podman
  5.7 quadlet path fails container create with 'image not known' for
  registry-prefixed refs even when present in storage (verified live).
- the health probe was shell-form and the distroless ko-build image has no
  shell; HealthCmd is now a JSON exec-form array, which passes through the
  quadlet generator's argv assembly verbatim.

Tests updated to assert the alias-tag reality plus the pull guard.
2026-08-28 11:18:41 -07:00
Frank 5829a0bfe8 docs: rename docs/ -> serverAppConfigs-docs/ per system-wide PROJECTNAME-docs convention
All in-repo path references (AGENTS.md, README, old scripts, report artifacts,
test code paths) rewritten in the same commit; focused-test map extended for
.gitignore, old/scripts/*, dankclaw/comfyui/*, and report/* per this repo's
own convention ('add one before committing'). Obsidian wikilinks are
title-based and unaffected.
2026-08-28 02:20:06 -07:00