Commit Graph
100 Commits
Author SHA1 Message Date
ginnoirandClaude Opus 4.8 eba51a52a7 docs(llm): record final 64k config, perf, and Pascal/Hermes gotchas
Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
2026-06-26 17:14:26 -05:00
ginnoirandClaude Opus 4.8 4aa2cd9468 fix(llm): q8_0 V-cache (q4_0 tanked generation to 1.3 tok/s on Pascal)
The q4_0 V-cache + flash-attention path is pathological on the GP100: 1.28
tok/s generation at 5-8% GPU util. q8_0 V-cache gives 9.2 tok/s and still fits
64k context in 16GB (15.3GB used, ~950MB free).

Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
2026-06-26 17:04:17 -05:00
ginnoirandClaude Opus 4.8 13424fcf75 fix(llm): override-kv context_length=65536 so slot isn't capped to 32k
llama-server caps the slot to the GGUF training context (32768) and ignores the
YaRN-extended size, leaving per-seq context at 32k. Raise qwen2.context_length
metadata to 65536 so the full window is served per request.

Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
2026-06-26 16:45:33 -05:00
ginnoirandClaude Opus 4.8 74791105b3 fix(llm): --parallel 1 so a single request gets the full 64k context
With the default 4 slots, llama-server splits ctx into 32k per sequence, which
fails Hermes' 64K minimum. One slot serves the full 65536 per request (serial
agent use; concurrent calls queue).

Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
2026-06-26 16:42:41 -05:00
ginnoirandClaude Opus 4.8 265b407e8d feat(llm): serve 64k context (YaRN) to meet Hermes' 64K minimum
Hermes Agent rejects models with <64K context. Qwen2.5-14B is 32k native, so
enable YaRN rope-scaling (2x → 65536) and drop the V-cache to q4_0 for VRAM
headroom on the 16GB P100.

Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
2026-06-26 16:39:56 -05:00
ginnoirandClaude Opus 4.8 605c6d3709 fix(llm): use --flash-attn on (this llama.cpp build requires explicit value)
The server-cuda image parses -fa as --flash-attn [on|off|auto], so a bare -fa
swallowed the following --cache-type-k as its value and crash-looped.

Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
2026-06-26 16:31:01 -05:00
ginnoirandClaude Opus 4.8 8e7682985d feat(llm): add llama.cpp inference stack for Hermes (Qwen2.5-14B on P100)
New stacks/llm/ serves Qwen2.5-14B-Instruct (Q4_K_M GGUF) via llama.cpp's
OpenAI-compatible server on the Tesla P100 (CDI nvidia.com/gpu=0), published on
172.20.0.1:8090 for the host-side Hermes agent. vLLM was rejected: the P100
(cc 6.0) lacks the DP4A INT8 instructions its AWQ/GPTQ kernels need.

