From 5b830a4653dd49feb6feda4f2809c7827aad6b3a Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Oliver=20G=C3=BCnther?= Date: Mon, 1 Dec 2025 10:27:57 +0100 Subject: [PATCH] Bundle addon-postgres --- .pkgr.yml | 2 +- packaging/addons/addon-postgres/README.md | 25 ++ packaging/addons/addon-postgres/bin/compile | 3 + packaging/addons/addon-postgres/bin/configure | 192 ++++++++++++++ .../addons/addon-postgres/bin/postinstall | 33 +++ .../addons/addon-postgres/bin/preinstall | 238 ++++++++++++++++++ packaging/addons/addon-postgres/templates | 47 ++++ 7 files changed, 539 insertions(+), 1 deletion(-) create mode 100644 packaging/addons/addon-postgres/README.md create mode 100755 packaging/addons/addon-postgres/bin/compile create mode 100755 packaging/addons/addon-postgres/bin/configure create mode 100755 packaging/addons/addon-postgres/bin/postinstall create mode 100755 packaging/addons/addon-postgres/bin/preinstall create mode 100644 packaging/addons/addon-postgres/templates diff --git a/.pkgr.yml b/.pkgr.yml index f6160f1c334..014e23e2bb1 100644 --- a/.pkgr.yml +++ b/.pkgr.yml @@ -45,7 +45,7 @@ installer: https://github.com/pkgr/installer.git wizards: - https://github.com/pkgr/addon-legacy-installer.git - ./packaging/addons/openproject-edition - - https://github.com/pkgr/addon-postgres + - ./packaging/addons/addon-postgres - https://github.com/pkgr/addon-apache2.git#set-host-header - ./packaging/addons/repositories - https://github.com/pkgr/addon-memcached.git diff --git a/packaging/addons/addon-postgres/README.md b/packaging/addons/addon-postgres/README.md new file mode 100644 index 00000000000..cfb2d055384 --- /dev/null +++ b/packaging/addons/addon-postgres/README.md @@ -0,0 +1,25 @@ +# addon-postgres + +PostgreSQL addon for pkgr. + +If autoinstall mode is selected, it will attempt to setup a PostgreSQL v17 cluster, using the packages from https://www.postgresql.org/download/linux/. + +Supported distributions: + +- SLES12 +- Enterprise Linux 7, Enterprise Linux 7 +- Ubuntu 14.04, 16.04, 18.04, 20.04 +- Debian 7, 8, 9, 10 + +## Development + + sudo apt-get update -qq && sudo apt-get install dialog -y + + export APP_NAME="testapp" + export APP_SAFE_NAME="testapp" + export INSTALLER_DIR="/path/to/pkgr-installer-dir" + sudo useradd "$APP_NAME" + sudo mkdir -p /etc/testapp/conf.d + + sudo -E INSTALLER_DEBUG=no WIZ_RECONFIGURE=no DATABASE=/tmp/test1 ./bin/configure + sudo -E INSTALLER_DEBUG=no WIZ_RECONFIGURE=no DATABASE=/tmp/test1 ./bin/preinstall diff --git a/packaging/addons/addon-postgres/bin/compile b/packaging/addons/addon-postgres/bin/compile new file mode 100755 index 00000000000..8c3cbfc39d9 --- /dev/null +++ b/packaging/addons/addon-postgres/bin/compile @@ -0,0 +1,3 @@ +#!/bin/bash + +exit 0 diff --git a/packaging/addons/addon-postgres/bin/configure b/packaging/addons/addon-postgres/bin/configure new file mode 100755 index 00000000000..182f814c00c --- /dev/null +++ b/packaging/addons/addon-postgres/bin/configure @@ -0,0 +1,192 @@ +#!/bin/bash + +set -e + +. "${INSTALLER_DIR}/wizard" + +input_start() { + STATE="postgres_installation_type" +} + +input_postgres_installation_type() { + wiz_put "postgres/autoinstall" + if wiz_ask ; then + RET=$(wiz_get "postgres/autoinstall") + case "$RET" in + "skip") + STATE="done" + ;; + "install") + STATE="done" + wiz_get_or_set "postgres/db_host" "127.0.0.1" + wiz_get_or_set "postgres/db_port" "45432" + wiz_get_or_set "postgres/db_name" "${APP_SAFE_NAME}" + wiz_get_or_set "postgres/db_username" "${APP_SAFE_NAME:0:16}" + wiz_get_or_set "postgres/db_password" "$(wiz_random_password 32)" + STATE="postgres_check_connection" + ;; + "reuse") + STATE="postgres_params_host" + ;; + esac + else + STATE="done" + echo "PostgreSQL configuration canceled by user." + exit 1 + fi +} + +input_postgres_params_host() { + wiz_put "postgres/db_host" + wiz_put "postgres/db_port" + + if wiz_ask ; then + STATE="postgres_params_user" + else + STATE="start" + fi +} + +input_postgres_params_user() { + wiz_put "postgres/db_username" + wiz_put "postgres/db_password" + wiz_put "postgres/db_name" + + if wiz_ask ; then + STATE="postgres_check_connection" + else + STATE="postgres_params_host" + fi +} + +input_postgres_check_connection() { + if _postgres_check_connection ; then + echo "Postgres connection OK" + STATE="done" + else + wiz_unseen "postgres/retry" + wiz_put "postgres/retry" + if wiz_ask ; then + case "$(wiz_get "postgres/retry")" in + "retry") + _reset + STATE="start" + ;; + "ignore") + echo "Warning: PostgreSQL connection has not been successfully tested." + STATE="done" + ;; + *) + echo "Error: PostgreSQL configuration failed. Aborting." + STATE="done" + exit 1 + ;; + esac + else + STATE="start" + fi + fi +} + +function _postgres_already_installed() { + # Debian & Ubuntu + if [ -f "/etc/init.d/postgresql" ]; then + return 0; + fi + if [ -d "/var/lib/postgresql" ]; then + return 0; + fi + + # Enterprise Linux & SuSE + if wiz_check_package "postgresql-server" ; then + return 0; + fi + if [ -f "/usr/lib/systemd/system/postgresql.service" ]; then + return 0; + fi + if [ -d "/var/lib/pgsql" ]; then + return 0; + fi + + return 1; +} + +function _reset() { + wiz_unseen "postgres/autoinstall" + wiz_unseen "postgres/db_host" + wiz_unseen "postgres/db_port" + wiz_unseen "postgres/db_username" + wiz_unseen "postgres/db_password" + wiz_unseen "postgres/db_name" +} + +function _postgres_check_connection() { + # https://www.postgresql.org/docs/9.3/libpq-envars.html + export PGPASSWORD="$(wiz_get "postgres/db_password")" + export PGHOST="$(wiz_get "postgres/db_host")" + export PGPORT="$(wiz_get "postgres/db_port")" + export PGUSER="$(wiz_get "postgres/db_username")" + export PGDATABASE="$(wiz_get "postgres/db_name")" + export PGCONNECT_TIMEOUT=5 + local command="select 1;" + + case "$(wiz_get "postgres/autoinstall")" in + "skip") + return 0; + ;; + "install") + return 0; + ;; + "reuse") + echo "Trying to connect through password-based authentication..." + + # return early if psql not installed + if ! [ -x "$(command -v psql)" ]; then + echo "psql command not present. Skipping check." + return 0; + elif psql --no-password --command="$command" ; then + echo "Connection OK" + return 0; + else + echo "Connection KO" + return 1; + fi + ;; + esac + + return 0; + +} + +state_machine() { + case "$1" in + "start") + input_start + ;; + "postgres_params_host") + input_postgres_params_host + ;; + "postgres_params_user") + input_postgres_params_user + ;; + "postgres_params_source") + input_postgres_params_source + ;; + "postgres_installation_type") + input_postgres_installation_type + ;; + "postgres_check_connection") + input_postgres_check_connection + ;; + "done") + echo "DONE" + exit 0 + ;; + *) + echo "invalid state ${STATE}" + exit 1 + ;; + esac +} + +wizard "start" diff --git a/packaging/addons/addon-postgres/bin/postinstall b/packaging/addons/addon-postgres/bin/postinstall new file mode 100755 index 00000000000..cb6730103b7 --- /dev/null +++ b/packaging/addons/addon-postgres/bin/postinstall @@ -0,0 +1,33 @@ +#!/bin/bash + +set -e + +. "${INSTALLER_DIR}/wizard" + +CONF_FILE="/etc/${APP_NAME}/conf.d/00_addon_postgres" + +function generate_database_template() { + PGPASSWORD="$(wiz_get "postgres/db_password")" + PGHOST="$(wiz_get "postgres/db_host")" + PGPORT="$(wiz_get "postgres/db_port")" + PGUSER="$(wiz_get "postgres/db_username")" + PGDATABASE="$(wiz_get "postgres/db_name")" + + local encoded_password="$(wiz_urlencode "$PGPASSWORD")" + + echo "export DATABASE_URL=\"postgres://${PGUSER}:${encoded_password}@${PGHOST}:${PGPORT}/${PGDATABASE}\"" > "$CONF_FILE" + chown "${APP_USER}.${APP_GROUP}" "$CONF_FILE" +} + +case "$(wiz_get "postgres/autoinstall")" in + "reuse") + generate_database_template + ;; + "install") + generate_database_template + ;; + *) + ;; +esac + +exit 0 diff --git a/packaging/addons/addon-postgres/bin/preinstall b/packaging/addons/addon-postgres/bin/preinstall new file mode 100755 index 00000000000..849b69591d3 --- /dev/null +++ b/packaging/addons/addon-postgres/bin/preinstall @@ -0,0 +1,238 @@ +#!/bin/bash + +set -e + +. "${INSTALLER_DIR}/wizard" + +ADDON_VERSION="v1" + +MSG_CONFLICTING_INSTALL="ERROR: It seems like you already have PostgreSQL installed. Please run '$APP_NAME reconfigure' and choose to use the existing installation instead." +MSG_UNKNOWN_DISTRIBUTION_VERSION="ERROR: The current distribution is not supported by this wizard. Please install PostgreSQL manually and retry." +MSG_CONNECTION_KO="ERROR: Connection KO. Aborting postgres installation. You should check the wizard configuration in /etc/$APP_NAME/installer.dat" + +PGHOST="$(wiz_get "postgres/db_host" || echo "127.0.0.1")" +PGPORT="$(wiz_get "postgres/db_port" || echo "5432")" +PGDATABASE="$(wiz_get "postgres/db_name" || echo "$APP_SAFE_NAME")" +PGUSER="$(wiz_get "postgres/db_username" || echo "$APP_SAFE_NAME")" +PGPASSWORD="$(wiz_get "postgres/db_password" || echo "")" + +CONF_FILE="/etc/${APP_NAME}/conf.d/00_addon_postgres" + +install_postgres_server() { + case $(wiz_fact "osfamily") in + "debian") + case $(wiz_fact "osversion") in + "7") + codename="wheezy" + ;; + "8") + codename="jessie" + ;; + "9") + codename="stretch" + ;; + "10") + codename="buster" + ;; + "11") + codename="bullseye" + ;; + "12") + codename="bookworm" + ;; + "14.04") + codename="trusty" + ;; + "16.04") + codename="xenial" + ;; + "18.04") + codename="bionic" + ;; + "20.04") + codename="focal" + ;; + "22.04") + codename="jammy" + ;; + esac + + if [ "$codename" != "" ]; then + if ! wiz_check_package "postgresql-17" ; then + _ensure_port_available + echo "deb https://apt.postgresql.org/pub/repos/apt/ ${codename}-pgdg main" > /etc/apt/sources.list.d/pgdg.list + echo -n "INFO: Adding repository signing key from PostgreSQL... " + wget --quiet -O - https://www.postgresql.org/media/keys/ACCC4CF8.asc | apt-key add - + echo "INFO: Installing PostgreSQL v17..." + apt-get update -qq + DEBIAN_FRONTEND=noninteractive apt-get install postgresql-17 -y + + su - postgres -c "/usr/lib/postgresql/17/bin/pg_ctl -D /var/lib/postgresql/17/main -w -t 10 stop || true" + _configure_postgres_server "/etc/postgresql/17/main" + sleep 3 + su - postgres -c "/usr/lib/postgresql/17/bin/pg_ctl -D /var/lib/postgresql/17/main -w -t 10 -l logfile restart" + else + _error_if_conflicting_install + fi + _configure_database_and_user + else + echo "$MSG_UNKNOWN_DISTRIBUTION_VERSION" + exit 1 + fi + ;; + "redhat") + case $(wiz_fact "osversion") in + 7*) + repo="https://download.postgresql.org/pub/repos/yum/reporpms/EL-7-x86_64/pgdg-redhat-repo-latest.noarch.rpm" + ;; + 8*) + repo="https://download.postgresql.org/pub/repos/yum/reporpms/EL-8-x86_64/pgdg-redhat-repo-latest.noarch.rpm" + dnf -qy module disable postgresql + ;; + 9*) + repo="http://download.postgresql.org/pub/repos/yum/reporpms/EL-9-x86_64/pgdg-redhat-repo-latest.noarch.rpm" + dnf -qy module disable postgresql + ;; + *) + echo "$MSG_UNKNOWN_DISTRIBUTION_VERSION" + exit 1 + ;; + esac + + if ! wiz_check_package "postgresql17-server" ; then + _ensure_port_available + echo "INFO: Installing PostgreSQL v17..." + yum install -y "$repo" + yum install -y postgresql17-server postgresql17 postgresql17-contrib + PGSETUP_INITDB_OPTIONS="--auth-local peer --auth-host md5" /usr/pgsql-17/bin/postgresql-17-setup initdb + + _configure_postgres_server "/var/lib/pgsql/17/data" + wiz_service_enable postgresql-17 + wiz_service_restart postgresql-17 + else + _error_if_conflicting_install + fi + _configure_database_and_user + + ;; + "suse") + case $(wiz_fact "osversion") in + 12*) + repo="https://download.postgresql.org/pub/repos/zypp/repo/pgdg-sles-17.repo" + ;; + 15*) + repo="https://download.postgresql.org/pub/repos/zypp/repo/pgdg-sles-15-pg17.repo" + ;; + *) + repo="" + ;; + esac + + if [ "$repo" == "" ]; then + echo "$MSG_UNKNOWN_DISTRIBUTION_VERSION" + exit 1 + else + if ! wiz_check_package "postgresql17-server" ; then + _ensure_port_available + echo "INFO: Installing PostgreSQL v17..." + zypper addrepo "$repo" + zypper --gpg-auto-import-keys install --repo pgdg-17 -y postgresql17-server postgresql17-contrib + + PGSETUP_INITDB_OPTIONS="--auth-local peer --auth-host md5" /usr/pgsql-17/bin/postgresql-17-setup initdb + _configure_postgres_server "/var/lib/pgsql/17/data" + systemctl enable postgresql-17 + systemctl restart postgresql-17 + else + _error_if_conflicting_install + fi + _configure_database_and_user + fi + ;; + esac +} + +function _error_if_conflicting_install() { + local addon_version="$(wiz_get "postgres/addon_version" || echo "v0")" + + if [ "$addon_version" == "$ADDON_VERSION" ]; then + echo "INFO: PostgreSQL server has already been configured by this addon." + else + echo "$MSG_CONFLICTING_INSTALL" + exit 1 + fi +} + +function _ensure_connection_ok() { + echo -n "INFO: Checking connection to PostgreSQL server... " + if env -i PATH="$PATH" PGCONNECT_TIMEOUT=5 PGPORT="$PGPORT" PGHOST="$PGHOST" PGDATABASE="$PGDATABASE" PGUSER="$PGUSER" PGPASSWORD="$PGPASSWORD" \ + psql --no-readline --no-password -c "select 1;" ; then + echo "OK" + else + echo "KO" + echo "$MSG_CONNECTION_KO" + exit 1 + fi +} + +function _ensure_port_available() { + echo -n "INFO: Checking whether port $PGPORT is available... " + # assume port is free if netstat unavailable + if ! which netstat &>/dev/null ; then + echo "OK (netstat not found)" + return 0; + fi + + if netstat -tulpn | grep ":$PGPORT" &>/dev/null ; then + echo "KO" + echo "ERROR: port $PGPORT is already in use. Can't install new PostgreSQL server." + exit 1 + else + echo "OK" + return 0 + fi +} + +function _configure_postgres_server() { + local base_dir="$1" + sed -i "s|^#include_dir = .*|include_dir = 'conf.d'|" $base_dir/postgresql.conf + mkdir -p $base_dir/conf.d + echo "port = $PGPORT" > $base_dir/conf.d/custom.conf + chown -R postgres:postgres $base_dir/conf.d +} + +function _configure_database_and_user() { + if su - postgres -c "createuser -p $PGPORT --createdb --login --superuser $PGUSER 2>&1 || true" | grep -q "already exists" ; then + echo "INFO: user $PGUSER already exists" + fi + su - postgres -c "psql -p $PGPORT --no-readline --no-password -c \"alter user $PGUSER with encrypted password '$PGPASSWORD';\"" + + if su - postgres -c "createdb -p $PGPORT -O $PGUSER $PGDATABASE 2>&1 || true" | grep -q "already exists" ; then + echo "INFO: database $PGDATABASE already exists" + fi +} + +case "$(wiz_get "postgres/autoinstall")" in + "skip") + echo "INFO: autoinstall=skip. Skipping to next step." + ;; + "install") + echo "INFO: autoinstall=install. A new PostgreSQL v17 server will be installed locally unless a conflicting installation is found." + if [ -f "$CONF_FILE" ]; then + echo "INFO: existing installation found. Skipping to next step." + _ensure_connection_ok + else + install_postgres_server + wiz_set "postgres/addon_version" "$ADDON_VERSION" + _ensure_connection_ok + fi + ;; + "reuse") + echo "INFO: autoinstall=reuse. Skipping to next step." + ;; + *) + echo "ERROR: Unknown value for postgres/autoinstall" + exit 1 + ;; +esac + +exit 0 diff --git a/packaging/addons/addon-postgres/templates b/packaging/addons/addon-postgres/templates new file mode 100644 index 00000000000..c1a8cf2cb6c --- /dev/null +++ b/packaging/addons/addon-postgres/templates @@ -0,0 +1,47 @@ +Template: postgres/autoinstall +Type: select +Choices: skip, install, reuse +Translations: Skip, Install a new PostgreSQL server and database locally, Use an existing PostgreSQL database +Default: reuse +Description: Do you want to use this wizard to help setup your PostgreSQL database? + If you choose to SKIP this wizard, you will have to then manually configure the database used by the _APP_NAME_. + . + If you choose to INSTALL, a new PostgreSQL v17 server will be downloaded and installed on your server, and the database will be automatically created. + Make sure this does not conflict with any existing PostgreSQL installation. + If you choose to USE an existing installation, you must create the database beforehand and provide the credentials in the next page. + +Template: postgres/retry +Type: select +Choices: retry, abort, ignore +Default: abort +Description: Connection to PostgreSQL server failed, what do you want to do? + It looks like the connection to the PostgreSQL server can't be established with the information you've specified. + +Template: postgres/db_host +Type: string +Default: 127.0.0.1 +Description: PostgreSQL IP or hostname: + Enter the IP or hostname of your PostgreSQL server. + +Template: postgres/db_port +Type: string +Default: 5432 +Description: PostgreSQL port: + Enter the port where your PostgreSQL server is listening. + +Template: postgres/db_username +Type: string +Default: _APP_SAFE_NAME_SHORT_ +Description: Username used by _APP_NAME_ to connect to the PostgreSQL server: + Enter the username used by _APP_NAME_ to connect to your PostgreSQL server. + +Template: postgres/db_password +Type: password +Description: Password used by _APP_NAME_ to connect to the PostgreSQL server: + Enter the password used by _APP_NAME_ to connect to your PostgreSQL server. + +Template: postgres/db_name +Type: string +Default: _APP_SAFE_NAME_ +Description: Name of the database for _APP_NAME_: + Name of the database that will host the data of _APP_NAME_.