mirror of
https://github.com/MBombeck/HealthLog.git
synced 2026-11-09 04:50:59 +00:00
Merge the release with the security review fixes into the data-safety review fixes
This commit is contained in:
commit
bcb31c80db
98 files changed
+3166
-608
No files matched your search
@@ -11,7 +11,11 @@
|
||||
# empty the new database and run the move again.
|
||||
# 5. Empty the new volume: it must refuse to import the old state again,
|
||||
# and move it once more after the marker is removed as the guide says.
|
||||
# 6. A new install with no old volume: nothing to do.
|
||||
# 6. Going back to 16 after a move that did not finish: db-upgrade leaves
|
||||
# the live 16 database alone.
|
||||
# 7. Using 16 again after a move, then updating: refused, not the old copy.
|
||||
# 8. Updating again as the guide says: the current 16 database moves.
|
||||
# 9. A new install with no old volume: nothing to do.
|
||||
#
|
||||
# Needs Docker and the repo's node_modules (for the migrations). Run it from
|
||||
# anywhere in the repo: `bash scripts/compose-db-upgrade-check.sh`.
|
||||
@@ -85,7 +89,7 @@ wait_for_port() {
|
||||
migrate_old() {
|
||||
local started=$SECONDS
|
||||
until DATABASE_URL="postgresql://healthlog:$POSTGRES_PASSWORD@127.0.0.1:$PORT/healthlog?schema=public" \
|
||||
node "$ROOT/node_modules/prisma/build/index.js" migrate deploy --schema "$ROOT/prisma/schema.prisma" >"$WORK/migrate.log" 2>&1; do
|
||||
node "$ROOT/node_modules/prisma/build/index.js" migrate deploy --schema "$WORK/old-prisma/prisma/schema.prisma" >"$WORK/migrate.log" 2>&1; do
|
||||
if [ $((SECONDS - started)) -ge 30 ] || ! grep -q "P1001" "$WORK/migrate.log"; then
|
||||
cat "$WORK/migrate.log" >&2
|
||||
return 1
|
||||
@@ -94,6 +98,18 @@ migrate_old() {
|
||||
done
|
||||
}
|
||||
|
||||
# The v1.45 schema, migrated with v1.45's own migrations.
|
||||
mkdir -p "$WORK/old-prisma"
|
||||
git -C "$ROOT" archive "$OLD_REF" prisma | tar -x -C "$WORK/old-prisma"
|
||||
# The current compose file with its database pointed back at Postgres 16, the
|
||||
# way docs/ops/postgres-major-upgrade.md "Going back" describes it.
|
||||
sed -e 's|image: postgres:18\.[0-9]*-alpine|image: postgres:16.15-alpine|' \
|
||||
-e 's|- postgres-data:/var/lib/postgresql$|- pgdata:/var/lib/postgresql/data|' \
|
||||
"$ROOT/docker-compose.yml" >"$WORK/back.yml"
|
||||
grep -q 'image: postgres:16.15-alpine' "$WORK/back.yml" && grep -q -- '- pgdata:/var/lib/postgresql/data' "$WORK/back.yml" ||
|
||||
{ echo "FAIL: could not derive the going-back compose file" >&2; exit 1; }
|
||||
back() { docker compose -p "$PROJECT" -f "$WORK/back.yml" "$@"; }
|
||||
|
||||
down_all
|
||||
step "a v1.45 database on Postgres 16"
|
||||
old up -d --wait db >"$WORK/up.log" 2>&1 || { cat "$WORK/up.log" >&2; fail "the v1.45 database did not start"; }
|
||||
@@ -157,10 +173,42 @@ CODE=$(run_upgrade)
|
||||
[ "$CODE" = 0 ] || fail "db-upgrade exited $CODE after the marker was removed"
|
||||
[ "$(probe docker exec healthlog-db)" = "$PROBE" ] || fail "the probe rows differ after starting over"
|
||||
|
||||
step "going back to 16 after a move that did not finish leaves 16 alone"
|
||||
new down >/dev/null 2>&1
|
||||
docker volume rm "${PROJECT}_postgres-data" >/dev/null
|
||||
docker run --rm -v "${PROJECT}_pgdata:/old" postgres:16.15-alpine \
|
||||
mv /old/HEALTHLOG_MOVED_TO_POSTGRES_18 /old/HEALTHLOG_MOVING_TO_POSTGRES_18
|
||||
back up -d db-upgrade >/dev/null 2>&1 || true
|
||||
CODE=$(docker wait healthlog-db-upgrade)
|
||||
upgrade_log
|
||||
[ "$CODE" = 0 ] || fail "db-upgrade exited $CODE beside a Postgres 16 database service"
|
||||
upgrade_log | grep -q 'not 18: nothing to move' || fail "db-upgrade did not recognise the Postgres 16 service"
|
||||
[ "$(probe docker exec healthlog-db)" = "$PROBE" ] || fail "the live Postgres 16 data changed beside db-upgrade"
|
||||
|
||||
step "using 16 again after a move, then updating, is refused instead of serving the old copy"
|
||||
back down >/dev/null 2>&1
|
||||
CODE=$(run_upgrade)
|
||||
[ "$CODE" = 0 ] || fail "the move after going back exited $CODE"
|
||||
back up -d db >/dev/null 2>&1
|
||||
back exec -T db psql -U healthlog -d healthlog -v ON_ERROR_STOP=1 -qc \
|
||||
"INSERT INTO check_probe.rows VALUES (50001, 'written on 16 after the move')"
|
||||
back down >/dev/null 2>&1
|
||||
CODE=$(run_upgrade)
|
||||
[ "$CODE" = 1 ] || fail "db-upgrade exited $CODE after 16 was used again, expected 1"
|
||||
upgrade_log | grep -q 'changed after it was moved' || fail "the refusal did not say that 16 changed"
|
||||
|
||||
step "updating again as the guide says moves the current 16 database"
|
||||
new down >/dev/null 2>&1
|
||||
docker volume rm "${PROJECT}_postgres-data" >/dev/null
|
||||
new run --rm --entrypoint rm db-upgrade /var/lib/postgresql/data/HEALTHLOG_MOVED_TO_POSTGRES_18 >/dev/null 2>&1
|
||||
CODE=$(run_upgrade)
|
||||
[ "$CODE" = 0 ] || fail "db-upgrade exited $CODE when moving the current 16 database"
|
||||
[ "$(sql "SELECT count(*) FROM check_probe.rows")" = 50001 ] || fail "the row written on 16 did not arrive"
|
||||
|
||||
step "a new install: nothing to do"
|
||||
new down -v >/dev/null 2>&1
|
||||
CODE=$(run_upgrade)
|
||||
[ "$CODE" = 0 ] || fail "db-upgrade exited $CODE on a new install"
|
||||
upgrade_log | tail -1 | grep -q 'no Postgres 16 database to move' || fail "the new install did not say there was nothing to move"
|
||||
|
||||
echo "OK: the Postgres 16 -> 18 move behaves in all six cases"
|
||||
echo "OK: the Postgres 16 -> 18 move behaves in all nine cases"
|
||||
@@ -268,7 +268,12 @@
|
||||
},
|
||||
{
|
||||
"name": "DEPLOY_WEBHOOK_REQUIRE_TIMESTAMP",
|
||||
"purpose": "\"true\" (or \"1\") accepts only signed deploy-webhook requests (X-Deploy-Webhook-Signature with a fresh X-Deploy-Webhook-Timestamp); the secret header alone is refused with 401. Leave unset for Coolify's stock sender, which can only send the secret header.",
|
||||
"purpose": "\"true\" (or \"1\") requires a fresh X-Deploy-Webhook-Timestamp (within 5 minutes) on a deploy-webhook request that authenticates with the secret header; one without it is refused with 401. Keeps a stale capture out, not a fresh forgery by someone who saw the secret. Leave unset for Coolify's stock sender, which sends no timestamp.",
|
||||
"example": "true"
|
||||
},
|
||||
{
|
||||
"name": "DEPLOY_WEBHOOK_REQUIRE_SIGNATURE",
|
||||
"purpose": "\"true\" (or \"1\") accepts only signed deploy-webhook requests (X-Deploy-Webhook-Signature with a fresh X-Deploy-Webhook-Timestamp); the secret header alone is refused with 401. The setting that stops a replay. Leave unset for Coolify's stock sender, which can only send the secret header.",
|
||||
"example": "true"
|
||||
}
|
||||
]
|
||||
@@ -432,6 +437,11 @@
|
||||
"purpose": "Trusted reverse-proxy hop count; the client IP is read that many entries from the right of X-Forwarded-For. Forwarding headers are read only from a peer whose own address is not public (loopback, private, CGNAT, unique-local, link-local, reserved, multicast).",
|
||||
"example": "1"
|
||||
},
|
||||
{
|
||||
"name": "TRUSTED_PROXY_CIDRS",
|
||||
"purpose": "Comma-separated CIDRs (IPv4 or IPv6; a bare address is one host) the reverse proxy connects from. Set, only a connection from inside them may report the client address in X-Forwarded-For or X-Real-IP; every other connection is its own client. Unset, any non-public address may, which behind Docker Desktop, OrbStack or docker-proxy includes every caller of a published port. Same host: 127.0.0.1/32,::1/128; Docker network: the proxy's subnet. An entry that is not a CIDR lets no connection report an address and is named at boot.",
|
||||
"example": "127.0.0.1/32,::1/128"
|
||||
},
|
||||
{
|
||||
"name": "TRUST_CF_CONNECTING_IP",
|
||||
"purpose": "\"1\" takes the client IP from Cloudflare's CF-Connecting-IP header, from every connection and before the peer check. Safe only when the origin accepts connections from Cloudflare alone (a Tunnel, or a firewall admitting only Cloudflare's ranges); otherwise any caller forges the address rate limits and the audit log record. Off by default.",
|
||||
|
||||
Reference in new issue
Block a user