11 Commits
Author SHA1 Message Date
ginnoirandClaude Opus 5 f70963e166 fix(proxy): pin public resolvers on caddy so ACME DNS-01 works
Deploy Caddyfile to valhalla / deploy (push) Successful in 1m32s
The LAN resolver (OPNsense Unbound) is authoritative for ginnoir.com via the
split-horizon override, but its local-zone holds only A records, so
`SOA ginnoir.com` returns NODATA. certmagic's zone lookup walks up the label
chain hunting for an SOA, finds none at ginnoir.com, climbs to `com.`, and asks
Cloudflare for a `com` zone:

  adding temporary record for zone "com.": expected 1 zone, got 0 for com.

Every DNS-01 renewal has failed for ~17 days (attempt 91 on the oldest), and
Caddy fell back to the LE staging endpoint. Certs began expiring as they rolled
off: 5etools (-4d), files (-1.9d), auth (-15.6h), fam (-15.6h), with ~20 more
queued behind them.

The expired auth.ginnoir.com cert is what broke Nextcloud SSO: its server-side
discovery fetch fails TLS verification ("certificate has expired"), and
user_oidc's LoginController catches that and returns 404 "provider unreachable".
Browsers were unaffected because they let you click through an expired cert;
PHP/curl does not.

Pinning 1.1.1.1/1.0.0.1 on the caddy container sends the SOA lookup to public
DNS. Verified Docker's embedded resolver still serves container names and the
gitea.ginnoir.com alias, which take priority over the external servers.

Also corrects the imgstudio comment, which credited its working TLS to avoiding
a "false .com" in the hostname. The actual reason was its explicit `resolvers`
line -- the same fix, applied to one site.

Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
2026-08-05 09:51:54 -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
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 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 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 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 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 1e2970d220 chore: add env_file: stack.env to all compose services
Portainer git-stack deployments require an explicit env_file reference
in the compose file to load variables from the repo's stack.env.
Adds env_file: [stack.env] before every service-level environment:
block across all 10 stacks.
2026-06-04 22:11:51 -05:00
ginnoir 441e1ee272 chore: rename stack .env files to stack.env for Portainer git stack compatibility
Portainer git-stack deploys require stack.env (not .env) in the repo.
Renames all stacks/*/. env → stacks/*/stack.env so Portainer reads
secrets directly from git on each redeploy, making the repo the single
source of truth instead of requiring manual UI sync.

Also fixes the dev stack BOOKSTACK_APP_KEY gap — the key was already
present in the file but missing from Portainer's stored envVars; it
will now be picked up automatically from stack.env on next redeploy.

Updates CLAUDE.md to reflect the new filename convention.
2026-06-04 21:41:56 -05:00
ginnoir 57cd6ed270 refactor: split monolith into per-domain stacks (Phase A: build)
Add stacks/<domain>/ compose + env for the 11 target stacks (proxy, media,
foundry, owncloud, resume, famapp, authentik, notify, monitoring, remote, dev).
Each app stack joins a shared external `edge` network for Caddy and keeps its
DB/cache co-located (no shared backing services). All named volumes convert to
tiered bind mounts: DBs/configs -> /config (SSD), blobs/repos/registry ->
/storage1/labdata (ZFS). Gitea repos+LFS split to ZFS.

Move Vault into the management plane (portainer-compose.yml) and add the shared
`edge` network there. apply-compose.ps1 -Portainer now also pushes vault.hcl.

Additive only: root docker-compose.yml/.env/Caddyfile untouched, so the live
monolith is unchanged. Live cutover (Phase B) is next.
2026-06-04 16:11:31 -05:00