mirror of
https://github.com/MHSanaei/3x-ui.git
synced 2026-05-26 07:08:01 +00:00
feat(bash): prompt for PostgreSQL (#4472)
* feat(install): prompt for SQLite vs PostgreSQL during install * fix(install): write env file to per-distro path and handle pg-install failure The env file was hardcoded to /etc/default/x-ui, but RHEL/Fedora units read /etc/sysconfig/x-ui, Arch reads /etc/conf.d/x-ui, and Alpine OpenRC auto- sources /etc/conf.d/x-ui. PostgreSQL selection was silently dropped on every distro except Debian. Also initdb on openSUSE (service wouldn't start) and prompt the operator on local-install failure instead of silently demoting to SQLite. * fix(scripts): make x-ui.sh and update.sh PostgreSQL-aware update.sh ran setting -show and migrate without sourcing the env file, so PostgreSQL users had migrations applied to the SQLite default and settings introspection read the wrong DB. Sourcing the per-distro env file at the start of update_x-ui exports XUI_DB_TYPE/XUI_DB_DSN to all binary calls. x-ui.sh now shows the active backend in View Current Settings (password masked) and removes the env file on uninstall so a later reinstall doesn't inherit a stale DSN.
This commit is contained in:
151
install.sh
151
install.sh
@@ -110,6 +110,83 @@ gen_random_string() {
|
|||||||
| head -c "$length"
|
| 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
|
||||||
|
if [[ ! -f /var/lib/pgsql/data/PG_VERSION ]]; then
|
||||||
|
install -d -o postgres -g postgres -m 700 /var/lib/pgsql/data >&2 || return 1
|
||||||
|
su - postgres -c "initdb -D /var/lib/pgsql/data" >&2 || return 1
|
||||||
|
fi
|
||||||
|
;;
|
||||||
|
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() {
|
install_acme() {
|
||||||
echo -e "${green}Installing acme.sh for SSL certificate management...${plain}"
|
echo -e "${green}Installing acme.sh for SSL certificate management...${plain}"
|
||||||
cd ~ || return 1
|
cd ~ || return 1
|
||||||
@@ -741,6 +818,79 @@ config_after_install() {
|
|||||||
local config_username=$(gen_random_string 10)
|
local config_username=$(gen_random_string 10)
|
||||||
local config_password=$(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
|
||||||
|
local xui_env_file
|
||||||
|
case "${release}" in
|
||||||
|
ubuntu | debian | armbian)
|
||||||
|
xui_env_file="/etc/default/x-ui"
|
||||||
|
;;
|
||||||
|
arch | manjaro | parch | alpine)
|
||||||
|
xui_env_file="/etc/conf.d/x-ui"
|
||||||
|
;;
|
||||||
|
*)
|
||||||
|
xui_env_file="/etc/sysconfig/x-ui"
|
||||||
|
;;
|
||||||
|
esac
|
||||||
|
|
||||||
|
local xui_dsn=""
|
||||||
|
local pg_mode=""
|
||||||
|
while [[ -z "$xui_dsn" ]]; do
|
||||||
|
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}"
|
||||||
|
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 ""
|
||||||
|
echo -e "${red}PostgreSQL installation failed.${plain}"
|
||||||
|
echo -e " 1) Retry local install"
|
||||||
|
echo -e " 2) Enter an external DSN instead"
|
||||||
|
echo -e " 3) Abort install"
|
||||||
|
echo -e " 4) Fall back to SQLite"
|
||||||
|
read -rp "Choose [1]: " pg_fail
|
||||||
|
pg_fail="${pg_fail:-1}"
|
||||||
|
case "$pg_fail" in
|
||||||
|
2) pg_mode="2" ;;
|
||||||
|
3) echo -e "${red}Install aborted.${plain}"; exit 1 ;;
|
||||||
|
4) db_choice="1"; xui_dsn=""; break ;;
|
||||||
|
*) xui_dsn="" ;;
|
||||||
|
esac
|
||||||
|
fi
|
||||||
|
fi
|
||||||
|
done
|
||||||
|
if [[ -n "$xui_dsn" ]]; then
|
||||||
|
install -d -m 755 "$(dirname "$xui_env_file")"
|
||||||
|
umask 077
|
||||||
|
cat > "$xui_env_file" << EOF
|
||||||
|
XUI_DB_TYPE=postgres
|
||||||
|
XUI_DB_DSN=${xui_dsn}
|
||||||
|
EOF
|
||||||
|
chmod 600 "$xui_env_file"
|
||||||
|
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
|
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
|
if [[ "${config_confirm}" == "y" || "${config_confirm}" == "Y" ]]; then
|
||||||
read -rp "Please set up the panel port: " config_port
|
read -rp "Please set up the panel port: " config_port
|
||||||
@@ -775,6 +925,7 @@ config_after_install() {
|
|||||||
echo -e "${green}Password: ${config_password}${plain}"
|
echo -e "${green}Password: ${config_password}${plain}"
|
||||||
echo -e "${green}Port: ${config_port}${plain}"
|
echo -e "${green}Port: ${config_port}${plain}"
|
||||||
echo -e "${green}WebBasePath: ${config_webBasePath}${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}Access URL: ${SSL_SCHEME}://${SSL_HOST}:${config_port}/${config_webBasePath}${plain}"
|
||||||
echo -e "${green}API Token: ${config_apiToken}${plain}"
|
echo -e "${green}API Token: ${config_apiToken}${plain}"
|
||||||
echo -e "${green}═══════════════════════════════════════════${plain}"
|
echo -e "${green}═══════════════════════════════════════════${plain}"
|
||||||
|
|||||||
27
update.sh
27
update.sh
@@ -105,6 +105,31 @@ gen_random_string() {
|
|||||||
| head -c "$length"
|
| head -c "$length"
|
||||||
}
|
}
|
||||||
|
|
||||||
|
xui_env_file_path() {
|
||||||
|
case "${release}" in
|
||||||
|
ubuntu | debian | armbian)
|
||||||
|
echo "/etc/default/x-ui"
|
||||||
|
;;
|
||||||
|
arch | manjaro | parch | alpine)
|
||||||
|
echo "/etc/conf.d/x-ui"
|
||||||
|
;;
|
||||||
|
*)
|
||||||
|
echo "/etc/sysconfig/x-ui"
|
||||||
|
;;
|
||||||
|
esac
|
||||||
|
}
|
||||||
|
|
||||||
|
load_xui_env() {
|
||||||
|
local env_file
|
||||||
|
env_file="$(xui_env_file_path)"
|
||||||
|
if [[ -r "$env_file" ]]; then
|
||||||
|
set -a
|
||||||
|
# shellcheck disable=SC1090
|
||||||
|
source "$env_file"
|
||||||
|
set +a
|
||||||
|
fi
|
||||||
|
}
|
||||||
|
|
||||||
install_base() {
|
install_base() {
|
||||||
echo -e "${green}Updating and install dependency packages...${plain}"
|
echo -e "${green}Updating and install dependency packages...${plain}"
|
||||||
case "${release}" in
|
case "${release}" in
|
||||||
@@ -775,6 +800,8 @@ config_after_update() {
|
|||||||
update_x-ui() {
|
update_x-ui() {
|
||||||
cd ${xui_folder%/x-ui}/
|
cd ${xui_folder%/x-ui}/
|
||||||
|
|
||||||
|
load_xui_env
|
||||||
|
|
||||||
if [ -f "${xui_folder}/x-ui" ]; then
|
if [ -f "${xui_folder}/x-ui" ]; then
|
||||||
current_xui_version=$(${xui_folder}/x-ui -v)
|
current_xui_version=$(${xui_folder}/x-ui -v)
|
||||||
echo -e "${green}Current x-ui version: ${current_xui_version}${plain}"
|
echo -e "${green}Current x-ui version: ${current_xui_version}${plain}"
|
||||||
|
|||||||
27
x-ui.sh
27
x-ui.sh
@@ -179,6 +179,20 @@ delete_script() {
|
|||||||
exit 1
|
exit 1
|
||||||
}
|
}
|
||||||
|
|
||||||
|
xui_env_file_path() {
|
||||||
|
case "${release}" in
|
||||||
|
ubuntu | debian | armbian)
|
||||||
|
echo "/etc/default/x-ui"
|
||||||
|
;;
|
||||||
|
arch | manjaro | parch | alpine)
|
||||||
|
echo "/etc/conf.d/x-ui"
|
||||||
|
;;
|
||||||
|
*)
|
||||||
|
echo "/etc/sysconfig/x-ui"
|
||||||
|
;;
|
||||||
|
esac
|
||||||
|
}
|
||||||
|
|
||||||
uninstall() {
|
uninstall() {
|
||||||
confirm "Are you sure you want to uninstall the panel? xray will also uninstalled!" "n"
|
confirm "Are you sure you want to uninstall the panel? xray will also uninstalled!" "n"
|
||||||
if [[ $? != 0 ]]; then
|
if [[ $? != 0 ]]; then
|
||||||
@@ -202,6 +216,7 @@ uninstall() {
|
|||||||
|
|
||||||
rm /etc/x-ui/ -rf
|
rm /etc/x-ui/ -rf
|
||||||
rm ${xui_folder}/ -rf
|
rm ${xui_folder}/ -rf
|
||||||
|
rm -f "$(xui_env_file_path)"
|
||||||
|
|
||||||
echo ""
|
echo ""
|
||||||
echo -e "Uninstalled Successfully.\n"
|
echo -e "Uninstalled Successfully.\n"
|
||||||
@@ -289,6 +304,18 @@ check_config() {
|
|||||||
fi
|
fi
|
||||||
LOGI "${info}"
|
LOGI "${info}"
|
||||||
|
|
||||||
|
local db_env_file
|
||||||
|
db_env_file="$(xui_env_file_path)"
|
||||||
|
if [[ -r "$db_env_file" ]] && grep -q '^XUI_DB_TYPE=postgres' "$db_env_file"; then
|
||||||
|
local dsn
|
||||||
|
dsn="$(grep -E '^XUI_DB_DSN=' "$db_env_file" | head -1 | cut -d= -f2-)"
|
||||||
|
local dsn_safe
|
||||||
|
dsn_safe="$(echo "$dsn" | sed -E 's|(://[^:/@]+:)[^@]+@|\1****@|')"
|
||||||
|
echo -e "${green}Database: PostgreSQL — ${dsn_safe}${plain}"
|
||||||
|
else
|
||||||
|
echo -e "${green}Database: SQLite (/etc/x-ui/x-ui.db)${plain}"
|
||||||
|
fi
|
||||||
|
|
||||||
local existing_webBasePath=$(echo "$info" | grep -Eo 'webBasePath: .+' | awk '{print $2}')
|
local existing_webBasePath=$(echo "$info" | grep -Eo 'webBasePath: .+' | awk '{print $2}')
|
||||||
local existing_port=$(echo "$info" | grep -Eo 'port: .+' | awk '{print $2}')
|
local existing_port=$(echo "$info" | grep -Eo 'port: .+' | awk '{print $2}')
|
||||||
local existing_cert=$(${xui_folder}/x-ui setting -getCert true | grep 'cert:' | awk -F': ' '{print $2}' | tr -d '[:space:]')
|
local existing_cert=$(${xui_folder}/x-ui setting -getCert true | grep 'cert:' | awk -F': ' '{print $2}' | tr -d '[:space:]')
|
||||||
|
|||||||
Reference in New Issue
Block a user