Backs the Obsidian 'Second Brain' vault (private repo: git.hobbs.farm/jeremy/
second-brain) with self-hosted multi-device sync. LAN-only for now; no public
Traefik route yet.
- couchdb:3.4 pinned, Watchtower disabled, mem_limit 1g.
- Data on LOCAL disk (/var/lib/couchdb) -- CouchDB file locking breaks over
NFSv3, same class as guacamole-db and semaphore-db.
- local.ini mounted READ-WRITE, deliberately: CouchDB 3.x writes runtime config
back into the last-loaded ini, and with :ro it exits 1 and logs NOTHING --
a silent crash-loop that is very hard to diagnose.
- CORS allows app://obsidian.md and capacitor://localhost (LiveSync desktop +
mobile origins); a wildcard origin is not allowed alongside credentials.
- require_valid_user everywhere EXCEPT /_up, so the blackbox probe can health
check it without credentials. Anonymous callers get 401 on all data.
- Admin credentials in Vaultwarden ('CouchDB - Obsidian LiveSync'); .env is
gitignored, .env.example carries a placeholder.
Prometheus probe added (probe_success=1). Vault database: 'secondbrain'.
Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
Evaluated and torn down at the user's request. Container, image, source
(/opt/lifeos), SQLite data (/var/lib/lifeos) and compose dir removed from
hf-pdocker-02; Prometheus probe removed and both instances reloaded; port
8095 released.
Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
The container served a blank page. Four upstream assumptions broke a
root-served, Supabase-less deployment; all are patched at build time with
grep assertions so a silent upstream rename fails the build instead of
shipping a blank page again.
- React Router was pinned to basename '/app' (upstream is hosted under an
/app path). At '/' it matched no route and rendered nothing -- silently,
with only a console warning. This was the blank page.
- supabase.ts calls createClient() at module scope, which throws
'supabaseUrl is required' on an empty string and killed the bundle before
React mounted. Dummy values fix it; nothing reads Supabase in local mode.
- initAuth() only booted the local user for Tauri/Electron, so a browser
build fell through to a Supabase login screen the backend cannot serve
(it has no /api/auth/login or /api/auth/signup -- it is single-user).
- The local API adapter has no realtime layer, so supabase.channel() was
undefined and every subscribing component tripped the ErrorBoundary
('Something went wrong'). Added no-op stubs; realtime is meaningless on a
single-user instance.
Verified in a browser: dashboard and routed pages render, 0 fatal errors.
Known gap: the Flask backend implements only a subset of the cloud schema,
so quests, messages, partnerships, grocery_lists, recurring_transactions,
junction_traditions and habit_suggestions 404. Non-fatal; those features
degrade. Core (tasks/habits/goals/health/finance/journal/XP/AI chat) works.
Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
Post-Swarm: node-exporter must run standalone with pid:host, since Swarm mode
blocked it and cross-node /proc namespaces contaminated swap metrics. Marks the
stacks/ definition superseded.
Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
Self-hosted LifeOS (github.com/lifeos-app/lifeos, pinned 3009bf6) in local
mode: no Supabase. Multi-stage build - Node builds the Vite bundle, gunicorn
serves it plus the bundled Flask/SQLite API from one process.
LAN-only on purpose: the backend is single-user with no auth, so anyone who
reaches the port has full read/write. Needs Traefik basicAuth before it can
ever be exposed publicly.
Two upstream bugs patched via sed (build fails loudly if they are renamed):
the chat model was hardcoded to the author's private 'sentient-teddy' bridge,
and a hardcoded 30s timeout failed every first message because Ollama needs
~46s to cold-load the model (0.7s warm). Both are env vars now.
SQLite stays on local disk - NFSv3 breaks WAL locking.
Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
Watchtower pulled gitea/gitea:latest three times (Mar 12, Apr 19, Apr 25)
and at least one pull resulted in a broken image with git binary failures.
Pin to stable gitea/gitea:1.26.1 and add watchtower.enable=false label
so the image is only updated by deliberate human action.
Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>