feat(obsidian): add CouchDB stack for Obsidian LiveSync sync

Self-hosted sync backend for the Obsidian LiveSync plugin, following
https://blog.admin-intelligence.de/selbsthosting-von-obsidian-mit-couchdb-kostenlose-synchronisation-einrichten/.
local.ini.example carries the required chttpd/cors config; local.ini itself
is gitignored since CouchDB rewrites it in place (hashed admin password,
node uuid) on first start, so a tracked copy would never stay clean. The
config also has to be mounted read-write, not :ro: CouchDB's entrypoint
chowns everything under /opt/couchdb and aborts under set -e if that fails.

Co-Authored-By: Claude Sonnet 5 <noreply@anthropic.com>
This commit is contained in:
2026-08-20 20:54:55 +02:00
co-authored by Claude Sonnet 5
parent 00cc3583ec
commit a9f9a6765b
5 changed files with 77 additions and 0 deletions
+36
View File
@@ -0,0 +1,36 @@
services:
obsidian:
image: couchdb:latest
container_name: obsidian
environment:
TZ: ${TIMEZONE:-Europe/Amsterdam}
COUCHDB_USER: ${COUCHDB_USER}
COUCHDB_PASSWORD: ${COUCHDB_PASSWORD}
volumes:
- ../.data/obsidian:/opt/couchdb/data
- ./local.ini:/opt/couchdb/etc/local.d/local.ini
restart: always
healthcheck:
test: ["CMD-SHELL", "curl -sf -u \"$$COUCHDB_USER:$$COUCHDB_PASSWORD\" http://localhost:5984/_up || exit 1"]
interval: 5s
timeout: 5s
retries: 5
labels:
- "traefik.enable=true"
- "traefik.http.middlewares.obsidian-redirect-web-secure.redirectscheme.scheme=https"
- "traefik.http.routers.obsidian-web.middlewares=obsidian-redirect-web-secure"
- "traefik.http.routers.obsidian-web.rule=Host(`${TRAEFIK_HOST}`)"
- "traefik.http.routers.obsidian-web.entrypoints=web"
- "traefik.http.routers.obsidian-web-secure.rule=Host(`${TRAEFIK_HOST}`)"
- "traefik.http.routers.obsidian-web-secure.tls.certresolver=resolver"
- "traefik.http.routers.obsidian-web-secure.entrypoints=web-secure"
- "traefik.http.routers.obsidian-web-secure.middlewares=security-headers@file,no-index@file"
- "traefik.http.services.obsidian-web-secure.loadbalancer.server.port=5984"
- "traefik.docker.network=${NETWORK_NAME}"
networks:
- compose_network
networks:
compose_network:
name: ${NETWORK_NAME}
external: true