feat: deploy CouchDB on hf-pdocker-02 for Obsidian LiveSync (:5984)

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>
This commit is contained in:
2026-07-11 12:03:15 -05:00
parent f0e2918bd1
commit 0e4b2f7d1a
3 changed files with 59 additions and 0 deletions
@@ -0,0 +1,2 @@
COUCHDB_USER=obsidian
COUCHDB_PASSWORD=REPLACE_AT_DEPLOY
@@ -0,0 +1,27 @@
services:
couchdb:
image: couchdb:3.4
container_name: couchdb
restart: unless-stopped
ports:
- "5984:5984"
environment:
- COUCHDB_USER=${COUCHDB_USER}
- COUCHDB_PASSWORD=${COUCHDB_PASSWORD}
- TZ=America/Chicago
volumes:
# LOCAL disk, not NFS: CouchDB's file locking breaks over NFSv3, the same
# way it did for guacamole-db (MySQL) and semaphore-db.
- /var/lib/couchdb/data:/opt/couchdb/data
# NOT :ro -- CouchDB 3.x writes runtime config back into the last-loaded ini.
# With a read-only mount it exits 1 immediately and logs NOTHING at all.
- /var/lib/couchdb/config/local.ini:/opt/couchdb/etc/local.d/local.ini
labels:
- "com.centurylinklabs.watchtower.enable=false"
mem_limit: 1g
healthcheck:
test: ["CMD", "curl", "-fsS", "http://localhost:5984/_up"]
interval: 60s
timeout: 10s
retries: 3
start_period: 30s
+30
View File
@@ -0,0 +1,30 @@
; CouchDB config for Obsidian LiveSync.
; Obsidian talks to CouchDB from an app:// origin, so CORS must allow it explicitly --
; a wildcard origin is not permitted alongside credentials.
[couchdb]
single_node = true
max_document_size = 50000000
[chttpd]
require_valid_user = true
; ...but leave /_up open, so the Prometheus blackbox probe can health-check it
; without credentials. Everything else still returns 401 to anonymous callers.
require_valid_user_except_for_up = true
max_http_request_size = 4294967296
bind_address = 0.0.0.0
[chttpd_auth]
require_valid_user = true
authentication_redirect = /_utils/session.html
[httpd]
WWW-Authenticate = Basic realm="couchdb"
enable_cors = true
[cors]
credentials = true
; Obsidian desktop is app://obsidian.md; mobile uses capacitor://localhost.
origins = app://obsidian.md,capacitor://localhost,http://localhost
methods = GET,PUT,POST,HEAD,DELETE
headers = accept,authorization,content-type,origin,referer,x-csrf-token