Commit Graph
535 Commits
Author SHA1 Message Date
Frank 9ef034e5e6 sightsound: move FLM NPU endpoint port 52626 -> 7771
Env file is the source of truth (unit ExecStart runs the serve script which
sources it); serve-script default and the deployer health-gate URL flipped in
lockstep so the post-restart health gate polls the new port. Docs, fleet table,
and both index bullets updated to match.
2026-08-30 14:06:54 -07:00
Frank 9b9f0f9051 docs(sightsound): correct unknown-model-tag contract to live-probed behavior
Prior docs claimed unknown tags silently serve llama3.2:1b. Live probes on the
live endpoint disprove it: /v1/chat/completions answers HTTP 200 with a flat
{"error":"Failed to load <tag> model!"} body and no choices; /v1/completions
answers a nested OpenAI-shaped server_error (code 500) under HTTP 200. Valid
tags route per-request to the named model (response echoes the requested tag);
no restart needed to switch between registry tags. Corrected in the runbook,
the AGENTS.md runtime section, the serve-script header comment, and the
historical FastFlowLM incident note.
2026-08-30 11:41:15 -07:00
Frank 150412bbca docs(sightsound): NPU sight+sound runbook, fleet table, IOMMU/SVA root cause
frank-default-sightsound (FLM v1.0.1, XDNA2 NPU, port 52626) is live on
Dankclaw. Documents the first-deploy crash-loop root cause: iommu=off on the
kernel cmdline breaks the XDNA2 SVA bind (amdxdna_drm_open ret -19), so every
/dev/accel/accel0 open fails with ENODEV; fixed with iommu=pt + reboot.
Whole-registry single-port serving with per-request routing by exact FLM tag;
unknown tags fall back to llama3.2:1b (no 404). Health = GET /v1/version.
Vision + audio towers proven live (image_url color probe; audio control-pair
token-count probe). Updates AGENTS.md fleet table + runtime section, both
index pages, and the change log.
2026-08-30 09:05:22 -07:00
Frank 443adb04a7 hermes: drop the stale NetworkMode key from the gateway unit
The v1 quadlet generator skips the whole unit when [Container] holds an
unsupported key; the stale key was a leftover of a draft edit. Network=host is
the only host-networking key this generator version accepts.
2026-08-30 09:00:14 -07:00
Frank 39f0712746 hermes: Network= is the quadlet v1 key; NetworkMode= is not
The v1 generator on this host skips a unit whose [Container] section holds an
unknown key, so the deploy-time regeneration dropped hermes.service entirely
while the container kept running unmanaged. Network=host generates
--network host verbatim (v1 passes extension-less values through).
2026-08-30 08:39:53 -07:00
Frank e062fdfeff hermes: gateway dials the signal-cli daemon over loopback on host networking
The gateway unit ran on dankclaw_default and could not reach the host
daemon: from that network only DNAT'd published ports accept connections to
the LAN address. The compose era ran the gateway with network_mode: host, so
the daemon was reachable; the unit silently changed topology at takeover and
broke the adapter. Host networking + a loopback dial removes the dependency
entirely — the gateway is an outbound-only client and publishes nothing.
2026-08-30 07:42:07 -07:00
Frank 915d49d663 hermes: boot-persistent quadlet units for the gateway, dashboard, and webui
The trio ran as bare compose containers and died silently at the Aug 26
reboot — nothing restarts compose containers at boot. Each now has a
boot-persistent unit (WantedBy=default.target; the v1 quadlet generator on
this host cannot enable generated units). The deploy handler retires the
compose-era containers only while the units are not yet active, then
(re)starts each unit.

Units run the image under a localhost/hermes-agent:latest alias tag (the
quadlet create path on this host cannot resolve registry-prefixed refs from
local storage); the deploy handler tags first. The gateway's :8090 publish
is dropped — nothing consumes it; the public vhost now routes to the
dashboard's login-gated UI on 9119.
2026-08-30 07:22:20 -07:00
Frank 56763e014e fix(hermes): point the signal adapter at the verified alias path and route hermes.franksdank.cloud to the dashboard
The gateway's SIGNAL_HTTP_URL pointed at the host LAN IP. From container
space on netavark networks only DNAT'd published ports accept connections
to that address; :8080 has no forward, so every connection was refused
and the Signal adapter stayed disconnected since the Aug 26 reboot.
host.containers.internal is the verified working path (probed live from a
probe container on dankclaw_default).

