Files
serverAppConfigs/serverAppConfigs-docs/Dankclaw/Swap Configuration.md
T
Frank 33eae71d33 docs: distill the managed skill library into the vault (waves 1-7)
All ~173 managed skills read in full and merged, one polished reference
page per skill-cluster:

- LLM cross-cutting (17 pages): GGUF Compatibility, Llama Cpp Serving
  Sizing, Llama Cpp Multi-Device Splits, PCIe Link and Atomics, RDNA4
  Container Serving, RDNA4 MoE Expert Offload VRAM Budget, vLLM Boot
  Forensics, vLLM Porting and Compile Triage, LLM Bench Windows, LLM
  Performance Diagnosis, Model Swap and Rollback, Tcclaviger Fork Ops,
  Heterogeneous Split Triage, FreeToken Builds + deltas folded into the
  retired runbooks (GLM DFlash2 port laws, Lucebox dual-R9700, R9V
  qualification pipeline, FLM pack registration, ik hybrid envelope,
  frank-medium split rebalance, llama.cpp GGUF preflight, batch-ubatch
  split section, bench-window D-state/stale-read notes, second-endpoint
  bring-up).
- Architecture (3): Stale Signal Audit, Quadlet Lifecycle, Deploy State
  Triage.
- Operations (6 + index): Remote Job Runner, Payload and Disk Reclaim,
  Container Host Reachability, Fleet Ops Playbook, Fleet Audit and
  Posture, SSH and Remote Access.
- Infrastructure: Observability Provisioning + Homepage Status Probes;
  updates to Authentik, Anubis, LAN-DNS (per-client DoH bypass, Porkbun
  zone ops), Swap Configuration, OpenWebUI, Hermes (pre-existing page
  preserved and extended).
- FrankBook-Pro: ARR-Stack filled (API split, schema-first probing,
  auth-posture, auth-config trap); qBittorrent E2E verification.
- Desktop/Agent/Research: Noctalia and Niri, OMP Harness, Agent Docs and
  Edits, Command Center Dotfiles, PICO-8 Asset Standards.
- Indexes: LLM Cross-Cutting References section, Operations/ and Agent/
  index pages, root-index Skill Distillation section, AGENTS.md pointer.
- log.md carries the wave plan.

check-vault-links.py 0 unresolved (185 pages); ./tests/run.sh 366/366.
2026-10-05 21:19:15 -07:00

6.2 KiB

type, title, description, tags, timestamp
type title description tags timestamp
configuration Dankclaw Swap Configuration The host swapfile on Dankclaw — 64 GiB at /swap.img on ext4, fstab-driven via the generated swap.img.swap unit. Covers why it was raised from 8 GiB, the safe resize ordering that avoids an OOM on a host whose MemAvailable is inflated by pinned model weights, and the swappiness caveat.
dankclaw
host
memory
swap
2026-09-12

Dankclaw Swap Configuration

Host: Dankclaw (192.168.0.143) — Filesystem: ext4 on /dev/nvme0n1p2

Item Value
Swapfile /swap.img
Size 64 GiB (raised from 8 GiB on 2026-09-12)
Filesystem ext4 — swapfiles fully supported, no btrfs nocow handling needed
Allocation fallocate (preallocated, hole-free; 530 extents)
Persistence /etc/fstab line 12: /swap.img none swap sw 0 0
systemd unit swap.img.swap — loaded (/etc/fstab; generated), active
vm.swappiness 60 (distro default, unchanged)
zswap disabled (/sys/module/zswap/parameters/enabled = N)
Free on / after 748 GiB of 1.9 TiB

The unit is generated from fstab, not a hand-written unit file. fstab is the only control point; systemctl daemon-reload re-reads it. Nothing in this repository references the swapfile — it is host-level state, documented here so it is not invisible.

Why 64 GiB

Dankclaw is shared. frank-large alone holds 103.5 GiB of the 121.2 GiB host (68.0 weights + 14.4 KV pool + 21.1 working), leaving roughly 7.1 GiB for 28 co-tenant containers whose working set is ~4.3 GiB. The engine itself warns that when that runs out, frank-large and its neighbours "can stall for minutes at a time at full CPU with no disk activity and no output". Swap is the valve that turns an OOM kill into slow paging.

