Files
pg18-1C_for_deb13/install_pg1c.sh

327 lines
9.8 KiB
Bash
Raw Blame History

This file contains ambiguous Unicode characters
This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.
#!/usr/bin/env bash
set -Eeuo pipefail
SCRIPT_DIR="$(cd -- "$(dirname -- "${BASH_SOURCE[0]}")" && pwd)"
ENV_FILE="${ENV_FILE:-${SCRIPT_DIR}/.env}"
log() {
printf '[%s] %s
' "$(date '+%F %T')" "$*"
}
fail() {
printf 'ERROR: %s
' "$*" >&2
exit 1
}
need_cmd() {
command -v "$1" >/dev/null 2>&1 || fail "Не найдена команда: $1"
}
bool_norm() {
case "${1:-}" in
1|true|TRUE|yes|YES|on|ON) echo "true" ;;
0|false|FALSE|no|NO|off|OFF) echo "false" ;;
*) fail "Неверное булево значение: ${1:-<empty>}" ;;
esac
}
require_root() {
[[ "$(id -u)" -eq 0 ]] || fail "Скрипт нужно запускать от root"
}
load_env() {
[[ -f "$ENV_FILE" ]] || fail "Файл окружения не найден: $ENV_FILE"
set -a
# shellcheck disable=SC1090
. "$ENV_FILE"
set +a
: "${REPO_ADD_URL:?В .env должна быть переменная REPO_ADD_URL}"
: "${PGPRO_BIN_DIR:?В .env должна быть переменная PGPRO_BIN_DIR}"
: "${SERVICE_NAME:?В .env должна быть переменная SERVICE_NAME}"
: "${PACKAGE_STANDALONE:?В .env должна быть переменная PACKAGE_STANDALONE}"
: "${PACKAGE_PARALLEL:?В .env должна быть переменная PACKAGE_PARALLEL}"
: "${PG_ADMIN_USER:?В .env должна быть переменная PG_ADMIN_USER}"
: "${PG_ADMIN_PASSWORD:?В .env должна быть переменная PG_ADMIN_PASSWORD}"
INSTALL_MODE="${INSTALL_MODE:-standalone}"
PG_ADMIN_SUPERUSER="$(bool_norm "${PG_ADMIN_SUPERUSER:-true}")"
PG_CREATE_DB="$(bool_norm "${PG_CREATE_DB:-false}")"
PG_SERVICE_ENABLE="$(bool_norm "${PG_SERVICE_ENABLE:-true}")"
PG_SERVICE_START="$(bool_norm "${PG_SERVICE_START:-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}")"
POSTGRES_SOCKET_DIR="${POSTGRES_SOCKET_DIR:-/var/run/postgresql}"
PG_DB_NAME="${PG_DB_NAME:-}"
REPO_ADD_TMP="${REPO_ADD_TMP:-/tmp/pgpro-repo-add.sh}"
case "$INSTALL_MODE" in
standalone|parallel) ;;
*) fail "INSTALL_MODE должен быть standalone или parallel" ;;
esac
case "$REPLACE_LOCAL_PEER_WITH" in
scram-sha-256|md5|password|trust) ;;
*) fail "REPLACE_LOCAL_PEER_WITH должен быть scram-sha-256, md5, password или trust" ;;
esac
case "$REPLACE_HOST_AUTH_WITH" in
scram-sha-256|md5|password|trust) ;;
*) fail "REPLACE_HOST_AUTH_WITH должен быть scram-sha-256, md5, password или trust" ;;
esac
if [[ "$PG_CREATE_DB" == "true" && -z "$PG_DB_NAME" ]]; then
fail "Если PG_CREATE_DB=true, нужно указать PG_DB_NAME"
fi
PSQL="${PGPRO_BIN_DIR}/psql"
PGSETUP="${PGPRO_BIN_DIR}/pg-setup"
PG_ISREADY="${PGPRO_BIN_DIR}/pg_isready"
}
check_os() {
[[ -f /etc/os-release ]] || fail "Не найден /etc/os-release"
# shellcheck disable=SC1091
. /etc/os-release
[[ "${ID:-}" == "debian" ]] || fail "Скрипт рассчитан на Debian. Найдено: ${ID:-unknown}"
[[ "${VERSION_ID:-}" == "13" ]] || fail "Скрипт рассчитан на Debian 13. Найдено: ${VERSION_ID:-unknown}"
}
ensure_base_packages() {
export DEBIAN_FRONTEND=noninteractive
apt-get update
apt-get install -y wget ca-certificates gnupg apt-transport-https sed grep coreutils
}
ensure_repo() {
if [[ -f /etc/apt/sources.list.d/postgresql-1c-18.list ]]; then
log "Репозиторий PostgreSQL for 1C 18 уже добавлен"
apt-get update
return
fi
log "Скачиваю vendor-скрипт добавления репозитория"
wget -O "$REPO_ADD_TMP" "$REPO_ADD_URL"
chmod +x "$REPO_ADD_TMP"
sh "$REPO_ADD_TMP"
rm -f "$REPO_ADD_TMP"
}
install_pgpro() {
export DEBIAN_FRONTEND=noninteractive
if [[ "$INSTALL_MODE" == "standalone" ]]; then
log "Устанавливаю пакет ${PACKAGE_STANDALONE}"
apt-get install -y "$PACKAGE_STANDALONE"
else
log "Устанавливаю пакет ${PACKAGE_PARALLEL} для параллельной установки"
apt-get install -y "$PACKAGE_PARALLEL"
[[ -x "$PGSETUP" ]] || fail "Не найден $PGSETUP"
if [[ ! -d /var/lib/pgpro/1c-18/data/base ]]; then
log "Инициализирую новый кластер Postgres Pro 1C 18"
"$PGSETUP" initdb
else
log "Кластер уже инициализирован, initdb пропускаю"
fi
fi
}
enable_and_start_service() {
if ! systemctl list-unit-files | grep -q "^${SERVICE_NAME}\.service"; then
fail "Не найден unit-файл ${SERVICE_NAME}.service"
fi
if [[ "$PG_SERVICE_ENABLE" == "true" ]]; then
log "Включаю автозапуск ${SERVICE_NAME}"
systemctl enable "$SERVICE_NAME"
fi
if [[ "$PG_SERVICE_START" == "true" ]]; then
log "Запускаю ${SERVICE_NAME}"
systemctl restart "$SERVICE_NAME"
fi
}
wait_for_postgres() {
[[ -x "$PG_ISREADY" ]] || fail "Не найден $PG_ISREADY"
log "Жду готовности PostgreSQL"
local i
for i in {1..30}; do
if runuser -u postgres -- "$PG_ISREADY" -h "$POSTGRES_SOCKET_DIR" -d postgres >/dev/null 2>&1; then
return 0
fi
sleep 1
done
systemctl status "$SERVICE_NAME" --no-pager || true
fail "PostgreSQL не поднялся за ожидаемое время"
}
psql_postgres() {
runuser -u postgres -- "$PSQL" -v ON_ERROR_STOP=1 -h "$POSTGRES_SOCKET_DIR" -d postgres "$@"
}
configure_role() {
[[ -x "$PSQL" ]] || fail "Не найден $PSQL"
log "Создаю или обновляю роль ${PG_ADMIN_USER}"
local role_attr="LOGIN"
if [[ "$PG_ADMIN_SUPERUSER" == "true" ]]; then
role_attr+=" SUPERUSER"
else
role_attr+=" NOSUPERUSER CREATEDB CREATEROLE"
fi
local safe_user safe_pass
safe_user="${PG_ADMIN_USER//'/''}"
safe_pass="${PG_ADMIN_PASSWORD//'/''}"
psql_postgres <<SQL
DO \$do\$
BEGIN
IF EXISTS (SELECT 1 FROM pg_roles WHERE rolname = '${safe_user}') THEN
EXECUTE format('ALTER ROLE %I WITH ${role_attr} PASSWORD %L', '${safe_user}', '${safe_pass}');
ELSE
EXECUTE format('CREATE ROLE %I WITH ${role_attr} PASSWORD %L', '${safe_user}', '${safe_pass}');
END IF;
END
\$do\$;
SQL
}
configure_database() {
[[ "$PG_CREATE_DB" == "true" ]] || return 0
log "Создаю базу ${PG_DB_NAME}, если она отсутствует"
local safe_db safe_user
safe_db="${PG_DB_NAME//'/''}"
safe_user="${PG_ADMIN_USER//'/''}"
psql_postgres <<SQL
SELECT 'CREATE DATABASE "' || replace('${safe_db}', '"', '""') || '" OWNER "' || replace('${safe_user}', '"', '""') || '"'
WHERE NOT EXISTS (SELECT 1 FROM pg_database WHERE datname = '${safe_db}')
\gexec
SQL
}
detect_hba_file() {
psql_postgres -Atqc "SHOW hba_file;"
}
backup_hba_if_needed() {
local hba_file="$1"
if [[ "$CREATE_HBA_BACKUP" == "true" ]]; then
local backup_file="${hba_file}.bak.$(date +%Y%m%d_%H%M%S)"
cp -a "$hba_file" "$backup_file"
log "Создан бэкап pg_hba.conf: $backup_file"
fi
}
configure_pg_hba() {
[[ "$ENFORCE_PASSWORD_AUTH" == "true" ]] || {
log "Правка pg_hba.conf отключена: ENFORCE_PASSWORD_AUTH=false"
return 0
}
local hba_file
hba_file="$(detect_hba_file)"
[[ -n "$hba_file" ]] || fail "Не удалось определить путь к pg_hba.conf"
[[ -f "$hba_file" ]] || fail "Файл pg_hba.conf не найден: $hba_file"
log "Настраиваю парольную аутентификацию в $hba_file"
backup_hba_if_needed "$hba_file"
local tmp_file
tmp_file="$(mktemp)"
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"
systemctl restart "$SERVICE_NAME"
wait_for_postgres
}
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
Готово.
Что сделано:
- добавлен репозиторий PostgreSQL for 1C 18;
- установлен пакет в режиме: ${INSTALL_MODE};
- сервис: ${SERVICE_NAME};
- роль БД: ${PG_ADMIN_USER};
- суперпользователь: ${PG_ADMIN_SUPERUSER};
- база создана: ${PG_CREATE_DB}${PG_DB_NAME:+ (${PG_DB_NAME})};
- парольная аутентификация в pg_hba.conf: ${auth_mode_note}.
Проверки:
systemctl status ${SERVICE_NAME}
sudo -u postgres ${PSQL} -h ${POSTGRES_SOCKET_DIR} -d postgres -c "\du"
sudo -u postgres ${PSQL} -h ${POSTGRES_SOCKET_DIR} -d postgres -c "\l"
Подключение под новым пользователем:
${PSQL} -h 127.0.0.1 -U ${PG_ADMIN_USER} -d ${PG_DB_NAME:-postgres} -W
Если хотите использовать свой .env, просто скопируйте:
cp env.example .env
nano .env
sudo ./install_pg1c.sh
EOF
}
main() {
require_root
need_cmd systemctl
need_cmd runuser
need_cmd apt-get
need_cmd wget
need_cmd awk
need_cmd sed
load_env
check_os
ensure_base_packages
ensure_repo
install_pgpro
enable_and_start_service
wait_for_postgres
configure_role
configure_database
configure_pg_hba
show_summary
}
main "$@"