Includes design spec and implementation plan under docs/superpowers/.

Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
2026-06-26 16:22:57 -05:00
ginnoirandClaude Sonnet 4.6 847edff1f8 fix(proxy): SameSite=Lax on share_gate cookie to fix Safari/Firefox redirect
Deploy Caddyfile to valhalla / deploy (push) Successful in 2m19s
SameSite=Strict caused Safari and Firefox to drop the freshly-set cookie on
the immediate same-site redirect when the top-level navigation originated
from an external app (Discord). SameSite=Lax explicitly permits the cookie
on same-site redirects regardless of the initiating context.

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
2026-06-24 15:30:14 -05:00
ginnoirandClaude Sonnet 4.6 d654e6df90 fix(proxy): use parse-time {$SHARE_KEY} in share_gate instead of runtime placeholder
Deploy Caddyfile to valhalla / deploy (push) Successful in 44s
{env.SHARE_KEY} is not resolved by Caddy's query matcher or CEL expression at
request time — the literal placeholder string was compared against the URL key,
causing every external request to fall through to 403. {$SHARE_KEY} is
substituted by the Caddyfile adapter at reload/start, baking the literal key
value into the compiled config.

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
2026-06-24 01:45:11 -05:00
ginnoir bf8caccd88 fix(media): raise nofile ulimit to 65536 for *arr containers
sonarr/radarr/prowlarr/whisparr/bazarr were hitting the default Docker
nofile limit of 1024, causing EMFILE errors and excessive virtiofsd FD
churn on the /storage1 virtiofs mount.
2026-06-24 01:28:08 -05:00
ginnoirandClaude Sonnet 4.6 f477465a1d feat(proxy): add share_gate for Discord-group external access
Deploy Caddyfile to valhalla / deploy (push) Failing after 4s
Capability-URL snippet: external users visit ?k=SHARE_KEY once, Caddy
sets a 30-day HttpOnly cookie and redirects to the clean path. Subsequent
visits check the cookie only. Internal IPs and tailnet pass through
unconditionally. Applied to roms.ginnoir.com and romhacks.ginnoir.com.

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
2026-06-24 01:02:06 -05:00
ginnoir b4a45a6735 fix: block public hermes browser UI
Deploy Caddyfile to valhalla / deploy (push) Successful in 51s
2026-06-21 14:46:22 -05:00
ginnoir d38048faf0 fix: preserve hermes dashboard host guard
Deploy Caddyfile to valhalla / deploy (push) Successful in 1m10s
2026-06-21 14:40:01 -05:00
ginnoir 12cb5279d0 feat: expose hermes dashboard backend
Deploy Caddyfile to valhalla / deploy (push) Failing after 3m28s
2026-06-21 14:36:39 -05:00
ginnoirandClaude Opus 4.8 466ffe9588 fix(remote): correct hbbs relay flag to lowercase -r
The previous commit used `hbbs -R 192.168.1.69` (uppercase -R sets
rendezvous/cluster servers), so hbbs advertised an empty relay list and
clients failed with "failed to connect to relay server". Lowercase -r is
the relay-server flag; hbbs now advertises 192.168.1.69 and LAN clients
relay correctly.

Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
2026-06-18 04:54:04 -05:00
ginnoir 73f25d20a1 fix(remote): add -R 192.168.1.69 to hbbs so relay address is reachable from LAN 2026-06-18 03:48:50 -05:00
ginnoirandClaude Opus 4.8 6cfa2a50c9 chore(roms): unpin RomM from 4.9.0-beta.2 to floating :4 stable
The save-sync (/api/sync/*) and raw content_hash fixes that forced the
beta pin shipped in stable 4.9.x (now 4.9.2). Return to the watchtower-
tracked :4 tag per the original design.

Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
2026-06-18 02:41:11 -05:00
ginnoirandClaude Opus 4.8 c5d487effe chore: add migration helper scripts + cutover plan doc
R510 -> R730XD/Proxmox migration helpers (consistent DB dumps, B2/Kopia snapshot refresh, cutover final backup) plus the previously-untracked gitea-portainer-registry cutover plan under docs/.

Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
2026-06-17 23:27:55 -05:00
ginnoir 4ede8c483a feat: add check_uptime.js script for scheduled checks 2026-06-17 12:31:10 -05:00
ginnoir 8dd90854af fix: improve onlyoffice container runtime 2026-06-16 00:23:36 -05:00
ginnoirandClaude Sonnet 4.6 3283187741 feat(files): mount /storage1/ROMs into Nextcloud container
Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
2026-06-15 23:44:30 -05:00
ginnoirandClaude Sonnet 4.6 2cf48222b8 fix(claude): correct Authentik provider template scope PKs and grant_types
grant_types must be set explicitly ([] = all auth rejected). Scope PKs
were truncated placeholders — replaced with actual UUIDs from this
Authentik instance. Signing key was already correct.

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
2026-06-15 23:17:06 -05:00
ginnoirandClaude Sonnet 4.6 ba6724a1c3 docs: record Nextcloud migration; drop TB-021 paperless-ngx
TB-021 dropped — user wanted Google Docs replacement, not document OCR.
Migrated ownCloud → Nextcloud 34 + OnlyOffice (files.ginnoir.com).
Authentik OIDC configured via user_oidc app; office.ginnoir.com internal.

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
2026-06-15 23:11:24 -05:00
ginnoirandClaude Sonnet 4.6 1c02bfe2fc docs(caddy): update nextcloud staging comment post-cutover
Deploy Caddyfile to valhalla / deploy (push) Successful in 47s
Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
2026-06-15 23:09:37 -05:00
ginnoirandClaude Sonnet 4.6 ac6f233988 feat: cut files.ginnoir.com over to Nextcloud; fix scope PKs
Deploy Caddyfile to valhalla / deploy (push) Successful in 55s
Switch files.ginnoir.com from ownCloud to Nextcloud (internal-only).
Fix Authentik scope PKs in CLAUDE.md — the last UUID segments were
wrong and would have caused provider creation failures.

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
2026-06-15 23:07:18 -05:00
ginnoirandClaude Sonnet 4.6 a1c57ca899 feat: add Nextcloud + OnlyOffice files stack
Deploy Caddyfile to valhalla / deploy (push) Successful in 2m20s
Replaces ownCloud with Nextcloud (postgres + redis) and adds OnlyOffice
Document Server for Google Docs-style editing. Migration is staged:
nextcloud.ginnoir.com for testing, files.ginnoir.com still points at
ownCloud until cutover is verified.

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
2026-06-15 22:55:00 -05:00
ginnoirandClaude Sonnet 4.6 a937de7bda docs: document Authentik OIDC standard for new services
Pattern A (native OAuth2) is preferred — create provider + app in
Authentik, configure service with discovery URL. Pattern B (Caddy
forward_auth) is the fallback for services with no native auth.
Reusable Authentik flow/scope PKs pinned so they don't need re-deriving.

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
2026-06-15 22:44:59 -05:00
ginnoirandClaude Sonnet 4.6 acdf61500c chore(plans): mark TB-019 Immich done
Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
2026-06-15 22:21:36 -05:00
ginnoirandClaude Sonnet 4.6 dbe4a95059 feat(photos): add Immich stack
Deploy Caddyfile to valhalla / deploy (push) Successful in 46s
Self-hosted photo backup at photos.ginnoir.com (internal/tailnet only).
Server + machine-learning + postgres (vectorchord) + redis.
Upload storage: /storage1/labdata/immich/upload (ZFS).
DB/model-cache: /config/immich/ (SSD).

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
2026-06-15 22:15:28 -05:00
ginnoirandClaude Sonnet 4.6 11f51559b0 chore(plans): record new service decisions and drop list
New services: all in except TB-020 Mealie (deferred to famapp).
Active interest: TB-015 Vault, TB-027 Jellyfin, TB-028 HA, TB-031 Pingvin.
Dropped: TB-017 MinIO consolidation, TB-018 Plane, TB-029 Firefly III,
TB-030 AdGuard (handled at router), TB-032 Wiki.js (using BookStack).

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
2026-06-15 22:08:55 -05:00
ginnoirandClaude Sonnet 4.6 c6e8af7e62 chore(media): remove maintainerr
Deploy Caddyfile to valhalla / deploy (push) Successful in 48s
Too complex to configure for the use case; not worth the overhead.

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
2026-06-15 22:03:12 -05:00
ginnoirandClaude Sonnet 4.6 29d04980fd feat(media): update maintainerr to v3 (new GHCR org)
Image moved from ghcr.io/jorenn92/maintainerr to ghcr.io/maintainerr/maintainerr
with the v3.x release series. v3 runs its own DB migrations on startup.

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
2026-06-15 21:35:26 -05:00
ginnoirandClaude Sonnet 4.6 fb3938c71b feat: migrate Overseerr → Seerr
Deploy Caddyfile to valhalla / deploy (push) Successful in 1m20s
Replace sctx/overseerr:latest with ghcr.io/seerr-team/seerr:latest.
Same port (5055), same config volume (/config/overseerr:/app/config) —
Seerr auto-migrates the DB on first boot. Add init: true as required.
Rename container overseerr → seerr; update Caddy upstream to match.

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
2026-06-15 21:00:09 -05:00
ginnoirandClaude Sonnet 4.6 1bc648f33b fix(maintainerr): correct data volume path and enable TLS bypass for Plex
- Mount /config/maintainerr to /opt/data (actual DB location, not /opt/maintainerr/data)
- Add NODE_TLS_REJECT_UNAUTHORIZED=0 so Node.js accepts Plex's self-signed cert
- Mark TB-007/008/009/012/013/016 tasks as done/dropped in improvement plan

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
2026-06-15 20:52:06 -05:00
ginnoir 79b99cf883 docs: document plex as external systemd service on valhalla 2026-06-15 20:27:48 -05:00
ginnoir f923cd5b49 feat(media): add maintainerr for stale overseerr request cleanup
Deploy Caddyfile to valhalla / deploy (push) Successful in 1m11s
2026-06-15 20:25:51 -05:00
ginnoir 8ef2f689f6 chore(media): retire deluge, qbit is the sole torrent client
Deploy Caddyfile to valhalla / deploy (push) Successful in 1m7s
2026-06-15 20:19:16 -05:00
ginnoir 76679dd030 fix(code-server): scope mount to projects dir and ai extension configs 2026-06-15 20:15:38 -05:00
ginnoir ecf5c955f3 feat: add wa4.ginnoir.com chest checklist static site
Deploy Caddyfile to valhalla / deploy (push) Successful in 46s
2026-06-15 02:06:39 -05:00
ginnoirandClaude Sonnet 4.6 a44adc4814 docs: document gitea-first homelab deploys
Switch CLAUDE.md and AGENTS.md to Gitea-primary language. Remove
github-runner from the management plane now that Gitea Actions handles
Caddy reloads and famapp builds. Disable GitHub deploy workflow.
Update apply-compose.ps1 status text.

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
2026-06-15 00:38:15 -05:00
ginnoirandClaude Sonnet 4.6 e3937dcf52 fix(famapp): pull image from valhalla registry
Switch famapp container from ghcr.io/ginnoir/famapp:latest to
registry.ginnoir.com/ginnoir/famapp:latest.

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
2026-06-15 00:17:28 -05:00
ginnoirandClaude Sonnet 4.6 fb4de751ed fix: alias gitea.ginnoir.com on Caddy for Portainer go-git TLS
Portainer go-git resolves gitea.ginnoir.com inside Docker. Alias was on
the gitea container → port 443 refused. Moved alias to Caddy so go-git
reaches Caddy:443 (TLS ok) → proxies to gitea:3000.

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
2026-06-15 00:04:08 -05:00
ginnoir 1138e41e22 fix: add gitea.ginnoir.com edge alias so Portainer go-git resolves internally 2026-06-14 23:36:38 -05:00
ginnoir 67234b3948 fix(caddy-deploy): install docker.io in job container for docker exec
Deploy Caddyfile to valhalla / deploy (push) Successful in 49s
2026-06-14 23:14:34 -05:00
ginnoir 5558c03bac ci: add gitea caddy deploy workflow
Deploy Caddyfile to valhalla / deploy (push) Failing after 27s
2026-06-14 22:59:04 -05:00
ginnoir ef107dd743 fix: make portainer stacks use stack env only 2026-06-14 22:56:38 -05:00
ginnoir 2a76a8f1f8 refactor: move gitea and registry to management plane 2026-06-14 22:54:31 -05:00
ginnoir 3918f24970 chore: add registry auth credentials 2026-06-14 22:53:22 -05:00
ginnoir 0b58c11f2b test: add portainer stack env guard 2026-06-14 22:52:13 -05:00
ginnoir 1289e0a615 fix: preserve gitea database password in dev stack 2026-06-12 01:22:42 -05:00
ginnoirandClaude Sonnet 4.6 17be6410ba chore: rotate GITHUB_STACKS_PAT
Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
2026-06-11 23:33:22 -05:00
ginnoirandClaude Sonnet 4.6 96e3ef9a4d chore(authentik): upgrade to 2026.5.2 (hop 2 of 2)
Final target version. Intermediate 2025.12.5 hop applied and validated
before this upgrade.

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
2026-06-11 23:07:38 -05:00
ginnoirandClaude Sonnet 4.6 113af2d8e2 chore(authentik): upgrade to 2025.12.5 (hop 1 of 2)
Intermediate step on the way to 2026.5.2 — Authentik requires passing
through the latest 2025 release before jumping to 2026.

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
2026-06-11 22:57:41 -05:00
ginnoir eff906f298 feat: add uptime checking script for scheduled reports 2026-06-11 20:14:07 -05:00
ginnoir e3bf11d18e Add Caddy bypasses so MCP can reach *arr and Uptime Kuma through Authentik.
Deploy to valhalla / deploy (push) Has been cancelled
TB-006 forward_auth blocks machine clients with HTML/302; route /api on *arr
sites and /api plus socket.io on uptime (LAN/tailnet only) before forward_auth.
Also add Cursor interview-first rule and small Authentik/FreshRSS debug helpers.
2026-06-11 17:37:21 -05:00
ginnoir 776478c035 feat(proxy): add idlegame internal site
Deploy to valhalla / deploy (push) Has been cancelled
2026-06-11 17:31:05 -05:00
ginnoir fdc2eddf03 fix(dev): use resolvable bookstack mariadb tag 2026-06-11 17:18:38 -05:00
ginnoir f91a993c58 feat(dev): add gitea actions runner 2026-06-11 17:13:39 -05:00
ginnoirandClaude Sonnet 4.6 993504106e feat(caddy): bypass Authentik forward_auth for Plane API key requests
Deploy to valhalla / deploy (push) Has been cancelled
Adds a named matcher @plane_api that matches /api/* requests carrying
X-API-Key, routing them directly to plane_api:8000 without hitting the
Authentik outpost. Browser/UI sessions still go through forward_auth.

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
2026-06-11 15:32:09 -05:00
ginnoir 792305e5fa Mark homelab quick wins complete in plan briefs and task menu.
Close TB-002–004 and TB-033 with done-when checkboxes and update PLAN-BRIEF priority to the next themes.
2026-06-11 03:00:45 -05:00
ginnoir 67be0d6aff Replace expired GITHUB_STACKS_PAT so Portainer git pulls match the working token in Obsidian. 2026-06-11 02:55:49 -05:00
ginnoir 9bad6f3d22 Point Servarr download clients at internal Docker hosts so API calls bypass Authentik forward_auth.
After batch 2 SSO, Sonarr/Radarr hitting nzbget.ginnoir.com got 302 from Caddy instead of NZBGet JSON-RPC.
2026-06-11 02:47:54 -05:00
ginnoir 51acb44322 Ship homelab quick wins: Recyclarr, infra pins, jd.ginnoir.com, and LAN lockdown.
Deploy to valhalla / deploy (push) Has been cancelled
Add Recyclarr to the media stack, pin database/object-store/Caddy/Vault images with Watchtower disabled, expose JDownloader at jd.ginnoir.com, and restrict minio/homarr/docs to internal_only. Mark TB-002–004 and TB-033 complete; bundle batch-3 OIDC env for FreshRSS, ownCloud, and Reactive Resume.
2026-06-11 02:28:06 -05:00
ginnoir 1ce63153ab Persist TB-006 batch 2 media SSO and batch 1 auth fixes to the repo.
Media sites get Caddy forward_auth; Authentik scripts cover all proxy providers. BookStack OIDC and Plane admin routing fixes included, plus ops scripts for external auth on valhalla.
2026-06-11 01:19:06 -05:00
ginnoir 63889fc150 Complete TB-006 batch 1 SSO so admin apps use Authentik without double login.
Deploy to valhalla / deploy (push) Has been cancelled
Native OAuth/OIDC for Homarr, BookStack, Gitea, and MinIO console; forward_auth with local auth disabled for code-server, uptime, and kopia; Caddy and Authentik scripts updated to match.
2026-06-10 23:52:14 -05:00
ginnoir 109cc0d5cb Fix Homarr appdata bind mount and deploy Authentik forward auth on admin sites.
Deploy to valhalla / deploy (push) Has been cancelled
Homarr-labs stores state under /appdata; the old compose mapped empty paths and lost the dashboard on redeploy. TB-006 batch 1 adds Caddy forward_auth for 12 admin UIs with API and webhook bypasses.
2026-06-10 23:14:32 -05:00
ginnoir 1253825541 Mark TB-005 Obsidian hardening complete.
Record deployed internal_only gate and update plan brief gaps.
2026-06-10 22:47:02 -05:00
ginnoir 80b0fc6904 Restrict Obsidian LiveSync to LAN and tailnet only.
Deploy to valhalla / deploy (push) Has been cancelled
Closes TB-005: obsidian.ginnoir.com was publicly reachable; sync clients use tailnet.
2026-06-10 22:19:50 -05:00
ginnoir d5a54b24cc Mark TB-001 backup stack complete.
Kopia+B2 deployed, cron scheduled, ntfy wired, restore tests passed.
2026-06-10 22:17:29 -05:00
ginnoir c053f285b8 Fix backup cron scripts for Kopia password and MariaDB dumps.
Pass KOPIA_REPOSITORY_PASSWORD into snapshot create; use MARIADB_ROOT_PASSWORD for romm and bookstack app user for bookstack root mismatch.
2026-06-10 22:01:26 -05:00
ginnoir 4bb9413391 Set explicit Kopia UI credentials for web login.
Use HTTP basic auth username kopia with KOPIA_REPOSITORY_PASSWORD; document in README.
2026-06-10 21:38:10 -05:00
ginnoir 9878f17673 Add internal-only Caddy proxy for Kopia backup UI.
backup.ginnoir.com reverse-proxies kopia:51515; regenerate bookmark pages.
2026-06-10 21:32:06 -05:00
ginnoir bb18e0e338 Mount backup scripts from /config/backup on host.
Portainer CE git stacks cannot bind-mount relative repo paths; sync auxiliary files to the host path documented in README.
2026-06-10 21:28:56 -05:00
ginnoir f660bc9c4b Fix backup stack env for Portainer git deploy.
Remove compose ${VAR} overrides that blanked stack.env values and map KOPIA_REPOSITORY_PASSWORD in init-kopia; use hostname-only B2 endpoint.
2026-06-10 21:26:02 -05:00
ginnoir 7c7f6dfebc Add Kopia backup stack with Backblaze B2 offsite target.
Protects /config, selective labdata, and nightly DB dumps; documents homelab improvement plan briefs.
2026-06-10 21:21:34 -05:00
ginnoir 225078afbe chore(roms): pin romm to 4.9.0-beta.2 for save-sync endpoints + content_hash fix 2026-06-09 18:36:14 -05:00
ginnoir 3cc86d866f fix(vault): raise memlock ulimit to unlimited
Newer hashicorp/vault:latest mlocks more memory than docker's default
64KB memlock ulimit allows; vault crash-looped for ~5900 restarts with
'Failed to lock memory: cannot allocate memory' despite cap_add IPC_LOCK.
Deployed via apply-compose.ps1 -Portainer (mgmt plane, not a git stack).
2026-06-09 18:06:38 -05:00
ginnoir 7aa95fa00a refactor: pure env_file stack.env convention across all stacks
Every service now reads stack.env via env_file with container-exact var
names — no ${VAR} parse-time interpolation, no Portainer UI env vars
(except stacks/dev, kept on UI-env interpolation as documented exception).

- media: drop PUID/PGID/TZ env lines (env_file covers); resolve ${ROOT}
- foundry: secrets via env_file; FOUNDRY_PATCH_URLS -> CONTAINER_PATCH_URLS
- monitoring: HOMARR_SECRET_ENCRYPTION_KEY -> SECRET_ENCRYPTION_KEY
- notify: FRESHRSS_USER composed in stack.env; TZ via env_file
- owncloud: container-exact OWNCLOUD_*/MYSQL_* keys; runtime $$ healthcheck
- resume/famapp: composites (DATABASE_URL etc.) written out in stack.env
- authentik: container-exact keys; image tag pinned in compose
- notes: couchdb creds via env_file
- remote: gains stack.env (no secrets; convention completeness)
- CLAUDE.md: env convention, valhalla-lab registration-only note, correct
  on-host Portainer working-copy path (/config/portainer/compose/<id>)

Validated with docker compose config on valhalla for all 15 stacks.
2026-06-09 16:03:47 -05:00
ginnoir bb2bc6a20e feat: serve romhack archive site
Deploy to valhalla / deploy (push) Has been cancelled
2026-06-08 21:17:22 -05:00
ginnoir 27aa1bf2fe fix(romhacks): only link library files that exist on disk
handoff.json lists files captured at routing time, but the
extraction-cruft cleanup later removes files extracted out of a kept
archive. The Caddy file_server can only serve real files (not archive
interiors), so existence-filter the art + guide rel-paths against
library/<slug>/ before embedding/linking them — dropping phantom
entries that would 404.
2026-06-08 05:02:34 -05:00
ginnoir 9210cd23f8 feat(romhacks): serve library over internal Caddy file_server; notes embed art + guide links
Deploy to valhalla / deploy (push) Has been cancelled
- proxy: read-only bind /storage1/labdata/romhacks/library -> /srv/romhacks
- Caddyfile: romhacks-files.ginnoir.com (internal_only) file_server + browse
- render_catalog_notes.py + handoff.py: embed box art and link guides/
  spreadsheets via https://romhacks-files.ginnoir.com/<slug>/<file>
  (handoff art/guides; guide filter drops buried game-data txt, caps at 30)
- regenerate bookmarks
2026-06-08 04:44:38 -05:00
ginnoir 8224a8fddb chore(romhacks): catalog publisher tooling (analyze + render Obsidian notes) 2026-06-08 04:25:58 -05:00
ginnoir ae57c7f661 chore(romhacks): add extraction-cruft cleanup script (keeps archives, audits for loss) 2026-06-08 03:38:37 -05:00
ginnoir 1360a8fa65 feat(romhacks): automated hand-off — route downloads to RomM + library, render notes
handoff.py classifies completed downloads (console rom vs RPG-Maker fangame vs
patch, via bsdtar archive peek incl. RAR5), copies console roms into
Emulation/roms/<platform> for RomM, moves the full folder (rom + guides) into
the library archive, and renders note.md + handoff.json per hack for the
Obsidian publish step. Wired into the cycle; single /data mount keeps moves as
fast renames. Validated on 4 real games.
2026-06-07 20:25:30 -05:00
ginnoir 328b5df776 feat(romhacks): arm downloads (DRY_RUN=false) + fix dry-run state burn
process_file now marks messages processed only after a real crawljob write, so
DRY_RUN no longer poisons the state and link-less posts get re-checked after the
host filter widens. State file reset alongside this so the arm cycle re-enqueues
all threads.
2026-06-07 19:55:00 -05:00
ginnoir 4fda9a3b3e feat(romhacks): widen host filter (pokeharbor, raw.githubusercontent, pokehostel) 2026-06-07 19:40:01 -05:00
ginnoir d9724f39e6 fix(romhacks): build on Alpine DCE base (apk + self-contained CLI)
The tyrrrz/discordchatexporter image is Alpine, not Debian, and ships DCE as a
self-contained executable (no dotnet on PATH). Use apk for python3 and invoke
/opt/app/DiscordChatExporter.Cli directly.
2026-06-07 18:57:42 -05:00
ginnoir ba207a0fcd feat(romhacks): add Discord rom-hack ingestion stack (DCE -> JDownloader -> RomM)
Inert by default: empty token keeps the orchestrator idle and DRY_RUN=true
suppresses downloads. Orchestrator exports per-generation forum threads via
DiscordChatExporter, extracts download links + art, stages metadata, and writes
JDownloader crawljobs. Armed here with an alt account token and all 11 romhack
forums, still in DRY_RUN pending first-cycle validation.
2026-06-07 18:53:23 -05:00
ginnoir 91d6724175 feat(deck): add SteamGridDB batch art scripts and skill
scripts/deck-sgdb-art.py  — runs on Deck; fetches hero, wide capsule,
and portrait/poster art from SGDB for all RomM-synced shortcuts.
scripts/deck-sgdb-art.ps1 — Windows wrapper; handles SSH ASKPASS
upload and execution.
.claude/skills/deck-sgdb/ — Claude skill documenting invocation,
file naming conventions, appid formula, and known gotchas.
2026-06-07 18:17:45 -05:00
ginnoir 49bda4234a fix(caddy): make roms.ginnoir.com internal-only
Deploy to valhalla / deploy (push) Has been cancelled
External access for a trusted friend now goes through the share stack's
Tailscale serve node (roms-share.<tailnet>.ts.net), so roms.ginnoir.com
no longer needs public exposure. Add import internal_only (LAN + tailnet).
2026-06-06 23:18:22 -05:00
ginnoir bf68f5a3da fix(share): absolute host bind for serve config
Portainer's git-stack checkout does not materialize sibling repo files
at the relative bind path, so ./serve-roms.json mounted as an empty
auto-created directory and tailscale serve failed ('is a directory').
Switch to an absolute /config/share/serve-roms.json bind (matching every
other stack's /config convention); the file is mirrored on the host.
2026-06-06 23:06:30 -05:00
ginnoir 2aa8122cd3 feat(share): Tailscale serve stack to share internal services with external tailnet users
Adds stacks/share/ — a dedicated stack of userspace Tailscale 'serve'
nodes that expose individual internal services to external tailnet
users (a friend on his own tailnet) over each node's 100.x identity.
No public exposure, no LAN access, immune to the friend's home-subnet
addressing. First node ts-roms serves RomM at roms-share.<tailnet>.ts.net
-> romm:8080. One reusable tag:share auth key + one ACL rule cover every
node; adding a service is a serve-<svc>.json + a copied service block.

roms stack reverted to a pointer comment.
2026-06-06 22:52:15 -05:00
ginnoir dc0a4eb58f revert(caddy): drop RomM empty-Bearer workaround
Deploy to valhalla / deploy (push) Has been cancelled
decky-romm-sync has completed its first-run token mint, so the
Authorization: Bearer (empty token) probe that crashed RomM 4.8.x no
longer occurs. Collapse roms.ginnoir.com back to a plain reverse_proxy.
2026-06-06 20:53:19 -05:00
ginnoir cb18047973 feat: add RomM save staging and import utility scripts 2026-06-06 20:51:52 -05:00
ginnoir ca4cdf3d8a fix(caddy): allow Tailscale CGNAT range in internal_only snippet
Deploy to valhalla / deploy (push) Has been cancelled
Tailnet clients that reach Caddy without subnet-route SNAT arrive from
100.64.0.0/10 and were getting 403 from LAN-only site blocks. Add the
range to the internal_only matcher so split-DNS tailnet access works
regardless of the --snat-subnet-routes setting.
2026-06-06 20:31:39 -05:00
ginnoir 04202a97b7 feat: add RomM database path mismatch resolver script 2026-06-06 19:50:21 -05:00
ginnoir 3bcfe26db9 chore: track Codex/Antigravity agent config (.agents skills + .codex) 2026-06-06 19:44:51 -05:00
ginnoir cba0ae7f4b docs: add AGENTS.md pointer so Codex/Antigravity load project context 2026-06-06 18:24:22 -05:00
ginnoir a96ff619a8 fix(caddy): strip empty Bearer header on roms so RomM stops 500ing decky-romm-sync
Deploy to valhalla / deploy (push) Has been cancelled
RomM 4.8.x crashes with HTTP 500 on a malformed Authorization header:
hybrid_auth.py unpacks `scheme, token = header.split()` with no guard, so
any value without exactly two space-separated parts raises ValueError.

decky-romm-sync >=0.20.0 (Client API Token auth, added 2026-06-05) sends
`Authorization: Bearer ` with an empty token on its first-run heartbeat/
platforms/devices probes, before it has minted a token, which trips that
crash and deadlocks setup. The Basic-auth mint (POST /api/client-tokens)
is never reached.

Strip the empty-token header for the roms host so the probe gets a clean
200 and the mint can run; thereafter the plugin sends a real Bearer rmm_
token. Well-formed Bearer tokens and browser session-cookie auth are
unaffected. Remove once the plugin omits the empty header or RomM guards
the split.
2026-06-06 16:00:25 -05:00
ginnoir 7ec4e2ca57 chore: spin off Pokémon ROM-hack material to standalone repo
The Pokémon catalog + pipeline are moved out of this infra repo. The catalog
notes now live in the self-hosted Obsidian vault (Pokémon ROM Hacks/); the
acquisition/patching scripts live in their own repo at Documents\pokemon.
homelabstack stays focused on the homelab.

- rm pokemon-romhack-vault/ (75 hack notes + Index/Types/README/Platforms)
- rm scripts/{build-romhack-vault,romhack-import,romhack-fetch,romhack-apply}.py
- rm pokemon-romhacks-wanted.md
- .gitignore: drop the now-dead pokemon/ drop-folder rule
- .claude/skills/vault/SKILL.md: condense the Pokemon-vault subtree to a one-line pointer

RomM stack (stacks/roms) and the general igir library scripts stay.
2026-06-06 15:49:26 -05:00