Swap does not relieve the pinned-weights problem — see the caveat below. It protects the co-tenants and buys headroom for burst allocation.

The safe resize ordering

You cannot grow an active swapfile; it must be swapped off first. On a host like this, never swapoff before the replacement is online. The old 8 GiB held 4 GiB of live pages, and MemAvailable read 73 GiB while only ~5 GiB was genuinely free — the pinned model weights are counted as reclaimable page cache, so the headline number is a lie by roughly the size of the model (see halogen-flash-server). Swapping off into that apparent space, with nothing else to receive the pages, is how you invite the OOM killer.

The ordering that avoids it — create and enable the new swap first, so the pages have somewhere to go:

# 1. Preallocate + format + enable the replacement, old swap still live
sudo fallocate -l 64G /swap2.img
sudo chmod 600 /swap2.img
sudo mkswap /swap2.img          # also rejects files with holes
sudo swapon /swap2.img          # total swap now 72 GiB

# 2. Only now drain the old one — pages migrate into /swap2.img, not into RAM
sudo swapoff /swap.img          # took 65 s for 4 GiB

# 3. Consolidate onto the conventional path so fstab needs no edit
sudo swapoff /swap2.img         # 725 MiB left, trivial
sudo mkdir -p ~/.AGENTTRASH/20260912-swapfile-8g
sudo mv /swap.img ~/.AGENTTRASH/20260912-swapfile-8g/swap.img
sudo mv /swap2.img /swap.img
sudo swapon /swap.img

Step 3 is chained tightly because it leaves the host with zero swap for a few seconds. Do not leave that window open.

mkswap succeeding is itself a check: it refuses swapfiles containing holes, so a fallocate that produced a sparse file fails here rather than at 3 a.m. under memory pressure.

Verification

swapon --show=NAME,TYPE,SIZE,USED,PRIO   # /swap.img file 64G
systemctl is-active swap.img.swap        # active
grep swap /etc/fstab                     # line 12 intact -> boot persistence
free -h | tail -2                        # Swap: 63Gi total

Then confirm the inference service is unaffected — a completion, not just /health:

curl -s http://127.0.0.1:7770/v1/chat/completions \
  -H 'Content-Type: application/json' \
  -d '{"model":"frank-large","messages":[{"role":"user","content":"Reply with exactly: SWAP64-OK"}],"max_tokens":48,"reasoning_effort":"low"}'

As run 2026-09-12: finish_reason: stop, SWAP64-OK, 28 containers up, frank-large health=200 throughout.

Caveats

  • Swap cannot help the pinned weights. frank-large's ~68 GiB of weights are held deliberately; paging them is a stall, not a relief. More swap does not make the doubled KV pool affordable — see the reserve/pool ceiling in halogen-flash-server.

  • vm.swappiness=60 is untested against this workload. Under real pressure the kernel will happily page anonymous memory, and frank-large's KV pool and working set are anonymous. Swapping the KV pool would be far worse than the OOM kill it prevents. If the box ever starts thrashing, lowering swappiness (or capping the engine's cgroup) is the knob, not more swap.

  • free still lies after the change. MemAvailable reads ~70 GiB while the model is loaded. Trust the engine's host memory left for everything else line, not free.

  • Filesystem prerequisite (other hosts). ext4 and xfs take swapfiles directly. btrfs needs chattr +C (NOCOW), no compression, and no snapshots in the swapfile path — check df -T before planning, or mkswap will reject the file.

  • Renaming an active swapfile works (inode-based) but leaves a stale path in /proc/swaps — swap it off first, then rename, then swapon (which is exactly what the step-3 consolidation does). Migration is observable while it runs: in the 2026-09-12 run swapoff of 4 GiB took 65 s and used-RAM rose only ~3 GiB (pages touched during migration), the rest relocating on disk. If used-RAM climbs toward the whole swapped amount, let it finish rather than aborting.

Trash

The previous 8 GiB /swap.img (dated 2026-07-21) is staged, not deleted, at dankclaw:~/.AGENTTRASH/20260912-swapfile-8g/swap.img (8.1 GiB). Purge only on explicit approval.

See Also