Обновить install_pg1c.sh

This commit is contained in:
2026-03-25 10:25:54 +00:00
parent e900bd4c82
commit 6804aa09ae

View File

@@ -5,13 +5,11 @@ SCRIPT_DIR="$(cd -- "$(dirname -- "${BASH_SOURCE[0]}")" && pwd)"
ENV_FILE="${ENV_FILE:-${SCRIPT_DIR}/.env}" ENV_FILE="${ENV_FILE:-${SCRIPT_DIR}/.env}"
log() { log() {
printf '[%s] %s printf '[%s] %s\n' "$(date '+%F %T')" "$*"
' "$(date '+%F %T')" "$*"
} }
fail() { fail() {
printf 'ERROR: %s printf 'ERROR: %s\n' "$*" >&2
' "$*" >&2
exit 1 exit 1
} }
@@ -48,37 +46,56 @@ load_env() {
: "${PG_ADMIN_PASSWORD:?В .env должна быть переменная PG_ADMIN_PASSWORD}" : "${PG_ADMIN_PASSWORD:?В .env должна быть переменная PG_ADMIN_PASSWORD}"
INSTALL_MODE="${INSTALL_MODE:-standalone}" INSTALL_MODE="${INSTALL_MODE:-standalone}"
PG_ADMIN_SUPERUSER="$(bool_norm "${PG_ADMIN_SUPERUSER:-true}")" PG_ADMIN_SUPERUSER="$(bool_norm "${PG_ADMIN_SUPERUSER:-true}")"
PG_CREATE_DB="$(bool_norm "${PG_CREATE_DB:-false}")" PG_CREATE_DB="$(bool_norm "${PG_CREATE_DB:-false}")"
PG_SERVICE_ENABLE="$(bool_norm "${PG_SERVICE_ENABLE:-true}")" PG_SERVICE_ENABLE="$(bool_norm "${PG_SERVICE_ENABLE:-true}")"
PG_SERVICE_START="$(bool_norm "${PG_SERVICE_START:-true}")" PG_SERVICE_START="$(bool_norm "${PG_SERVICE_START:-true}")"
ENFORCE_PASSWORD_AUTH="$(bool_norm "${ENFORCE_PASSWORD_AUTH:-true}")" ENFORCE_PASSWORD_AUTH="$(bool_norm "${ENFORCE_PASSWORD_AUTH:-true}")"
REPLACE_LOCAL_PEER_WITH="${REPLACE_LOCAL_PEER_WITH:-scram-sha-256}"
REPLACE_HOST_AUTH_WITH="${REPLACE_HOST_AUTH_WITH:-scram-sha-256}"
CREATE_HBA_BACKUP="$(bool_norm "${CREATE_HBA_BACKUP:-true}")" CREATE_HBA_BACKUP="$(bool_norm "${CREATE_HBA_BACKUP:-true}")"
POSTGRES_SOCKET_DIR="${POSTGRES_SOCKET_DIR:-/var/run/postgresql}" POSTGRES_SOCKET_DIR="${POSTGRES_SOCKET_DIR:-/var/run/postgresql}"
PG_DB_NAME="${PG_DB_NAME:-}" PG_DB_NAME="${PG_DB_NAME:-}"
REPO_ADD_TMP="${REPO_ADD_TMP:-/tmp/pgpro-repo-add.sh}" REPO_ADD_TMP="${REPO_ADD_TMP:-/tmp/pgpro-repo-add.sh}"
# Точечные правила для прикладного доступа
APP_LOCAL_AUTH_METHOD="${APP_LOCAL_AUTH_METHOD:-scram-sha-256}"
APP_HOST_AUTH_METHOD="${APP_HOST_AUTH_METHOD:-scram-sha-256}"
APP_HOST_IPV4_CIDR="${APP_HOST_IPV4_CIDR:-127.0.0.1/32}"
APP_HOST_IPV6_CIDR="${APP_HOST_IPV6_CIDR:-::1/128}"
# Оставить ли peer для локального системного postgres
PRESERVE_POSTGRES_PEER_LOCAL="$(bool_norm "${PRESERVE_POSTGRES_PEER_LOCAL:-true}")"
# Нужно ли задать пароль роли postgres тоже
SET_POSTGRES_ROLE_PASSWORD="$(bool_norm "${SET_POSTGRES_ROLE_PASSWORD:-false}")"
POSTGRES_ROLE_PASSWORD="${POSTGRES_ROLE_PASSWORD:-}"
case "$INSTALL_MODE" in case "$INSTALL_MODE" in
standalone|parallel) ;; standalone|parallel) ;;
*) fail "INSTALL_MODE должен быть standalone или parallel" ;; *) fail "INSTALL_MODE должен быть standalone или parallel" ;;
esac esac
case "$REPLACE_LOCAL_PEER_WITH" in case "$APP_LOCAL_AUTH_METHOD" in
scram-sha-256|md5|password|trust) ;; scram-sha-256|md5|password|trust|peer) ;;
*) fail "REPLACE_LOCAL_PEER_WITH должен быть scram-sha-256, md5, password или trust" ;; *) fail "APP_LOCAL_AUTH_METHOD должен быть scram-sha-256, md5, password, trust или peer" ;;
esac esac
case "$REPLACE_HOST_AUTH_WITH" in case "$APP_HOST_AUTH_METHOD" in
scram-sha-256|md5|password|trust) ;; scram-sha-256|md5|password|trust) ;;
*) fail "REPLACE_HOST_AUTH_WITH должен быть scram-sha-256, md5, password или trust" ;; *) fail "APP_HOST_AUTH_METHOD должен быть scram-sha-256, md5, password или trust" ;;
esac esac
if [[ "$PG_CREATE_DB" == "true" && -z "$PG_DB_NAME" ]]; then if [[ "$PG_CREATE_DB" == "true" && -z "$PG_DB_NAME" ]]; then
fail "Если PG_CREATE_DB=true, нужно указать PG_DB_NAME" fail "Если PG_CREATE_DB=true, нужно указать PG_DB_NAME"
fi fi
if [[ "$SET_POSTGRES_ROLE_PASSWORD" == "true" && -z "$POSTGRES_ROLE_PASSWORD" ]]; then
fail "Если SET_POSTGRES_ROLE_PASSWORD=true, нужно указать POSTGRES_ROLE_PASSWORD"
fi
PSQL="${PGPRO_BIN_DIR}/psql" PSQL="${PGPRO_BIN_DIR}/psql"
PGSETUP="${PGPRO_BIN_DIR}/pg-setup" PGSETUP="${PGPRO_BIN_DIR}/pg-setup"
PG_ISREADY="${PGPRO_BIN_DIR}/pg_isready" PG_ISREADY="${PGPRO_BIN_DIR}/pg_isready"
@@ -154,7 +171,7 @@ wait_for_postgres() {
log "Жду готовности PostgreSQL" log "Жду готовности PostgreSQL"
local i local i
for i in {1..30}; do for i in {1..60}; do
if runuser -u postgres -- "$PG_ISREADY" -h "$POSTGRES_SOCKET_DIR" -d postgres >/dev/null 2>&1; then if runuser -u postgres -- "$PG_ISREADY" -h "$POSTGRES_SOCKET_DIR" -d postgres >/dev/null 2>&1; then
return 0 return 0
fi fi
@@ -169,6 +186,10 @@ psql_postgres() {
runuser -u postgres -- "$PSQL" -v ON_ERROR_STOP=1 -h "$POSTGRES_SOCKET_DIR" -d postgres "$@" runuser -u postgres -- "$PSQL" -v ON_ERROR_STOP=1 -h "$POSTGRES_SOCKET_DIR" -d postgres "$@"
} }
sql_escape_literal() {
printf "%s" "$1" | sed "s/'/''/g"
}
configure_role() { configure_role() {
[[ -x "$PSQL" ]] || fail "Не найден $PSQL" [[ -x "$PSQL" ]] || fail "Не найден $PSQL"
@@ -178,12 +199,12 @@ configure_role() {
if [[ "$PG_ADMIN_SUPERUSER" == "true" ]]; then if [[ "$PG_ADMIN_SUPERUSER" == "true" ]]; then
role_attr+=" SUPERUSER" role_attr+=" SUPERUSER"
else else
role_attr+=" NOSUPERUSER CREATEDB CREATEROLE" role_attr+=" NOSUPERUSER"
fi fi
local safe_user safe_pass local safe_user safe_pass
safe_user="${PG_ADMIN_USER//'/''}" safe_user="$(sql_escape_literal "$PG_ADMIN_USER")"
safe_pass="${PG_ADMIN_PASSWORD//'/''}" safe_pass="$(sql_escape_literal "$PG_ADMIN_PASSWORD")"
psql_postgres <<SQL psql_postgres <<SQL
DO \$do\$ DO \$do\$
@@ -198,14 +219,26 @@ END
SQL SQL
} }
configure_postgres_role_password_if_needed() {
[[ "$SET_POSTGRES_ROLE_PASSWORD" == "true" ]] || return 0
log "Устанавливаю пароль для роли postgres"
local safe_pass
safe_pass="$(sql_escape_literal "$POSTGRES_ROLE_PASSWORD")"
psql_postgres <<SQL
ALTER ROLE postgres WITH PASSWORD '${safe_pass}';
SQL
}
configure_database() { configure_database() {
[[ "$PG_CREATE_DB" == "true" ]] || return 0 [[ "$PG_CREATE_DB" == "true" ]] || return 0
log "Создаю базу ${PG_DB_NAME}, если она отсутствует" log "Создаю базу ${PG_DB_NAME}, если она отсутствует"
local safe_db safe_user local safe_db safe_user
safe_db="${PG_DB_NAME//'/''}" safe_db="$(sql_escape_literal "$PG_DB_NAME")"
safe_user="${PG_ADMIN_USER//'/''}" safe_user="$(sql_escape_literal "$PG_ADMIN_USER")"
psql_postgres <<SQL psql_postgres <<SQL
SELECT 'CREATE DATABASE "' || replace('${safe_db}', '"', '""') || '" OWNER "' || replace('${safe_user}', '"', '""') || '"' SELECT 'CREATE DATABASE "' || replace('${safe_db}', '"', '""') || '" OWNER "' || replace('${safe_user}', '"', '""') || '"'
@@ -227,6 +260,47 @@ backup_hba_if_needed() {
fi fi
} }
strip_managed_hba_block() {
local hba_file="$1"
local tmp_file
tmp_file="$(mktemp)"
awk '
BEGIN { skip=0 }
/^# BEGIN MANAGED BY install_pg1c\.sh$/ { skip=1; next }
/^# END MANAGED BY install_pg1c\.sh$/ { skip=0; next }
skip == 0 { print }
' "$hba_file" > "$tmp_file"
cat "$tmp_file" > "$hba_file"
rm -f "$tmp_file"
}
prepend_managed_hba_block() {
local hba_file="$1"
local tmp_file
tmp_file="$(mktemp)"
{
echo "# BEGIN MANAGED BY install_pg1c.sh"
if [[ "$PRESERVE_POSTGRES_PEER_LOCAL" == "true" ]]; then
echo "local all postgres peer"
fi
echo "local all ${PG_ADMIN_USER} ${APP_LOCAL_AUTH_METHOD}"
echo "host all ${PG_ADMIN_USER} ${APP_HOST_IPV4_CIDR} ${APP_HOST_AUTH_METHOD}"
echo "host all ${PG_ADMIN_USER} ${APP_HOST_IPV6_CIDR} ${APP_HOST_AUTH_METHOD}"
echo "# END MANAGED BY install_pg1c.sh"
echo
cat "$hba_file"
} > "$tmp_file"
cat "$tmp_file" > "$hba_file"
rm -f "$tmp_file"
}
configure_pg_hba() { configure_pg_hba() {
[[ "$ENFORCE_PASSWORD_AUTH" == "true" ]] || { [[ "$ENFORCE_PASSWORD_AUTH" == "true" ]] || {
log "Правка pg_hba.conf отключена: ENFORCE_PASSWORD_AUTH=false" log "Правка pg_hba.conf отключена: ENFORCE_PASSWORD_AUTH=false"
@@ -238,27 +312,11 @@ configure_pg_hba() {
[[ -n "$hba_file" ]] || fail "Не удалось определить путь к pg_hba.conf" [[ -n "$hba_file" ]] || fail "Не удалось определить путь к pg_hba.conf"
[[ -f "$hba_file" ]] || fail "Файл pg_hba.conf не найден: $hba_file" [[ -f "$hba_file" ]] || fail "Файл pg_hba.conf не найден: $hba_file"
log "Настраиваю парольную аутентификацию в $hba_file" log "Настраиваю точечные правила парольной аутентификации в $hba_file"
backup_hba_if_needed "$hba_file" backup_hba_if_needed "$hba_file"
local tmp_file strip_managed_hba_block "$hba_file"
tmp_file="$(mktemp)" prepend_managed_hba_block "$hba_file"
awk -v local_method="$REPLACE_LOCAL_PEER_WITH" -v host_method="$REPLACE_HOST_AUTH_WITH" '
/^[[:space:]]*#/ { print; next }
/^[[:space:]]*$/ { print; next }
{
if ($1 == "local" && $4 ~ /^(peer|ident)$/) {
$4 = local_method
} else if (($1 == "host" || $1 == "hostssl" || $1 == "hostnossl") && $5 ~ /^(peer|ident|md5|scram-sha-256|password|trust)$/) {
$5 = host_method
}
print
}
' "$hba_file" > "$tmp_file"
cat "$tmp_file" > "$hba_file"
rm -f "$tmp_file"
log "Перезапускаю ${SERVICE_NAME} после правки pg_hba.conf" log "Перезапускаю ${SERVICE_NAME} после правки pg_hba.conf"
systemctl restart "$SERVICE_NAME" systemctl restart "$SERVICE_NAME"
@@ -266,13 +324,6 @@ configure_pg_hba() {
} }
show_summary() { show_summary() {
local auth_mode_note
if [[ "$ENFORCE_PASSWORD_AUTH" == "true" ]]; then
auth_mode_note="да (${REPLACE_LOCAL_PEER_WITH} / ${REPLACE_HOST_AUTH_WITH})"
else
auth_mode_note="нет"
fi
cat <<EOF cat <<EOF
Готово. Готово.
@@ -284,7 +335,9 @@ show_summary() {
- роль БД: ${PG_ADMIN_USER}; - роль БД: ${PG_ADMIN_USER};
- суперпользователь: ${PG_ADMIN_SUPERUSER}; - суперпользователь: ${PG_ADMIN_SUPERUSER};
- база создана: ${PG_CREATE_DB}${PG_DB_NAME:+ (${PG_DB_NAME})}; - база создана: ${PG_CREATE_DB}${PG_DB_NAME:+ (${PG_DB_NAME})};
- парольная аутентификация в pg_hba.conf: ${auth_mode_note}. - точечные правила в pg_hba.conf: ${ENFORCE_PASSWORD_AUTH};
- сохранён local peer для postgres: ${PRESERVE_POSTGRES_PEER_LOCAL};
- пароль роли postgres задан: ${SET_POSTGRES_ROLE_PASSWORD}.
Проверки: Проверки:
systemctl status ${SERVICE_NAME} systemctl status ${SERVICE_NAME}
@@ -294,10 +347,9 @@ show_summary() {
Подключение под новым пользователем: Подключение под новым пользователем:
${PSQL} -h 127.0.0.1 -U ${PG_ADMIN_USER} -d ${PG_DB_NAME:-postgres} -W ${PSQL} -h 127.0.0.1 -U ${PG_ADMIN_USER} -d ${PG_DB_NAME:-postgres} -W
Если хотите использовать свой .env, просто скопируйте: Повторный запуск скрипта безопасен:
cp env.example .env - блок в pg_hba.conf обновляется адресно;
nano .env - доступ sudo -u postgres не теряется, если PRESERVE_POSTGRES_PEER_LOCAL=true.
sudo ./install_pg1c.sh
EOF EOF
} }
@@ -318,9 +370,10 @@ main() {
enable_and_start_service enable_and_start_service
wait_for_postgres wait_for_postgres
configure_role configure_role
configure_postgres_role_password_if_needed
configure_database configure_database
configure_pg_hba configure_pg_hba
show_summary show_summary
} }
main "$@" main "$@"