The public hostname also routed to hermes:8090, which serves nothing —
the gateway has no HTTP listener. It now routes to the dashboard's login-
gated admin UI on :9119, behind the existing Anubis+Authentik guard.
2026-08-30 04:43:15 -07:00
Frank cf0c541cc9 deploy-remote: allow frank-default-sightsound on the dankclaw target
The first deploy attempt pulled c3ed3a6 on the target but the remote runner
rejected the explicit --service selection because service_is_allowed() keeps
its own per-target allowlist; add the new LLM service to it.
2026-08-30 04:40:57 -07:00
Frank c3ed3a6e12 sightsound: new FLM NPU sight+sound service on XDNA2 (gemma4-it:e4b)
New Dankclaw service frank-default-sightsound: FLM 1.0.1 serving the
Gemma4-E4B-IT-NPU2 pack (vision+audio+reasoning, 131072 ctx) on the XDNA2
NPU at port 52626. Model choice rationale: gemma4-it is the only NPU2 model
family with BOTH image and audio towers; the uncensored candidate qwythos:9b
is text-only, so sight+sound wins over uncensored here.

Deployer wiring: planner maps env/unit/serve files to the new service name;
deploy-remote gains deploy_llm_sightsound (relink + daemon-reload + enable +
restart + health gate on /v1/version — FLM has no /health route). Unlike the
retired frank-default-npu relink-only path, this unit is boot-enabled.
2026-08-30 04:37:42 -07:00
Frank 0937cfb047 docs: record fleet double swap (large -> kingjones STRIX on pinned fork, small -> Huihui FP8 on FreeToken)
- kingjones-strix-rocmfp4 reactivated as the ACTIVE large runbook:
  runtime build recipe (WEBUI=OFF gotcha), deployed serving profile,
  fa-on-works-unpatched evidence, MTP heads documented unloadable,
  swap procedure + 2026-08-30 validation record
- agentionai-fast-imatrix marked RETIRED (rollback record kept)
- freetoken-frank-default-small: model/lineage/template sections now
  Huihui abliterated FP8; new operational quirk: chat API 422 without
  explicit model field
- LLM index + AGENTS fleet table/runtime sections current; both
  services' history chains fixed (small was still Tiel in AGENTS.md)
- worklog entry added; models.json contextWindow for large corrected
  to the real per-slot 131072 (llama clamps n_ctx_train/parallel)
2026-08-30 02:35:38 -07:00
Frank aa9c1d065a frank-default-small: swap to batsclamp Huihui-Qwen3.6-35B-A3B-abliterated-FP8 on FreeToken
- same qwen3_5_moe arch and native block-fp8 format (e4m3, 128x128
  weight_block_size, un-fused per-expert layout) as the official
  Qwen FP8 checkpoint: identical FreeToken loader path, pool numbers
  unchanged (2048 MoE slots / 453005 KV tokens / 4 requests)
- checkpoint downloaded to /home/dank/models/huihui-qwen36-35b-a3b-abliterated-fp8
  (26 shards, ~35G); official checkpoint kept for rollback
- ships froggeric fixed Qwen3.6 chat template, read from checkpoint
- also refresh both .service Descriptions (large still said STRIX_LEAN)
2026-08-30 02:26:49 -07:00
Frank 3066d810ee frank-default-large: swap to kingjones STRIX model on card-pinned kingjones30/ROCmFPX runtime
- runtime: charlie build-qwen38 -> kingjones30/ROCmFPX (card recipe
  build, LLAMA_BUILD_WEBUI=OFF since npm/HF-bucket provisioning fails;
  all 35 of our serving flags verified present in the tree)
- model: agentionai FAST imatrix -> kingjones777 STRIX single GGUF
  (on-host copy sha256 == HF LFS oid c6770d74...49fa verified)
- args unchanged from our validated profile (401408x2, b4096/ub512,
  t16/tb16, f16 KV, fa on, fit off); mmap stays default per card
  (PLE streams via page cache; --no-mmap = silent cgroup OOM)
