diff --git a/install.sh b/install.sh index 63d81863..2e73b579 100644 --- a/install.sh +++ b/install.sh @@ -110,6 +110,79 @@ gen_random_string() { | head -c "$length" } +install_postgres_local() { + local pg_user="xui" + local pg_db="xui" + local pg_pass + pg_pass=$(gen_random_string 24) + + case "${release}" in + ubuntu | debian | armbian) + apt-get update >&2 && apt-get install -y -q postgresql >&2 || return 1 + ;; + fedora | amzn | virtuozzo | rhel | almalinux | rocky | ol) + dnf install -y -q postgresql-server postgresql-contrib >&2 || return 1 + [[ -d /var/lib/pgsql/data && -f /var/lib/pgsql/data/PG_VERSION ]] || postgresql-setup --initdb >&2 || return 1 + ;; + centos) + if [[ "${VERSION_ID}" =~ ^7 ]]; then + yum install -y postgresql-server postgresql-contrib >&2 || return 1 + else + dnf install -y -q postgresql-server postgresql-contrib >&2 || return 1 + fi + [[ -d /var/lib/pgsql/data && -f /var/lib/pgsql/data/PG_VERSION ]] || postgresql-setup --initdb >&2 || return 1 + ;; + arch | manjaro | parch) + pacman -Syu --noconfirm postgresql >&2 || return 1 + if [[ ! -f /var/lib/postgres/data/PG_VERSION ]]; then + sudo -u postgres initdb -D /var/lib/postgres/data >&2 || return 1 + fi + ;; + opensuse-tumbleweed | opensuse-leap) + zypper -q install -y postgresql-server postgresql-contrib >&2 || return 1 + ;; + alpine) + apk add --no-cache postgresql postgresql-contrib >&2 || return 1 + if [[ ! -f /var/lib/postgresql/data/PG_VERSION ]]; then + /etc/init.d/postgresql setup >&2 || return 1 + fi + rc-update add postgresql default >&2 2> /dev/null || true + rc-service postgresql start >&2 || return 1 + ;; + *) + echo -e "${red}Unsupported distro for automatic PostgreSQL install: ${release}${plain}" >&2 + return 1 + ;; + esac + + if [[ "${release}" != "alpine" ]]; then + systemctl enable --now postgresql >&2 || return 1 + fi + + # Wait briefly for the server to accept connections. + local i + for i in 1 2 3 4 5; do + sudo -u postgres psql -tAc 'SELECT 1' > /dev/null 2>&1 && break + sleep 1 + done + + # Idempotent role/db creation. + sudo -u postgres psql -tAc "SELECT 1 FROM pg_roles WHERE rolname='${pg_user}'" 2> /dev/null \ + | grep -q 1 \ + || sudo -u postgres psql -c "CREATE USER ${pg_user} WITH PASSWORD '${pg_pass}';" >&2 || return 1 + + sudo -u postgres psql -tAc "SELECT 1 FROM pg_database WHERE datname='${pg_db}'" 2> /dev/null \ + | grep -q 1 \ + || sudo -u postgres psql -c "CREATE DATABASE ${pg_db} OWNER ${pg_user};" >&2 || return 1 + + sudo -u postgres psql -c "ALTER USER ${pg_user} WITH PASSWORD '${pg_pass}';" >&2 || return 1 + + local pg_pass_enc + pg_pass_enc=$(printf '%s' "${pg_pass}" | sed -e 's/%/%25/g' -e 's/:/%3A/g' -e 's/@/%40/g' -e 's|/|%2F|g' -e 's/?/%3F/g' -e 's/#/%23/g') + echo "postgres://${pg_user}:${pg_pass_enc}@127.0.0.1:5432/${pg_db}?sslmode=disable" + return 0 +} + install_acme() { echo -e "${green}Installing acme.sh for SSL certificate management...${plain}" cd ~ || return 1 @@ -741,6 +814,51 @@ config_after_install() { local config_username=$(gen_random_string 10) local config_password=$(gen_random_string 10) + local db_label="SQLite (/etc/x-ui/x-ui.db)" + echo "" + echo -e "${green}═══════════════════════════════════════════${plain}" + echo -e "${green} Database Selection ${plain}" + echo -e "${green}═══════════════════════════════════════════${plain}" + echo -e " 1) SQLite (default — recommended for < 1000 clients)" + echo -e " 2) PostgreSQL (recommended for high client counts / many nodes)" + read -rp "Choose [1]: " db_choice + db_choice="${db_choice:-1}" + if [[ "$db_choice" == "2" ]]; then + echo "" + echo -e " 1) Install PostgreSQL locally and create a dedicated user/db (recommended)" + echo -e " 2) Use an existing PostgreSQL server (enter DSN)" + read -rp "Choose [1]: " pg_mode + pg_mode="${pg_mode:-1}" + local xui_dsn="" + if [[ "$pg_mode" == "2" ]]; then + while [[ -z "$xui_dsn" ]]; do + read -rp "Enter PostgreSQL DSN (postgres://user:pass@host:port/dbname?sslmode=disable): " xui_dsn + xui_dsn="${xui_dsn// /}" + done + db_label="PostgreSQL (external)" + else + echo -e "${yellow}Installing PostgreSQL — this may take a moment...${plain}" + if xui_dsn=$(install_postgres_local); then + db_label="PostgreSQL (xui@127.0.0.1:5432/xui)" + else + echo -e "${red}PostgreSQL installation failed; falling back to SQLite.${plain}" + xui_dsn="" + fi + fi + if [[ -n "$xui_dsn" ]]; then + install -d -m 755 /etc/default + umask 077 + cat > /etc/default/x-ui << EOF +XUI_DB_TYPE=postgres +XUI_DB_DSN=${xui_dsn} +EOF + chmod 600 /etc/default/x-ui + umask 022 + export XUI_DB_TYPE=postgres + export XUI_DB_DSN="${xui_dsn}" + fi + fi + read -rp "Would you like to customize the Panel Port settings? (If not, a random port will be applied) [y/n]: " config_confirm if [[ "${config_confirm}" == "y" || "${config_confirm}" == "Y" ]]; then read -rp "Please set up the panel port: " config_port @@ -775,6 +893,7 @@ config_after_install() { echo -e "${green}Password: ${config_password}${plain}" echo -e "${green}Port: ${config_port}${plain}" echo -e "${green}WebBasePath: ${config_webBasePath}${plain}" + echo -e "${green}Database: ${db_label}${plain}" echo -e "${green}Access URL: ${SSL_SCHEME}://${SSL_HOST}:${config_port}/${config_webBasePath}${plain}" echo -e "${green}API Token: ${config_apiToken}${plain}" echo -e "${green}═══════════════════════════════════════════${plain}"