diff --git a/docs/operations/production-release-runbook-20261014.md b/docs/operations/production-release-runbook-20261014.md index c8aae66f..63b0edf1 100644 --- a/docs/operations/production-release-runbook-20261014.md +++ b/docs/operations/production-release-runbook-20261014.md @@ -106,7 +106,21 @@ Gitea → Deploy production。Use workflow from:`main`。 1. 整库还原。没有单独按钮。只允许 `RECOVERY_FORMAT=2` 的恢复点。先看 `/opt/jyotisha-production/.state/recovery-baseline.env`:没有 `RECOVERY_FORMAT=2` 就停,回到第 4 步再点一次创建恢复点。8 月的旧备份不能用。第 4 步的 `recovery_reference` 斜杠后面就是备份文件名,例如 `production-pre-migration-20261014T120000Z.dump.enc`。文件在 `/opt/jyotisha-production/backups/` 下面。先 `sha256sum` 这个文件,和同一份 `recovery-baseline.env` 里的 `RECOVERY_SHA256` 对上,再继续。 -先停 `api` 和 `web`,不要停 `postgres`。口令和密钥只用主机上已有的环境文件,不要贴出来。 +**先证明备份能解开、能读,再动生产库。** 顺序不能反:先删库再发现备份解不开,网站就停在一个空库上。口令和密钥只用主机上已有的环境文件,不要贴出来,也不要 `echo`: + +```text +cd /opt/jyotisha-production +set -a; . ./.env.production.database; set +a +backup=/opt/jyotisha-production/backups/<备份文件名> +sha256sum "$backup" # 必须等于 recovery-baseline.env 里的 RECOVERY_SHA256 +postgres_id=$(sudo -n docker ps -q --filter label=com.docker.compose.project=jyotisha-production --filter label=com.docker.compose.service=postgres) +openssl enc -d -aes-256-cbc -pbkdf2 -pass env:PRODUCTION_BACKUP_ENCRYPTION_KEY -in "$backup" \ + | sudo -n docker exec -i "$postgres_id" pg_restore --list >/dev/null && echo backup_readable=1 +``` + +上面只读备份、不碰任何库。必须看到 `backup_readable=1`;没看到(解密失败、文件损坏)就停,不要往下做,问产品负责人。 + +看到之后,再停 `api` 和 `web`,不要停 `postgres`: ```text api_id=$(sudo -n docker ps -q --filter label=com.docker.compose.project=jyotisha-production --filter label=com.docker.compose.service=api) @@ -119,7 +133,7 @@ sudo -n docker exec -e PGPASSWORD="$POSTGRES_PASSWORD" "$postgres_id" \ sudo -n docker exec -e PGPASSWORD="$POSTGRES_PASSWORD" "$postgres_id" \ psql -U "$POSTGRES_USER" -d postgres -v ON_ERROR_STOP=1 \ -c "CREATE DATABASE jyotisha;" -openssl enc -d -aes-256-cbc -pbkdf2 -pass env:PRODUCTION_BACKUP_ENCRYPTION_KEY -in <备份文件> \ +openssl enc -d -aes-256-cbc -pbkdf2 -pass env:PRODUCTION_BACKUP_ENCRYPTION_KEY -in "$backup" \ | sudo -n docker exec -i -e PGPASSWORD="$POSTGRES_PASSWORD" "$postgres_id" \ pg_restore -U "$POSTGRES_USER" -d jyotisha --exit-on-error sudo -n docker exec -e PGPASSWORD="$POSTGRES_PASSWORD" "$postgres_id" \