From cff802bd3fd6c7e8873b91f3a1ef8f4567cebbe2 Mon Sep 17 00:00:00 2001 From: Julien Calixte Date: Mon, 1 Jun 2026 20:45:32 +0200 Subject: [PATCH] fix: drop curl healthcheck and cors.ini mount; configure CORS via API The couchdb:3 image purges curl after the build, so the curl-based healthcheck could never succeed. The cors.ini bind-mount also looks like the cause of the ~600ms container exit observed in the first two Coolify deploys. Both pieces are removed; CORS is now applied by the init sidecar via PUTs against /_node/_local/_config/..., which is idempotent on redeploy. --- README.md | 13 +++++++------ couchdb/local.d/cors.ini | 8 -------- docker-compose.yml | 37 ++++++++++++++++++++++++++----------- 3 files changed, 33 insertions(+), 25 deletions(-) delete mode 100644 couchdb/local.d/cors.ini diff --git a/README.md b/README.md index 539664d..45da022 100644 --- a/README.md +++ b/README.md @@ -1,6 +1,6 @@ # coolcouch -CouchDB 3 on Coolify, with CORS enabled and system databases bootstrapped at first start. +CouchDB 3 on Coolify. The `couchdb-init` sidecar waits for the server to come up, creates the three system databases, and enables CORS via the config API — no file mounts required. ## Deploy @@ -9,7 +9,7 @@ CouchDB 3 on Coolify, with CORS enabled and system databases bootstrapped at fir - `COUCHDB_PASSWORD` — required - `COUCHDB_USER` — optional, defaults to `admin` 3. In the resource's **Domains** tab, assign a domain to the `couchdb` service on port `5984`. Coolify fills `SERVICE_FQDN_COUCHDB_5984` from this. -4. **Deploy.** The `couchdb-init` one-shot service will wait for CouchDB to be healthy, then `PUT` `_users`, `_replicator`, `_global_changes` and exit. +4. **Deploy.** `couchdb-init` runs once, exits, and won't restart. ## Verify @@ -24,13 +24,14 @@ curl -fsS -I -X OPTIONS https://$DOMAIN/ \ -H "Access-Control-Request-Method: GET" ``` -Expected: `_up` returns `{"status":"ok",...}`; `/` returns the CouchDB welcome JSON; `_all_dbs` returns `["_global_changes","_replicator","_users"]`; the preflight returns a 2xx with an `Access-Control-Allow-Origin` header. +Expected: `_up` returns `{"status":"ok",...}`; `/` returns the CouchDB welcome JSON; `_all_dbs` returns `["_global_changes","_replicator","_users"]`; the preflight returns 2xx with an `Access-Control-Allow-Origin` header. + +If the init logs show CORS errors, you can re-trigger only that step by redeploying — the PUTs against `/_node/_local/_config/...` are idempotent. ## CORS -Wildcard origin (`*`), `credentials = false` — the only browser-spec-legal combination with a wildcard. If a client needs cookie/credentialed auth, switch `origins` in `couchdb/local.d/cors.ini` to an explicit list and set `credentials = true`. +Wildcard origin (`*`) with `credentials = false` — the only browser-spec-legal combination with a wildcard. For credentialed auth from the browser, edit the `put_config cors origins`/`credentials` lines in `docker-compose.yml`. ## Files -- `docker-compose.yml` — services, volume, Traefik labels, healthcheck, init sidecar -- `couchdb/local.d/cors.ini` — mounted into `/opt/couchdb/etc/local.d/` so CouchDB picks it up at startup +- `docker-compose.yml` — services, volume, Traefik labels, init sidecar diff --git a/couchdb/local.d/cors.ini b/couchdb/local.d/cors.ini deleted file mode 100644 index ee4b778..0000000 --- a/couchdb/local.d/cors.ini +++ /dev/null @@ -1,8 +0,0 @@ -[chttpd] -enable_cors = true - -[cors] -origins = * -credentials = false -methods = GET, PUT, POST, HEAD, DELETE -headers = accept, authorization, content-type, origin, referer, x-csrf-token diff --git a/docker-compose.yml b/docker-compose.yml index 65fd6c8..5f5cb04 100644 --- a/docker-compose.yml +++ b/docker-compose.yml @@ -10,13 +10,6 @@ services: - "5984" volumes: - couchdb_data:/opt/couchdb/data - - ./couchdb/local.d/cors.ini:/opt/couchdb/etc/local.d/cors.ini:ro - healthcheck: - test: ["CMD", "curl", "-fsS", "http://localhost:5984/_up"] - interval: 10s - timeout: 5s - retries: 12 - start_period: 30s labels: - "traefik.enable=true" - "traefik.http.routers.couchdb.rule=Host(`${SERVICE_FQDN_COUCHDB_5984}`)" @@ -28,8 +21,7 @@ services: image: curlimages/curl:latest restart: "no" depends_on: - couchdb: - condition: service_healthy + - couchdb environment: COUCHDB_USER: ${COUCHDB_USER:-admin} COUCHDB_PASSWORD: ${COUCHDB_PASSWORD} @@ -38,13 +30,36 @@ services: - | set -eu base="http://$${COUCHDB_USER}:$${COUCHDB_PASSWORD}@couchdb:5984" + + echo "waiting for couchdb..." + i=0 + until curl -fsS "http://couchdb:5984/_up" >/dev/null 2>&1; do + i=$$((i + 1)) + if [ $$i -gt 60 ]; then + echo "couchdb did not become ready in 120s"; exit 1 + fi + sleep 2 + done + echo "couchdb ready" + for db in _users _replicator _global_changes; do code=$$(curl -s -o /dev/null -w "%{http_code}" -X PUT "$$base/$$db") case "$$code" in - 201|202|412) echo "$$db: ok ($$code)" ;; - *) echo "$$db: failed ($$code)"; exit 1 ;; + 201|202|412) echo "db $$db: ok ($$code)" ;; + *) echo "db $$db: failed ($$code)"; exit 1 ;; esac done + put_config() { + curl -fsS -X PUT -H "Content-Type: application/json" \ + "$$base/_node/_local/_config/$$1/$$2" -d "\"$$3\"" >/dev/null + echo "cfg $$1/$$2 = $$3" + } + put_config chttpd enable_cors true + put_config cors origins '*' + put_config cors credentials false + put_config cors methods 'GET, PUT, POST, HEAD, DELETE' + put_config cors headers 'accept, authorization, content-type, origin, referer, x-csrf-token' + volumes: couchdb_data: