#!/usr/bin/env bash # 在 fnsvr-01 的共享 PostgreSQL 上给「生产」建独立的库与角色。 # # 为什么独立角色:生产库和开发库在同一个实例(fnsvr-01:8432)。复用 dadao_app # 等于拿到开发口令就能连生产;所以生产用 dadao_prod_owner / dadao_prod_app, # 迁移里的 GRANT 与 DEFAULT PRIVILEGES 会按 APP_DB_ROLE / OWNER_DB_ROLE 生成。 # # 在 fnsvr-01 上以 root 执行(需要 docker 权限): # OWNER_PW='...' APP_PW='...' bash deploy/prod/provision-db.sh # # 幂等:角色或库已存在时跳过创建(不会重置已有口令)。 set -euo pipefail CONTAINER=${CONTAINER:-1Panel-postgresql-wIKz} DB=${DB:-dadaotask_prod} OWNER_ROLE=${OWNER_ROLE:-dadao_prod_owner} APP_ROLE=${APP_ROLE:-dadao_prod_app} : "${OWNER_PW:?需要 OWNER_PW 环境变量(迁移角色口令)}" : "${APP_PW:?需要 APP_PW 环境变量(应用角色口令)}" echo "== 建角色与库:$DB(owner=$OWNER_ROLE app=$APP_ROLE)==" docker exec -i "$CONTAINER" psql -U dbadmin -d postgres -v ON_ERROR_STOP=1 -q \ -v owner_role="$OWNER_ROLE" -v owner_pw="$OWNER_PW" \ -v app_role="$APP_ROLE" -v app_pw="$APP_PW" -v db="$DB" <<'SQL' SELECT format('CREATE ROLE %I LOGIN PASSWORD %L', :'owner_role', :'owner_pw') WHERE NOT EXISTS (SELECT 1 FROM pg_roles WHERE rolname = :'owner_role')\gexec SELECT format('CREATE ROLE %I LOGIN PASSWORD %L', :'app_role', :'app_pw') WHERE NOT EXISTS (SELECT 1 FROM pg_roles WHERE rolname = :'app_role')\gexec -- 应用角色绝不能是 superuser / bypassrls,否则 RLS 直接被跳过 SELECT format('ALTER ROLE %I NOSUPERUSER NOBYPASSRLS NOCREATEDB NOCREATEROLE', :'app_role')\gexec SELECT format('ALTER ROLE %I NOSUPERUSER NOBYPASSRLS', :'owner_role')\gexec SELECT format('CREATE DATABASE %I OWNER %I', :'db', :'owner_role') WHERE NOT EXISTS (SELECT 1 FROM pg_database WHERE datname = :'db')\gexec SQL echo "== 库内权限(schema 归 owner,app 只能读写数据)==" docker exec -i "$CONTAINER" psql -U dbadmin -d "$DB" -v ON_ERROR_STOP=1 -q \ -v owner_role="$OWNER_ROLE" -v app_role="$APP_ROLE" <<'SQL' REVOKE CREATE ON SCHEMA public FROM PUBLIC; SELECT format('ALTER SCHEMA public OWNER TO %I', :'owner_role')\gexec SELECT format('GRANT CONNECT ON DATABASE %I TO %I', current_database(), :'app_role')\gexec SELECT format('GRANT USAGE ON SCHEMA public TO %I', :'app_role')\gexec SQL echo "== 自检 ==" docker exec -i "$CONTAINER" psql -U dbadmin -d "$DB" -tAc \ "select current_database(), (select rolname from pg_roles where rolname='$APP_ROLE'), (select rolsuper from pg_roles where rolname='$APP_ROLE'), (select rolbypassrls from pg_roles where rolname='$APP_ROLE')" echo "完成。注意:建表与 RLS 由 alembic(deploy.sh 第 3 步)负责。"