fix: harden owner bootstrap and auth persistence
This commit is contained in:
@@ -43,20 +43,13 @@ jobs:
|
||||
- name: Prepare .env
|
||||
run: |
|
||||
set -euo pipefail
|
||||
HOST_OWNER_PASSWORD=$(docker run --rm -v "${DEPLOY_PATH}:/host-deploy:ro" alpine:latest sh -c "grep '^OWNER_PASSWORD=' /host-deploy/.env | cut -d= -f2-" 2>/dev/null || true)
|
||||
if [ -z "${HOST_OWNER_PASSWORD}" ]; then
|
||||
echo "ERROR: OWNER_PASSWORD not found in ${DEPLOY_PATH}/.env"
|
||||
exit 1
|
||||
fi
|
||||
printf 'POSTGRES_DB=nexus\n' > "${ENV_TMPFILE}"
|
||||
printf 'POSTGRES_USER=nexus\n' >> "${ENV_TMPFILE}"
|
||||
printf 'POSTGRES_PASSWORD=%s\n' "${ENV_POSTGRES_PASSWORD}" >> "${ENV_TMPFILE}"
|
||||
printf 'JWT_KEY=%s\n' "${ENV_JWT_KEY}" >> "${ENV_TMPFILE}"
|
||||
printf 'JWT_ISSUER=nexus\n' >> "${ENV_TMPFILE}"
|
||||
printf 'JWT_AUDIENCE=nexus-web\n' >> "${ENV_TMPFILE}"
|
||||
printf 'OWNER_EMAIL=vmbao62@hotmail.de\n' >> "${ENV_TMPFILE}"
|
||||
printf 'OWNER_PASSWORD=%s\n' "${HOST_OWNER_PASSWORD}" >> "${ENV_TMPFILE}"
|
||||
printf 'OWNER_DISPLAY_NAME=\n' >> "${ENV_TMPFILE}"
|
||||
printf 'BOOTSTRAP_OWNER_EMAIL=vmbao62@hotmail.de\n' >> "${ENV_TMPFILE}"
|
||||
printf 'OPENCLAW_BASE_URL=http://host.docker.internal:18789\n' >> "${ENV_TMPFILE}"
|
||||
printf 'OPENCLAW_GATEWAY_TOKEN=%s\n' "${ENV_OPENCLAW_TOKEN}" >> "${ENV_TMPFILE}"
|
||||
printf 'OPENCLAW_GATEWAY_PASSWORD=\n' >> "${ENV_TMPFILE}"
|
||||
@@ -82,16 +75,10 @@ jobs:
|
||||
printf 'trap "rm -f /tmp/nexus-deploy-env" EXIT\n' >> "$SCRIPT"
|
||||
printf 'cat > /tmp/nexus-deploy-env\n' >> "$SCRIPT"
|
||||
printf '\n' >> "$SCRIPT"
|
||||
printf '# ── Graceful shutdown (preserves DB volume integrity) ──\n' >> "$SCRIPT"
|
||||
printf 'docker compose --env-file /tmp/nexus-deploy-env stop postgres 2>/dev/null || true\n' >> "$SCRIPT"
|
||||
printf 'docker compose --env-file /tmp/nexus-deploy-env down --remove-orphans 2>/dev/null || true\n' >> "$SCRIPT"
|
||||
printf 'docker rm -f nexus-postgres-1 nexus-api-1 nexus-web-1 2>/dev/null || true\n' >> "$SCRIPT"
|
||||
printf '\n' >> "$SCRIPT"
|
||||
printf 'PG_VOL=$(docker volume ls -q --filter name=nexus-postgres 2>/dev/null | head -1)\n' >> "$SCRIPT"
|
||||
printf 'if [ -n "$PG_VOL" ]; then\n' >> "$SCRIPT"
|
||||
printf ' echo "Checking postgres WAL integrity..."\n' >> "$SCRIPT"
|
||||
printf ' docker run --rm -v "$PG_VOL:/var/lib/postgresql/data" --entrypoint sh postgres:17-alpine -c "pg_resetwal -f /var/lib/postgresql/data && echo WAL reset OK" 2>&1 || echo "pg_resetwal failed (may be benign)"\n' >> "$SCRIPT"
|
||||
printf 'else\n' >> "$SCRIPT"
|
||||
printf ' echo "Postgres volume not found - will be created fresh"\n' >> "$SCRIPT"
|
||||
printf 'fi\n' >> "$SCRIPT"
|
||||
printf 'echo "Postgres volume preserved (nexus-postgres) — no WAL reset"\n' >> "$SCRIPT"
|
||||
printf '\n' >> "$SCRIPT"
|
||||
printf 'echo "Deploying all services"\n' >> "$SCRIPT"
|
||||
printf 'docker compose --env-file /tmp/nexus-deploy-env build --no-cache\n' >> "$SCRIPT"
|
||||
|
||||
@@ -52,9 +52,8 @@ jobs:
|
||||
ENV_POSTGRES_PASSWORD: ${{ secrets.ENV_POSTGRES_PASSWORD }}
|
||||
ENV_JWT_KEY: ${{ secrets.ENV_JWT_KEY }}
|
||||
ENV_OPENCLAW_TOKEN: ${{ secrets.ENV_OPENCLAW_TOKEN }}
|
||||
# OWNER_PASSWORD is read from the host's persistent .env — NOT from a Gitea secret.
|
||||
# This ensures the password stays consistent across deploys and the DB is the
|
||||
# single source of truth after initial seed (enforced by SeedAudit guard).
|
||||
# Owner password is not injected at deploy time.
|
||||
# After first seed, the database is the only password source.
|
||||
|
||||
steps:
|
||||
# ═══════════════════════════════════════════════════
|
||||
@@ -113,37 +112,25 @@ jobs:
|
||||
echo "mutated_main=false" >> "$GITEA_OUTPUT"
|
||||
|
||||
# ═══════════════════════════════════════════════════
|
||||
# Step 4: Build .env from secrets + host .env (SAFE)
|
||||
# Step 4: Build .env from secrets (SAFE)
|
||||
#
|
||||
# Secrets are written to /tmp/nexus-deploy-env — NEVER
|
||||
# to a file inside the workspace that gets rsync'd to
|
||||
# the host. The temp file is deleted immediately after
|
||||
# compose operations complete.
|
||||
#
|
||||
# OWNER_PASSWORD is read from the host's persistent .env
|
||||
# to ensure it stays the single source of truth. Other
|
||||
# secrets (POSTGRES_PASSWORD, JWT_KEY, OPENCLAW_TOKEN)
|
||||
# Owner password is deliberately omitted so production deploys
|
||||
# cannot overwrite the persisted DB password.
|
||||
# Other secrets (POSTGRES_PASSWORD, JWT_KEY, OPENCLAW_TOKEN)
|
||||
# come from Gitea secrets.
|
||||
# ═══════════════════════════════════════════════════
|
||||
- name: Prepare .env (secrets + host .env → temp file)
|
||||
- name: Prepare .env (secrets → temp file)
|
||||
run: |
|
||||
set -euo pipefail
|
||||
|
||||
# Read OWNER_PASSWORD from the host's persistent .env
|
||||
HOST_OWNER_PASSWORD=""
|
||||
if [ -f "${DEPLOY_PATH}/.env" ]; then
|
||||
HOST_OWNER_PASSWORD=$(grep '^OWNER_PASSWORD=' "${DEPLOY_PATH}/.env" | cut -d= -f2- || true)
|
||||
fi
|
||||
if [ -z "${HOST_OWNER_PASSWORD}" ]; then
|
||||
echo "❌ OWNER_PASSWORD not found in ${DEPLOY_PATH}/.env"
|
||||
echo " The host .env is the single source of truth for the owner password."
|
||||
echo " Ensure OWNER_PASSWORD is set in the deploy-path .env before deploying."
|
||||
exit 1
|
||||
fi
|
||||
|
||||
cat > "${ENV_TMPFILE}" <<EOF
|
||||
# Nexus Production Environment — auto-generated by CD pipeline
|
||||
# Managed via Gitea Secrets + host .env → do NOT edit manually on the host.
|
||||
# Managed via Gitea Secrets → do NOT edit manually.
|
||||
# This file lives in /tmp and is removed after deploy completes.
|
||||
POSTGRES_DB=nexus
|
||||
POSTGRES_USER=nexus
|
||||
@@ -151,9 +138,7 @@ jobs:
|
||||
JWT_KEY=${ENV_JWT_KEY}
|
||||
JWT_ISSUER=nexus
|
||||
JWT_AUDIENCE=nexus-web
|
||||
OWNER_EMAIL=vmbao62@hotmail.de
|
||||
OWNER_PASSWORD=${HOST_OWNER_PASSWORD}
|
||||
OWNER_DISPLAY_NAME=
|
||||
BOOTSTRAP_OWNER_EMAIL=vmbao62@hotmail.de
|
||||
OPENCLAW_BASE_URL=http://host.docker.internal:18789
|
||||
OPENCLAW_GATEWAY_TOKEN=${ENV_OPENCLAW_TOKEN}
|
||||
OPENCLAW_GATEWAY_PASSWORD=
|
||||
@@ -205,18 +190,10 @@ set -e
|
||||
trap 'rm -f /tmp/nexus-deploy-env' EXIT
|
||||
cat > /tmp/nexus-deploy-env
|
||||
|
||||
# ── Clean up zombie containers ──
|
||||
# ── Graceful shutdown (preserves DB volume integrity) ──
|
||||
docker compose --env-file /tmp/nexus-deploy-env stop postgres 2>/dev/null || true
|
||||
docker compose --env-file /tmp/nexus-deploy-env down --remove-orphans 2>/dev/null || true
|
||||
docker rm -f nexus-postgres-1 nexus-api-1 nexus-web-1 2>/dev/null || true
|
||||
|
||||
# ── WAL recovery ──
|
||||
PG_VOL=$(docker volume ls -q --filter name=nexus-postgres 2>/dev/null | head -1)
|
||||
if [ -n "$PG_VOL" ]; then
|
||||
echo "Checking postgres WAL integrity..."
|
||||
docker run --rm -v "$PG_VOL:/var/lib/postgresql/data" --entrypoint sh postgres:17-alpine -c "pg_resetwal -f /var/lib/postgresql/data && echo 'WAL reset OK'" 2>&1 || echo "pg_resetwal failed (may be benign)"
|
||||
else
|
||||
echo "Postgres volume not found - will be created fresh"
|
||||
fi
|
||||
echo "Postgres volume preserved (nexus-postgres) — no WAL reset"
|
||||
|
||||
BUILD_ARGS="${DEPLOY_BUILD_ARGS:-}"
|
||||
SERVICE="${DEPLOY_SERVICE:-}"
|
||||
|
||||
@@ -94,22 +94,12 @@ jobs:
|
||||
fi
|
||||
|
||||
# ═══════════════════════════════════════════════════
|
||||
# Step 3: Prepare .env from secrets + host .env (safe temp file)
|
||||
# Step 3: Prepare .env from secrets (safe temp file)
|
||||
# ═══════════════════════════════════════════════════
|
||||
- name: Prepare .env (secrets + host .env → temp file)
|
||||
- name: Prepare .env (secrets → temp file)
|
||||
run: |
|
||||
set -euo pipefail
|
||||
|
||||
# Read OWNER_PASSWORD from the host's persistent .env
|
||||
HOST_OWNER_PASSWORD=""
|
||||
if [ -f "${DEPLOY_PATH}/.env" ]; then
|
||||
HOST_OWNER_PASSWORD=$(grep '^OWNER_PASSWORD=' "${DEPLOY_PATH}/.env" | cut -d= -f2- || true)
|
||||
fi
|
||||
if [ -z "${HOST_OWNER_PASSWORD}" ]; then
|
||||
echo "❌ OWNER_PASSWORD not found in ${DEPLOY_PATH}/.env"
|
||||
exit 1
|
||||
fi
|
||||
|
||||
cat > "${ENV_TMPFILE}" <<EOF
|
||||
# Nexus Production Environment — auto-generated by CD pipeline
|
||||
POSTGRES_DB=nexus
|
||||
@@ -118,9 +108,7 @@ jobs:
|
||||
JWT_KEY=${ENV_JWT_KEY}
|
||||
JWT_ISSUER=nexus
|
||||
JWT_AUDIENCE=nexus-web
|
||||
OWNER_EMAIL=vmbao62@hotmail.de
|
||||
OWNER_PASSWORD=${HOST_OWNER_PASSWORD}
|
||||
OWNER_DISPLAY_NAME=
|
||||
BOOTSTRAP_OWNER_EMAIL=vmbao62@hotmail.de
|
||||
OPENCLAW_BASE_URL=http://host.docker.internal:18789
|
||||
OPENCLAW_GATEWAY_TOKEN=${ENV_OPENCLAW_TOKEN}
|
||||
OPENCLAW_GATEWAY_PASSWORD=
|
||||
|
||||
Reference in New Issue
Block a user