2026-08-30 02:05:03 -07:00
Frank f69efcdde6 fix serve script: restore : (not ::) for default-value assignments
The edit tool mangled : to :: on 4 lines. Bash requires : for default
value assignment (:: is not a valid command). Fixes exit code 127.
2026-08-30 01:34:21 -07:00
Frank 1ca3db4ae2 frank-default-large: ubatch 512, disable speculative decoding
- UBATCH_SIZE: 4096 -> 512 (reduce GPU memory pressure)
- SPEC_TYPE: ngram-mod -> none (disable speculative decoding entirely)
2026-08-30 01:24:40 -07:00
Frank e3bceb0506 docs(arr-chain): TV + music search chains proven live; all-off new-row gotcha 2026-08-30 00:43:30 -07:00
Frank 3626c7f40d docs(arr-chain): Prowlarr feed contract cracked, qB PBKDF2 persistence recipe, chain proof 2026-08-30 00:38:09 -07:00
Frank a04c9d7d02 frank-default-large: CTX_SIZE 32768→401408, PARALLEL 1→2 (untested experiment) 2026-08-30 00:04:47 -07:00
Frank a98cec3216 docs: log entry for the guarded-host sign-in fix (providers, :8016 uniform proxy, Anubis transport exemption, auth DNS record) 2026-08-29 23:58:09 -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 2a72efad44 anubis policy: allow /outpost.goauthentik.io/* transport paths
Login/PoW/POST traffic to the outpost URL space cannot solve a fresh PoW
challenge per request; exempt the transport prefix (authentik's own session
gate still protects it) so the guarded-host sign-in journey completes.
2026-08-29 23:49:42 -07:00
Frank 29f9a86884 caddy+authentik tests: uniform Host-preserving :8016 proxy through embedded outpost
The redirect-to-flow design with an absolute cross-host next= was rejected by
the flow's open-redirect guard at completion ("Request has been denied:
Invalid next URL"), and meta-header routing does not exist in this build
(providers route on the ORIGINAL Host). :8016 now proxies every request whole
to authentik-server:9000 preserving Host; the embedded outpost serves login
in place and forwards authenticated traffic back to :8017. Requires one proxy
provider per guarded host (provisioned live: search/hermes/prometheus/romm/
files + www, flows backfilled). Tests flipped from the meta-header claim to
the upheld contract: Host preserved, no absolute next= redirects.
2026-08-29 23:49:39 -07:00
Frank 7cb6eeb67a frank-default-large: re-enable --flash-attn on via QSA F32-mask patch
fa on aborted graph build: build_attn_qsa called ggml_fill on the
F16-converted kq mask (GGML_ASSERT F32 at ggml.c:5371). Patch mirrors the
MLA sparse path in llm_graph_context::build_attn (F32 base mask for the
top-k surgery, F16 cast only at the attention call, gated on
cparams.flash_attn). Vendored at scripts/patches/qwen4exp-qsa-f32-mask.patch
(sha256 f2f4a486...); the build-qwen38 binary on Dankclaw is rebuilt with
it and validated live at CTX_SIZE=32768 (health 200, real completion).
2026-08-29 23:43:25 -07:00
Frank 101b1f8be2 frank-default-large: cap CTX_SIZE at 32768 (author quick-start) — 87 GiB fully-resident model + context buffer OOMs HIP heap (50.8 GiB at 131072, 103 GiB at 262144) 2026-08-29 23:14:50 -07:00
Frank 7ac172c4f4 frank-default-large: cap CTX_SIZE at 131072 — 262144 OOMs SVM pool (cudaMalloc 103176 MiB failed with fully GPU-resident 87 GiB model) 2026-08-29 22:48:17 -07:00
Frank 2f153c89f4 frank-default-large: restore SPLIT_MODE/FIT/NGL env vars + NGL/FIT/REASONING_FORMAT script defaults (dropped in prior edit; crash-loop with 'NGL: unbound variable') 2026-08-29 22:06:05 -07:00
Frank 9865f9e307 frank-default-large: verify v2 main on build-qwen38 — flash-attn off required, MTP draft incompatible (ngram-mod fallback)
- Main model (v2 joined PLE layout, sha256 1e4160ca…) loads and serves on
  build-qwen38 only with --flash-attn off: the QSA indexer path calls
  ggml_fill on the F16-cast kq mask and aborts graph build (GGML_ASSERT
  F32 at ggml.c:5371). Verified live: model loaded, health 200, real
  completion.
- MTP draft head (agentionai FAST, 2.28 GiB) does not load on this binary:
  qwen4exp loader requires full per-layer blk.<il>.hc_attn_norm.weight,
  head carries only blk.48. Third confirmation (EasiiX Q8_0 + agentionai
  FAST vs kingjones STRIX_LEAN previously, now own-matched pair). Spec
  decoding runs ngram-mod only; head retained for a future compatible build.
- FLASH_ATTN=off and SPEC_TYPE=ngram-mod wired through env + serve script;
  runbook and AGENTS.md updated with the verified constraints.
2026-08-29 21:39:37 -07:00
Frank 3c2a5d2fe7 frank-default-large: swap to agentionai Qwen3.8-Flash-Next ROCmFP4-FAST imatrix + own MTP draft
Model: agentionai/Qwen3.8-Flash-Next-ROCmFP4-FAST-imatrix-GGUF (87.06 GiB,
Q4_0_ROCMFP4_FAST imatrix-calibrated, per-head PLE table inside the GGUF —
fully VRAM-resident). Draft: agentionai/Qwen3.8-Flash-Next-MTP-ROCmFP4-FAST
(2.28 GiB, matched ROCmFP4-FAST quant, ~66% acceptance at n-max 3).
Vision tower (f16) loaded via mmproj/.

Runtime: charlie12345/ROCmFPX build-qwen38 (HIP, ROCm 7.2.4, gfx1151) —
the only binary with the ROCmFP4 FAST types. Replaces the jcbtc CIRU v1.1
deployment (ciru-ai runtime).

Profile: card sampling table (temp 0.7, top_p 0.8, top_k 20, min_p 0.0,
presence 1.5) mixed with the validated build-qwen38 serving profile:
262144 ctx x 1 slot, b 4096 / ub 4096, t 16 / tb 16, f16 KV, fa on,
cont-batching, prompt cache + 8 GiB cache-ram + idle slots, 16 ctx
checkpoints (no --checkpoint-min-step — unsupported on this binary),
--fit off (auto-fit segfaults on qwen4exp hyper-connection config),
--spec-type draft-mtp,ngram-mod with n-max 3 (adaptive p-split measured
worse per author card), p-min 0.75. Qwen-Sharp chat template kept;
reasoning stays in DeepSeek format.

The 2026-08-28 failure of this draft head on the kingjones STRIX_LEAN
model was a cross-vendor pairing problem: the head carries
blk.48.hc_attn_norm.weight (verified in-GGUF, same shape as the working
CIRU draft). Docs: new runbook agentionai-fast-imatrix, index updates.
2026-08-29 20:41:12 -07:00
Frank e22631d892 frank-default-large: swap to CIRU v1.1 runtime + jcbtc Qwen3.8-Flash-CIRU-STRIX-IU4
Runtime: ciru-ai/Qwen3.8-Flash-CIRU-STRIX-IU4 llama.cpp at tag v1.1, built
with the vendor build-linux-amd.sh flag set plus GGML_CUDA_FA +
GGML_CUDA_FA_ALL_QUANTS (the Q4_1_MOE_FORCE_J path is live in the hipified
mmq kernels). Model: jcbtc/Qwen3.8-Flash-CIRU-STRIX-IU4 (Q4_1 IU4 experts,
MTP Q8_0 draft, CIRUPLE1 PLE sidecar) with checksums verified at download.

Vendor production profile verbatim on first deployment: 262144 ctx x 1 slot,
b 2048 / ub 512, t 8 / tb 8, f16 KV, fa on, cont-batching, prompt cache +
8 GiB cache-ram + idle slots, 32 ctx checkpoints (min step 8192), MTP depth
3 with p-split 0.10, PLE pager env knobs (Q41_MOE_FORCE_J=32,
PLE_WORKERS=16, PLE_STRICT_SHA=0, HIPBLASLT=1). Qwen-Sharp chat template
kept deliberately; reasoning stays in DeepSeek format.
2026-08-29 19:30:04 -07:00
Frank d29d2ea29e caddy: guarded vhosts route to Authentik's flow endpoint, not the outpost prefix
This 2026.x build does not mount /outpost.goauthentik.io/* for proxy-provider
meta-header routing (probed live: ping answers 204, app paths with full meta
headers 404). Guarded vhosts now redirect to /if/flow/default-authentication-flow/
with next= back to the app — unauthenticated sees the login page in place,
authenticated sessions complete instantly and bounce straight to the app.
2026-08-29 18:29:57 -07:00
Frank 8898740ca4 caddy: www holds the homepage; naked domain redirects at the TLS edge
The proxy provider matches external_host exactly, so Host=www matched zero
providers and Authentik answered its error page while the naked domain
served the homepage. Flip the topology: www.franksdank.cloud is the one
guarded vhost carrying the homepage through Anubis -> Authentik -> :8017;
franksdank.cloud (plus legacy names and the bare-IP catch-all) 308-redirects
onto www before any challenge. Tests flipped to assert the new contract.
2026-08-29 15:11:18 -07:00
Frank 808349bc2b docs(arr): chain complete 4/4 + auth-config pitfall (v1 DryIoc 500 sprawl)
All four arr roots live: /tv, /movies via API; /music, /books created after
v1 validator layers peeled back (quality/metadata profile ids must reference
existing profiles; v1 has no /api/v1/profile endpoint). Auth pitfall: the
literal AuthenticationRequired=Disabled string throws DryIoc.ScopedItemException
in v1 AuthorizationMiddleware on every request — the valid no-auth state is
ABSENCE of the key. Fixed live on four containers, verified boot clean.
2026-08-29 08:19:39 -07:00
Frank 151495c978 docs(arr): chain completion — roots live on sonarr/radarr, PUID=0 identity fix rationale
Sonarr/Radarr root folders created via API (201). Lidarr/Readarr deferred to
first-run wizard (v1 validators demand quality-profile ids that don't exist
yet). Root cause of the write failures: LSIO PUID=1000 under rootless podman
maps to host uid 101000 — a phantom user owning nothing; PUID=0 maps to the
host user that owns every media dir.
2026-08-29 07:30:03 -07:00
Frank b9de886509 fix(dankserver): run arr stack and qb as container-root (PUID=0)
Under rootless podman, LSIO's PUID=1000 maps to host uid 101000 — a phantom
user owning nothing: Sonarr's own validator rejected /tv because the process
could not write it. Container-root under a single-user userns maps to the host
user (dank), which owns every /mnt/entropy media dir and /opt config dir.
Identity is now mapping-independent instead of depending on subuid offsets.
calibre-web untouched (working; churn avoided).
2026-08-29 07:18:50 -07:00
Frank 3a361385a1 docs(arr): record live chain wiring — per-arr qB clients, Prowlarr Applications rows, test-before-enable policy
Verified live: indexers->Prowlarr->per-arr QBittorrent download clients with
category routing. Readarr's client parked (qB proxy auth defect in abandoned
upstream). EZTV/1337x parked with reason (CloudFlare-blocked at this egress);
Nyaa/sukebei/RuTor/Byrutor/YTS passed live tests and are enabled. Prowlarr v2
Applications rows now carry real arr baseUrl+apiKeys; before this every sync
attempt threw NullConfig in GetIndexerMappings.
2026-08-29 06:31:10 -07:00
Frank e4644de722 docs(arr): record live auth posture — zero-user login gate, first-account-wins
Verified live: AuthenticationMethod=None + AuthenticationRequired=Enabled on
all five arrs; unauthenticated API probes return 401 both locally and through
the vhosts. Also records the as-built divergences (entropy mounts, LA timezone,
readarr tag pin, prowlarr mount fix) that supersede the design compose.
2026-08-29 04:58:33 -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 7e900f6400 fix(caddy): drop h2c transport on jellyfin vhost
Jellyfin's Kestrel backend rejects the h2c upgrade preface, so Caddy turned
every request into a 502 while the same port answers 200 over plain HTTP/1.1
from Caddy's network. Default transport (HTTP/1.1) restores the vhost.
2026-08-29 04:23:59 -07:00
Frank 7190720a9e docs(dankserver): copyparty doc matches the ac edition's real interface
The page claimed an env-var interface (COPAY_PASS/COPAY_MODE) and a /data
volume convention that this image does not implement: the ac edition consumes
accounts and volumes as argv flags (-a USER:PASS, -v SRC:DST:PERMS), serves
the LUKS array at /w, and answers HTTP 500 with its own error page when zero
volumes are configured. Image ref corrected to copyparty-ac (bare latest tag
does not exist on ghcr).
2026-08-29 03:39:23 -07:00
Frank 2c8e65e82f fix(dankserver): copyparty ac edition takes accounts and volumes as argv flags
Ground truth from the image itself: python3 -m copyparty --help-accounts shows
-a takes USER:PASS and -v takes SRC:DST:PERMS:FLAGS — the COPAY_PASS/COPAY_MODE
envs this compose carried are not consumed by this image at all (zero COPAY_
references in the package). With no accounts and no volumes configured, the ac
edition serves its cwd read/write for everyone: the stack was running an
unauthenticated world-writable share of the 91T array. Now: admin account dank
with the A flag on volume /w; anonymous gets nothing.
2026-08-29 03:32:18 -07:00
Frank f3ebe0943a revert(dankserver): drop copyparty command override
The ac edition's entrypoint (cpp.sh -> python3 -m copyparty) consumes config
via /z/initcfg, not argv; -v is the volume flag and ate the next arg,
crash-looping argparse. The image mounts everything under /cfg/copyparty as
volumes by marker-file convention — plant the marker on the host instead.
2026-08-29 03:26:46 -07:00
Frank 9cbd8b8822 fix(dankserver): copyparty ac edition takes volumes as command args
The image entrypoint is /bin/ash /z/cpp.sh -c /z/initcfg: copyparty flags are
passed through command, and the ac edition mounts volumes with -m, not via a
COPAY_VOL env. Without any volume mounted every request resolved zero volumes
and the app answered HTTP 500 with its own error page. Verbose flag included
for the bring-up; drop it once stable.
2026-08-29 03:19:41 -07:00
Frank c70d203ad9 fix(dankserver): copyparty volume root via COPAY_VOL
The ac edition maps volumes from COPAY_* envs; without a volume root every
request resolves zero volumes and the app answers HTTP 500 with its own error
page. Point it at /w where the LUKS array is mounted.
2026-08-29 03:17:02 -07:00
Frank 03fd9e244d fix(dankserver): copyparty serves /w from the array; image is the ac edition
ghcr.io/9001/copyparty:latest does not exist — ghcr answers 403 on the token
request for nonexistent repos, which is why the bring-up failed at pull. The
upstream publishes ghcr.io/9001/copyparty-ac (ac = full edition) and serves
whatever is mounted at /w, so the compose mounts the LUKS array there; config
persists in /opt/copyparty/cfg per upstream layout.
2026-08-29 03:09:27 -07:00
Frank d74ea5bf39 fix(dankserver): jellyfin user-mapping and readarr image tag
Jellyfin ran as user 1000:1000 inside a rootless user namespace, where host
uid 1000 maps to container uid 0 — the pinned uid is unmapped, so /config/log
creation EACCES'd and the service SIGSEGV'd on boot. Container root (= host
dank) is correct under rootless podman; group_add 992 (render) still maps via
the userns group map, so GPU access is preserved.

Readarr: lscr.io/linuxserver/readarr:latest does not exist — LSIO ships only
arch-prefixed nightly/version tags for readarr (verified against the ghcr tag
API). Pin amd64-1.0.980, the newest stable tag.
2026-08-29 03:03:55 -07:00
Frank 67de5cfe9b fix(dankserver): point media mounts at the real entropy array paths
The compose stack mounted /mnt/media/{movies,shows,tv,music,books,downloads}
— a prefix that has never existed on this host. The 91T LUKS array mounts at
/mnt/entropy and its libraries are case-exact (Movies, TVShows, Music,
eBooks). Also restores prowlarr's config mount (eaten by an off-by-one in the
prior edit) and fixes TZ New_York->Los_Angeles on the arr stack.
2026-08-29 02:54:24 -07:00
Frank 2523f3ed43 docs(dankserver): document Plex (native systemd) and Tautulli (snap) as they actually run
Live-verified 2026-08-29: plexmediaserver.service is an enabled native
systemd unit on Dankserver (not a quadlet; updates via apt, not deploy.sh),
and tautulli runs as a snap with no auth wall on 0.0.0.0:8181. The hunt list
named both; neither had a page. Index linked per the docs-completeness seam.
2026-08-29 02:12:08 -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 e10ebf3df4 fix(anubis): ALLOW is the allow action in v1.13.0, not ACCEPT
The pinned binary's policy parser rejects unknown actions and exits 1 on
startup (verified against the image binary: the valid action literals are
ALLOW, CHALLENGE, DENY). The first cut of the own-endpoints accept rule
used ACCEPT and crash-looped the unit on deploy.
2026-08-29 01:20:19 -07:00
Frank a8206a42ae fix(anubis): accept Anubis's own endpoints before the challenge-all rule
The catch-all path_regex "." policy challenged everything, including
Anubis's own API namespace /.within.website/x/cmd/anubis/*
(make-challenge, pass-challenge, static assets). In whole-request proxy
mode a JS-capable browser POSTs its challenge solution to
pass-challenge and received another challenge page (HTML) instead of the
verification verdict (JSON): the challenge app's fetch failed and the
browser rendered its own error — 'the request filters did not return an
alternative response'. Non-JS clients never POST the solution, so every
curl probe looked green while every human hit a wall.

Accept rule ordered above the catch-all; policy is volume-mounted ro from
this checkout, so the deploy updates it in place.
2026-08-29 01:13:17 -07:00